From e986da96554abe0275ecaf80abbaddad7506df42 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 11:35:17 +0000 Subject: Fixed @throws statements in javadoc git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603890 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/render/afp/modca/AbstractStructuredAFPObject.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java index bc2bf9f99..f9348b81c 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java @@ -45,7 +45,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractNamedAFPObject /** * Helper method to write the start of the Object. * @param os The stream to write to - * @throws an I/O exception if one occurred + * @throws IOException an I/O exception if one occurred */ protected void writeStart(OutputStream os) throws IOException { } @@ -53,7 +53,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractNamedAFPObject /** * Helper method to write the contents of the Object. * @param os The stream to write to - * @throws an I/O exception if one occurred + * @throws IOException an I/O exception if one occurred */ protected void writeContent(OutputStream os) throws IOException { } @@ -61,7 +61,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractNamedAFPObject /** * Helper method to write the end of the Object. * @param os The stream to write to - * @throws an I/O exception if one occurred + * @throws IOException an I/O exception if one occurred */ protected void writeEnd(OutputStream os) throws IOException { } @@ -69,7 +69,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractNamedAFPObject /** * Accessor method to write the AFP datastream for the Image Object * @param os The stream to write to - * @throws java.io.IOException in the event that an I/O exception occurred + * @throws IOException in the event that an I/O exception occurred */ public void writeDataStream(OutputStream os) throws IOException { -- cgit v1.2.3 From 26b5548ee2bec051c2cc18bccbda31b86edfa560 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 13 Dec 2007 14:43:08 +0000 Subject: Minor tweaks: * only add text to a fo:wrapper if it is not a direct flow-descendant * error if an fo:wrapper that is a direct flow-descendant contains inline-level children git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603926 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/Wrapper.java | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index c7ca33a10..8b833f6b7 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -19,9 +19,12 @@ package org.apache.fop.fo.flow; +import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObjMixed; +import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.pagination.Flow; import org.xml.sax.Locator; /** @@ -35,12 +38,24 @@ public class Wrapper extends FObjMixed { // used for FO validation private boolean blockOrInlineItemFound = false; + private boolean isFlowChild = false; /** * @param parent FONode that is the parent of this object */ public Wrapper(FONode parent) { super(parent); + /* Check if the fo:wrapper is a child of an fo:flow or fo:static-content + * (or a descendant in nested fo:wrapper sequence, the first of which + * is a child of an fo:flow or fo:static-content */ + FONode ancestor = this.parent; + while (!(ancestor instanceof Flow) + && ancestor instanceof Wrapper) { + ancestor = ancestor.getParent(); + } + if (ancestor instanceof Flow) { + this.isFlowChild = true; + } } /** @@ -49,6 +64,7 @@ public class Wrapper extends FObjMixed { * Additionally (unimplemented): "An fo:wrapper that is a child of an * fo:multi-properties is only permitted to have children that would * be permitted in place of the fo:multi-properties." + * */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -58,12 +74,33 @@ public class Wrapper extends FObjMixed { "(#PCDATA|%inline;|%block;)"); } } else if (isBlockOrInlineItem(nsURI, localName)) { + if (isFlowChild + && isInlineItem(nsURI, localName) + && !isNeutralItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName, + "fo:" + localName + " not allowed as child of an fo:wrapper " + + "that is a child of an fo:flow or fo:static-content"); + } blockOrInlineItemFound = true; } else { invalidChildError(loc, nsURI, localName); } } + /** {@inheritDoc} */ + protected void addCharacters( + char[] data, + int start, + int end, + PropertyList pList, + Locator locator) throws FOPException { + /* Only add text if the fo:wrapper is not a child of an fo:flow + * or fo:static-content */ + if (!this.isFlowChild) { + super.addCharacters(data, start, end, pList, locator); + } + } + /** {@inheritDoc} */ public String getLocalName() { return "wrapper"; -- cgit v1.2.3 From 5ea761b17a5cbdcc2ac36f6c841d7a22d8bdd974 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 15:55:29 +0000 Subject: Removed calls to removeLegalBreaks since they aren't necessary (the whole content is put in a single box anyway) and the method is buggy. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603943 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/ElementListUtils.java | 45 +++++----------------- .../layoutmgr/table/TableContentLayoutManager.java | 2 - 2 files changed, 10 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java index 08450db98..a2baba2fc 100644 --- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java +++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java @@ -30,31 +30,6 @@ import org.apache.fop.traits.MinOptMax; */ public class ElementListUtils { - /** - * Removes all legal breaks in an element list. - * @param elements the element list - */ - public static void removeLegalBreaks(LinkedList elements) { - ListIterator i = elements.listIterator(); - while (i.hasNext()) { - ListElement el = (ListElement)i.next(); - if (el.isPenalty()) { - BreakElement breakPoss = (BreakElement)el; - //Convert all penalties no break inhibitors - if (breakPoss.getPenaltyValue() < KnuthPenalty.INFINITE) { - breakPoss.setPenaltyValue(KnuthPenalty.INFINITE); - } - } else if (el.isGlue()) { - i.previous(); - if (el.isBox()) { - i.next(); - i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, - null, false)); - } - } - } - } - /** * 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 @@ -66,7 +41,7 @@ public class ElementListUtils { 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 @@ -84,7 +59,7 @@ public class ElementListUtils { KnuthPenalty penalty = (KnuthPenalty)el; //Convert all penalties to break inhibitors if (penalty.getP() < KnuthPenalty.INFINITE) { - iter.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, + iter.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary())); } } else if (el.isGlue()) { @@ -94,7 +69,7 @@ public class ElementListUtils { el = (ListElement)iter.previous(); iter.next(); if (el.isBox()) { - iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, + iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, null, false)); } iter.next(); @@ -131,7 +106,7 @@ public class ElementListUtils { KnuthPenalty penalty = (KnuthPenalty)el; //Convert all penalties to break inhibitors 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())); } } else if (el.isGlue()) { @@ -140,7 +115,7 @@ public class ElementListUtils { el = (ListElement)i.previous(); i.next(); if (el.isBox()) { - i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, + i.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, null, false)); } } else if (el.isUnresolvedElement()) { @@ -163,7 +138,7 @@ public class ElementListUtils { } return true; } - + /** * Calculates the content length of the given element list. Warning: It doesn't take any * stretch and shrink possibilities into account. @@ -193,7 +168,7 @@ public class ElementListUtils { } return len; } - + /** * Calculates the content length of the given element list. Warning: It doesn't take any * stretch and shrink possibilities into account. @@ -203,7 +178,7 @@ public class ElementListUtils { public static int calcContentLength(List elems) { return calcContentLength(elems, 0, elems.size() - 1); } - + /** * Indicates whether the given element list ends with a forced break. * @param elems the element list @@ -213,7 +188,7 @@ public class ElementListUtils { ListElement last = (ListElement)elems.getLast(); return last.isForcedBreak(); } - + /** * Determines the position of the previous break before the start index on an * element list. @@ -232,5 +207,5 @@ public class ElementListUtils { } return prevBreak; } - + } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index c08216480..bcd7f0244 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -136,7 +136,6 @@ public class TableContentLayoutManager implements PercentBaseContext { if (headerIter != null && headerList == null) { this.headerList = getKnuthElementsForRowIterator( headerIter, context, alignment, TableRowIterator.HEADER); - ElementListUtils.removeLegalBreaks(this.headerList); this.headerNetHeight = ElementListUtils.calcContentLength(this.headerList); if (log.isDebugEnabled()) { @@ -157,7 +156,6 @@ public class TableContentLayoutManager implements PercentBaseContext { if (footerIter != null && footerList == null) { this.footerList = getKnuthElementsForRowIterator( footerIter, context, alignment, TableRowIterator.FOOTER); - ElementListUtils.removeLegalBreaks(this.footerList); this.footerNetHeight = ElementListUtils.calcContentLength(this.footerList); if (log.isDebugEnabled()) { -- cgit v1.2.3 From 709bda3d6c3bc23050e6bf69d16b32ed6b35b541 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 16:10:32 +0000 Subject: Implemented the resolution of collapsing borders in the FO tree, for every situation (normal, cell at the top of a page, cell broken), taking conditionality, headers and footers into account. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603945 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- .../fop/fo/flow/table/BorderSpecification.java | 24 +- .../fo/flow/table/CollapsingBorderResolver.java | 413 ++++++++++++++++----- .../fop/fo/flow/table/ConditionalBorder.java | 204 ++++++++++ .../apache/fop/fo/flow/table/EmptyGridUnit.java | 11 +- .../org/apache/fop/fo/flow/table/GridUnit.java | 160 ++++++-- .../org/apache/fop/fo/flow/table/TableBody.java | 4 + .../org/apache/fop/fo/flow/table/TableFObj.java | 44 ++- .../org/apache/fop/fo/flow/table/TableHeader.java | 5 + .../properties/CommonBorderPaddingBackground.java | 58 ++- .../fop/layoutmgr/table/CollapsingBorderModel.java | 15 + .../table/CollapsingBorderModelEyeCatching.java | 22 ++ 12 files changed, 822 insertions(+), 140 deletions(-) create mode 100644 src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index e0acfca7e..5d1a6f31a 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1141,7 +1141,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericSpace); corr = new SpacePropertyMaker(m); corr.setCorresponding(PR_MARGIN_TOP, PR_MARGIN_TOP, PR_MARGIN_RIGHT); - corr.setUseParent(true); + corr.setUseParent(false); corr.setRelative(true); addPropertyMaker("space-before", m); diff --git a/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java b/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java index 214f9be07..ce6e1b802 100644 --- a/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java +++ b/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java @@ -20,6 +20,7 @@ package org.apache.fop.fo.flow.table; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; /** @@ -28,6 +29,8 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; */ public/*TODO*/ class BorderSpecification { + private static BorderSpecification defaultBorder; + private BorderInfo borderInfo; private int holder; @@ -43,6 +46,14 @@ public/*TODO*/ class BorderSpecification { this.holder = holder; } + static synchronized BorderSpecification getDefaultBorder() { + if (defaultBorder == null) { + defaultBorder = new BorderSpecification(CommonBorderPaddingBackground + .getDefaultBorderInfo(), Constants.FO_TABLE_CELL); + } + return defaultBorder; + } + /** * Returns this border's informations. * @@ -66,6 +77,17 @@ public/*TODO*/ class BorderSpecification { /** {@inheritDoc} */ public String toString() { - return "{" + borderInfo + ", " + holder + "}"; + String holderName = ""; + switch (holder) { + case Constants.FO_TABLE: holderName = "table"; break; + case Constants.FO_TABLE_COLUMN: holderName = "table-column"; break; + case Constants.FO_TABLE_HEADER: holderName = "table-header"; break; + case Constants.FO_TABLE_FOOTER: holderName = "table-footer"; break; + case Constants.FO_TABLE_BODY: holderName = "table-body"; break; + case Constants.FO_TABLE_ROW: holderName = "table-row"; break; + case Constants.FO_TABLE_CELL: holderName = "table-cell"; break; + default: assert false; + } + return "{" + borderInfo + ", " + holderName + "}"; } } diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index c4f7f9a78..f92f7bb30 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -19,6 +19,7 @@ package org.apache.fop.fo.flow.table; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -31,138 +32,366 @@ class CollapsingBorderResolver implements BorderResolver { private Table table; - private List previousRow; - /** - * The flow of rows is interrupted by the table-footer. Save the header's last row (if - * any) for resolution between it and the body's first row. + * The previously registered row, either in the header or the body(-ies), but not in + * the footer (handled separately). */ - private List previousRowSave; - - private TableBody currentTablePart; + private List/**/ previousRow; private boolean firstInTable; - private boolean firstInPart; + private List/**/ footerFirstRow; - private List footerFirstRow; + /** The last currently registered footer row. */ + private List/**/ footerLastRow; - private List footerLastRow; + private Resolver delegate; - private boolean inFooter; + private Resolver resolverInFooter; - CollapsingBorderResolver(Table table) { - this.table = table; - firstInTable = true; - } + private List/**/ leadingBorders; - /** {@inheritDoc} */ - public void endRow(List row, TableCellContainer container) { - // Resolve before- and after-borders for the table-row - if (container instanceof TableRow) { - TableRow tableRow = (TableRow) container; - for (Iterator iter = row.iterator(); iter.hasNext();) { - GridUnit gu = (GridUnit) iter.next(); + private List/**/ trailingBorders; + + /** + * Base class for delegate resolvers. Implementation of the State design pattern: the + * treatment differs slightly whether we are in the table's header, footer or body. To + * avoid complicated if statements, specialised delegate resolvers will be used + * instead. + */ + private abstract class Resolver { + + protected TableBody tablePart; + + protected boolean firstInPart; + + /** + * Integrates border-before specified on the table and its column. + * + * @param row the first row of the table (in the header, or in the body if the + * table has no header) + * @param withLeadingTrailing + * @param withNonLeadingTrailing + * @param withRest + */ + void resolveBordersFirstRowInTable(List/**/ row, boolean withLeadingTrailing, + boolean withNonLeadingTrailing, boolean withRest) { + assert firstInTable; + for (int i = 0; i < row.size(); i++) { + TableColumn column = table.getColumn(i); + ((GridUnit) row.get(i)).integrateBorderSegment( + CommonBorderPaddingBackground.BEFORE, column, withLeadingTrailing, + withNonLeadingTrailing, withRest); + } + firstInTable = false; + } + + /** + * Resolves border-after for the first row, border-before for the second one. + * + * @param rowBefore + * @param rowAfter + */ + void resolveBordersBetweenRows(List/**/ rowBefore, List/**/ rowAfter) { + assert rowBefore != null && rowAfter != null; + for (int i = 0; i < rowAfter.size(); i++) { + GridUnit gu = (GridUnit) rowAfter.get(i); if (gu.getRowSpanIndex() == 0) { - gu.resolveBorder(CommonBorderPaddingBackground.BEFORE, tableRow); - } - if (gu.isLastGridUnitRowSpan()) { - gu.resolveBorder(CommonBorderPaddingBackground.AFTER, tableRow); + GridUnit beforeGU = (GridUnit) rowBefore.get(i); + gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE); } } } - if (inFooter) { - if (footerFirstRow == null) { - footerFirstRow = row; + + /** Integrates the border-after of the part. */ + void resolveBordersLastRowInPart(List/**/ row, boolean withLeadingTrailing, + boolean withNonLeadingTrailing, boolean withRest) { + for (int i = 0; i < row.size(); i++) { + ((GridUnit) row.get(i)).integrateBorderSegment(CommonBorderPaddingBackground.AFTER, + tablePart, withLeadingTrailing, withNonLeadingTrailing, withRest); } - footerLastRow = row; - } else if (firstInTable) { - // Resolve border-before for the first row in the table + } + + /** + * Integrates border-after specified on the table and its columns. + * + * @param row the last row of the footer, or of the last body if the table has no + * footer + * @param withLeadingTrailing + * @param withNonLeadingTrailing + * @param withRest + */ + void resolveBordersLastRowInTable(List/**/ row, boolean withLeadingTrailing, + boolean withNonLeadingTrailing, boolean withRest) { for (int i = 0; i < row.size(); i++) { TableColumn column = table.getColumn(i); - ((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE, column); + ((GridUnit) row.get(i)).integrateBorderSegment(CommonBorderPaddingBackground.AFTER, + column, withLeadingTrailing, withNonLeadingTrailing, withRest); } - firstInTable = false; } - if (firstInPart) { - // Resolve border-before for the first row in the part - for (int i = 0; i < row.size(); i++) { - ((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE, - currentTablePart); + + /** + * Integrates either border-before specified on the table and its columns if the + * table has no header, or border-after specified on the cells of the header's + * last row. For the case the grid unit are at the top of a page. + * + * @param row + */ + void integrateLeadingBorders(List/**/ row) { + for (int i = 0; i < table.getNumberOfColumns(); i++) { + GridUnit gu = (GridUnit) row.get(i); + ConditionalBorder border = (ConditionalBorder) leadingBorders.get(i); + gu.integrateCompetingBorder(CommonBorderPaddingBackground.BEFORE, border, + true, false, true); } - firstInPart = false; } - if (previousRow != null) { - // Resolve after/before borders between rows - for (int i = 0; i < row.size(); i++) { + + /** + * Integrates either border-after specified on the table and its columns if the + * table has no footer, or border-before specified on the cells of the footer's + * first row. For the case the grid unit are at the bottom of a page. + * + * @param row + */ + void integrateTrailingBorders(List/**/ row) { + for (int i = 0; i < table.getNumberOfColumns(); i++) { GridUnit gu = (GridUnit) row.get(i); - if (gu.getRowSpanIndex() == 0) { - GridUnit beforeGU = (GridUnit) previousRow.get(i); - gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE); - } + ConditionalBorder border = (ConditionalBorder) trailingBorders.get(i); + gu.integrateCompetingBorder(CommonBorderPaddingBackground.AFTER, border, + true, false, true); } } - // Resolve start/end borders in the row - Iterator guIter = row.iterator(); - GridUnit gu = (GridUnit) guIter.next(); - gu.resolveBorder(CommonBorderPaddingBackground.START, container); - while (guIter.hasNext()) { - GridUnit guEnd = (GridUnit) guIter.next(); - if (gu.isLastGridUnitColSpan()) { - gu.resolveBorder(guEnd, CommonBorderPaddingBackground.END); + + void startPart(TableBody part) { + tablePart = part; + firstInPart = true; + } + + /** + * Resolves the applicable borders for the given row. + *
    + *
  • Integrates the border-before/after of the containing table-row if any;
  • + *
  • Integrates the border-before of the containing part, if first row;
  • + *
  • Resolves border-start/end between grid units.
  • + *
+ * + * @param row the row being finished + * @param container the containing element + */ + void endRow(List/**/ row, TableCellContainer container) { + // Resolve before- and after-borders for the table-row + if (container instanceof TableRow) { + TableRow tableRow = (TableRow) container; + for (Iterator iter = row.iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + if (gu.getRowSpanIndex() == 0) { + gu.integrateBorderSegment(CommonBorderPaddingBackground.BEFORE, tableRow, + true, true, true); + } + if (gu.isLastGridUnitRowSpan()) { + gu.integrateBorderSegment(CommonBorderPaddingBackground.AFTER, tableRow, + true, true, true); + } + } + } + if (firstInPart) { + // Integrate the border-before of the part + for (int i = 0; i < row.size(); i++) { + ((GridUnit) row.get(i)).integrateBorderSegment( + CommonBorderPaddingBackground.BEFORE, tablePart, true, true, true); + } + firstInPart = false; + } + // Resolve start/end borders in the row + Iterator guIter = row.iterator(); + GridUnit gu = (GridUnit) guIter.next(); + gu.integrateBorderSegment(CommonBorderPaddingBackground.START, container); + while (guIter.hasNext()) { + GridUnit guEnd = (GridUnit) guIter.next(); + if (gu.isLastGridUnitColSpan()) { + gu.resolveBorder(guEnd, CommonBorderPaddingBackground.END); + } + gu = guEnd; } - gu = guEnd; + gu.integrateBorderSegment(CommonBorderPaddingBackground.END, container); } - gu.resolveBorder(CommonBorderPaddingBackground.END, container); - previousRow = row; + void endPart() { + resolveBordersLastRowInPart(previousRow, true, true, true); + } + + abstract void endTable(); } - /** {@inheritDoc} */ - public void startPart(TableBody part) { - firstInPart = true; - currentTablePart = part; - if (part.isTableFooter()) { - inFooter = true; - previousRowSave = previousRow; - previousRow = null; + private class ResolverInHeader extends Resolver { + + void endRow(List/**/ row, TableCellContainer container) { + super.endRow(row, container); + if (previousRow != null) { + resolveBordersBetweenRows(previousRow, row); + } else { + /* + * This is a bit hacky... + * The two only sensible values for border-before on the header's first row are: + * - at the beginning of the table (normal case) + * - if the header is repeated after each page break + * To represent those values we (ab)use the nonLeadingTrailing and the rest + * fields of ConditionalBorder. But strictly speaking this is not their + * purposes. + */ + for (Iterator guIter = row.iterator(); guIter.hasNext();) { + ConditionalBorder borderBefore = ((GridUnit) guIter.next()).borderBefore; + borderBefore.leadingTrailing = null; + borderBefore.rest = borderBefore.nonLeadingTrailing; + } + resolveBordersFirstRowInTable(row, false, true, true); + } + previousRow = row; } - } - /** {@inheritDoc} */ - public void endPart(TableBody part) { - // Resolve border-after for the last row in the part - for (int i = 0; i < previousRow.size(); i++) { - ((GridUnit) previousRow.get(i)) - .resolveBorder(CommonBorderPaddingBackground.AFTER, part); + void endPart() { + super.endPart(); + leadingBorders = new ArrayList(table.getNumberOfColumns()); + /* + * Another hack... + * The border-after of a header is always the same. Leading and rest don't + * apply to cells in the header since they are never broken. To ease + * resolution we override the (normally unused) leadingTrailing and rest + * fields of ConditionalBorder with the only sensible nonLeadingTrailing + * field. That way grid units from the body will always resolve against the + * same, normal header border. + */ + for (Iterator guIter = previousRow.iterator(); guIter.hasNext();) { + ConditionalBorder borderAfter = ((GridUnit) guIter.next()).borderAfter; + borderAfter.leadingTrailing = borderAfter.nonLeadingTrailing; + borderAfter.rest = borderAfter.nonLeadingTrailing; + leadingBorders.add(borderAfter); + } } - if (inFooter) { - inFooter = false; - previousRow = previousRowSave; + + void endTable() { + throw new IllegalStateException(); } } - /** {@inheritDoc} */ - public void endTable() { - if (footerFirstRow != null) { + private class ResolverInFooter extends Resolver { + + void endRow(List/**/ row, TableCellContainer container) { + super.endRow(row, container); + if (footerFirstRow == null) { + footerFirstRow = row; + } else { + // There is a previous row + resolveBordersBetweenRows(footerLastRow, row); + } + footerLastRow = row; + } + + void endPart() { + resolveBordersLastRowInPart(footerLastRow, true, true, true); + trailingBorders = new ArrayList(table.getNumberOfColumns()); + // See same method in ResolverInHeader for an explanation of the hack + for (Iterator guIter = footerFirstRow.iterator(); guIter.hasNext();) { + ConditionalBorder borderBefore = ((GridUnit) guIter.next()).borderBefore; + borderBefore.leadingTrailing = borderBefore.nonLeadingTrailing; + borderBefore.rest = borderBefore.nonLeadingTrailing; + trailingBorders.add(borderBefore); + } + } + + void endTable() { // Resolve after/before border between the last row of table-body and the // first row of table-footer - for (int i = 0; i < footerFirstRow.size(); i++) { - GridUnit gu = (GridUnit) footerFirstRow.get(i); - GridUnit beforeGU = (GridUnit) previousRow.get(i); - gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE); + resolveBordersBetweenRows(previousRow, footerFirstRow); + // See endRow method in ResolverInHeader for an explanation of the hack + for (Iterator guIter = footerLastRow.iterator(); guIter.hasNext();) { + ConditionalBorder borderAfter = ((GridUnit) guIter.next()).borderAfter; + borderAfter.leadingTrailing = null; + borderAfter.rest = borderAfter.nonLeadingTrailing; } + resolveBordersLastRowInTable(footerLastRow, false, true, true); } - List lastRow; - if (footerLastRow != null) { - lastRow = footerLastRow; - } else { - lastRow = previousRow; + } + + private class ResolverInBody extends Resolver { + + void endRow(List/**/ row, TableCellContainer container) { + super.endRow(row, container); + if (firstInTable) { + resolveBordersFirstRowInTable(row, true, true, true); + } else { + // Either there is a header, and then previousRow is set to the header's last row, + // or this is not the first row in the body, and previousRow is not null + resolveBordersBetweenRows(previousRow, row); + integrateLeadingBorders(row); + } + integrateTrailingBorders(row); + previousRow = row; } - // Resolve border-after for the last row of the table - for (int i = 0; i < lastRow.size(); i++) { - TableColumn column = table.getColumn(i); - ((GridUnit) lastRow.get(i)).resolveBorder(CommonBorderPaddingBackground.AFTER, column); + + void endTable() { + if (resolverInFooter != null) { + resolverInFooter.endTable(); + } else { + // Trailing and rest borders already resolved with integrateTrailingBorders + resolveBordersLastRowInTable(previousRow, false, true, false); + } } } + + CollapsingBorderResolver(Table table) { + this.table = table; + firstInTable = true; + } + + /** {@inheritDoc} */ + public void endRow(List/**/ row, TableCellContainer container) { + delegate.endRow(row, container); + } + + /** {@inheritDoc} */ + public void startPart(TableBody part) { + if (part.isTableHeader()) { + delegate = new ResolverInHeader(); + } else { + if (leadingBorders == null) { + // No header, leading borders determined by the table + leadingBorders = new ArrayList(table.getNumberOfColumns()); + for (Iterator colIter = table.getColumns().iterator(); colIter.hasNext();) { + // See endRow method in ResolverInHeader for an explanation of the hack + ConditionalBorder border = ((TableColumn) colIter.next()).borderBefore; + border.leadingTrailing = border.rest; + leadingBorders.add(border); + } + } + if (part.isTableFooter()) { + resolverInFooter = new ResolverInFooter(); + delegate = resolverInFooter; + } else { + if (trailingBorders == null) { + // No footer, trailing borders determined by the table + trailingBorders = new ArrayList(table.getNumberOfColumns()); + for (Iterator colIter = table.getColumns().iterator(); colIter.hasNext();) { + // See endRow method in ResolverInHeader for an explanation of the hack + ConditionalBorder border = ((TableColumn) colIter.next()).borderAfter; + border.leadingTrailing = border.rest; + trailingBorders.add(border); + } + } + delegate = new ResolverInBody(); + } + } + delegate.startPart(part); + } + + /** {@inheritDoc} */ + public void endPart(TableBody part) { + delegate.endPart(); + } + + /** {@inheritDoc} */ + public void endTable() { + delegate.endTable(); + delegate = null; + } } diff --git a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java new file mode 100644 index 000000000..e03e11a15 --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.flow.table; + +import org.apache.fop.layoutmgr.table.CollapsingBorderModel; + +/** + * A class that holds the three possible values for a border-before/after on a table-cell, + * in the collapsing model. These three values are (for border-before, similar for + * border-after): + *
    + *
  • non-leading: common case, when a cell follows the cell before on a same page;
  • + *
  • leading: when the table is broken and the cell appears at the top of a page, in + * which case its border must be resolved with the header (or the top of the table) + * instead of with the previous cell;
  • + *
  • rest: when a cell is broken over several pages; same as leading but with + * conditionality taken into account.
  • + *
+ */ +public class ConditionalBorder { + + /** Special case: the cell is at the top or the bottom of the page. */ + BorderSpecification leadingTrailing; + + /** Normal case, no break. */ + BorderSpecification nonLeadingTrailing; + + /** Special case: break inside the cell. */ + BorderSpecification rest; + + /** The model used to resolve borders. */ + private CollapsingBorderModel collapsingBorderModel; + + private ConditionalBorder(BorderSpecification leadingTrailing, + BorderSpecification nonLeadingTrailing, BorderSpecification rest, + CollapsingBorderModel collapsingBorderModel) { + this.leadingTrailing = leadingTrailing; + this.nonLeadingTrailing = nonLeadingTrailing; + this.rest = rest; + this.collapsingBorderModel = collapsingBorderModel; + } + + /** + * Creates a new conditional border. + * + * @param borderSpecification the border specification to take as a basis + * @param collapsingBorderModel the model that will be used to resolved borders + */ + ConditionalBorder(BorderSpecification borderSpecification, + CollapsingBorderModel collapsingBorderModel) { + leadingTrailing = borderSpecification; + nonLeadingTrailing = leadingTrailing; + if (borderSpecification.getBorderInfo().getWidth().isDiscard()) { + rest = BorderSpecification.getDefaultBorder(); + } else { + rest = leadingTrailing; + } + this.collapsingBorderModel = collapsingBorderModel; + } + + /** + * Resolves and updates the relevant parts of this border as well as the given one. + * + * @param competitor + * @param withLeadingTrailing + * @param withNonLeadingTrailing + * @param withRest + */ + void resolve(ConditionalBorder competitor, boolean withLeadingTrailing, + boolean withNonLeadingTrailing, boolean withRest) { + if (withLeadingTrailing) { + BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( + leadingTrailing, competitor.leadingTrailing); + if (resolvedBorder != null) { + leadingTrailing = resolvedBorder; + competitor.leadingTrailing = resolvedBorder; + } + } + if (withNonLeadingTrailing) { + BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( + nonLeadingTrailing, competitor.nonLeadingTrailing); + if (resolvedBorder != null) { + nonLeadingTrailing = resolvedBorder; + competitor.nonLeadingTrailing = resolvedBorder; + } + } + if (withRest) { + BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(rest, + competitor.rest); + if (resolvedBorder != null) { + rest = resolvedBorder; + competitor.rest = resolvedBorder; + } + } + } + + /** + * Integrates the given segment in this border. Unlike for + * {@link #integrateSegment(ConditionalBorder, boolean, boolean, boolean)}, this + * method nicely handles the case where the CollapsingBorderModel returns null, by + * keeping the components to their old values. + * + * @param competitor + * @param withLeadingTrailing + * @param withNonLeadingTrailing + * @param withRest + */ + void integrateCompetingSegment(ConditionalBorder competitor, boolean withLeadingTrailing, + boolean withNonLeadingTrailing, boolean withRest) { + if (withLeadingTrailing) { + BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( + leadingTrailing, competitor.leadingTrailing); + if (resolvedBorder != null) { + leadingTrailing = resolvedBorder; + } + } + if (withNonLeadingTrailing) { + BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( + nonLeadingTrailing, competitor.nonLeadingTrailing); + if (resolvedBorder != null) { + nonLeadingTrailing = resolvedBorder; + } + } + if (withRest) { + BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(rest, + competitor.rest); + if (resolvedBorder != null) { + rest = resolvedBorder; + } + } + } + + /** + * Updates this border after taking into account the given segment. The + * CollapsingBorderModel is not expected to return null. + * + * @param segment + * @param withLeadingTrailing + * @param withNonLeadingTrailing + * @param withRest + */ + void integrateSegment(ConditionalBorder segment, boolean withLeadingTrailing, + boolean withNonLeadingTrailing, boolean withRest) { + if (withLeadingTrailing) { + leadingTrailing = collapsingBorderModel.determineWinner(leadingTrailing, + segment.leadingTrailing); + assert leadingTrailing != null; + } + if (withNonLeadingTrailing) { + nonLeadingTrailing = collapsingBorderModel.determineWinner(nonLeadingTrailing, + segment.nonLeadingTrailing); + assert nonLeadingTrailing != null; + } + if (withRest) { + rest = collapsingBorderModel.determineWinner(rest, segment.rest); + assert rest != null; + } + } + + /** + * Returns a shallow copy of this border. + * + * @return a copy of this border + */ + ConditionalBorder copy() { + return new ConditionalBorder(leadingTrailing, nonLeadingTrailing, rest, + collapsingBorderModel); + } + + /** {@inheritDoc} */ + public String toString() { + return "{non-leading: " + nonLeadingTrailing + ", leading: " + leadingTrailing + ", rest: " + + rest + "}"; + } + + /** + * Returns a default border specification. + * + * @param collapsingBorderModel the model that will be used to resolve borders + * @return a border with style 'none' for all of the three components + */ + static ConditionalBorder getDefaultBorder(CollapsingBorderModel collapsingBorderModel) { + BorderSpecification defaultBorderSpec = BorderSpecification.getDefaultBorder(); + return new ConditionalBorder(defaultBorderSpec, defaultBorderSpec, defaultBorderSpec, + collapsingBorderModel); + } +} diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java index be487931b..7a8b0be62 100644 --- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java @@ -19,8 +19,6 @@ package org.apache.fop.fo.flow.table; -import org.apache.fop.fo.Constants; -import org.apache.fop.fo.properties.CommonBorderPaddingBackground; /** * GridUnit subclass for empty grid units. @@ -40,10 +38,11 @@ public class EmptyGridUnit extends GridUnit { } /** {@inheritDoc} */ - protected void setBorder(int side) { - resolvedBorders[side] = new BorderSpecification( - CommonBorderPaddingBackground.getDefaultBorderInfo(), - Constants.FO_TABLE_CELL); + protected void setBordersFromCell() { + borderBefore = ConditionalBorder.getDefaultBorder(collapsingBorderModel); + borderAfter = ConditionalBorder.getDefaultBorder(collapsingBorderModel); + borderStart = BorderSpecification.getDefaultBorder(); + borderEnd = BorderSpecification.getDefaultBorder(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java index f7c7672e3..d6d622d57 100644 --- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java @@ -90,9 +90,12 @@ public class GridUnit { /** flags for the grid unit */ private byte flags = 0; - protected BorderSpecification[] resolvedBorders; + ConditionalBorder borderBefore; + ConditionalBorder borderAfter; + BorderSpecification borderStart; + BorderSpecification borderEnd; - private CollapsingBorderModel collapsingBorderModel; + protected CollapsingBorderModel collapsingBorderModel; /** * Creates a new grid unit. @@ -156,26 +159,27 @@ public class GridUnit { if (table.isSeparateBorderModel()) { assignBorderForSeparateBorderModel(); } else { - resolvedBorders = new BorderSpecification[4]; collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table .getBorderCollapse()); - if (rowSpanIndex == 0) { - setBorder(CommonBorderPaddingBackground.BEFORE); - } - if (isLastGridUnitRowSpan()) { - setBorder(CommonBorderPaddingBackground.AFTER); - } - if (colSpanIndex == 0) { - setBorder(CommonBorderPaddingBackground.START); - } - if (isLastGridUnitColSpan()) { - setBorder(CommonBorderPaddingBackground.END); - } + setBordersFromCell(); } } - protected void setBorder(int side) { - resolvedBorders[side] = cell.resolvedBorders[side]; + protected void setBordersFromCell() { + borderBefore = cell.borderBefore.copy(); + if (rowSpanIndex > 0) { + borderBefore.nonLeadingTrailing = null; + } + borderAfter = cell.borderAfter.copy(); + if (!isLastGridUnitRowSpan()) { + borderAfter.nonLeadingTrailing = null; + } + if (colSpanIndex == 0) { + borderStart = cell.borderStart; + } + if (isLastGridUnitColSpan()) { + borderEnd = cell.borderEnd; + } } public TableCell getCell() { @@ -301,8 +305,30 @@ public class GridUnit { } private void setBorderInfo(int side) { - if (resolvedBorders[side] != null) { - effectiveBorders.setBorderInfo(resolvedBorders[side].getBorderInfo(), side); + switch (side) { + case CommonBorderPaddingBackground.BEFORE: + if (borderBefore.nonLeadingTrailing/*TODO*/ != null) { + effectiveBorders.setBorderInfo(borderBefore.nonLeadingTrailing.getBorderInfo(), + side); + } + break; + case CommonBorderPaddingBackground.AFTER: + if (borderAfter.nonLeadingTrailing/*TODO*/ != null) { + effectiveBorders.setBorderInfo(borderAfter.nonLeadingTrailing.getBorderInfo(), + side); + } + break; + case CommonBorderPaddingBackground.START: + if (borderStart != null) { + effectiveBorders.setBorderInfo(borderStart.getBorderInfo(), side); + } + break; + case CommonBorderPaddingBackground.END: + if (borderEnd != null) { + effectiveBorders.setBorderInfo(borderEnd.getBorderInfo(), side); + } + break; + default: assert false; } } @@ -332,26 +358,96 @@ public class GridUnit { * CommonBorderPaddingBackground.BEFORE|AFTER|START|END) */ void resolveBorder(GridUnit other, int side) { - BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( - resolvedBorders[side], other.resolvedBorders[CollapsingBorderModel - .getOtherSide(side)]); - if (resolvedBorder != null) { - this.resolvedBorders[side] = resolvedBorder; - other.resolvedBorders[CollapsingBorderModel.getOtherSide(side)] = resolvedBorder; + switch (side) { + case CommonBorderPaddingBackground.BEFORE: + borderBefore.resolve(other.borderAfter, false, true, false); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter.resolve(other.borderBefore, false, true, false); + break; + case CommonBorderPaddingBackground.START: + BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( + borderStart, other.borderEnd); + if (resolvedBorder != null) { + this.borderStart = resolvedBorder; + other.borderEnd = resolvedBorder; + } + break; + case CommonBorderPaddingBackground.END: + resolvedBorder = collapsingBorderModel.determineWinner( + borderEnd, other.borderStart); + if (resolvedBorder != null) { + this.borderEnd = resolvedBorder; + other.borderStart = resolvedBorder; + } + break; + default: assert false; } } /** - * Resolves the border on the given side of this grid unit, comparing it against the - * same border of the given parent element. + * For the given side, integrates in the conflict resolution the border segment of the + * given parent element. * - * @param side the side to resolve (one of + * @param side the side to consider (either CommonBorderPaddingBackground.BEFORE or + * AFTER) + * @param parent a table element whose corresponding border coincides on the given + * side + */ + void integrateBorderSegment(int side, TableFObj parent, boolean withLeadingTrailing, + boolean withNonLeadingTrailing, boolean withRest) { + switch (side) { + case CommonBorderPaddingBackground.BEFORE: + borderBefore.integrateSegment(parent.borderBefore, withLeadingTrailing, + withNonLeadingTrailing, withRest); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter.integrateSegment(parent.borderAfter, withLeadingTrailing, + withNonLeadingTrailing, withRest); + break; + default: assert false; + } + } + + /** + * For the given side, integrates in the conflict resolution the border segment of the + * given parent element. + * + * @param side the side to consider (one of * CommonBorderPaddingBackground.BEFORE|AFTER|START|END) - * @param parent the parent element holding a competing border + * @param parent a table element whose corresponding border coincides on the given side */ - void resolveBorder(int side, TableFObj parent) { - resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side], - parent.resolvedBorders[side]); + void integrateBorderSegment(int side, TableFObj parent) { + switch (side) { + case CommonBorderPaddingBackground.BEFORE: + case CommonBorderPaddingBackground.AFTER: + integrateBorderSegment(side, parent, true, true, true); + break; + case CommonBorderPaddingBackground.START: + borderStart = collapsingBorderModel.determineWinner(borderStart, + parent.borderStart); + break; + case CommonBorderPaddingBackground.END: + borderEnd = collapsingBorderModel.determineWinner(borderEnd, + parent.borderEnd); + break; + default: assert false; + } + } + + void integrateCompetingBorder(int side, ConditionalBorder competitor, + boolean withLeadingTrailing, boolean withNonLeadingTrailing, boolean withRest) { + switch (side) { + case CommonBorderPaddingBackground.BEFORE: + borderBefore.integrateCompetingSegment(competitor, withLeadingTrailing, + withNonLeadingTrailing, withRest); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter.integrateCompetingSegment(competitor, withLeadingTrailing, + withNonLeadingTrailing, withRest); + break; + default: assert false; + } } /** diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index 6b12271fc..c1453bdfa 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -261,6 +261,10 @@ public class TableBody extends TableCellContainer { return FO_TABLE_BODY; } + protected boolean isTableHeader() { + return false; + } + protected boolean isTableFooter() { return false; } diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 236556a05..4b90ccac3 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -42,7 +42,10 @@ public abstract class TableFObj extends FObj { private Numeric borderEndPrecedence; private Numeric borderStartPrecedence; - BorderSpecification[] resolvedBorders = new BorderSpecification[4]; // TODO + ConditionalBorder borderBefore; + ConditionalBorder borderAfter; + BorderSpecification borderStart; + BorderSpecification borderEnd; CollapsingBorderModel collapsingBorderModel; @@ -200,7 +203,6 @@ public abstract class TableFObj extends FObj { if (!inMarker() && !table.isSeparateBorderModel()) { collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table .getBorderCollapse()); - resolvedBorders = new BorderSpecification[4]; setCollapsedBorders(); } } @@ -226,8 +228,23 @@ public abstract class TableFObj extends FObj { * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END */ protected void createBorder(int side) { - resolvedBorders[side] = new BorderSpecification(getCommonBorderPaddingBackground() - .getBorderInfo(side), getNameId()); + BorderSpecification borderSpec = new BorderSpecification( + getCommonBorderPaddingBackground().getBorderInfo(side), getNameId()); + switch (side) { + case CommonBorderPaddingBackground.BEFORE: + borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.START: + borderStart = borderSpec; + break; + case CommonBorderPaddingBackground.END: + borderEnd = borderSpec; + break; + default: assert false; + } } /** @@ -240,7 +257,22 @@ public abstract class TableFObj extends FObj { */ protected void createBorder(int side, TableFObj competitor) { createBorder(side); - resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side], - competitor.resolvedBorders[side]); + switch (side) { + case CommonBorderPaddingBackground.BEFORE: + borderBefore.integrateSegment(competitor.borderBefore, true, true, true); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter.integrateSegment(competitor.borderAfter, true, true, true); + break; + case CommonBorderPaddingBackground.START: + borderStart = collapsingBorderModel.determineWinner(borderStart, + competitor.borderStart); + break; + case CommonBorderPaddingBackground.END: + borderEnd = collapsingBorderModel.determineWinner(borderEnd, + competitor.borderEnd); + break; + default: assert false; + } } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java index 01ada2aa7..e248a0f7e 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java +++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java @@ -66,4 +66,9 @@ public class TableHeader extends TableBody { public int getNameId() { return FO_TABLE_HEADER; } + + /** {@inheritDoc} */ + protected boolean isTableHeader() { + return true; + } } diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index 6ea08f19c..c5a4950f4 100755 --- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java +++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java @@ -130,6 +130,59 @@ public class CommonBorderPaddingBackground { */ private static BorderInfo defaultBorderInfo; + /** + * A conditional length of value 0. Returned by the + * {@link CommonBorderPaddingBackground#getBorderInfo(int)} method when the + * corresponding border isn't specified, to avoid to callers painful checks for null. + */ + private static class ConditionalNullLength extends CondLengthProperty { + + /** {@inheritDoc} */ + public Property getComponent(int cmpId) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + public Property getConditionality() { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + public Length getLength() { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + public Property getLengthComponent() { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + public int getLengthValue() { + return 0; + } + + /** {@inheritDoc} */ + public int getLengthValue(PercentBaseContext context) { + return 0; + } + + /** {@inheritDoc} */ + public boolean isDiscard() { + return true; + } + + /** {@inheritDoc} */ + public void setComponent(int cmpId, Property cmpnValue, boolean isDefault) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + public String toString() { + return "CondLength[0mpt, discard]"; + } + } + /** * Returns a default BorderInfo of style none. * @@ -137,8 +190,9 @@ public class CommonBorderPaddingBackground { */ public static synchronized BorderInfo getDefaultBorderInfo() { if (defaultBorderInfo == null) { - /* It is enough to set color and width to null, as they should never be consulted */ - defaultBorderInfo = new BorderInfo(Constants.EN_NONE, null, null); + /* It is enough to set color to null, as it should never be consulted */ + defaultBorderInfo = new BorderInfo(Constants.EN_NONE, + new ConditionalNullLength(), null); } return defaultBorderInfo; } diff --git a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java index a0bff3b5e..c3df74800 100644 --- a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java +++ b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java @@ -181,8 +181,23 @@ public abstract class CollapsingBorderModel { * * @param border1 a border specification * @param border2 another border specification + * @param discard true if the .conditionality component of the border width must be + * taken into account * @return the winning border, null if the two borders are equivalent */ + public abstract BorderSpecification determineWinner(BorderSpecification border1, + BorderSpecification border2, boolean discard); + + /** + * Returns the border which wins the border conflict resolution. Same as + * {@link #determineWinner(BorderSpecification, BorderSpecification, boolean) + * determineWinner(border1, border2, false)}. + * + * @param border1 a border specification + * @param border2 another border specification + * @return the winning border, null if the two borders are equivalent + * @see determineWinner + */ public abstract BorderSpecification determineWinner(BorderSpecification border1, BorderSpecification border2); diff --git a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java index 5f979c986..c1a9380a3 100644 --- a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java +++ b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java @@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr.table; import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.BorderSpecification; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; /** @@ -30,6 +31,27 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; */ public class CollapsingBorderModelEyeCatching extends CollapsingBorderModel { + /** {@inheritDoc} */ + public BorderSpecification determineWinner(BorderSpecification border1, + BorderSpecification border2, boolean discard) { + BorderInfo bi1 = border1.getBorderInfo(); + BorderInfo bi2 = border2.getBorderInfo(); + if (discard) { + if (bi1.getWidth().isDiscard()) { + if (bi2.getWidth().isDiscard()) { + return new BorderSpecification( + CommonBorderPaddingBackground.getDefaultBorderInfo(), 0/*TODO*/); + } else { + return border2; + } + } else if (bi2.getWidth().isDiscard()) { + return border1; + } + } + // Otherwise, fall back to the default resolution algorithm + return determineWinner(border1, border2); + } + /** {@inheritDoc} */ public BorderSpecification determineWinner(BorderSpecification border1, BorderSpecification border2) { -- cgit v1.2.3 From 9957e3b9ae746fabc891d2d9223f708ec9709bd3 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 17:21:24 +0000 Subject: Reverted change accidentally introduced in the previous commit. A proper fix needs to be found for this one. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603959 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 5d1a6f31a..d393c1d7c 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1150,7 +1150,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericSpace); corr = new SpacePropertyMaker(m); corr.setCorresponding(PR_MARGIN_BOTTOM, PR_MARGIN_BOTTOM, PR_MARGIN_LEFT); - corr.setUseParent(true); + corr.setUseParent(false); corr.setRelative(true); addPropertyMaker("space-after", m); -- cgit v1.2.3 From f585893200a94a360b0e8f8015758aaf8f3ad2d7 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 17:31:26 +0000 Subject: Ok, now /really/ revert the previous commit :-\ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603961 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index d393c1d7c..5d1a6f31a 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1150,7 +1150,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericSpace); corr = new SpacePropertyMaker(m); corr.setCorresponding(PR_MARGIN_BOTTOM, PR_MARGIN_BOTTOM, PR_MARGIN_LEFT); - corr.setUseParent(false); + corr.setUseParent(true); corr.setRelative(true); addPropertyMaker("space-after", m); -- cgit v1.2.3 From ecf8547e04c4994fcb5017351ec63203f344cf7e Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 17:32:43 +0000 Subject: Style only: removed trailing white spaces git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603962 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/fo/flow/table/ConditionalBorder.java | 2 +- .../org/apache/fop/fo/flow/table/TableBody.java | 4 +- .../org/apache/fop/fo/flow/table/TableFObj.java | 4 +- .../properties/CommonBorderPaddingBackground.java | 107 ++++++++++----------- 4 files changed, 58 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java index e03e11a15..4f3cca046 100644 --- a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java +++ b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java @@ -199,6 +199,6 @@ public class ConditionalBorder { static ConditionalBorder getDefaultBorder(CollapsingBorderModel collapsingBorderModel) { BorderSpecification defaultBorderSpec = BorderSpecification.getDefaultBorder(); return new ConditionalBorder(defaultBorderSpec, defaultBorderSpec, defaultBorderSpec, - collapsingBorderModel); + collapsingBorderModel); } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index c1453bdfa..dced3c062 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -138,7 +138,7 @@ public class TableBody extends TableCellContainer { protected void finishLastRowGroup() throws ValidationException { if (!inMarker()) { - RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder(); + RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder(); if (tableRowsFound) { rowGroupBuilder.endRow(lastRow); } else if (!lastCellEndsRow) { @@ -211,7 +211,7 @@ public class TableBody extends TableCellContainer { rowsStarted = true; TableCell cell = (TableCell) child; addTableCellChild(cell, firstRow); - lastCellEndsRow = cell.endsRow(); + lastCellEndsRow = cell.endsRow(); if (lastCellEndsRow) { firstRow = false; columnNumberManager.prepareForNextRow(pendingSpans); diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 4b90ccac3..9618d7ff4 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -48,7 +48,7 @@ public abstract class TableFObj extends FObj { BorderSpecification borderEnd; CollapsingBorderModel collapsingBorderModel; - + /** * Main constructor * @@ -208,7 +208,7 @@ public abstract class TableFObj extends FObj { } /* - * TODO made public so that RetrieveMarker can access it. + * TODO made public so that RetrieveMarker can access it. */ /** {@inheritDoc} */ public void endOfNode() throws FOPException { diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index c5a4950f4..866a020e2 100755 --- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java +++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java @@ -64,20 +64,20 @@ public class CommonBorderPaddingBackground { * The "background-position-vertical" property. */ public Length backgroundPositionVertical; - - + + private FopImage fopimage; - - - /** the "before" edge */ + + + /** the "before" edge */ public static final int BEFORE = 0; - /** the "after" edge */ + /** the "after" edge */ public static final int AFTER = 1; - /** the "start" edge */ + /** the "start" edge */ public static final int START = 2; - /** the "end" edge */ + /** the "end" edge */ public static final int END = 3; - + public static class BorderInfo { private int mStyle; // Enum for border style private Color mColor; // Border color @@ -88,15 +88,15 @@ public class CommonBorderPaddingBackground { mWidth = width; mColor = color; } - + public int getStyle() { return this.mStyle; } - + public Color getColor() { return this.mColor; } - + public CondLengthProperty getWidth() { return this.mWidth; } @@ -109,7 +109,7 @@ public class CommonBorderPaddingBackground { return mWidth.getLengthValue(); } } - + /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer("BorderInfo"); @@ -204,9 +204,8 @@ public class CommonBorderPaddingBackground { * Construct a CommonBorderPaddingBackground object. */ public CommonBorderPaddingBackground() { - } - + /** * Construct a CommonBorderPaddingBackground object. * @@ -214,7 +213,7 @@ public class CommonBorderPaddingBackground { * @throws PropertyException if there's an error while binding the properties */ public CommonBorderPaddingBackground(PropertyList pList) throws PropertyException { - + backgroundAttachment = pList.get(Constants.PR_BACKGROUND_ATTACHMENT).getEnum(); backgroundColor = pList.get(Constants.PR_BACKGROUND_COLOR).getColor( pList.getFObj().getUserAgent()); @@ -231,7 +230,7 @@ public class CommonBorderPaddingBackground { Constants.PR_BACKGROUND_POSITION_HORIZONTAL).getLength(); backgroundPositionVertical = pList.get( Constants.PR_BACKGROUND_POSITION_VERTICAL).getLength(); - + //Additional processing: preload image String url = ImageFactory.getURL(backgroundImage); FOUserAgent userAgent = pList.getFObj().getUserAgent(); @@ -242,37 +241,37 @@ public class CommonBorderPaddingBackground { } else { // load dimensions if (!fopimage.load(FopImage.DIMENSIONS)) { - Property.log.error("Cannot read background image dimensions: " + Property.log.error("Cannot read background image dimensions: " + backgroundImage); } } //TODO Report to caller so he can decide to throw an exception } - initBorderInfo(pList, BEFORE, - Constants.PR_BORDER_BEFORE_COLOR, - Constants.PR_BORDER_BEFORE_STYLE, - Constants.PR_BORDER_BEFORE_WIDTH, + initBorderInfo(pList, BEFORE, + Constants.PR_BORDER_BEFORE_COLOR, + Constants.PR_BORDER_BEFORE_STYLE, + Constants.PR_BORDER_BEFORE_WIDTH, Constants.PR_PADDING_BEFORE); - initBorderInfo(pList, AFTER, - Constants.PR_BORDER_AFTER_COLOR, - Constants.PR_BORDER_AFTER_STYLE, - Constants.PR_BORDER_AFTER_WIDTH, + initBorderInfo(pList, AFTER, + Constants.PR_BORDER_AFTER_COLOR, + Constants.PR_BORDER_AFTER_STYLE, + Constants.PR_BORDER_AFTER_WIDTH, Constants.PR_PADDING_AFTER); - initBorderInfo(pList, START, - Constants.PR_BORDER_START_COLOR, - Constants.PR_BORDER_START_STYLE, - Constants.PR_BORDER_START_WIDTH, + initBorderInfo(pList, START, + Constants.PR_BORDER_START_COLOR, + Constants.PR_BORDER_START_STYLE, + Constants.PR_BORDER_START_WIDTH, Constants.PR_PADDING_START); - initBorderInfo(pList, END, - Constants.PR_BORDER_END_COLOR, - Constants.PR_BORDER_END_STYLE, - Constants.PR_BORDER_END_WIDTH, + initBorderInfo(pList, END, + Constants.PR_BORDER_END_COLOR, + Constants.PR_BORDER_END_STYLE, + Constants.PR_BORDER_END_WIDTH, Constants.PR_PADDING_END); } - private void initBorderInfo(PropertyList pList, int side, + private void initBorderInfo(PropertyList pList, int side, int colorProp, int styleProp, int widthProp, int paddingProp) throws PropertyException { padding[side] = pList.get(paddingProp).getCondLength(); @@ -285,7 +284,7 @@ public class CommonBorderPaddingBackground { pList.get(colorProp).getColor(ua)), side); } } - + /** * Sets a border. * @param info the border information @@ -294,7 +293,7 @@ public class CommonBorderPaddingBackground { public void setBorderInfo(BorderInfo info, int side) { this.borderInfo[side] = info; } - + /** * @param side the side to retrieve * @return the border info for a side @@ -306,7 +305,7 @@ public class CommonBorderPaddingBackground { return this.borderInfo[side]; } } - + /** * Set padding. * @param source the padding info to copy from @@ -314,7 +313,7 @@ public class CommonBorderPaddingBackground { public void setPadding(CommonBorderPaddingBackground source) { this.padding = source.padding; } - + /** * @return the background image as a preloaded FopImage, null if there is * no background image. @@ -322,7 +321,7 @@ public class CommonBorderPaddingBackground { public FopImage getFopImage() { return this.fopimage; } - + /** * @param bDiscard indicates whether the .conditionality component should be * considered (start of a reference-area) @@ -405,7 +404,7 @@ public class CommonBorderPaddingBackground { return padding[side].getLengthValue(context); } } - + /** * Returns the CondLengthProperty for the padding on one side. * @param side the side @@ -416,21 +415,21 @@ public class CommonBorderPaddingBackground { } /** - * Return all the border and padding width in the inline progression + * Return all the border and padding width in the inline progression * dimension. * @param bDiscard the discard flag. * @param context for percentage evaluation. * @return all the padding and border width. */ public int getIPPaddingAndBorder(boolean bDiscard, PercentBaseContext context) { - return getPaddingStart(bDiscard, context) - + getPaddingEnd(bDiscard, context) - + getBorderStartWidth(bDiscard) - + getBorderEndWidth(bDiscard); + return getPaddingStart(bDiscard, context) + + getPaddingEnd(bDiscard, context) + + getBorderStartWidth(bDiscard) + + getBorderEndWidth(bDiscard); } - + /** - * Return all the border and padding height in the block progression + * Return all the border and padding height in the block progression * dimension. * @param bDiscard the discard flag. * @param context for percentage evaluation @@ -438,7 +437,7 @@ public class CommonBorderPaddingBackground { */ public int getBPPaddingAndBorder(boolean bDiscard, PercentBaseContext context) { return getPaddingBefore(bDiscard, context) + getPaddingAfter(bDiscard, context) - + getBorderBeforeWidth(bDiscard) + getBorderAfterWidth(bDiscard); + + getBorderBeforeWidth(bDiscard) + getBorderAfterWidth(bDiscard); } /** {@inheritDoc} */ @@ -448,7 +447,7 @@ public class CommonBorderPaddingBackground { + getBorderStartWidth(false) + ", " + getBorderEndWidth(false) + ")\n" + "Border Colors: (" + getBorderColor(BEFORE) + ", " + getBorderColor(AFTER) + ", " + getBorderColor(START) + ", " + getBorderColor(END) + ")\n" - + "Padding: (" + getPaddingBefore(false, null) + ", " + getPaddingAfter(false, null) + + "Padding: (" + getPaddingBefore(false, null) + ", " + getPaddingAfter(false, null) + ", " + getPaddingStart(false, null) + ", " + getPaddingEnd(false, null) + ")\n"; } @@ -461,19 +460,19 @@ public class CommonBorderPaddingBackground { /** @return true if border is non-zero. */ public boolean hasBorder() { - return ((getBorderBeforeWidth(false) + getBorderAfterWidth(false) + return ((getBorderBeforeWidth(false) + getBorderAfterWidth(false) + getBorderStartWidth(false) + getBorderEndWidth(false)) > 0); } /** * @param context for percentage based evaluation. - * @return true if padding is non-zero. + * @return true if padding is non-zero. */ public boolean hasPadding(PercentBaseContext context) { - return ((getPaddingBefore(false, context) + getPaddingAfter(false, context) + return ((getPaddingBefore(false, context) + getPaddingAfter(false, context) + getPaddingStart(false, context) + getPaddingEnd(false, context)) > 0); } - + /** @return true if there are any borders defined. */ public boolean hasBorderInfo() { return (borderInfo[BEFORE] != null || borderInfo[AFTER] != null -- cgit v1.2.3 From 7ed67aba5bec4a02c3a9ef237e42d6a3d6136808 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 18:28:56 +0000 Subject: Fixed the handling of columns in the border resolution, especially in case of column-spanning cells git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603968 13f79535-47bb-0310-9956-ffa450edef68 --- .../fo/flow/table/CollapsingBorderResolver.java | 14 +++++-- .../org/apache/fop/fo/flow/table/TableCell.java | 11 +----- .../table_border-collapse_collapse_resolution.xml | 45 ++++++++++++++++++++++ ..._border-collapse_collapse_resolution_no-col.xml | 3 +- 4 files changed, 60 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index f92f7bb30..f59019b92 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -205,14 +205,22 @@ class CollapsingBorderResolver implements BorderResolver { // Resolve start/end borders in the row Iterator guIter = row.iterator(); GridUnit gu = (GridUnit) guIter.next(); + Iterator colIter = table.getColumns().iterator(); + TableColumn col = (TableColumn) colIter.next(); + gu.integrateBorderSegment(CommonBorderPaddingBackground.START, col); gu.integrateBorderSegment(CommonBorderPaddingBackground.START, container); while (guIter.hasNext()) { - GridUnit guEnd = (GridUnit) guIter.next(); + GridUnit nextGU = (GridUnit) guIter.next(); + TableColumn nextCol = (TableColumn) colIter.next(); if (gu.isLastGridUnitColSpan()) { - gu.resolveBorder(guEnd, CommonBorderPaddingBackground.END); + gu.integrateBorderSegment(CommonBorderPaddingBackground.END, col); + nextGU.integrateBorderSegment(CommonBorderPaddingBackground.START, nextCol); + gu.resolveBorder(nextGU, CommonBorderPaddingBackground.END); } - gu = guEnd; + gu = nextGU; + col = nextCol; } + gu.integrateBorderSegment(CommonBorderPaddingBackground.END, col); gu.integrateBorderSegment(CommonBorderPaddingBackground.END, container); } diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java index f85d0e97e..80dbe5e2a 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCell.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java @@ -138,15 +138,8 @@ public class TableCell extends TableFObj { protected void setCollapsedBorders() { createBorder(CommonBorderPaddingBackground.BEFORE); createBorder(CommonBorderPaddingBackground.AFTER); - Table table = getTable(); - if (table.hasExplicitColumns()) { - TableColumn col = table.getColumn(getColumnNumber() - 1); - createBorder(CommonBorderPaddingBackground.START, col); - createBorder(CommonBorderPaddingBackground.END, col); - } else { - createBorder(CommonBorderPaddingBackground.START); - createBorder(CommonBorderPaddingBackground.END); - } + createBorder(CommonBorderPaddingBackground.START); + createBorder(CommonBorderPaddingBackground.END); } /** {@inheritDoc} */ diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution.xml index 6aa054d7d..20cabace2 100644 --- a/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution.xml +++ b/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution.xml @@ -166,6 +166,30 @@ + + Between tables + + + + + + + Cell 1.1 + + + + + Cell 2.1 + + + Cell 2.2 + + + + + After the tables @@ -333,5 +357,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution_no-col.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution_no-col.xml index b9b5c49b9..c0538b2e0 100644 --- a/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution_no-col.xml +++ b/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution_no-col.xml @@ -20,7 +20,8 @@ -- cgit v1.2.3 From 757fdc23d3f01bd940dc13cb1920ac2daf40a56c Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 18:52:48 +0000 Subject: Removed parameter from the endPart method, since the part is already passed as a parameter of the previously called startPart method git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603975 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/BorderResolver.java | 4 +--- src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java | 2 +- src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java | 2 +- src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java index 0a8f3d39e..5322b08d3 100644 --- a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java @@ -44,10 +44,8 @@ interface BorderResolver { /** * Receives notification of the end of a table-header/footer/body. - * - * @param part the part that has ended */ - void endPart(TableBody part); + void endPart(); /** * Receives notification of the end of the table. diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index f59019b92..16fc55cfc 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -393,7 +393,7 @@ class CollapsingBorderResolver implements BorderResolver { } /** {@inheritDoc} */ - public void endPart(TableBody part) { + public void endPart() { delegate.endPart(); } diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index a5c0b1b8b..f87ed47f3 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -170,7 +170,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { "A table-cell is spanning more rows than available in its parent element."); } setFlagForCols(GridUnit.LAST_IN_PART, lastRow); - borderResolver.endPart(tableBody); + borderResolver.endPart(); inFooter = false; } diff --git a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java index 37e3cb6e8..c6d46ecf5 100644 --- a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java @@ -35,7 +35,7 @@ class SeparateBorderResolver implements BorderResolver { } /** {@inheritDoc} */ - public void endPart(TableBody part) { + public void endPart() { } /** {@inheritDoc} */ -- cgit v1.2.3 From 4090cb592401b107f4a560fede22b27ffc41667d Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 18:57:25 +0000 Subject: Removed parameter from the endTablePart method, as the part is already passed as as a parameter of the previously called startTablePart method git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603979 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java | 2 +- src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java | 3 +-- src/java/org/apache/fop/fo/flow/table/TableBody.java | 2 +- src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index f87ed47f3..7df071191 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -164,7 +164,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void endTablePart(TableBody tableBody) throws ValidationException { + void endTablePart() throws ValidationException { if (rows.size() > 0) { throw new ValidationException( "A table-cell is spanning more rows than available in its parent element."); diff --git a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java index 220eff85b..f25886581 100644 --- a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java @@ -77,10 +77,9 @@ abstract class RowGroupBuilder { * row-group is checked for emptiness. This row group builder is reset for handling * further possible table parts. * - * @param tableBody the table part being ended * @throws ValidationException if a row-spanning cell overflows the given table part */ - abstract void endTablePart(TableBody tableBody) throws ValidationException; + abstract void endTablePart() throws ValidationException; /** * Receives notification of the end of the table. diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index dced3c062..7df1ed0a7 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -145,7 +145,7 @@ public class TableBody extends TableCellContainer { rowGroupBuilder.endRow(this); } try { - rowGroupBuilder.endTablePart(this); + rowGroupBuilder.endTablePart(); } catch (ValidationException e) { e.setLocator(locator); throw e; diff --git a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java index 66322b1b7..47c96dcca 100644 --- a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java @@ -91,11 +91,11 @@ class VariableColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void endTablePart(final TableBody tableBody) throws ValidationException { + void endTablePart() throws ValidationException { // TODO catch the ValidationException sooner? events.add(new Event() { public void play(RowGroupBuilder rowGroupBuilder) throws ValidationException { - rowGroupBuilder.endTablePart(tableBody); + rowGroupBuilder.endTablePart(); } }); } -- cgit v1.2.3 From 61a2bba18f742acc0d1404e77af3db921ce410c3 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 13 Dec 2007 19:17:12 +0000 Subject: Throw a ValidationException if table-footer is put after table-body and the table uses the collapsing border model. The footer must be known to properly resolve borders. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603990 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/Table.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index 4933ab4dc..a915edf87 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -192,9 +192,17 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { tooManyNodesError(loc, "table-footer"); } else { tableFooterFound = true; - if (tableBodyFound && getUserAgent().validateStrictly()) { - nodesOutOfOrderError(loc, "fo:table-footer", - "(table-body+)"); + if (tableBodyFound) { + if (getUserAgent().validateStrictly()) { + nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)"); + } else if (!isSeparateBorderModel()) { + nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)." + + " This table uses the collapsing border" + + " model. In order to resolve borders in an efficient way" + + " the table-footer must be known before any table-body" + + " is parsed. Either put the footer at the correct place" + + " or switch to the separate border model"); + } } } } else if ("table-body".equals(localName)) { -- cgit v1.2.3 From c6363fe8a30d2d5c6fa6f588966a35f4352f7ac0 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 14 Dec 2007 11:32:51 +0000 Subject: Clean up: removed all reset and resetPosition methods, which pre-date the Knuth era and are no longer needed git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604171 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/AbstractLayoutManager.java | 39 ---------------------- .../fop/layoutmgr/BlockContainerLayoutManager.java | 9 ----- .../apache/fop/layoutmgr/BlockLayoutManager.java | 13 -------- .../apache/fop/layoutmgr/FlowLayoutManager.java | 8 ----- .../org/apache/fop/layoutmgr/LayoutManager.java | 7 ---- .../fop/layoutmgr/inline/ContentLayoutManager.java | 7 ---- .../inline/InlineStackingLayoutManager.java | 35 ------------------- .../fop/layoutmgr/inline/LineLayoutManager.java | 27 --------------- .../fop/layoutmgr/inline/TextLayoutManager.java | 30 ----------------- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 13 -------- .../list/ListItemContentLayoutManager.java | 14 -------- .../fop/layoutmgr/list/ListItemLayoutManager.java | 11 ------ .../table/TableAndCaptionLayoutManager.java | 11 ------ .../layoutmgr/table/TableCaptionLayoutManager.java | 11 ------ .../layoutmgr/table/TableCellLayoutManager.java | 11 ------ .../fop/layoutmgr/table/TableLayoutManager.java | 11 ------ 16 files changed, 257 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 21af512fc..f0365d0e4 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -129,45 +129,6 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager return childLMiter.hasNext(); } - /** - * Reset the layoutmanager "iterator" so that it will start - * with the passed Position's generating LM - * on the next call to getChildLM. - * @param pos a Position returned by a child layout manager - * representing a potential break decision. - * If pos is null, then back up to the first child LM. - */ - protected void reset(org.apache.fop.layoutmgr.Position pos) { - //if (lm == null) return; - LayoutManager lm = (pos != null) ? pos.getLM() : null; - if (curChildLM != lm) { - // ASSERT curChildLM == (LayoutManager)childLMiter.previous() - if (childLMiter.hasPrevious() && curChildLM - != (LayoutManager) childLMiter.previous()) { - //log.error("LMiter problem!"); - } - while (curChildLM != lm && childLMiter.hasPrevious()) { - curChildLM.resetPosition(null); - curChildLM = (LayoutManager) childLMiter.previous(); - } - // Otherwise next returns same object - childLMiter.next(); - } - if (curChildLM != null) { - curChildLM.resetPosition(pos); - } - if (isFinished()) { - setFinished(false); - } - } - - /** {@inheritDoc} */ - public void resetPosition(Position resetPos) { - // if (resetPos == null) { - // reset(null); - // } - } - /** * Tell whether this LayoutManager has handled all of its content. * @return True if there are no more break possibilities, diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 9c3c8ce59..03aa380d2 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -938,15 +938,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } - /** - * {@inheritDoc} - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } - } - /** * Force current area to be added to parent area. * {@inheritDoc} diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 62e41ac16..bb39def8d 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -476,19 +476,6 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } } - /** - * {@inheritDoc} - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - childBreaks.clear(); - } else { - //reset(resetPos); - LayoutManager lm = resetPos.getLM(); - } - } - /** * convenience method that returns the Block node * @return the block node diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index f5d912111..a70dd0883 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -342,14 +342,6 @@ public class FlowLayoutManager extends BlockStackingLayoutManager return parentArea; } - /** - * {@inheritDoc} - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } - } /** * Returns the IPD of the content area * @return the IPD of the content area diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManager.java b/src/java/org/apache/fop/layoutmgr/LayoutManager.java index 39b970682..0b17c9a27 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManager.java @@ -58,13 +58,6 @@ public interface LayoutManager extends PercentBaseContext { */ PageSequenceLayoutManager getPSLM(); - /** - * Reset to the position. - * - * @param position the Position to reset to - */ - void resetPosition(Position position); - /** * Return a value indicating whether this LayoutManager has laid out * all its content (or generated BreakPossibilities for all content.) diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index 22a01f9fb..03e9b382a 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -212,13 +212,6 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager //to be done } - /** - * {@inheritDoc} - */ - public void resetPosition(Position position) { - //to be done - } - /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index 7da7cc49f..4d0872a6d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -154,41 +154,6 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager return null; } - /** - * Reset position for returning next BreakPossibility. - * @param prevPos a Position returned by this layout manager - * representing a potential break decision. - */ - public void resetPosition(Position prevPos) { - if (prevPos != null) { - // ASSERT (prevPos.getLM() == this) - if (prevPos.getLM() != this) { - //getLogger().error( - // "InlineStackingLayoutManager.resetPosition: " + - // "LM mismatch!!!"); - } - // Back up the child LM Position - Position childPos = prevPos.getPosition(); - reset(childPos); - /* - if (prevBP != null - && prevBP.getLayoutManager() != childPos.getLM()) { - childLC = null; - } - prevBP = new BreakPoss(childPos); - */ - } else { - // Backup to start of first child layout manager - //prevBP = null; - // super.resetPosition(prevPos); - reset(prevPos); - // If any areas created, we are restarting! - bAreaCreated = false; - } - // Do we need to reset some context like pending or prevContent? - // What about prevBP? - } - /** * TODO: Explain this method * @param lm ??? diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index e722162d8..6df7ac00c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -1555,33 +1555,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager } } - /** - * Reset the positions to the given position. - * - * @param resetPos the position to reset to - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - setFinished(false); - iReturnedLBP = 0; - } else { - if (isFinished()) { - // if isFinished is true, iReturned LBP == breakpoints.size() - // and breakpoints.get(iReturnedLBP) would generate - // an IndexOutOfBoundException - setFinished(false); - iReturnedLBP--; - } - // It is not clear that the member lineLayouts has the correct value; - // because the method is not called, this cannot be checked. - while ((LineBreakPosition) lineLayouts.getChosenPosition(iReturnedLBP) - != (LineBreakPosition) resetPos) { - iReturnedLBP--; - } - iReturnedLBP++; - } - } - /** * Add the areas with the break points. * diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 63f11147c..40e1c087a 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -224,36 +224,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } - /** - * Reset position for returning next BreakPossibility. - * - * @param prevPos the position to reset to - */ - public void resetPosition(Position prevPos) { - if (prevPos != null) { - // ASSERT (prevPos.getLM() == this) - if (prevPos.getLM() != this) { - log.error("TextLayoutManager.resetPosition: " - + "LM mismatch!!!"); - } - LeafPosition tbp = (LeafPosition) prevPos; - AreaInfo ai = (AreaInfo) vecAreaInfo.get(tbp.getLeafPos()); - if (ai.iBreakIndex != iNextStart) { - iNextStart = ai.iBreakIndex; - vecAreaInfo.ensureCapacity(tbp.getLeafPos() + 1); - // TODO: reset or recalculate total IPD = sum of all word IPD - // up to the break position - ipdTotal = ai.ipdArea; - setFinished(false); - } - } else { - // Reset to beginning! - vecAreaInfo.clear(); - iNextStart = 0; - setFinished(false); - } - } - // TODO: see if we can use normal getNextBreakPoss for this with // extra hyphenation information in LayoutContext private boolean getHyphenIPD(HyphContext hc, MinOptMax hyphIPD) { diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index acd9bf718..470cbbe9c 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -277,19 +277,6 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } } - /** - * Reset the position of this layout manager. - * - * @param resetPos the position to reset to - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } else { - //TODO Something to put here? - } - } - /** {@inheritDoc} */ public boolean mustKeepTogether() { //TODO Keeps will have to be more sophisticated sooner or later diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index e1171d6fd..853b1a128 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -220,20 +220,6 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { } } - /** - * Reset the position of the layout. - * - * @param resetPos the position to reset to - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } else { - setFinished(false); - //reset(resetPos); - } - } - /** {@inheritDoc} */ public boolean mustKeepTogether() { //TODO Keeps will have to be more sophisticated sooner or later diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 7b7cb52b0..dc28e98e2 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -623,17 +623,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } } - /** - * Reset the position of this layout manager. - * - * @param resetPos the position to reset to - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } - } - /** {@inheritDoc} */ public boolean mustKeepTogether() { //TODO Keeps will have to be more sophisticated sooner or later diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index 55b67053f..6d2e49e96 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -194,16 +194,5 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { curBlockArea.addBlock((Block) childArea); } } - - /** - * Reset the position of this layout manager. - * - * @param resetPos the position to reset to - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } - } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 58c85e8cd..4c21df937 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -193,16 +193,5 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { curBlockArea.addBlock((Block) childArea); } } - - /** - * Reset the layout position. - * - * @param resetPos the position to reset to - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } - } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 46bdecf63..63810e057 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -504,17 +504,6 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } } - /** - * Reset the position of the layout. - * - * @param resetPos the position to reset to - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } - } - /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index e33773695..2e366f36d 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -404,17 +404,6 @@ public class TableLayoutManager extends BlockStackingLayoutManager } } - /** - * Reset the position of this layout manager. - * - * @param resetPos the position to reset to - */ - public void resetPosition(Position resetPos) { - if (resetPos == null) { - reset(null); - } - } - /** {@inheritDoc} */ public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) { // TODO Auto-generated method stub -- cgit v1.2.3 From 79d9dab416b7676bbb914dcecd80416a422b5c48 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 14 Dec 2007 12:23:10 +0000 Subject: Reduced visibility of methods from public to package-private git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604180 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 8 ++++---- .../fop/layoutmgr/table/TableContentLayoutManager.java | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 1ea0d308e..73cce29e4 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -79,7 +79,7 @@ class RowPainter { private int[] partBPD; private TableContentLayoutManager tclm; - public RowPainter(TableContentLayoutManager tclm, LayoutContext layoutContext) { + RowPainter(TableContentLayoutManager tclm, LayoutContext layoutContext) { this.tclm = tclm; this.layoutContext = layoutContext; this.colCount = tclm.getColumns().getColumnCount(); @@ -91,7 +91,7 @@ class RowPainter { Arrays.fill(end, -1); } - public int getAccumulatedBPD() { + int getAccumulatedBPD() { return this.accumulatedBPD; } @@ -101,7 +101,7 @@ class RowPainter { * * @param tcpos a position representing the row fragment */ - public void handleTableContentPosition(TableContentPosition tcpos) { + void handleTableContentPosition(TableContentPosition tcpos) { if (lastRow != tcpos.row && lastRow != null) { addAreasAndFlushRow(false); } @@ -146,7 +146,7 @@ class RowPainter { * part * @return the height of the (grid) row */ - public int addAreasAndFlushRow(boolean forcedFlush) { + int addAreasAndFlushRow(boolean forcedFlush) { int actualRowHeight = 0; int bt = lastRow.getBodyType(); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index bcd7f0244..fca0557b7 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -74,7 +74,7 @@ public class TableContentLayoutManager implements PercentBaseContext { * Main constructor * @param parent Parent layout manager */ - public TableContentLayoutManager(TableLayoutManager parent) { + TableContentLayoutManager(TableLayoutManager parent) { this.tableLM = parent; Table table = getTableLM().getTable(); this.bodyIter = new TableRowIterator(table, TableRowIterator.BODY); @@ -89,7 +89,7 @@ public class TableContentLayoutManager implements PercentBaseContext { /** * @return the table layout manager */ - public TableLayoutManager getTableLM() { + TableLayoutManager getTableLM() { return this.tableLM; } @@ -101,7 +101,7 @@ public class TableContentLayoutManager implements PercentBaseContext { /** * @return the column setup of this table */ - public ColumnSetup getColumns() { + ColumnSetup getColumns() { return getTableLM().getColumns(); } @@ -281,7 +281,7 @@ public class TableContentLayoutManager implements PercentBaseContext { * @param parentIter the position iterator * @param layoutContext the layout context for adding areas */ - public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { + void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { this.usedBPD = 0; RowPainter painter = new RowPainter(this, layoutContext); @@ -437,7 +437,7 @@ public class TableContentLayoutManager implements PercentBaseContext { * @param row the table-row object or null * @return the row area or null if there's no background to paint */ - public Block getRowArea(TableRow row) { + Block getRowArea(TableRow row) { if (row == null || !row.getCommonBorderPaddingBackground().hasBackground()) { return null; } else { @@ -455,7 +455,7 @@ public class TableContentLayoutManager implements PercentBaseContext { * @param ipd inline-progression-dimension of the row * @param yoffset Y offset at which to paint */ - public void addRowBackgroundArea(TableRow row, int bpd, int ipd, int yoffset) { + void addRowBackgroundArea(TableRow row, int bpd, int ipd, int yoffset) { //Add row background if any Block rowBackground = getRowArea(row); if (rowBackground != null) { @@ -474,14 +474,14 @@ public class TableContentLayoutManager implements PercentBaseContext { * Sets the overall starting x-offset. Used for proper placement of cells. * @param startXOffset starting x-offset (table's start-indent) */ - public void setStartXOffset(int startXOffset) { + void setStartXOffset(int startXOffset) { this.startXOffset = startXOffset; } /** * @return the amount of block-progression-dimension used by the content */ - public int getUsedBPD() { + int getUsedBPD() { return this.usedBPD; } -- cgit v1.2.3 From 00ba9d896e3138faa1ceeff440dbcfad7808b194 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 14 Dec 2007 13:16:06 +0000 Subject: Fixed copy constructor git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604185 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/AFPGraphics2D.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java index bdd33f3de..a64b77d35 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java @@ -89,13 +89,18 @@ public class AFPGraphics2D extends AbstractGraphics2D { } /** - * Creates a new AbstractGraphics2D from an existing instance. + * Creates a new AFPGraphics2D from an existing instance. * * @param g - * the AbstractGraphics2D whose properties should be copied + * the AFPGraphics2D whose properties should be copied */ public AFPGraphics2D(AFPGraphics2D g) { super(g); + this.graphicsObj = g.graphicsObj; + this.fallbackTextHandler = g.fallbackTextHandler; + this.customTextHandler = g.customTextHandler; + this.afpInfo = g.afpInfo; + this.afpState = g.afpState; } /** -- cgit v1.2.3 From aaa21e830458ecfb4043237325e86b486a5a3bad Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 14 Dec 2007 20:58:53 +0000 Subject: Bugfix: DecodeParms -> DecodeParams (introduced when I changed to generic PDF structures) (fixes CCITT encoded images) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604293 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFFilterList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFFilterList.java b/src/java/org/apache/fop/pdf/PDFFilterList.java index 8004e1e60..ab7439bd5 100644 --- a/src/java/org/apache/fop/pdf/PDFFilterList.java +++ b/src/java/org/apache/fop/pdf/PDFFilterList.java @@ -296,7 +296,7 @@ public class PDFFilterList { private String buildDecodeParms(List parms) { StringBuffer sb = new StringBuffer(); boolean needParmsEntry = false; - sb.append("\n/DecodeParms "); + sb.append("\n/DecodeParams "); if (parms.size() > 1) { sb.append("[ "); -- cgit v1.2.3 From 96f18dd5f91bd4189f1a7c62b9a49f80c67984fe Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 14 Dec 2007 21:24:14 +0000 Subject: Don't hack when you're tired! Reverting r604293 and instead fixing the right value. It's DecodeParams -> DecodeParms! git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604299 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFFilterList.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFFilterList.java b/src/java/org/apache/fop/pdf/PDFFilterList.java index ab7439bd5..e866fc88e 100644 --- a/src/java/org/apache/fop/pdf/PDFFilterList.java +++ b/src/java/org/apache/fop/pdf/PDFFilterList.java @@ -296,7 +296,7 @@ public class PDFFilterList { private String buildDecodeParms(List parms) { StringBuffer sb = new StringBuffer(); boolean needParmsEntry = false; - sb.append("\n/DecodeParams "); + sb.append("\n/DecodeParms "); if (parms.size() > 1) { sb.append("[ "); @@ -335,9 +335,9 @@ public class PDFFilterList { } if (array.length() > 0 & needParmsEntry) { if (array.length() > 1) { - dict.put("DecodeParams", array); + dict.put("DecodeParms", array); } else { - dict.put("DecodeParams", array.get(0)); + dict.put("DecodeParms", array.get(0)); } } } -- cgit v1.2.3 From 4f9fc957bdb3b4a1ecf9af8f6ed9aabf238a5022 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 16 Dec 2007 19:54:00 +0000 Subject: Streamlining/Correction of the changes made in r603926 - delegate validation of the fo:wrapper's children to the parent: added static FONode.validateChildNode() - narrow the condition for processing text-childnodes: this is not only constrained to fo:flow and fo:static-content, but the same goes for a fo:wrapper that is a direct descendant of a fo:block-container or fo:inline-container, which only allow block-level content (interpretation) - minor javadoc fixups/improvements git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604678 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FONode.java | 44 ++++++++++++++++++++++++---- src/java/org/apache/fop/fo/flow/Wrapper.java | 35 +++++++++------------- 2 files changed, 52 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index cb884781a..7c517e418 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -45,6 +45,7 @@ public abstract class FONode implements Cloneable { /** the XSL-FO namespace URI */ protected static final String FO_URI = FOElementMapping.URI; + /** FOP's proprietary extension namespace URI */ protected static final String FOX_URI = ExtensionElementMapping.URI; /** Parent FO node */ @@ -197,11 +198,13 @@ public abstract class FONode implements Cloneable { /** * Checks to make sure, during SAX processing of input document, that the * incoming node is valid for the this (parent) node (e.g., checking to - * see that fo:table is not an immediate child of fo:root) - * called within FObj constructor + * see that fo:table is not an immediate child of fo:root) + * called from {@link FOTreeBuilder#startElement(String, String, String, Attributes)} + * before constructing the child {@link FObj}. + * * @param loc location in the FO source file * @param namespaceURI namespace of incoming node - * @param localName (e.g. "table" for "fo:table") + * @param localName name of the incoming node (without namespace prefix) * @throws ValidationException if incoming node not valid for parent */ protected void validateChildNode(Locator loc, String namespaceURI, String localName) @@ -209,6 +212,27 @@ public abstract class FONode implements Cloneable { //nop } + /** + * Static version of {@link FONode#validateChildNode(Locator, String, String)} that + * can be used by subclasses that need to validate children against a different node + * (for example: fo:wrapper needs to check if the incoming node is a + * valid child to its parent) + * + * @param fo the FONode to validate against + * @param loc location in the source file + * @param namespaceURI namespace of the incoming node + * @param localName name of the incoming node (without namespace prefix) + * @throws ValidationException if the incoming node is not a valid child for the given FO + */ + protected static void validateChildNode( + FONode fo, + Locator loc, + String namespaceURI, + String localName) + throws ValidationException { + fo.validateChildNode(loc, namespaceURI, localName); + } + /** * Adds characters (does nothing here) * @param data array of characters containing text to be added @@ -572,8 +596,8 @@ public abstract class FONode implements Cloneable { } /** - * Returns the Constants class integer value of this node - * @return the integer enumeration of this FO (e.g., FO_ROOT) + * Returns the {@link Constants} class integer value of this node + * @return the integer enumeration of this FO (e.g. FO_ROOT) * if a formatting object, FO_UNKNOWN_NODE otherwise */ public int getNameId() { @@ -632,6 +656,14 @@ public abstract class FONode implements Cloneable { } } + /** + * This method is used when adding child nodes to a FO that already + * contains at least one child. In this case, the new child becomes a + * sibling to the previous one + * + * @param precedingSibling the previous child + * @param followingSibling the new child + */ protected static void attachSiblings(FONode precedingSibling, FONode followingSibling) { if (precedingSibling.siblings == null) { @@ -688,7 +720,7 @@ public abstract class FONode implements Cloneable { * @return the last node in the list * @throws NoSuchElementException if the list is empty */ - public FONode lastNode(); + public FONode lastNode(); } } diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index 8b833f6b7..b116eddeb 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -38,49 +38,43 @@ public class Wrapper extends FObjMixed { // used for FO validation private boolean blockOrInlineItemFound = false; - private boolean isFlowChild = false; + private boolean inlineChildrenAllowed = false; /** * @param parent FONode that is the parent of this object */ public Wrapper(FONode parent) { super(parent); - /* Check if the fo:wrapper is a child of an fo:flow or fo:static-content + /* Check if the fo:wrapper is a child of a FO that allows mixed content * (or a descendant in nested fo:wrapper sequence, the first of which - * is a child of an fo:flow or fo:static-content */ + * is a child of a FO that allows mixed content) */ FONode ancestor = this.parent; - while (!(ancestor instanceof Flow) - && ancestor instanceof Wrapper) { + while (ancestor instanceof Wrapper) { ancestor = ancestor.getParent(); } - if (ancestor instanceof Flow) { - this.isFlowChild = true; + if (ancestor instanceof FObjMixed ) { + inlineChildrenAllowed = true; } } /** * {@inheritDoc} - * XSL Content Model: marker* (#PCDATA|%inline;|%block;)* - * Additionally (unimplemented): "An fo:wrapper that is a child of an + *
XSL Content Model: marker* (#PCDATA|%inline;|%block;)* + *
Additionally (unimplemented): "An fo:wrapper that is a child of an * fo:multi-properties is only permitted to have children that would - * be permitted in place of the fo:multi-properties." + * be permitted in place of the fo:multi-properties." * */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { + if (FO_URI.equals(nsURI) && "marker".equals(localName)) { if (blockOrInlineItemFound) { nodesOutOfOrderError(loc, "fo:marker", "(#PCDATA|%inline;|%block;)"); } } else if (isBlockOrInlineItem(nsURI, localName)) { - if (isFlowChild - && isInlineItem(nsURI, localName) - && !isNeutralItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName, - "fo:" + localName + " not allowed as child of an fo:wrapper " - + "that is a child of an fo:flow or fo:static-content"); - } + //delegate validation to parent + FONode.validateChildNode(this.parent, loc, nsURI, localName); blockOrInlineItemFound = true; } else { invalidChildError(loc, nsURI, localName); @@ -94,9 +88,8 @@ public class Wrapper extends FObjMixed { int end, PropertyList pList, Locator locator) throws FOPException { - /* Only add text if the fo:wrapper is not a child of an fo:flow - * or fo:static-content */ - if (!this.isFlowChild) { + /* Only add text if the fo:wrapper's parent allows inline children */ + if (this.inlineChildrenAllowed) { super.addCharacters(data, start, end, pList, locator); } } -- cgit v1.2.3 From 916e1325a2033ddd8ed9a707049076b391b49e8b Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 17 Dec 2007 10:21:04 +0000 Subject: Organized imports git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604814 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/Wrapper.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index b116eddeb..adf9b2101 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -24,7 +24,6 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.pagination.Flow; import org.xml.sax.Locator; /** -- cgit v1.2.3 From 040987c53225a7d4e634e89167e848be40514a2d Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 17 Dec 2007 18:56:46 +0000 Subject: Renaming GridUnitPart into the more accurate CellPart. Moreover I was always making the confusion between gup and pgu git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604965 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 10 +-- .../org/apache/fop/layoutmgr/table/CellPart.java | 73 ++++++++++++++++++++++ .../apache/fop/layoutmgr/table/GridUnitPart.java | 73 ---------------------- .../org/apache/fop/layoutmgr/table/RowPainter.java | 22 +++---- .../layoutmgr/table/TableContentLayoutManager.java | 2 +- .../fop/layoutmgr/table/TableContentPosition.java | 12 ++-- .../apache/fop/layoutmgr/table/TableStepper.java | 13 ++-- 7 files changed, 103 insertions(+), 102 deletions(-) create mode 100644 src/java/org/apache/fop/layoutmgr/table/CellPart.java delete mode 100644 src/java/org/apache/fop/layoutmgr/table/GridUnitPart.java (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 139eacf43..a1957eb27 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -266,12 +266,12 @@ class ActiveCell { } /** - * Creates and returns a GridUnitPart instance for the content of this cell which + * Creates and returns a CellPart instance for the content of this cell which * is included in the next step. * - * @return a GridUnitPart instance + * @return a CellPart instance */ - GridUnitPart createGridUnitPart() { + CellPart createCellPart() { if (end + 1 == elementList.size()) { if (pgu.getFlag(GridUnit.KEEP_WITH_NEXT_PENDING)) { keepWithNextSignal = true; @@ -284,9 +284,9 @@ class ActiveCell { && elementList.size() == 1 && elementList.get(0) instanceof KnuthBoxCellWithBPD) { //Special case: Cell with fixed BPD - return new GridUnitPart(pgu, 0, pgu.getElements().size() - 1); + return new CellPart(pgu, 0, pgu.getElements().size() - 1); } else { - return new GridUnitPart(pgu, start, end); + return new CellPart(pgu, start, end); } } diff --git a/src/java/org/apache/fop/layoutmgr/table/CellPart.java b/src/java/org/apache/fop/layoutmgr/table/CellPart.java new file mode 100644 index 000000000..bf5ad64cf --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/table/CellPart.java @@ -0,0 +1,73 @@ +/* + * 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.layoutmgr.table; + +import org.apache.fop.fo.flow.table.GridUnit; +import org.apache.fop.fo.flow.table.PrimaryGridUnit; + +/** + * Represents a non-dividable part of a grid unit. Used by the table stepper. + */ +class CellPart { + + /** Primary grid unit */ + protected PrimaryGridUnit pgu; + /** Index of the starting element of this part */ + protected int start; + /** Index of the ending element of this part */ + protected int end; + + /** + * Creates a new CellPart. + * @param pgu Primary grid unit + * @param start starting element + * @param end ending element + */ + protected CellPart(PrimaryGridUnit pgu, int start, int end) { + this.pgu = pgu; + this.start = start; + this.end = end; + } + + /** @return true if this part is the first part of a cell */ + public boolean isFirstPart() { + return (start == 0); + } + + /** @return true if this part is the last part of a cell */ + public boolean isLastPart() { + return (end >= 0 && end == pgu.getElements().size() - 1); + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer("Part: "); + sb.append(start).append("-").append(end); + sb.append(" [").append(isFirstPart() ? "F" : "-").append(isLastPart() ? "L" : "-"); + sb.append("] ").append(pgu); + return sb.toString(); + } + + boolean mustKeepWithPrevious() { + return pgu.getFlag(GridUnit.KEEP_WITH_PREVIOUS_PENDING) + || (pgu.getRow() != null && pgu.getRow().mustKeepWithPrevious()); + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/table/GridUnitPart.java b/src/java/org/apache/fop/layoutmgr/table/GridUnitPart.java deleted file mode 100644 index e0cdfccf1..000000000 --- a/src/java/org/apache/fop/layoutmgr/table/GridUnitPart.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.layoutmgr.table; - -import org.apache.fop.fo.flow.table.GridUnit; -import org.apache.fop.fo.flow.table.PrimaryGridUnit; - -/** - * Represents a non-dividable part of a grid unit. Used by the table stepper. - */ -class GridUnitPart { - - /** Primary grid unit */ - protected PrimaryGridUnit pgu; - /** Index of the starting element of this part */ - protected int start; - /** Index of the ending element of this part */ - protected int end; - - /** - * Creates a new GridUnitPart. - * @param pgu Primary grid unit - * @param start starting element - * @param end ending element - */ - protected GridUnitPart(PrimaryGridUnit pgu, int start, int end) { - this.pgu = pgu; - this.start = start; - this.end = end; - } - - /** @return true if this part is the first part of a cell */ - public boolean isFirstPart() { - return (start == 0); - } - - /** @return true if this part is the last part of a cell */ - public boolean isLastPart() { - return (end >= 0 && end == pgu.getElements().size() - 1); - } - - /** {@inheritDoc} */ - public String toString() { - StringBuffer sb = new StringBuffer("Part: "); - sb.append(start).append("-").append(end); - sb.append(" [").append(isFirstPart() ? "F" : "-").append(isLastPart() ? "L" : "-"); - sb.append("] ").append(pgu); - return sb.toString(); - } - - boolean mustKeepWithPrevious() { - return pgu.getFlag(GridUnit.KEEP_WITH_PREVIOUS_PENDING) - || (pgu.getRow() != null && pgu.getRow().mustKeepWithPrevious()); - } - -} diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 73cce29e4..f78d47b52 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -110,27 +110,27 @@ class RowPainter { } rowFO = tcpos.row.getTableRow(); lastRow = tcpos.row; - Iterator partIter = tcpos.gridUnitParts.iterator(); + Iterator partIter = tcpos.cellParts.iterator(); //Iterate over all grid units in the current step while (partIter.hasNext()) { - GridUnitPart gup = (GridUnitPart)partIter.next(); + CellPart cellPart = (CellPart)partIter.next(); if (log.isDebugEnabled()) { - log.debug(">" + gup); + log.debug(">" + cellPart); } - int colIndex = gup.pgu.getStartCol(); - if (primaryGridUnits[colIndex] != gup.pgu) { + int colIndex = cellPart.pgu.getStartCol(); + if (primaryGridUnits[colIndex] != cellPart.pgu) { if (primaryGridUnits[colIndex] != null) { log.warn("Replacing GU in slot " + colIndex + ". Some content may not be painted."); } - primaryGridUnits[colIndex] = gup.pgu; - start[colIndex] = gup.start; - end[colIndex] = gup.end; + primaryGridUnits[colIndex] = cellPart.pgu; + start[colIndex] = cellPart.start; + end[colIndex] = cellPart.end; } else { - if (gup.end < end[colIndex]) { + if (cellPart.end < end[colIndex]) { throw new IllegalStateException("Internal Error: stepper problem"); } - end[colIndex] = gup.end; + end[colIndex] = cellPart.end; } } } @@ -175,7 +175,7 @@ class RowPainter { if (forcedFlush || ((end[i] == primaryGridUnits[i].getElements().size() - 1) && (currentGU == null || currentGU.isLastGridUnitRowSpan()))) { //the last line in the "if" above is to avoid a premature end of a - //row-spanned cell because no GridUnitParts are generated after a cell is + //row-spanned cell because no CellParts are generated after a cell is //finished with its content. //See table-cell_number-rows-spanned_bug38397.xml addAreasForCell(primaryGridUnits[i], start[i], end[i], lastRow, partBPD[i], diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index fca0557b7..57972078e 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -387,7 +387,7 @@ public class TableContentLayoutManager implements PercentBaseContext { if (pos instanceof TableContentPosition) { TableContentPosition tcpos = (TableContentPosition)pos; lst.add(tcpos); - GridUnitPart part = (GridUnitPart)tcpos.gridUnitParts.get(0); + CellPart part = (CellPart)tcpos.cellParts.get(0); if (body == null) { body = part.pgu.getBody(); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java index 8986ea85f..68f55d88f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java @@ -36,8 +36,8 @@ class TableContentPosition extends Position { /** The position is the last of the row group. */ public static final int LAST_IN_ROWGROUP = 2; - /** the list of GridUnitParts making up this position */ - protected List gridUnitParts; + /** the list of CellParts making up this position */ + protected List cellParts; /** effective row this position belongs to */ protected EffRow row; /** flags for the position */ @@ -46,13 +46,13 @@ class TableContentPosition extends Position { /** * Creates a new TableContentPosition. * @param lm applicable layout manager - * @param gridUnitParts the list of GridUnitPart instances + * @param cellParts the list of CellPart instances * @param row effective row this position belongs to */ - protected TableContentPosition(LayoutManager lm, List gridUnitParts, + protected TableContentPosition(LayoutManager lm, List cellParts, EffRow row) { super(lm); - this.gridUnitParts = gridUnitParts; + this.cellParts = cellParts; this.row = row; } @@ -90,7 +90,7 @@ class TableContentPosition extends Position { sb.append(getFlag(FIRST_IN_ROWGROUP) ? "F" : "-"); sb.append(getFlag(LAST_IN_ROWGROUP) ? "L" : "-").append("]"); sb.append("("); - sb.append(gridUnitParts); + sb.append(cellParts); sb.append(")"); return sb.toString(); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 98b07778f..d4ed460b4 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -169,26 +169,27 @@ public class TableStepper { boolean forcedBreak = false; int breakClass = -1; //Put all involved grid units into a list - List gridUnitParts = new java.util.ArrayList(maxColumnCount); + List cellParts = new java.util.ArrayList(maxColumnCount); for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); if (activeCell.contributesContent()) { - GridUnitPart gup = activeCell.createGridUnitPart(); - gridUnitParts.add(gup); + CellPart part = activeCell.createCellPart(); + cellParts.add(part); forcedBreak = activeCell.isLastForcedBreak(); if (forcedBreak) { breakClass = activeCell.getLastBreakClass(); } - if (returnList.size() == 0 && gup.isFirstPart() && gup.mustKeepWithPrevious()) { + if (returnList.size() == 0 && part.isFirstPart() + && part.mustKeepWithPrevious()) { context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); } } } - //log.debug(">>> guPARTS: " + gridUnitParts); + //log.debug(">>> guPARTS: " + cellParts); //Create elements for step TableContentPosition tcpos = new TableContentPosition(getTableLM(), - gridUnitParts, rowGroup[normalRow]); + cellParts, rowGroup[normalRow]); if (returnList.size() == 0) { tcpos.setFlag(TableContentPosition.FIRST_IN_ROWGROUP, true); } -- cgit v1.2.3 From feca36df8615178172e20001c99a071b5fa3aa02 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 17 Dec 2007 19:05:27 +0000 Subject: Simplified addAreasAndFlushRow: there can no longer be null GridUnits, every hole in the grid is now filled with an EmptyGridUnit git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@604970 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index f78d47b52..880e44282 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -173,7 +173,7 @@ class RowPainter { if (primaryGridUnits[i] != null) { if (forcedFlush || ((end[i] == primaryGridUnits[i].getElements().size() - 1) - && (currentGU == null || currentGU.isLastGridUnitRowSpan()))) { + && currentGU.isLastGridUnitRowSpan())) { //the last line in the "if" above is to avoid a premature end of a //row-spanned cell because no CellParts are generated after a cell is //finished with its content. @@ -185,7 +185,7 @@ class RowPainter { end[i] = -1; partBPD[i] = 0; } - } else if (currentGU != null && !currentGU.isEmpty() + } else if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 && (forcedFlush || currentGU.isLastGridUnitRowSpan())) { //A row-spanned cell has finished contributing content on the previous page -- cgit v1.2.3 From 5323aed1fcf9375edd328b9c91a88e4a9b741e98 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 18 Dec 2007 11:56:38 +0000 Subject: Reset previousRowsLength before a new row-group is handled git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@605195 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/TableStepper.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index d4ed460b4..35bf4c844 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -75,6 +75,7 @@ public class TableStepper { private void setup(int columnCount) { this.columnCount = columnCount; this.activeRowIndex = 0; + this.previousRowsLength = 0; } /** -- cgit v1.2.3 From fd26360942bad4bc40c56d48dd672f75162ac7ce Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 18 Dec 2007 16:48:03 +0000 Subject: Simplification in RowPainter: avoid the use of an array to store rowOffsets and firstRow index for each part of the table (header, footer, body). One at a time is enough. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@605246 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/RowPainter.java | 45 +++++++++++----------- .../layoutmgr/table/TableContentLayoutManager.java | 1 + 2 files changed, 24 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 880e44282..d053c6ebd 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -20,6 +20,7 @@ package org.apache.fop.layoutmgr.table; import java.util.Arrays; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -47,17 +48,15 @@ class RowPainter { private EffRow lastRow = null; private LayoutContext layoutContext; /** - * For each part of the table (header, footer, body), index of the first row of that - * part present on the current page. + * Index of the first row of the current part present on the current page. */ - private int[] firstRow = new int[3]; + private int firstRow; /** - * Keeps track of the y-offsets of each row on a page (for body, header and footer separately). + * Keeps track of the y-offsets of each row on a page. * This is particularly needed for spanned cells where you need to know the y-offset * of the starting row when the area is generated at the time the cell is closed. */ - private Map[] rowOffsets = new Map[] {new java.util.HashMap(), - new java.util.HashMap(), new java.util.HashMap()}; + private Map rowOffsets = new HashMap(); //These three variables are our buffer to recombine the individual steps into cells /** Primary grid units corresponding to the currently handled grid units, per row. */ @@ -87,7 +86,7 @@ class RowPainter { this.start = new int[colCount]; this.end = new int[colCount]; this.partBPD = new int[colCount]; - Arrays.fill(firstRow, -1); + this.firstRow = -1; Arrays.fill(end, -1); } @@ -149,17 +148,16 @@ class RowPainter { int addAreasAndFlushRow(boolean forcedFlush) { int actualRowHeight = 0; - int bt = lastRow.getBodyType(); if (log.isDebugEnabled()) { log.debug("Remembering yoffset for row " + lastRow.getIndex() + ": " + yoffset); } - rowOffsets[bt].put(new Integer(lastRow.getIndex()), new Integer(yoffset)); + rowOffsets.put(new Integer(lastRow.getIndex()), new Integer(yoffset)); for (int i = 0; i < primaryGridUnits.length; i++) { if ((primaryGridUnits[i] != null) && (forcedFlush || (end[i] == primaryGridUnits[i].getElements().size() - 1))) { actualRowHeight = Math.max(actualRowHeight, computeSpanHeight( - primaryGridUnits[i], start[i], end[i], i, bt)); + primaryGridUnits[i], start[i], end[i], i)); } } actualRowHeight += 2 * tclm.getTableLM().getHalfBorderSeparationBPD(); @@ -226,8 +224,7 @@ class RowPainter { * {@link TableRowIterator#BODY} * @return the cell's height */ - private int computeSpanHeight(PrimaryGridUnit pgu, int start, int end, int columnIndex, - int bodyType) { + private int computeSpanHeight(PrimaryGridUnit pgu, int start, int end, int columnIndex) { if (log.isTraceEnabled()) { log.trace("getting len for " + columnIndex + " " + start + "-" + end); @@ -292,8 +289,8 @@ class RowPainter { len += pgu.getHalfMaxBeforeBorderWidth(); len += pgu.getHalfMaxAfterBorderWidth(); } - int startRow = Math.max(pgu.getStartRow(), firstRow[bodyType]); - Integer storedOffset = (Integer)rowOffsets[bodyType].get(new Integer(startRow)); + int startRow = Math.max(pgu.getStartRow(), firstRow); + Integer storedOffset = (Integer)rowOffsets.get(new Integer(startRow)); int effYOffset; if (storedOffset != null) { effYOffset = storedOffset.intValue(); @@ -306,12 +303,11 @@ class RowPainter { private void addAreasForCell(PrimaryGridUnit pgu, int startPos, int endPos, EffRow row, int contentHeight, int rowHeight) { - int bt = row.getBodyType(); - if (firstRow[bt] < 0) { - firstRow[bt] = row.getIndex(); + if (firstRow < 0) { + firstRow = row.getIndex(); } //Determine the first row in this sequence - int startRowIndex = Math.max(pgu.getStartRow(), firstRow[bt]); + int startRowIndex = Math.max(pgu.getStartRow(), firstRow); int lastRowIndex = lastRow.getIndex(); // In collapsing-border model, if the cell spans over several columns/rows then @@ -321,9 +317,9 @@ class RowPainter { int[] spannedGridRowHeights = null; if (!tclm.getTableLM().getTable().isSeparateBorderModel() && pgu.hasSpanning()) { spannedGridRowHeights = new int[lastRowIndex - startRowIndex + 1]; - int prevOffset = ((Integer)rowOffsets[bt].get(new Integer(startRowIndex))).intValue(); + int prevOffset = ((Integer)rowOffsets.get(new Integer(startRowIndex))).intValue(); for (int i = 0; i < lastRowIndex - startRowIndex; i++) { - int newOffset = ((Integer) rowOffsets[bt].get(new Integer(startRowIndex + i + 1))) + int newOffset = ((Integer) rowOffsets.get(new Integer(startRowIndex + i + 1))) .intValue(); spannedGridRowHeights[i] = newOffset - prevOffset; prevOffset = newOffset; @@ -332,12 +328,12 @@ class RowPainter { } //Determine y offset for the cell - Integer offset = (Integer)rowOffsets[bt].get(new Integer(startRowIndex)); + Integer offset = (Integer)rowOffsets.get(new Integer(startRowIndex)); while (offset == null) { //TODO Figure out what this does and when it's triggered //This block is probably never used, at least it's not triggered by any of our tests startRowIndex--; - offset = (Integer)rowOffsets[bt].get(new Integer(startRowIndex)); + offset = (Integer)rowOffsets.get(new Integer(startRowIndex)); } int effYOffset = offset.intValue(); int effCellHeight = rowHeight; @@ -364,4 +360,9 @@ class RowPainter { layoutContext, spannedGridRowHeights, startRowIndex - pgu.getStartRow(), lastRowIndex - pgu.getStartRow() + 1); } + + void endPart() { + firstRow = -1; + rowOffsets.clear(); + } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 57972078e..308b2cca7 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -418,6 +418,7 @@ public class TableContentLayoutManager implements PercentBaseContext { handleMarkersAndPositions(lst, body, firstPos, false, painter); } painter.addAreasAndFlushRow(true); + painter.endPart(); } private void handleMarkersAndPositions(List positions, TableBody body, boolean firstPos, -- cgit v1.2.3 From ef06a58b6802b5cf4b1b67f81f941be18bbb4d04 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 18 Dec 2007 17:01:45 +0000 Subject: Renamed firstRow into firstRowIndex and moved its initialization into handeTableContentPosition git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@605253 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index d053c6ebd..490f999cd 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -50,7 +50,7 @@ class RowPainter { /** * Index of the first row of the current part present on the current page. */ - private int firstRow; + private int firstRowIndex; /** * Keeps track of the y-offsets of each row on a page. * This is particularly needed for spanned cells where you need to know the y-offset @@ -86,7 +86,7 @@ class RowPainter { this.start = new int[colCount]; this.end = new int[colCount]; this.partBPD = new int[colCount]; - this.firstRow = -1; + this.firstRowIndex = -1; Arrays.fill(end, -1); } @@ -109,6 +109,9 @@ class RowPainter { } rowFO = tcpos.row.getTableRow(); lastRow = tcpos.row; + if (firstRowIndex < 0) { + firstRowIndex = lastRow.getIndex(); + } Iterator partIter = tcpos.cellParts.iterator(); //Iterate over all grid units in the current step while (partIter.hasNext()) { @@ -289,7 +292,7 @@ class RowPainter { len += pgu.getHalfMaxBeforeBorderWidth(); len += pgu.getHalfMaxAfterBorderWidth(); } - int startRow = Math.max(pgu.getStartRow(), firstRow); + int startRow = Math.max(pgu.getStartRow(), firstRowIndex); Integer storedOffset = (Integer)rowOffsets.get(new Integer(startRow)); int effYOffset; if (storedOffset != null) { @@ -303,11 +306,8 @@ class RowPainter { private void addAreasForCell(PrimaryGridUnit pgu, int startPos, int endPos, EffRow row, int contentHeight, int rowHeight) { - if (firstRow < 0) { - firstRow = row.getIndex(); - } //Determine the first row in this sequence - int startRowIndex = Math.max(pgu.getStartRow(), firstRow); + int startRowIndex = Math.max(pgu.getStartRow(), firstRowIndex); int lastRowIndex = lastRow.getIndex(); // In collapsing-border model, if the cell spans over several columns/rows then @@ -362,7 +362,7 @@ class RowPainter { } void endPart() { - firstRow = -1; + firstRowIndex = -1; rowOffsets.clear(); } } -- cgit v1.2.3 From f15db7d7e260738d22feddaef6cd73abdf5860b3 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 18 Dec 2007 18:58:29 +0000 Subject: Streamlined the recording of row offsets, by replacing Map with a List. Fixed bug #43633 in the same time. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@605295 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/RowPainter.java | 74 ++++++++++------- status.xml | 3 + .../table_row-span_missing-cell_bug43633.xml | 96 ++++++++++++++++++++++ 3 files changed, 145 insertions(+), 28 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table_row-span_missing-cell_bug43633.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 490f999cd..0b90bf9d8 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -19,10 +19,10 @@ package org.apache.fop.layoutmgr.table; +import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.Iterator; -import java.util.Map; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -56,7 +56,7 @@ class RowPainter { * This is particularly needed for spanned cells where you need to know the y-offset * of the starting row when the area is generated at the time the cell is closed. */ - private Map rowOffsets = new HashMap(); + private List rowOffsets = new ArrayList(); //These three variables are our buffer to recombine the individual steps into cells /** Primary grid units corresponding to the currently handled grid units, per row. */ @@ -154,7 +154,7 @@ class RowPainter { if (log.isDebugEnabled()) { log.debug("Remembering yoffset for row " + lastRow.getIndex() + ": " + yoffset); } - rowOffsets.put(new Integer(lastRow.getIndex()), new Integer(yoffset)); + recordRowOffset(lastRow.getIndex(), yoffset); for (int i = 0; i < primaryGridUnits.length; i++) { if ((primaryGridUnits[i] != null) @@ -292,15 +292,8 @@ class RowPainter { len += pgu.getHalfMaxBeforeBorderWidth(); len += pgu.getHalfMaxAfterBorderWidth(); } - int startRow = Math.max(pgu.getStartRow(), firstRowIndex); - Integer storedOffset = (Integer)rowOffsets.get(new Integer(startRow)); - int effYOffset; - if (storedOffset != null) { - effYOffset = storedOffset.intValue(); - } else { - effYOffset = yoffset; - } - len -= yoffset - effYOffset; + int cellOffset = getRowOffset(Math.max(pgu.getStartRow(), firstRowIndex)); + len -= yoffset - cellOffset; return len; } @@ -317,37 +310,28 @@ class RowPainter { int[] spannedGridRowHeights = null; if (!tclm.getTableLM().getTable().isSeparateBorderModel() && pgu.hasSpanning()) { spannedGridRowHeights = new int[lastRowIndex - startRowIndex + 1]; - int prevOffset = ((Integer)rowOffsets.get(new Integer(startRowIndex))).intValue(); + int prevOffset = getRowOffset(startRowIndex); for (int i = 0; i < lastRowIndex - startRowIndex; i++) { - int newOffset = ((Integer) rowOffsets.get(new Integer(startRowIndex + i + 1))) - .intValue(); + int newOffset = getRowOffset(startRowIndex + i + 1); spannedGridRowHeights[i] = newOffset - prevOffset; prevOffset = newOffset; } spannedGridRowHeights[lastRowIndex - startRowIndex] = rowHeight; } - //Determine y offset for the cell - Integer offset = (Integer)rowOffsets.get(new Integer(startRowIndex)); - while (offset == null) { - //TODO Figure out what this does and when it's triggered - //This block is probably never used, at least it's not triggered by any of our tests - startRowIndex--; - offset = (Integer)rowOffsets.get(new Integer(startRowIndex)); - } - int effYOffset = offset.intValue(); + int cellOffset = getRowOffset(startRowIndex); int effCellHeight = rowHeight; - effCellHeight += yoffset - effYOffset; + effCellHeight += yoffset - cellOffset; if (log.isDebugEnabled()) { log.debug("Creating area for cell:"); log.debug(" current row: " + row.getIndex()); - log.debug(" start row: " + pgu.getStartRow() + " " + yoffset + " " + effYOffset); + log.debug(" start row: " + pgu.getStartRow() + " " + yoffset + " " + cellOffset); log.debug(" contentHeight: " + contentHeight + " rowHeight=" + rowHeight + " effCellHeight=" + effCellHeight); } TableCellLayoutManager cellLM = pgu.getCellLM(); cellLM.setXOffset(tclm.getXOffsetOfGridUnit(pgu)); - cellLM.setYOffset(effYOffset); + cellLM.setYOffset(cellOffset); cellLM.setContentHeight(contentHeight); cellLM.setRowHeight(effCellHeight); //cellLM.setRowHeight(row.getHeight().opt); @@ -361,6 +345,40 @@ class RowPainter { lastRowIndex - pgu.getStartRow() + 1); } + /** + * Records the y-offset of the row with the given index. + * + * @param rowIndex index of the row + * @param offset y-offset of the row on the page + */ + private void recordRowOffset(int rowIndex, int offset) { + /* + * In some very rare cases a row may be skipped. See for example Bugzilla #43633: + * in a two-column table, a row contains a row-spanning cell and a missing cell. + * In TableStepper#goToNextRowIfCurrentFinished this row will immediately be + * considered as finished, since it contains no cell ending on this row. Thus no + * TableContentPosition will be created for this row. Thus its index will never be + * recorded by the #handleTableContentPosition method. + * + * The yoffset for such a row is the same as the next non-empty row. It's needed + * to correctly offset blocks for cells starting on this row. Hence the loop + * below. + */ + for (int i = rowOffsets.size(); i <= rowIndex - firstRowIndex; i++) { + rowOffsets.add(new Integer(offset)); + } + } + + /** + * Returns the offset of the row with the given index. + * + * @param rowIndex index of the row + * @return its y-offset on the page + */ + private int getRowOffset(int rowIndex) { + return ((Integer) rowOffsets.get(rowIndex - firstRowIndex)).intValue(); + } + void endPart() { firstRowIndex = -1; rowOffsets.clear(); diff --git a/status.xml b/status.xml index 46942d796..77f4dcb86 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Bugfix: content of a row with zero height overriding the previous row + Added SVG support for AFP (GOCA). diff --git a/test/layoutengine/standard-testcases/table_row-span_missing-cell_bug43633.xml b/test/layoutengine/standard-testcases/table_row-span_missing-cell_bug43633.xml new file mode 100644 index 000000000..5cf793bcf --- /dev/null +++ b/test/layoutengine/standard-testcases/table_row-span_missing-cell_bug43633.xml @@ -0,0 +1,96 @@ + + + + + +

+ Check for bug #43633: the second row of the table has only a spanning cell, and the second + cell is missing. This was leading to the spanning cell overlapping cell 1.1, because no + offset was recorded for the second row. +

+
+ + + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + + + Cell 3.2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-- cgit v1.2.3 From 23e00caa1c1932af9699618af8bf746315409979 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 19 Dec 2007 11:47:38 +0000 Subject: I said currentGU can no longer be null git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@605517 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 0b90bf9d8..6d2568afb 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -168,10 +168,7 @@ class RowPainter { //Add areas for row tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), yoffset); for (int i = 0; i < primaryGridUnits.length; i++) { - GridUnit currentGU = lastRow.safelyGetGridUnit(i); - //currentGU can be null if there's no grid unit - //at this place in the current row (empty cell and no borders to process) - + GridUnit currentGU = lastRow.getGridUnit(i); if (primaryGridUnits[i] != null) { if (forcedFlush || ((end[i] == primaryGridUnits[i].getElements().size() - 1) && currentGU.isLastGridUnitRowSpan())) { -- cgit v1.2.3 From 3311cbaf601724c5601e7ff7e6602016dbf862ac Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 20 Dec 2007 17:00:46 +0000 Subject: Remove commented code. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@605978 13f79535-47bb-0310-9956-ffa450edef68 --- .../inline/ExternalGraphicLayoutManager.java | 162 +-------------------- .../layoutmgr/inline/InstreamForeignObjectLM.java | 6 +- 2 files changed, 2 insertions(+), 166 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java index ecdbd68e4..ab05d60c3 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr.inline; -import java.awt.geom.Rectangle2D; import org.apache.fop.area.Area; import org.apache.fop.area.inline.Image; import org.apache.fop.fo.flow.ExternalGraphic; @@ -34,7 +33,6 @@ public class ExternalGraphicLayoutManager extends AbstractGraphicsLayoutManager /** * Constructor - * * @param node the fo:external-graphic formatting object that creates the area */ public ExternalGraphicLayoutManager(ExternalGraphic node) { @@ -42,165 +40,7 @@ public class ExternalGraphicLayoutManager extends AbstractGraphicsLayoutManager fobj = node; } - /** - * Setup this image. - * This gets the sizes for the image and the dimensions and clipping. - * @todo see if can simplify property handling logic - */ - /* - private void setup() { - // assume lr-tb for now and just use the .optimum value of the range - Length ipd = fobj.getInlineProgressionDimension().getOptimum(this).getLength(); - if (ipd.getEnum() != EN_AUTO) { - viewWidth = ipd.getValue(this); - } else { - ipd = fobj.getWidth(); - if (ipd.getEnum() != EN_AUTO) { - viewWidth = ipd.getValue(this); - } - } - Length bpd = fobj.getBlockProgressionDimension().getOptimum(this).getLength(); - if (bpd.getEnum() != EN_AUTO) { - viewHeight = bpd.getValue(this); - } else { - bpd = fobj.getHeight(); - if (bpd.getEnum() != EN_AUTO) { - viewHeight = bpd.getValue(this); - } - } - - int cwidth = -1; - int cheight = -1; - Length ch = fobj.getContentHeight(); - if (ch.getEnum() != EN_AUTO) { - if (ch.getEnum() == EN_SCALE_TO_FIT) { - if (viewHeight != -1) { - cheight = viewHeight; - } - } else { - cheight = ch.getValue(this); - } - } - Length cw = fobj.getContentWidth(); - if (cw.getEnum() != EN_AUTO) { - if (cw.getEnum() == EN_SCALE_TO_FIT) { - if (viewWidth != -1) { - cwidth = viewWidth; - } - } else { - cwidth = cw.getValue(this); - } - } - - int scaling = fobj.getScaling(); - if ((scaling == EN_UNIFORM) || (cwidth == -1) || cheight == -1) { - if (cwidth == -1 && cheight == -1) { - cwidth = fobj.getIntrinsicWidth(); - cheight = fobj.getIntrinsicHeight(); - } else if (cwidth == -1) { - cwidth = (int)(fobj.getIntrinsicWidth() * (double)cheight - / fobj.getIntrinsicHeight()); - } else if (cheight == -1) { - cheight = (int)(fobj.getIntrinsicHeight() * (double)cwidth - / fobj.getIntrinsicWidth()); - } else { - // adjust the larger - double rat1 = (double)cwidth / fobj.getIntrinsicWidth(); - double rat2 = (double)cheight / fobj.getIntrinsicHeight(); - if (rat1 < rat2) { - // reduce cheight - cheight = (int)(rat1 * fobj.getIntrinsicHeight()); - } else if (rat1 > rat2) { - cwidth = (int)(rat2 * fobj.getIntrinsicWidth()); - } - } - } - - if (viewWidth == -1) { - viewWidth = cwidth; - } - if (viewHeight == -1) { - viewHeight = cheight; - } - - if (cwidth > viewWidth || cheight > viewHeight) { - int overflow = fobj.getOverflow(); - if (overflow == EN_HIDDEN) { - clip = true; - } else if (overflow == EN_ERROR_IF_OVERFLOW) { - fobj.getLogger().error("Image: " + fobj.getURL() - + " overflows the viewport, clipping to viewport"); - clip = true; - } - } - - int xoffset = 0; - int yoffset = 0; - switch(fobj.getDisplayAlign()) { - case EN_BEFORE: - break; - case EN_AFTER: - yoffset = viewHeight - cheight; - break; - case EN_CENTER: - yoffset = (viewHeight - cheight) / 2; - break; - case EN_AUTO: - default: - break; - } - - switch(fobj.getTextAlign()) { - case EN_CENTER: - xoffset = (viewWidth - cwidth) / 2; - break; - case EN_END: - xoffset = viewWidth - cwidth; - break; - case EN_START: - break; - case EN_JUSTIFY: - default: - break; - } - - - CommonBorderPaddingBackground borderProps = fobj.getCommonBorderPaddingBackground(); - - //Determine extra BPD from borders etc. - int beforeBPD = borderProps.getPadding(CommonBorderPaddingBackground.BEFORE, false, this); - beforeBPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.BEFORE, - false); - int afterBPD = borderProps.getPadding(CommonBorderPaddingBackground.AFTER, false, this); - afterBPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.AFTER, false); - - yoffset += beforeBPD; - viewBPD = viewHeight; - viewHeight += beforeBPD; - viewHeight += afterBPD; - - //Determine extra IPD from borders etc. - int startIPD = borderProps.getPadding(CommonBorderPaddingBackground.START, - false, this); - startIPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.START, - false); - int endIPD = borderProps.getPadding(CommonBorderPaddingBackground.END, false, this); - endIPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.END, false); - - xoffset += startIPD; - viewIPD = viewWidth; - viewWidth += startIPD; - viewWidth += endIPD; - - placement = new Rectangle2D.Float(xoffset, yoffset, cwidth, cheight); - } - */ - - /** - * Get the inline area created by this element. - * - * @return the inline area - */ + /** {@inheritDoc} */ protected Area getChildArea() { return new Image(fobj.getSrc()); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java b/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java index 8ff6b346e..e7da50a9a 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java @@ -40,11 +40,7 @@ public class InstreamForeignObjectLM extends AbstractGraphicsLayoutManager { fobj = node; } - /** - * Get the inline area created by this element. - * - * @return the inline area - */ + /** {@inheritDoc} */ protected Area getChildArea() { XMLObj child = (XMLObj) fobj.getChildXMLObj(); -- cgit v1.2.3 From ed61f771c493e86046f3d13e3d6a553d825dd8f3 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 20 Dec 2007 19:19:19 +0000 Subject: Added support for scale-down-to-fit and scale-up-to-fit. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@606004 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/Constants.java | 8 +- src/java/org/apache/fop/fo/FOPropertyMapping.java | 7 +- .../inline/AbstractGraphicsLayoutManager.java | 32 +++++++- status.xml | 3 + ...rnal-graphic_content-height_content-width_2.xml | 92 ++++++++++++++++++++++ 5 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 test/layoutengine/standard-testcases/external-graphic_content-height_content-width_2.xml (limited to 'src') diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java index e0477c0a5..edfa68c1a 100644 --- a/src/java/org/apache/fop/fo/Constants.java +++ b/src/java/org/apache/fop/fo/Constants.java @@ -1087,6 +1087,12 @@ public interface Constants { int EN_SMALL_CAPTION = 184; /** Enumeration constant -- font shorthand */ int EN_STATUS_BAR = 185; + /** Enumeration constant -- for page-position, XSL 1.1 */ + int EN_ONLY = 186; + /** Enumeration constant -- for instream-foreign-object and external-graphic, XSL 1.1 */ + int EN_SCALE_DOWN_TO_FIT = 187; + /** Enumeration constant -- for instream-foreign-object and external-graphic, XSL 1.1 */ + int EN_SCALE_UP_TO_FIT = 188; /** Number of enumeration constants defined */ - int ENUM_COUNT = 185; + int ENUM_COUNT = 188; } diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 5d1a6f31a..1fe9a32c4 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -25,13 +25,13 @@ import java.util.Map; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.fo.expr.PropertyException; +import org.apache.fop.fo.flow.table.TableFObj.ColumnNumberPropertyMaker; import org.apache.fop.fo.properties.BackgroundPositionShorthandParser; import org.apache.fop.fo.properties.BorderSpacingShorthandParser; import org.apache.fop.fo.properties.BorderWidthPropertyMaker; import org.apache.fop.fo.properties.BoxPropShorthandParser; import org.apache.fop.fo.properties.CharacterProperty; import org.apache.fop.fo.properties.ColorProperty; -import org.apache.fop.fo.flow.table.TableFObj.ColumnNumberPropertyMaker; import org.apache.fop.fo.properties.CondLengthProperty; import org.apache.fop.fo.properties.CorrespondingPropertyMaker; import org.apache.fop.fo.properties.DimensionPropertyMaker; @@ -1353,6 +1353,8 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.addEnum("scale-to-fit", getEnumProperty(EN_SCALE_TO_FIT, "SCALE_TO_FIT")); + l.addEnum("scale-down-to-fit", getEnumProperty(EN_SCALE_DOWN_TO_FIT, "SCALE_DOWN_TO_FIT")); + l.addEnum("scale-up-to-fit", getEnumProperty(EN_SCALE_UP_TO_FIT, "SCALE_UP_TO_FIT")); l.setDefault("auto"); l.setPercentBase(LengthBase.IMAGE_INTRINSIC_HEIGHT); addPropertyMaker("content-height", l); @@ -1362,6 +1364,8 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.addEnum("scale-to-fit", getEnumProperty(EN_SCALE_TO_FIT, "SCALE_TO_FIT")); + l.addEnum("scale-down-to-fit", getEnumProperty(EN_SCALE_DOWN_TO_FIT, "SCALE_DOWN_TO_FIT")); + l.addEnum("scale-up-to-fit", getEnumProperty(EN_SCALE_UP_TO_FIT, "SCALE_UP_TO_FIT")); l.setDefault("auto"); l.setPercentBase(LengthBase.IMAGE_INTRINSIC_WIDTH); addPropertyMaker("content-width", l); @@ -2223,6 +2227,7 @@ public final class FOPropertyMapping implements Constants { m.addEnum("last", getEnumProperty(EN_LAST, "LAST")); m.addEnum("rest", getEnumProperty(EN_REST, "REST")); m.addEnum("any", getEnumProperty(EN_ANY, "ANY")); + m.addEnum("only", getEnumProperty(EN_ONLY, "ONLY")); //XSL 1.1 m.setDefault("any"); addPropertyMaker("page-position", m); diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index ca82d3da7..75f852e06 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -104,21 +104,45 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage int cheight = -1; len = fobj.getContentWidth(); if (len.getEnum() != EN_AUTO) { - if (len.getEnum() == EN_SCALE_TO_FIT) { + switch (len.getEnum()) { + case EN_SCALE_TO_FIT: if (ipd != -1) { cwidth = ipd; } - } else { + break; + case EN_SCALE_DOWN_TO_FIT: + if (ipd != -1 && fobj.getIntrinsicWidth() > ipd) { + cwidth = ipd; + } + break; + case EN_SCALE_UP_TO_FIT: + if (ipd != -1 && fobj.getIntrinsicWidth() < ipd) { + cwidth = ipd; + } + break; + default: cwidth = len.getValue(this); } } len = fobj.getContentHeight(); if (len.getEnum() != EN_AUTO) { - if (len.getEnum() == EN_SCALE_TO_FIT) { + switch (len.getEnum()) { + case EN_SCALE_TO_FIT: if (bpd != -1) { cheight = bpd; } - } else { + break; + case EN_SCALE_DOWN_TO_FIT: + if (bpd != -1 && fobj.getIntrinsicHeight() > bpd) { + cheight = bpd; + } + break; + case EN_SCALE_UP_TO_FIT: + if (bpd != -1 && fobj.getIntrinsicHeight() < bpd) { + cheight = bpd; + } + break; + default: cheight = len.getValue(this); } } diff --git a/status.xml b/status.xml index 7487d67a0..0537ad75d 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Added support for scale-down-to-fit and scale-up-to-fit (introduced in XSL 1.1). + Bugfix: content of a row with zero height overriding the previous row diff --git a/test/layoutengine/standard-testcases/external-graphic_content-height_content-width_2.xml b/test/layoutengine/standard-testcases/external-graphic_content-height_content-width_2.xml new file mode 100644 index 000000000..281da9873 --- /dev/null +++ b/test/layoutengine/standard-testcases/external-graphic_content-height_content-width_2.xml @@ -0,0 +1,92 @@ + + + + + +

+ This test checks external-graphics with content-width + (values: scale-to-fit, scale-down-to-fit and scale-up-to-fit) +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-- cgit v1.2.3 From 0c87214d3a98d0836083d191b36aa7abf944d0dc Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 27 Dec 2007 10:34:15 +0000 Subject: Added new extension element: fox:external-document. It allows to add whole documents such as multi-page TIFF images to be inserted as peers to a page-sequence. Each image will make up an entire page. See the documentation for details. ATM, only single pages are possible. Multi-page images will be supported with the new image package. Some preparations for page-position="only" but the implementation is incomplete and "only" has no effect, yet. (Just uploaded some stuff I once started) Some javadoc cleanups. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@607032 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/extensions.xml | 73 ++++ .../org/apache/fop/apps/FormattingResults.java | 6 +- src/java/org/apache/fop/area/AreaTreeHandler.java | 34 +- src/java/org/apache/fop/area/RenderPagesModel.java | 2 +- src/java/org/apache/fop/fo/FOEventHandler.java | 15 + src/java/org/apache/fop/fo/GraphicsProperties.java | 81 +++++ src/java/org/apache/fop/fo/PropertyList.java | 8 +- .../fop/fo/extensions/ExtensionElementMapping.java | 7 + .../apache/fop/fo/extensions/ExternalDocument.java | 181 ++++++++++ .../org/apache/fop/fo/flow/AbstractGraphics.java | 87 +---- .../fop/fo/pagination/AbstractPageSequence.java | 154 +++++++++ .../pagination/ConditionalPageMasterReference.java | 8 +- .../org/apache/fop/fo/pagination/PageSequence.java | 113 ++---- .../fop/fo/pagination/PageSequenceMaster.java | 15 +- .../RepeatablePageMasterAlternatives.java | 13 +- .../pagination/RepeatablePageMasterReference.java | 7 + src/java/org/apache/fop/fo/pagination/Root.java | 19 +- .../fo/pagination/SinglePageMasterReference.java | 7 + .../fop/fo/pagination/SubSequenceSpecifier.java | 5 + .../fop/layoutmgr/AbstractLayoutManager.java | 4 +- .../AbstractPageSequenceLayoutManager.java | 385 +++++++++++++++++++++ .../layoutmgr/ExternalDocumentLayoutManager.java | 202 +++++++++++ .../apache/fop/layoutmgr/LayoutManagerMaker.java | 10 + .../apache/fop/layoutmgr/LayoutManagerMapping.java | 6 + src/java/org/apache/fop/layoutmgr/Page.java | 14 + .../org/apache/fop/layoutmgr/PageProvider.java | 2 +- .../fop/layoutmgr/PageSequenceLayoutManager.java | 383 ++------------------ .../fop/layoutmgr/TopLevelLayoutManager.java | 50 +++ .../inline/AbstractGraphicsLayoutManager.java | 197 ++--------- .../apache/fop/layoutmgr/inline/ImageLayout.java | 262 ++++++++++++++ src/java/org/apache/fop/render/rtf/RTFHandler.java | 3 +- .../org/apache/fop/render/xml/XMLRenderer.java | 4 +- status.xml | 5 + .../standard-testcases/fox_external-document_1.xml | 53 +++ .../standard-testcases/fox_external-document_2.xml | 81 +++++ 35 files changed, 1779 insertions(+), 717 deletions(-) create mode 100644 src/java/org/apache/fop/fo/GraphicsProperties.java create mode 100644 src/java/org/apache/fop/fo/extensions/ExternalDocument.java create mode 100644 src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java create mode 100644 src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java create mode 100644 src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java create mode 100644 src/java/org/apache/fop/layoutmgr/TopLevelLayoutManager.java create mode 100644 src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java create mode 100644 test/layoutengine/standard-testcases/fox_external-document_1.xml create mode 100644 test/layoutengine/standard-testcases/fox_external-document_2.xml (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/extensions.xml b/src/documentation/content/xdocs/trunk/extensions.xml index dd4a79535..288695286 100644 --- a/src/documentation/content/xdocs/trunk/extensions.xml +++ b/src/documentation/content/xdocs/trunk/extensions.xml @@ -115,6 +115,79 @@ to following pages. Here is an example of FO code creating such a table-header:< or list-block.

+
+ fox:external-document + + This feature is incomplete. Support for multi-page documents will be added shortly. + At the moment, only single-page images will work. And this will not work with RTF output. + +

+ This is a proprietary extension element which allows to add whole images as pages to + an FO document. For example, if you have a scanned document or a fax as multi-page TIFF + file, you can append or insert this document using the fox:external-document + element. Each page of the external document will create one full page in the target + format. +

+

+ The fox:external-document element is structurally a peer to + fo:page-sequence, so wherever you can put an fo:page-sequence + you could also place a fox:external-document. + Therefore, the specified contents for fo:root change to: +

+

+ + (layout-master-set, declarations?, bookmark-tree?, (page-sequence|page-sequence-wrapper|fox:external-document)+) + +

+
+ Specification +

+ The fox:external-document extension formatting object is used to specify + how to create a (sub-)sequence of pages within a document. The content of these pages + comes from the individual subimages/pages of an image or paged document (for example: + multi-page TIFF in the form of faxes or scanned documents, or PDF files). The + formatting object creates the necessary areas to display one image per page. +

+

+ In terms of page numbers, the behaviour is the same as for + fo:page-sequence. The placement of the image inside the page is similar + to that of fo:external-graphic or fo:instream-foreign-object, + i.e. the viewport (and therefore the page size) is defined by either the intrinsic + size of the image or by the size properties that apply to this formatting object. +

+

Content: EMPTY

+

The following properties apply to this formatting object:

+
    +
  • (Common Accessibility Properties) (not implemented, yet)
  • +
  • (Common Aural Properties) (not implemented, yet)
  • +
  • block-progression-dimension
  • +
  • content-height
  • +
  • content-type
  • +
  • content-width
  • +
  • display-align
  • +
  • height
  • +
  • id
  • +
  • inline-progression-dimension
  • +
  • overflow
  • +
  • pages: <page-set> (see below) (not implemented, yet)
  • +
  • reference-orientation
  • +
  • scaling
  • +
  • scaling-method
  • +
  • src
  • +
  • text-align
  • +
  • width
  • +
+

+ Datatype "page-set": Value: auto | <integer-range>, + Default: "auto" which means all pages/subimages of the document. + <integer-range> allows values such as "7" or "1-3" +

+ + fox:external-document is not suitable for concatenating FO documents. + For this, XInclude is recommended. + +
+
diff --git a/src/java/org/apache/fop/apps/FormattingResults.java b/src/java/org/apache/fop/apps/FormattingResults.java index 80449bd4b..86ac72a97 100644 --- a/src/java/org/apache/fop/apps/FormattingResults.java +++ b/src/java/org/apache/fop/apps/FormattingResults.java @@ -21,7 +21,7 @@ package org.apache.fop.apps; import java.util.List; -import org.apache.fop.fo.pagination.PageSequence; +import org.apache.fop.fo.pagination.AbstractPageSequence; /** * Class for reporting back formatting results to the calling application. @@ -69,10 +69,10 @@ public class FormattingResults { * Reports the result of one page sequence rendering * back into this object. * - * @param pageSequence the PageSequence which just completed rendering + * @param pageSequence the page sequence which just completed rendering * @param pageCount the number of pages rendered for that PageSequence */ - public void haveFormattedPageSequence(PageSequence pageSequence, int pageCount) { + public void haveFormattedPageSequence(AbstractPageSequence pageSequence, int pageCount) { this.pageCount += pageCount; if (this.pageSequences == null) { this.pageSequences = new java.util.ArrayList(); diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java index 6eb2d738b..a107da833 100644 --- a/src/java/org/apache/fop/area/AreaTreeHandler.java +++ b/src/java/org/apache/fop/area/AreaTreeHandler.java @@ -35,13 +35,17 @@ import org.apache.fop.apps.FormattingResults; import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.fo.extensions.ExternalDocument; import org.apache.fop.fo.extensions.destination.Destination; +import org.apache.fop.fo.pagination.AbstractPageSequence; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.Root; import org.apache.fop.fo.pagination.bookmarks.BookmarkTree; +import org.apache.fop.layoutmgr.ExternalDocumentLayoutManager; import org.apache.fop.layoutmgr.LayoutManagerMaker; import org.apache.fop.layoutmgr.LayoutManagerMapping; import org.apache.fop.layoutmgr.PageSequenceLayoutManager; +import org.apache.fop.layoutmgr.TopLevelLayoutManager; /** * Area tree handler for formatting objects. @@ -78,7 +82,7 @@ public class AreaTreeHandler extends FOEventHandler { // The formatting results to be handed back to the caller. private FormattingResults results = new FormattingResults(); - private PageSequenceLayoutManager prevPageSeqLM; + private TopLevelLayoutManager prevPageSeqLM; private int idGen = 0; @@ -234,6 +238,32 @@ public class AreaTreeHandler extends FOEventHandler { } } + /** + * @see org.apache.fop.fo.FOEventHandler#startExternalDocument(org.apache.fop.fo.extensions.ExternalDocument) + */ + public void startExternalDocument(ExternalDocument document) { + rootFObj = document.getRoot(); + finishPrevPageSequence(document.getInitialPageNumber()); + document.initPageNumber(); + } + + /** + * @see org.apache.fop.fo.FOEventHandler#endExternalDocument(org.apache.fop.fo.extensions.ExternalDocument) + */ + public void endExternalDocument(ExternalDocument document) { + if (statistics != null) { + statistics.end(); + } + + ExternalDocumentLayoutManager edLM; + edLM = getLayoutManagerMaker().makeExternalDocumentLayoutManager(this, document); + edLM.activateLayout(); + // preserve the current PageSequenceLayoutManger for the + // force-page-count check at the beginning of the next PageSequence + prevPageSeqLM = edLM; + + } + /** * Called by the PageSequenceLayoutManager when it is finished with a * page-sequence. @@ -241,7 +271,7 @@ public class AreaTreeHandler extends FOEventHandler { * @param pageSequence the page-sequence just finished * @param pageCount The number of pages generated for the page-sequence */ - public void notifyPageSequenceFinished(PageSequence pageSequence, + public void notifyPageSequenceFinished(AbstractPageSequence pageSequence, int pageCount) { this.results.haveFormattedPageSequence(pageSequence, pageCount); if (log.isDebugEnabled()) { diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java index a5257977a..1b3a22706 100644 --- a/src/java/org/apache/fop/area/RenderPagesModel.java +++ b/src/java/org/apache/fop/area/RenderPagesModel.java @@ -173,7 +173,7 @@ public class RenderPagesModel extends AreaTreeModel { } } catch (Exception e) { // use error handler to handle this FOP or IO Exception - log.error(e); + log.error("Error while rendering page " + pageViewport.getPageIndex(), e); if (e instanceof RuntimeException) { throw (RuntimeException)e; } diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 4af703c12..d226cfb6c 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -25,6 +25,7 @@ import java.util.Set; import org.xml.sax.SAXException; import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.fo.extensions.ExternalDocument; import org.apache.fop.fo.flow.BasicLink; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.BlockContainer; @@ -557,5 +558,19 @@ public abstract class FOEventHandler { public void characters(char data[], int start, int length) { } + /** + * Process the start of the external-document extension. + * @param document the external-document node + */ + public void startExternalDocument(ExternalDocument document) { + } + + /** + * Process the end of the external-document extension. + * @param document the external-document node + */ + public void endExternalDocument(ExternalDocument document) { + } + } diff --git a/src/java/org/apache/fop/fo/GraphicsProperties.java b/src/java/org/apache/fop/fo/GraphicsProperties.java new file mode 100644 index 000000000..5cee68679 --- /dev/null +++ b/src/java/org/apache/fop/fo/GraphicsProperties.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo; + +import org.apache.fop.datatypes.Length; +import org.apache.fop.fo.properties.LengthRangeProperty; + +/** + * This interface provides access to properties necessary to calculate the size and positioning + * of images and graphics inside a viewport. + */ +public interface GraphicsProperties { + + /** + * @return the "inline-progression-dimension" property. + */ + LengthRangeProperty getInlineProgressionDimension(); + + /** + * @return the "block-progression-dimension" property. + */ + LengthRangeProperty getBlockProgressionDimension(); + + /** + * @return the "height" property. + */ + Length getHeight(); + + /** + * @return the "width" property. + */ + Length getWidth(); + + /** + * @return the "content-height" property. + */ + Length getContentHeight(); + + /** + * @return the "content-width" property. + */ + Length getContentWidth(); + + /** + * @return the "scaling" property. + */ + int getScaling(); + + /** + * @return the "overflow" property. + */ + int getOverflow(); + + /** + * @return the "display-align" property. + */ + int getDisplayAlign(); + + /** + * @return the "text-align" property. + */ + int getTextAlign(); + +} diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java index 6d4dbd43c..1de74e2f0 100644 --- a/src/java/org/apache/fop/fo/PropertyList.java +++ b/src/java/org/apache/fop/fo/PropertyList.java @@ -20,6 +20,8 @@ package org.apache.fop.fo; // Java +import java.text.MessageFormat; + import org.xml.sax.Attributes; import org.apache.commons.logging.Log; @@ -355,9 +357,9 @@ public abstract class PropertyList { if (propId == -1 || (subpropId == -1 && findSubPropertyName(propertyName) != null)) { - StringBuffer errorMessage = new StringBuffer().append( - "Invalid property name \'").append(propertyName); - handleInvalidProperty(errorMessage.toString(), propertyName); + String errorMessage = MessageFormat.format( + "Invalid property name ''{0}''.", new Object[] {propertyName}); + handleInvalidProperty(errorMessage, propertyName); return false; } return true; diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java index 989726d22..de1d019f4 100644 --- a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java +++ b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java @@ -62,6 +62,7 @@ public class ExtensionElementMapping extends ElementMapping { foObjs.put("outline", new UnknownXMLObj.Maker(URI)); foObjs.put("label", new UnknownXMLObj.Maker(URI)); foObjs.put("destination", new DestinationMaker()); + foObjs.put("external-document", new ExternalDocumentMaker()); } } @@ -71,6 +72,12 @@ public class ExtensionElementMapping extends ElementMapping { } } + static class ExternalDocumentMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new ExternalDocument(parent); + } + } + /** {@inheritDoc} */ public String getStandardPrefix() { return "fox"; diff --git a/src/java/org/apache/fop/fo/extensions/ExternalDocument.java b/src/java/org/apache/fop/fo/extensions/ExternalDocument.java new file mode 100644 index 000000000..b8707726f --- /dev/null +++ b/src/java/org/apache/fop/fo/extensions/ExternalDocument.java @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.extensions; + +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.datatypes.Length; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.GraphicsProperties; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.pagination.AbstractPageSequence; +import org.apache.fop.fo.properties.LengthRangeProperty; + +/** + * Class for the fox:external-document extenstion element. + */ +public class ExternalDocument extends AbstractPageSequence implements GraphicsProperties { + + // The value of properties relevant for fox:external-document + private LengthRangeProperty blockProgressionDimension; + private Length contentHeight; + private Length contentWidth; + private int displayAlign; + private Length height; + private LengthRangeProperty inlineProgressionDimension; + private int overflow; + private int scaling; + private String src; + private int textAlign; + private Length width; + // Unused but valid items, commented out for performance: + // private CommonAccessibility commonAccessibility; + // private CommonAural commonAural; + // private String contentType; + // private int scalingMethod; + // End of property values + + /** + * Constructs a ExternalDocument object (called by Maker). + * @param parent the parent formatting object + */ + public ExternalDocument(FONode parent) { + super(parent); + } + + /** {@inheritDoc} */ + public void bind(PropertyList pList) throws FOPException { + super.bind(pList); + blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange(); + contentHeight = pList.get(PR_CONTENT_HEIGHT).getLength(); + contentWidth = pList.get(PR_CONTENT_WIDTH).getLength(); + displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum(); + height = pList.get(PR_HEIGHT).getLength(); + inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange(); + overflow = pList.get(PR_OVERFLOW).getEnum(); + scaling = pList.get(PR_SCALING).getEnum(); + textAlign = pList.get(PR_TEXT_ALIGN).getEnum(); + width = pList.get(PR_WIDTH).getLength(); + src = pList.get(PR_SRC).getString(); + + if (this.src == null || this.src.length() == 0) { + missingPropertyError("src"); + } + } + + protected void startOfNode() throws FOPException { + super.startOfNode(); + getFOEventHandler().startExternalDocument(this); + } + + /** + * @see org.apache.fop.fo.FONode#endOfNode + */ + protected void endOfNode() throws FOPException { + getFOEventHandler().endExternalDocument(this); + super.endOfNode(); + } + + /** + * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String) + XSL/FOP: empty + */ + protected void validateChildNode(Locator loc, String nsURI, String localName) + throws ValidationException { + invalidChildError(loc, nsURI, localName); + } + + /** + * Returns the src attribute (the URI to the embedded document). + * @return the src attribute + */ + public String getSrc() { + return this.src; + } + + /** {@inheritDoc} */ + public LengthRangeProperty getInlineProgressionDimension() { + return inlineProgressionDimension; + } + + /** {@inheritDoc} */ + public LengthRangeProperty getBlockProgressionDimension() { + return blockProgressionDimension; + } + + /** {@inheritDoc} */ + public Length getHeight() { + return height; + } + + /** {@inheritDoc} */ + public Length getWidth() { + return width; + } + + /** {@inheritDoc} */ + public Length getContentHeight() { + return contentHeight; + } + + /** {@inheritDoc} */ + public Length getContentWidth() { + return contentWidth; + } + + /** {@inheritDoc} */ + public int getScaling() { + return scaling; + } + + /** {@inheritDoc} */ + public int getOverflow() { + return overflow; + } + + /** {@inheritDoc} */ + public int getDisplayAlign() { + return displayAlign; + } + + /** {@inheritDoc} */ + public int getTextAlign() { + return textAlign; + } + + /** @see org.apache.fop.fo.FONode#getNamespaceURI() */ + public String getNamespaceURI() { + return ExtensionElementMapping.URI; + } + + /** @see org.apache.fop.fo.FONode#getNormalNamespacePrefix() */ + public String getNormalNamespacePrefix() { + return "fox"; + } + + /** @see org.apache.fop.fo.FONode#getLocalName() */ + public String getLocalName() { + return "external-document"; + } + +} + diff --git a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java index 74b91eb53..a58cc08f2 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java +++ b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java @@ -23,6 +23,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.GraphicsProperties; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; @@ -32,7 +33,7 @@ import org.apache.fop.fo.properties.SpaceProperty; * Common base class for instream-foreign-object and external-graphics * flow formatting objects. */ -public abstract class AbstractGraphics extends FObj { +public abstract class AbstractGraphics extends FObj implements GraphicsProperties { // The value of properties relevant for fo:instream-foreign-object // and external-graphics. @@ -100,56 +101,6 @@ public abstract class AbstractGraphics extends FObj { width = pList.get(PR_WIDTH).getLength(); } - /** - * Given the ipd and the content width calculates the - * required x offset based on the text-align property - * @param ipd the inline-progression-dimension of the object - * @param cwidth the calculated content width of the object - * @return the X offset - */ - public int computeXOffset (int ipd, int cwidth) { - int xoffset = 0; - switch (textAlign) { - case EN_CENTER: - xoffset = (ipd - cwidth) / 2; - break; - case EN_END: - xoffset = ipd - cwidth; - break; - case EN_START: - break; - case EN_JUSTIFY: - default: - break; - } - return xoffset; - } - - /** - * Given the bpd and the content height calculates the - * required y offset based on the display-align property - * @param bpd the block-progression-dimension of the object - * @param cheight the calculated content height of the object - * @return the Y offset - */ - public int computeYOffset(int bpd, int cheight) { - int yoffset = 0; - switch (displayAlign) { - case EN_BEFORE: - break; - case EN_AFTER: - yoffset = bpd - cheight; - break; - case EN_CENTER: - yoffset = (bpd - cheight) / 2; - break; - case EN_AUTO: - default: - break; - } - return yoffset; - } - /** * @return the "id" property. */ @@ -171,16 +122,12 @@ public abstract class AbstractGraphics extends FObj { return lineHeight; } - /** - * @return the "inline-progression-dimension" property. - */ + /** {@inheritDoc} */ public LengthRangeProperty getInlineProgressionDimension() { return inlineProgressionDimension; } - /** - * @return the "block-progression-dimension" property. - */ + /** {@inheritDoc} */ public LengthRangeProperty getBlockProgressionDimension() { return blockProgressionDimension; } @@ -199,34 +146,36 @@ public abstract class AbstractGraphics extends FObj { return width; } - /** - * @return the "content-height" property. - */ + /** {@inheritDoc} */ public Length getContentHeight() { return contentHeight; } - /** - * @return the "content-width" property. - */ + /** {@inheritDoc} */ public Length getContentWidth() { return contentWidth; } - /** - * @return the "scaling" property. - */ + /** {@inheritDoc} */ public int getScaling() { return scaling; } - /** - * @return the "overflow" property. - */ + /** {@inheritDoc} */ public int getOverflow() { return overflow; } + /** {@inheritDoc} */ + public int getDisplayAlign() { + return displayAlign; + } + + /** {@inheritDoc} */ + public int getTextAlign() { + return textAlign; + } + /** * @return the "alignment-adjust" property */ diff --git a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java new file mode 100644 index 000000000..70a09b720 --- /dev/null +++ b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.pagination; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.datatypes.Numeric; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.PropertyList; + +/** + * Abstract base class for the fo:page-sequence formatting object and the fox:external-document + * extension object. + */ +public abstract class AbstractPageSequence extends FObj { + + // The value of properties relevant for fo:page-sequence. + protected Numeric initialPageNumber; + protected int forcePageCount; + private String format; + private int letterValue; + private char groupingSeparator; + private int groupingSize; + private Numeric referenceOrientation; //XSL 1.1 + // End of property values + + private PageNumberGenerator pageNumberGenerator; + + protected int startingPageNumber = 0; + + /** + * Create a page sequence FO node. + * + * @param parent the parent FO node + */ + public AbstractPageSequence(FONode parent) { + super(parent); + } + + /** + * @see org.apache.fop.fo.FObj#bind(PropertyList) + */ + public void bind(PropertyList pList) throws FOPException { + super.bind(pList); + initialPageNumber = pList.get(PR_INITIAL_PAGE_NUMBER).getNumeric(); + forcePageCount = pList.get(PR_FORCE_PAGE_COUNT).getEnum(); + format = pList.get(PR_FORMAT).getString(); + letterValue = pList.get(PR_LETTER_VALUE).getEnum(); + groupingSeparator = pList.get(PR_GROUPING_SEPARATOR).getCharacter(); + groupingSize = pList.get(PR_GROUPING_SIZE).getNumber().intValue(); + referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); + } + + /** + * @see org.apache.fop.fo.FONode#startOfNode() + */ + protected void startOfNode() throws FOPException { + this.pageNumberGenerator = new PageNumberGenerator( + format, groupingSeparator, groupingSize, letterValue); + + } + + /** @see org.apache.fop.fo.FONode#endOfNode() */ + protected void endOfNode() throws FOPException { + } + + /** + * Initialize the current page number for the start of the page sequence. + */ + public void initPageNumber() { + int pageNumberType = 0; + + if (initialPageNumber.getEnum() != 0) { + // auto | auto-odd | auto-even. + startingPageNumber = getRoot().getEndingPageNumberOfPreviousSequence() + 1; + pageNumberType = initialPageNumber.getEnum(); + if (pageNumberType == EN_AUTO_ODD) { + if (startingPageNumber % 2 == 0) { + startingPageNumber++; + } + } else if (pageNumberType == EN_AUTO_EVEN) { + if (startingPageNumber % 2 == 1) { + startingPageNumber++; + } + } + } else { // for explicit page number + int pageStart = initialPageNumber.getValue(); + startingPageNumber = (pageStart > 0) ? pageStart : 1; // spec rule + } + } + + /** + * Get the starting page number for this page sequence. + * + * @return the starting page number + */ + public int getStartingPageNumber() { + return startingPageNumber; + } + + /** + * Retrieves the string representation of a page number applicable + * for this page sequence + * @param pageNumber the page number + * @return string representation of the page number + */ + public String makeFormattedPageNumber(int pageNumber) { + return pageNumberGenerator.makeFormattedPageNumber(pageNumber); + } + + /** + * Public accessor for the ancestor Root. + * @return the ancestor Root + */ + public Root getRoot() { + return (Root)this.getParent(); + } + + /** @return the force-page-count value */ + public int getForcePageCount() { + return forcePageCount; + } + + /** @return the initial-page-number property value */ + public Numeric getInitialPageNumber() { + return initialPageNumber; + } + + /** + * @return the "reference-orientation" property. + * @since XSL 1.1 + */ + public int getReferenceOrientation() { + return referenceOrientation.getValue(); + } + +} diff --git a/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java b/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java index c3d705de2..dfb4ba70b 100644 --- a/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java @@ -93,14 +93,20 @@ public class ConditionalPageMasterReference extends FObj { * @param isFirstPage True if page is first page * @param isLastPage True if page is last page * @param isBlankPage True if page is blank + * @param isOnlyPage True if page is the only page * @return True if the conditions for this reference are met */ protected boolean isValid(boolean isOddPage, boolean isFirstPage, boolean isLastPage, + boolean isOnlyPage, boolean isBlankPage) { // page-position - if (isFirstPage) { + if (isOnlyPage) { + if (pagePosition != EN_ONLY) { + return false; + } + } else if (isFirstPage) { if (pagePosition == EN_REST) { return false; } else if (pagePosition == EN_LAST) { diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java index f8f9f9277..91649fbc5 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java @@ -25,32 +25,22 @@ import java.util.Map; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; -import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Implementation of the fo:page-sequence formatting object. + * Abstract base implementation for page sequences. */ -public class PageSequence extends FObj { +public class PageSequence extends AbstractPageSequence { // The value of properties relevant for fo:page-sequence. private String country; - private String format; private String language; - private int letterValue; - private char groupingSeparator; - private int groupingSize; - private Numeric initialPageNumber; - private int forcePageCount; private String masterReference; + //private int writingMode; //XSL 1.1 // End of property values - /** The parent root object */ - private Root root; - // There doesn't seem to be anything in the spec requiring flows // to be in the order given, only that they map to the regions // defined in the page sequence, so all we need is this one hashmap @@ -59,9 +49,6 @@ public class PageSequence extends FObj { /** Map of flows to their flow name (flow-name, Flow) */ private Map flowMap; - private int startingPageNumber = 0; - private PageNumberGenerator pageNumberGenerator; - /** * The currentSimplePageMaster is either the page master for the * whole page sequence if master-reference refers to a simple-page-master, @@ -97,14 +84,9 @@ public class PageSequence extends FObj { public void bind(PropertyList pList) throws FOPException { super.bind(pList); country = pList.get(PR_COUNTRY).getString(); - format = pList.get(PR_FORMAT).getString(); language = pList.get(PR_LANGUAGE).getString(); - letterValue = pList.get(PR_LETTER_VALUE).getEnum(); - groupingSeparator = pList.get(PR_GROUPING_SEPARATOR).getCharacter(); - groupingSize = pList.get(PR_GROUPING_SIZE).getNumber().intValue(); - initialPageNumber = pList.get(PR_INITIAL_PAGE_NUMBER).getNumeric(); - forcePageCount = pList.get(PR_FORCE_PAGE_COUNT).getEnum(); masterReference = pList.get(PR_MASTER_REFERENCE).getString(); + //writingMode = pList.getWritingMode(); if (masterReference == null || masterReference.equals("")) { missingPropertyError("master-reference"); @@ -116,13 +98,12 @@ public class PageSequence extends FObj { */ protected void startOfNode() throws FOPException { super.startOfNode(); - this.root = (Root) parent; flowMap = new java.util.HashMap(); - this.simplePageMaster = root.getLayoutMasterSet().getSimplePageMaster(masterReference); + this.simplePageMaster = getRoot().getLayoutMasterSet().getSimplePageMaster(masterReference); if (this.simplePageMaster == null) { this.pageSequenceMaster - = root.getLayoutMasterSet().getPageSequenceMaster(masterReference); + = getRoot().getLayoutMasterSet().getPageSequenceMaster(masterReference); if (this.pageSequenceMaster == null) { throw new ValidationException("master-reference '" + masterReference + "' for fo:page-sequence matches no" @@ -130,9 +111,6 @@ public class PageSequence extends FObj { } } - this.pageNumberGenerator = new PageNumberGenerator( - format, groupingSeparator, groupingSize, letterValue); - getFOEventHandler().startPageSequence(this); } @@ -211,7 +189,7 @@ public class PageSequence extends FObj { + "\" found within fo:page-sequence", flow.getLocator()); } - if (!root.getLayoutMasterSet().regionNameExists(flowName) + if (!getRoot().getLayoutMasterSet().regionNameExists(flowName) && !flowName.equals("xsl-before-float-separator") && !flowName.equals("xsl-footnote-separator")) { throw new ValidationException("flow-name \"" @@ -221,31 +199,6 @@ public class PageSequence extends FObj { } } - /** - * Initialize the current page number for the start of the page sequence. - */ - public void initPageNumber() { - int pageNumberType = 0; - - if (initialPageNumber.getEnum() != 0) { - // auto | auto-odd | auto-even. - startingPageNumber = root.getEndingPageNumberOfPreviousSequence() + 1; - pageNumberType = initialPageNumber.getEnum(); - if (pageNumberType == EN_AUTO_ODD) { - if (startingPageNumber % 2 == 0) { - startingPageNumber++; - } - } else if (pageNumberType == EN_AUTO_EVEN) { - if (startingPageNumber % 2 == 1) { - startingPageNumber++; - } - } - } else { // for explicit page number - int pageStart = initialPageNumber.getValue(); - startingPageNumber = (pageStart > 0) ? pageStart : 1; // spec rule - } - } - // /** // * Returns true when there is more flow elements left to lay out. // */ @@ -306,15 +259,6 @@ public class PageSequence extends FObj { // return false; // } - /** - * Get the starting page number for this page sequence. - * - * @return the starting page number - */ - public int getStartingPageNumber() { - return startingPageNumber; - } - // private void forcePage(AreaTree areaTree, int firstAvailPageNumber) { // boolean makePage = false; // if (this.forcePageCount == ForcePageCount.AUTO) { @@ -433,6 +377,8 @@ public class PageSequence extends FObj { * page sequence * @param isLastPage indicator whether this page is the last page of the * page sequence + * @param isOnlyPage indicator whether this page is the only page of the + * page sequence * @param isBlank indicator whether the page will be blank * @return the SimplePageMaster to use for this page * @throws FOPException if there's a problem determining the page master @@ -440,6 +386,7 @@ public class PageSequence extends FObj { public SimplePageMaster getNextSimplePageMaster(int page, boolean isFirstPage, boolean isLastPage, + boolean isOnlyPage, boolean isBlank) throws FOPException { if (pageSequenceMaster == null) { @@ -450,11 +397,12 @@ public class PageSequence extends FObj { log.debug("getNextSimplePageMaster(page=" + page + " isOdd=" + isOddPage + " isFirst=" + isFirstPage - + " isLast=" + isLastPage + + " isLast=" + isLastPage + + " isOnly=" + isOnlyPage + " isBlank=" + isBlank + ")"); } return pageSequenceMaster.getNextSimplePageMaster(isOddPage, - isFirstPage, isLastPage, isBlank); + isFirstPage, isLastPage, isOnlyPage, isBlank); } /** @@ -478,24 +426,15 @@ public class PageSequence extends FObj { } } - /** - * Retrieves the string representation of a page number applicable - * for this page sequence - * @param pageNumber the page number - * @return string representation of the page number - */ - public String makeFormattedPageNumber(int pageNumber) { - return pageNumberGenerator.makeFormattedPageNumber(pageNumber); - } - - /** - * Public accessor for the ancestor Root. - * @return the ancestor Root - */ - public Root getRoot() { - return root; + /** @return true if the page-sequence has a page-master with page-position="only" */ + public boolean hasPagePositionOnly() { + if (pageSequenceMaster == null) { + return false; + } else { + return pageSequenceMaster.hasPagePositionOnly(); + } } - + /** @return the "master-reference" property. */ public String getMasterReference() { return masterReference; @@ -511,16 +450,6 @@ public class PageSequence extends FObj { return FO_PAGE_SEQUENCE; } - /** @return the force-page-count value */ - public int getForcePageCount() { - return forcePageCount; - } - - /** @return the initial-page-number property value */ - public Numeric getInitialPageNumber() { - return initialPageNumber; - } - /** @return the country property value */ public String getCountry() { return this.country; diff --git a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java index fd3484ee6..34ad299bd 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java @@ -171,11 +171,21 @@ public class PageSequenceMaster extends FObj { } } + /** @return true if the page-sequence-master has a page-master with page-position="only" */ + public boolean hasPagePositionOnly() { + if (currentSubSequence != null) { + return currentSubSequence.hasPagePositionOnly(); + } else { + return false; + } + } + /** * Returns the next simple-page-master. * @param isOddPage True if the next page number is odd * @param isFirstPage True if the next page is the first * @param isLastPage True if the next page is the last + * @param isOnlyPage True if the next page is the only page * @param isBlankPage True if the next page is blank * @return the requested page master * @throws FOPException if there's a problem determining the next page master @@ -183,6 +193,7 @@ public class PageSequenceMaster extends FObj { public SimplePageMaster getNextSimplePageMaster(boolean isOddPage, boolean isFirstPage, boolean isLastPage, + boolean isOnlyPage, boolean isBlankPage) throws FOPException { if (currentSubSequence == null) { @@ -193,7 +204,7 @@ public class PageSequenceMaster extends FObj { } } String pageMasterName = currentSubSequence - .getNextPageMasterName(isOddPage, isFirstPage, isLastPage, isBlankPage); + .getNextPageMasterName(isOddPage, isFirstPage, isLastPage, isOnlyPage, isBlankPage); boolean canRecover = true; while (pageMasterName == null) { SubSequenceSpecifier nextSubSequence = getNextSubSequence(); @@ -212,7 +223,7 @@ public class PageSequenceMaster extends FObj { currentSubSequence = nextSubSequence; } pageMasterName = currentSubSequence - .getNextPageMasterName(isOddPage, isFirstPage, isLastPage, isBlankPage); + .getNextPageMasterName(isOddPage, isFirstPage, isLastPage, isOnlyPage, isBlankPage); } SimplePageMaster pageMaster = this.layoutMasterSet .getSimplePageMaster(pageMasterName); diff --git a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java index 012abd11a..9d2fe652c 100644 --- a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java +++ b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java @@ -49,6 +49,7 @@ public class RepeatablePageMasterAlternatives extends FObj private List conditionalPageMasterRefs; private boolean hasPagePositionLast = false; + private boolean hasPagePositionOnly = false; /** * @see org.apache.fop.fo.FONode#FONode(FONode) @@ -124,6 +125,7 @@ public class RepeatablePageMasterAlternatives extends FObj public String getNextPageMasterName(boolean isOddPage, boolean isFirstPage, boolean isLastPage, + boolean isOnlyPage, boolean isBlankPage) { if (getMaximumRepeats() != INFINITE) { if (numberConsumed < getMaximumRepeats()) { @@ -138,7 +140,7 @@ public class RepeatablePageMasterAlternatives extends FObj for (int i = 0; i < conditionalPageMasterRefs.size(); i++) { ConditionalPageMasterReference cpmr = (ConditionalPageMasterReference)conditionalPageMasterRefs.get(i); - if (cpmr.isValid(isOddPage, isFirstPage, isLastPage, isBlankPage)) { + if (cpmr.isValid(isOddPage, isFirstPage, isLastPage, isOnlyPage, isBlankPage)) { return cpmr.getMasterReference(); } } @@ -155,6 +157,9 @@ public class RepeatablePageMasterAlternatives extends FObj if (cpmr.getPagePosition() == EN_LAST) { this.hasPagePositionLast = true; } + if (cpmr.getPagePosition() == EN_ONLY) { + this.hasPagePositionOnly = true; + } } /** {@inheritDoc} */ @@ -178,6 +183,12 @@ public class RepeatablePageMasterAlternatives extends FObj } /** {@inheritDoc} */ + /** @see org.apache.fop.fo.pagination.SubSequenceSpecifier#hasPagePositionOnly() */ + public boolean hasPagePositionOnly() { + return this.hasPagePositionOnly; + } + + /** @see org.apache.fop.fo.FONode#getLocalName() */ public String getLocalName() { return "repeatable-page-master-alternatives"; } diff --git a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java index dfd6ff6a9..172324232 100644 --- a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java @@ -93,6 +93,7 @@ public class RepeatablePageMasterReference extends FObj public String getNextPageMasterName(boolean isOddPage, boolean isFirstPage, boolean isLastPage, + boolean isOnlyPage, boolean isEmptyPage) { if (getMaximumRepeats() != INFINITE) { if (numberConsumed < getMaximumRepeats()) { @@ -140,6 +141,11 @@ public class RepeatablePageMasterReference extends FObj return false; } + /** {@inheritDoc} */ + public boolean hasPagePositionOnly() { + return false; + } + /** {@inheritDoc} */ public String getLocalName() { return "repeatable-page-master-reference"; @@ -150,4 +156,5 @@ public class RepeatablePageMasterReference extends FObj return FO_REPEATABLE_PAGE_MASTER_REFERENCE; } + } diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java index 2e2c38b82..139f7606a 100644 --- a/src/java/org/apache/fop/fo/pagination/Root.java +++ b/src/java/org/apache/fop/fo/pagination/Root.java @@ -25,6 +25,7 @@ import java.util.List; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; @@ -85,7 +86,7 @@ public class Root extends FObj { protected void endOfNode() throws FOPException { if (!pageSequenceFound || layoutMasterSet == null) { missingChildElementError("(layout-master-set, declarations?, " + - "bookmark-tree?, page-sequence+)"); + "bookmark-tree?, (page-sequence+|fox:external-document))"); } } @@ -129,7 +130,21 @@ public class Root extends FObj { invalidChildError(loc, nsURI, localName); } } else { - invalidChildError(loc, nsURI, localName); + if (FOX_URI.equals(nsURI)) { + if ("external-document".equals(localName)) { + pageSequenceFound = true; + } + } + //invalidChildError(loc, nsURI, localName); + //Ignore non-FO elements under root + } + } + + + /** @inheritDoc */ + protected void validateChildNode(Locator loc, FONode child) throws ValidationException { + if (child instanceof AbstractPageSequence) { + pageSequenceFound = true; } } diff --git a/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java b/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java index 68be2b82e..43d8e40dc 100644 --- a/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java @@ -85,6 +85,7 @@ public class SinglePageMasterReference extends FObj public String getNextPageMasterName(boolean isOddPage, boolean isFirstPage, boolean isLastPage, + boolean isOnlyPage, boolean isEmptyPage) { if (this.state == FIRST) { this.state = DONE; @@ -116,6 +117,11 @@ public class SinglePageMasterReference extends FObj return false; } + /** {@inheritDoc} */ + public boolean hasPagePositionOnly() { + return false; + } + /** {@inheritDoc} */ public String getLocalName() { return "single-page-master-reference"; @@ -125,5 +131,6 @@ public class SinglePageMasterReference extends FObj public int getNameId() { return FO_SINGLE_PAGE_MASTER_REFERENCE; } + } diff --git a/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java b/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java index af045624e..5da4945f1 100644 --- a/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java +++ b/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java @@ -32,6 +32,7 @@ public interface SubSequenceSpecifier { * @param isOddPage True if the next page number is odd * @param isFirstPage True if the next page is the first * @param isLastPage True if the next page is the last + * @param isOnlyPage True if the next page is the only page * @param isBlankPage True if the next page is blank * @return the page master name * @throws FOPException if there's a problem determining the next page master @@ -39,6 +40,7 @@ public interface SubSequenceSpecifier { String getNextPageMasterName(boolean isOddPage, boolean isFirstPage, boolean isLastPage, + boolean isOnlyPage, boolean isBlankPage) throws FOPException; @@ -57,5 +59,8 @@ public interface SubSequenceSpecifier { /** @return true if the subsequence has a page master for page-position "last" */ boolean hasPagePositionLast(); + /** @return true if the subsequence has a page master for page-position "only" */ + boolean hasPagePositionOnly(); + } diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index f0365d0e4..f75fffc0d 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -224,9 +224,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager return newLMs; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public PageSequenceLayoutManager getPSLM() { return parentLM.getPSLM(); } diff --git a/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java new file mode 100644 index 000000000..2b61fb6c6 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java @@ -0,0 +1,385 @@ +/* + * 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.layoutmgr; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.area.AreaTreeHandler; +import org.apache.fop.area.AreaTreeModel; +import org.apache.fop.area.IDTracker; +import org.apache.fop.area.PageViewport; +import org.apache.fop.area.Resolvable; +import org.apache.fop.datatypes.Numeric; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.flow.Marker; +import org.apache.fop.fo.flow.RetrieveMarker; +import org.apache.fop.fo.pagination.AbstractPageSequence; + +/** + * Abstract base class for a page sequence layout manager. + */ +public abstract class AbstractPageSequenceLayoutManager extends AbstractLayoutManager + implements TopLevelLayoutManager { + + private static Log log = LogFactory.getLog(AbstractPageSequenceLayoutManager.class); + + /** + * AreaTreeHandler which activates the PSLM and controls + * the rendering of its pages. + */ + protected AreaTreeHandler areaTreeHandler; + + /** ID tracker supplied by the AreaTreeHandler */ + protected IDTracker idTracker; + + /** page sequence formatting object being processed by this class */ + protected AbstractPageSequence pageSeq; + + /** Current page with page-viewport-area being filled by the PSLM. */ + protected Page curPage; + + /** the current page number */ + protected int currentPageNum = 0; + /** The stating page number */ + protected int startPageNum = 0; + + /** + * Constructor + * + * @param ath the area tree handler object + * @param pseq fo:page-sequence to process + */ + public AbstractPageSequenceLayoutManager(AreaTreeHandler ath, AbstractPageSequence pseq) { + super(pseq); + this.areaTreeHandler = ath; + this.idTracker = ath.getIDTracker(); + this.pageSeq = pseq; + } + + /** + * @return the LayoutManagerMaker object associated to the areaTreeHandler + */ + public LayoutManagerMaker getLayoutManagerMaker() { + return areaTreeHandler.getLayoutManagerMaker(); + } + + /** + * Provides access to the current page. + * @return the current Page + */ + public Page getCurrentPage() { + return curPage; + } + + /** + * Provides access for setting the current page. + * @param currentPage the new current Page + */ + protected void setCurrentPage(Page currentPage) { + this.curPage = currentPage; + } + + /** + * Provides access to the current page number + * @return the current page number + */ + protected int getCurrentPageNum() { + return currentPageNum; + } + + /** {@inheritDoc} */ + public void initialize() { + startPageNum = pageSeq.getStartingPageNumber(); + currentPageNum = startPageNum - 1; + } + + /** + * This returns the first PageViewport that contains an id trait + * matching the idref argument, or null if no such PV exists. + * + * @param idref the idref trait needing to be resolved + * @return the first PageViewport that contains the ID trait + */ + public PageViewport getFirstPVWithID(String idref) { + List list = idTracker.getPageViewportsContainingID(idref); + if (list != null && list.size() > 0) { + return (PageViewport) list.get(0); + } + return null; + } + + /** + * This returns the last PageViewport that contains an id trait + * matching the idref argument, or null if no such PV exists. + * + * @param idref the idref trait needing to be resolved + * @return the last PageViewport that contains the ID trait + */ + public PageViewport getLastPVWithID(String idref) { + List list = idTracker.getPageViewportsContainingID(idref); + if (list != null && list.size() > 0) { + return (PageViewport) list.get(list.size() - 1); + } + return null; + } + + /** + * Add an ID reference to the current page. + * When adding areas the area adds its ID reference. + * For the page layout manager it adds the id reference + * with the current page to the area tree. + * + * @param id the ID reference to add + */ + public void addIDToPage(String id) { + if (id != null && id.length() > 0) { + idTracker.associateIDWithPageViewport(id, curPage.getPageViewport()); + } + } + + /** + * Add an id reference of the layout manager in the AreaTreeHandler, + * if the id hasn't been resolved yet + * @param id the id to track + * @return a boolean indicating if the id has already been resolved + * TODO Maybe give this a better name + */ + public boolean associateLayoutManagerID(String id) { + if (log.isDebugEnabled()) { + log.debug("associateLayoutManagerID(" + id + ")"); + } + if (!idTracker.alreadyResolvedID(id)) { + idTracker.signalPendingID(id); + return false; + } else { + return true; + } + } + + /** + * Notify the areaTreeHandler that the LayoutManagers containing + * idrefs have finished creating areas + * @param id the id for which layout has finished + */ + public void notifyEndOfLayout(String id) { + idTracker.signalIDProcessed(id); + } + + /** + * Identify an unresolved area (one needing an idref to be + * resolved, e.g. the internal-destination of an fo:basic-link) + * for both the AreaTreeHandler and PageViewport object. + * + * The IDTracker keeps a document-wide list of idref's + * and the PV's needing them to be resolved. It uses this to + * send notifications to the PV's when an id has been resolved. + * + * The PageViewport keeps lists of id's needing resolving, along + * with the child areas (page-number-citation, basic-link, etc.) + * of the PV needing their resolution. + * + * @param id the ID reference to add + * @param res the resolvable object that needs resolving + */ + public void addUnresolvedArea(String id, Resolvable res) { + curPage.getPageViewport().addUnresolvedIDRef(id, res); + idTracker.addUnresolvedIDRef(id, curPage.getPageViewport()); + } + + /** + * Bind the RetrieveMarker to the corresponding Marker subtree. + * If the boundary is page then it will only check the + * current page. For page-sequence and document it will + * lookup preceding pages from the area tree and try to find + * a marker. + * If we retrieve a marker from a preceding page, + * then the containing page does not have a qualifying area, + * and all qualifying areas have ended. + * Therefore we use last-ending-within-page (Constants.EN_LEWP) + * as the position. + * + * @param rm the RetrieveMarker instance whose properties are to + * used to find the matching Marker. + * @return a bound RetrieveMarker instance, or null if no Marker + * could be found. + */ + public RetrieveMarker resolveRetrieveMarker(RetrieveMarker rm) { + AreaTreeModel areaTreeModel = areaTreeHandler.getAreaTreeModel(); + String name = rm.getRetrieveClassName(); + int pos = rm.getRetrievePosition(); + int boundary = rm.getRetrieveBoundary(); + + // get marker from the current markers on area tree + Marker mark = (Marker)getCurrentPV().getMarker(name, pos); + if (mark == null && boundary != EN_PAGE) { + // go back over pages until mark found + // if document boundary then keep going + boolean doc = boundary == EN_DOCUMENT; + int seq = areaTreeModel.getPageSequenceCount(); + int page = areaTreeModel.getPageCount(seq) - 1; + while (page < 0 && doc && seq > 1) { + seq--; + page = areaTreeModel.getPageCount(seq) - 1; + } + while (page >= 0) { + PageViewport pv = areaTreeModel.getPage(seq, page); + mark = (Marker)pv.getMarker(name, Constants.EN_LEWP); + if (mark != null) { + break; + } + page--; + if (page < 0 && doc && seq > 1) { + seq--; + page = areaTreeModel.getPageCount(seq) - 1; + } + } + } + + if (mark == null) { + log.debug("found no marker with name: " + name); + return null; + } else { + rm.bindMarker(mark); + return rm; + } + } + + /** + * Creates and returns a new page. + * @param pageNumber the page number + * @param isBlank true if it's a blank page + * @return the newly created page + */ + protected abstract Page createPage(int pageNumber, boolean isBlank); + + /** + * Makes a new page + * + * @param bIsBlank whether this page is blank or not + * @param bIsLast whether this page is the last page or not + * @return a new page + */ + protected Page makeNewPage(boolean isBlank, boolean isLast) { + if (curPage != null) { + finishPage(); + } + + currentPageNum++; + + curPage = createPage(currentPageNum, isBlank); + + if (log.isDebugEnabled()) { + log.debug("[" + curPage.getPageViewport().getPageNumberString() + + (isBlank ? "*" : "") + "]"); + } + + addIDToPage(pageSeq.getId()); + return curPage; + } + + /** + * Finishes a page in preparation for a new page. + */ + protected void finishPage() { + if (log.isTraceEnabled()) { + curPage.getPageViewport().dumpMarkers(); + } + + // Try to resolve any unresolved IDs for the current page. + // + idTracker.tryIDResolution(curPage.getPageViewport()); + // Queue for ID resolution and rendering + areaTreeHandler.getAreaTreeModel().addPage(curPage.getPageViewport()); + if (log.isDebugEnabled()) { + log.debug("page finished: " + curPage.getPageViewport().getPageNumberString() + + ", current num: " + currentPageNum); + } + curPage = null; + } + + /** {@inheritDoc} */ + public void doForcePageCount(Numeric nextPageSeqInitialPageNumber) { + + int forcePageCount = pageSeq.getForcePageCount(); + + // xsl-spec version 1.0 (15.oct 2001) + // auto | even | odd | end-on-even | end-on-odd | no-force | inherit + // auto: + // Force the last page in this page-sequence to be an odd-page + // if the initial-page-number of the next page-sequence is even. + // Force it to be an even-page + // if the initial-page-number of the next page-sequence is odd. + // If there is no next page-sequence + // or if the value of its initial-page-number is "auto" do not force any page. + + // if force-page-count is auto then set the value of forcePageCount + // depending on the initial-page-number of the next page-sequence + if (nextPageSeqInitialPageNumber != null && forcePageCount == Constants.EN_AUTO) { + if (nextPageSeqInitialPageNumber.getEnum() != 0) { + // auto | auto-odd | auto-even + int nextPageSeqPageNumberType = nextPageSeqInitialPageNumber.getEnum(); + if (nextPageSeqPageNumberType == Constants.EN_AUTO_ODD) { + forcePageCount = Constants.EN_END_ON_EVEN; + } else if (nextPageSeqPageNumberType == Constants.EN_AUTO_EVEN) { + forcePageCount = Constants.EN_END_ON_ODD; + } else { // auto + forcePageCount = Constants.EN_NO_FORCE; + } + } else { // for explicit page number + int nextPageSeqPageStart = nextPageSeqInitialPageNumber.getValue(); + // spec rule + nextPageSeqPageStart = (nextPageSeqPageStart > 0) ? nextPageSeqPageStart : 1; + if (nextPageSeqPageStart % 2 == 0) { // explicit even startnumber + forcePageCount = Constants.EN_END_ON_ODD; + } else { // explicit odd startnumber + forcePageCount = Constants.EN_END_ON_EVEN; + } + } + } + + if (forcePageCount == Constants.EN_EVEN) { + if ((currentPageNum - startPageNum + 1) % 2 != 0) { // we have an odd number of pages + curPage = makeNewPage(true, false); + } + } else if (forcePageCount == Constants.EN_ODD) { + if ((currentPageNum - startPageNum + 1) % 2 == 0) { // we have an even number of pages + curPage = makeNewPage(true, false); + } + } else if (forcePageCount == Constants.EN_END_ON_EVEN) { + if (currentPageNum % 2 != 0) { // we are now on an odd page + curPage = makeNewPage(true, false); + } + } else if (forcePageCount == Constants.EN_END_ON_ODD) { + if (currentPageNum % 2 == 0) { // we are now on an even page + curPage = makeNewPage(true, false); + } + } else if (forcePageCount == Constants.EN_NO_FORCE) { + // i hope: nothing special at all + } + + if (curPage != null) { + finishPage(); + } + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java new file mode 100644 index 000000000..5668f81ef --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java @@ -0,0 +1,202 @@ +/* + * 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.layoutmgr; + +import java.awt.Dimension; +import java.awt.Rectangle; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.area.AreaTreeHandler; +import org.apache.fop.area.Block; +import org.apache.fop.area.BodyRegion; +import org.apache.fop.area.CTM; +import org.apache.fop.area.LineArea; +import org.apache.fop.area.PageViewport; +import org.apache.fop.area.RegionViewport; +import org.apache.fop.area.inline.Image; +import org.apache.fop.area.inline.Viewport; +import org.apache.fop.datatypes.FODimension; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.extensions.ExternalDocument; +import org.apache.fop.image.FopImage; +import org.apache.fop.image.ImageFactory; +import org.apache.fop.layoutmgr.inline.ImageLayout; + +/** + * LayoutManager for an external-document extension element. This class is instantiated by + * area.AreaTreeHandler for each fo:external-document found in the + * input document. + */ +public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutManager { + + private static Log log = LogFactory.getLog(ExternalDocumentLayoutManager.class); + + private FopImage image; + private ImageLayout imageLayout; + + /** + * Constructor + * + * @param ath the area tree handler object + * @param pseq fo:page-sequence to process + */ + public ExternalDocumentLayoutManager(AreaTreeHandler ath, ExternalDocument document) { + super(ath, document); + } + + /** + * @return the ExternalDocument being managed by this layout manager + */ + protected ExternalDocument getExternalDocument() { + return (ExternalDocument)pageSeq; + } + + /** {@inheritDoc} */ + public PageSequenceLayoutManager getPSLM() { + throw new IllegalStateException("getPSLM() is illegal for " + getClass().getName()); + } + + /** {@inheritDoc} */ + public void activateLayout() { + initialize(); + + String uri = getExternalDocument().getSrc(); + FOUserAgent userAgent = pageSeq.getUserAgent(); + ImageFactory fact = userAgent.getFactory().getImageFactory(); + this.image = fact.getImage(uri, userAgent); + if (this.image == null) { + log.error("Image not available: " + uri); + return; + } else { + // load dimensions + if (!this.image.load(FopImage.DIMENSIONS)) { + log.error("Cannot read image dimensions: " + uri); + return; + } + } + Dimension intrinsicSize = new Dimension( + image.getIntrinsicWidth(), + image.getIntrinsicHeight()); + this.imageLayout = new ImageLayout(getExternalDocument(), this, intrinsicSize); + + areaTreeHandler.getAreaTreeModel().startPageSequence(null); + if (log.isDebugEnabled()) { + log.debug("Starting layout"); + } + + curPage = makeNewPage(false, false); + + fillPage(); //TODO Implement multi-page documents (using new image package) + + finishPage(); + } + + private void fillPage() { + + Dimension imageSize = this.imageLayout.getViewportSize(); + + Block blockArea = new Block(); + blockArea.setIPD(imageSize.width); + LineArea lineArea = new LineArea(); + + Image imageArea = new Image(getExternalDocument().getSrc()); + TraitSetter.setProducerID(imageArea, fobj.getId()); + transferForeignAttributes(imageArea); + + Viewport vp = new Viewport(imageArea); + TraitSetter.setProducerID(vp, fobj.getId()); + vp.setIPD(imageSize.width); + vp.setBPD(imageSize.height); + vp.setContentPosition(imageLayout.getPlacement()); + vp.setOffset(0); + + //Link them all together... + lineArea.addInlineArea(vp); + lineArea.updateExtentsFromChildren(); + blockArea.addLineArea(lineArea); + curPage.getPageViewport().getCurrentFlow().addBlock(blockArea); + curPage.getPageViewport().getCurrentSpan().notifyFlowsFinished(); + } + + /** {@inheritDoc} */ + public void finishPageSequence() { + if (pageSeq.hasId()) { + idTracker.signalIDProcessed(pageSeq.getId()); + } + + pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum, + (currentPageNum - startPageNum) + 1); + areaTreeHandler.notifyPageSequenceFinished(pageSeq, + (currentPageNum - startPageNum) + 1); + + if (log.isDebugEnabled()) { + log.debug("Ending layout"); + } + } + + protected Page createPage(int pageNumber, boolean isBlank) { + String pageNumberString = pageSeq.makeFormattedPageNumber(pageNumber); + + Dimension imageSize = this.imageLayout.getViewportSize(); + + // Set up the CTM on the page reference area based on writing-mode + // and reference-orientation + Rectangle referenceRect; + if (pageSeq.getReferenceOrientation() % 180 == 0) { + referenceRect = new Rectangle(0, 0, imageSize.width, imageSize.height); + } else { + referenceRect = new Rectangle(0, 0, imageSize.height, imageSize.width); + } + FODimension reldims = new FODimension(0, 0); + CTM pageCTM = CTM.getCTMandRelDims(pageSeq.getReferenceOrientation(), + Constants.EN_LR_TB, referenceRect, reldims); + + Page page = new Page(referenceRect, pageNumber, pageNumberString, isBlank); + + PageViewport pv = page.getPageViewport(); + org.apache.fop.area.Page pageArea = new org.apache.fop.area.Page(); + pv.setPage(pageArea); + + RegionViewport rv = new RegionViewport(referenceRect); + rv.setIPD(referenceRect.width); + rv.setBPD(referenceRect.height); + rv.setClip(true); + + BodyRegion body = new BodyRegion(Constants.FO_REGION_BODY, + "fop-image-region", rv, 1, 0); + body.setIPD(imageSize.width); + body.setBPD(imageSize.height); + body.setCTM(pageCTM); + rv.setRegionReference(body); + pageArea.setRegionViewport( + Constants.FO_REGION_BODY, rv); + //Set unique key obtained from the AreaTreeHandler + pv.setKey(areaTreeHandler.generatePageViewportKey()); + + //Also creates first normal flow region + pv.createSpan(false); + + return page; + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMaker.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMaker.java index b56aed866..abb7f0f04 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMaker.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMaker.java @@ -20,6 +20,7 @@ package org.apache.fop.layoutmgr; import java.util.List; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.extensions.ExternalDocument; import org.apache.fop.fo.pagination.Flow; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.SideRegion; @@ -61,6 +62,15 @@ public interface LayoutManagerMaker { public PageSequenceLayoutManager makePageSequenceLayoutManager( AreaTreeHandler ath, PageSequence ps); + /** + * Make a ExternalDocumentLayoutManager object for the fox:external-document extension. + * @param ath the AreaTreeHandler object the external-document interacts with + * @param ed the fox:external-document object to be processed + * @return The created ExternalDocumentLayoutManager object + */ + public ExternalDocumentLayoutManager makeExternalDocumentLayoutManager( + AreaTreeHandler ath, ExternalDocument ed); + /** * Make a FlowLayoutManager object. * @param pslm the parent PageSequenceLayoutManager object diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java index 575ab9fb8..ad7d48caf 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java @@ -32,6 +32,7 @@ import org.apache.fop.fo.FOElementMapping; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FOText; import org.apache.fop.fo.FObjMixed; +import org.apache.fop.fo.extensions.ExternalDocument; import org.apache.fop.fo.flow.BasicLink; import org.apache.fop.fo.flow.BidiOverride; import org.apache.fop.fo.flow.Block; @@ -405,4 +406,9 @@ public class LayoutManagerMapping implements LayoutManagerMaker { } } + public ExternalDocumentLayoutManager makeExternalDocumentLayoutManager( + AreaTreeHandler ath, ExternalDocument ed) { + return new ExternalDocumentLayoutManager(ath, ed); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/Page.java b/src/java/org/apache/fop/layoutmgr/Page.java index 5e9addd1e..6d6dbb233 100644 --- a/src/java/org/apache/fop/layoutmgr/Page.java +++ b/src/java/org/apache/fop/layoutmgr/Page.java @@ -19,6 +19,8 @@ package org.apache.fop.layoutmgr; +import java.awt.geom.Rectangle2D; + import org.apache.fop.area.PageViewport; import org.apache.fop.fo.pagination.SimplePageMaster; @@ -45,6 +47,18 @@ public class Page { this.pageViewport = new PageViewport(spm, pageNumber, pageNumberStr, blank); } + /** + * Auxiliary constructor used when there's no SimplePageMaster. + * @param viewArea the view area of the page + * @param pageNumber the page number (as an int) + * @param pageNumberStr the page number (as a String) + * @param blank true if this is a blank page + */ + public Page(Rectangle2D viewArea, int pageNumber, String pageNumberStr, boolean blank) { + this.spm = null; + this.pageViewport = new PageViewport(viewArea, pageNumber, pageNumberStr, null, blank); + } + /** @return the simple-page-master that created this page */ public SimplePageMaster getSimplePageMaster() { return this.spm; diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java index 0360e2942..e16c3396a 100644 --- a/src/java/org/apache/fop/layoutmgr/PageProvider.java +++ b/src/java/org/apache/fop/layoutmgr/PageProvider.java @@ -252,7 +252,7 @@ public class PageProvider implements Constants { try { String pageNumberString = pageSeq.makeFormattedPageNumber(index); SimplePageMaster spm = pageSeq.getNextSimplePageMaster( - index, (startPageOfPageSequence == index), isLastPage, isBlank); + index, (startPageOfPageSequence == index), isLastPage, false, isBlank); Region body = spm.getRegion(FO_REGION_BODY); if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) { diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java index abf1644c9..efe64d284 100644 --- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java @@ -21,61 +21,26 @@ package org.apache.fop.layoutmgr; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.datatypes.Numeric; import org.apache.fop.area.AreaTreeHandler; -import org.apache.fop.area.AreaTreeModel; -import org.apache.fop.area.IDTracker; -import org.apache.fop.area.PageViewport; import org.apache.fop.area.LineArea; -import org.apache.fop.area.Resolvable; - -import org.apache.fop.fo.Constants; -import org.apache.fop.fo.flow.Marker; -import org.apache.fop.fo.flow.RetrieveMarker; - import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.PageSequenceMaster; import org.apache.fop.fo.pagination.SideRegion; import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.layoutmgr.inline.ContentLayoutManager; -import java.util.List; - /** * LayoutManager for a PageSequence. This class is instantiated by * area.AreaTreeHandler for each fo:page-sequence found in the * input document. */ -public class PageSequenceLayoutManager extends AbstractLayoutManager { +public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager { private static Log log = LogFactory.getLog(PageSequenceLayoutManager.class); - /** - * AreaTreeHandler which activates the PSLM and controls - * the rendering of its pages. - */ - private AreaTreeHandler areaTreeHandler; - - /** - * fo:page-sequence formatting object being - * processed by this class - */ - private PageSequence pageSeq; - private PageProvider pageProvider; - private IDTracker idTracker; - - /** - * Current page with page-viewport-area being filled by - * the PSLM. - */ - private Page curPage; - - private int startPageNum = 0; - private int currentPageNum = 0; - /** * Constructor * @@ -83,20 +48,10 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { * @param pseq fo:page-sequence to process */ public PageSequenceLayoutManager(AreaTreeHandler ath, PageSequence pseq) { - super(pseq); - this.areaTreeHandler = ath; - this.idTracker = ath.getIDTracker(); - this.pageSeq = pseq; + super(ath, pseq); this.pageProvider = new PageProvider(ath, pseq); } - /** - * @return the LayoutManagerMaker object associated to the areaTreeHandler - */ - public LayoutManagerMaker getLayoutManagerMaker() { - return areaTreeHandler.getLayoutManagerMaker(); - } - /** @return the PageProvider applicable to this page-sequence. */ public PageProvider getPageProvider() { return this.pageProvider; @@ -106,25 +61,27 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { * @return the PageSequence being managed by this layout manager */ protected PageSequence getPageSequence() { - return pageSeq; + return (PageSequence)pageSeq; } /** - * Activate the layout of this page sequence. - * PageViewports corresponding to each page generated by this - * page sequence will be created and sent to the AreaTreeModel - * for rendering. + * Provides access to this object + * @return this PageSequenceLayoutManager instance */ + public PageSequenceLayoutManager getPSLM() { + return this; + } + + /** {@inheritDoc} */ public void activateLayout() { - startPageNum = pageSeq.getStartingPageNumber(); - currentPageNum = startPageNum - 1; + initialize(); LineArea title = null; - if (pageSeq.getTitleFO() != null) { + if (getPageSequence().getTitleFO() != null) { try { ContentLayoutManager clm = getLayoutManagerMaker(). - makeContentLayoutManager(this, pageSeq.getTitleFO()); + makeContentLayoutManager(this, getPageSequence().getTitleFO()); title = (LineArea) clm.getParentArea(null); } catch (IllegalStateException e) { // empty title; do nothing @@ -145,9 +102,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { finishPage(); } - /** - * Finished the page-sequence and notifies everyone about it. - */ + /** {@inheritDoc} */ public void finishPageSequence() { if (pageSeq.hasId()) { idTracker.signalIDProcessed(pageSeq.getId()); @@ -157,11 +112,11 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { (currentPageNum - startPageNum) + 1); areaTreeHandler.notifyPageSequenceFinished(pageSeq, (currentPageNum - startPageNum) + 1); - pageSeq.releasePageSequence(); + getPageSequence().releasePageSequence(); // If this sequence has a page sequence master so we must reset // it in preparation for the next sequence - String masterReference = pageSeq.getMasterReference(); + String masterReference = getPageSequence().getMasterReference(); PageSequenceMaster pageSeqMaster = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(masterReference); if (pageSeqMaster != null) { @@ -173,229 +128,18 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { } } - /** - * Provides access to the current page. - * @return the current Page - */ - public Page getCurrentPage() { - return curPage; - } - - /** - * Provides access for setting the current page. - * @param currentPage the new current Page - */ - protected void setCurrentPage(Page currentPage) { - this.curPage = currentPage; - } - - /** - * Provides access to the current page number - * @return the current page number - */ - protected int getCurrentPageNum() { - return currentPageNum; - } - - /** - * Provides access to the current page viewport. - * @return the current PageViewport - *//* - public PageViewport getCurrentPageViewport() { - return curPage.getPageViewport(); - }*/ - - /** - * Provides access to this object - * @return this PageSequenceLayoutManager instance - */ - public PageSequenceLayoutManager getPSLM() { - return this; + /** {@inheritDoc} */ + protected Page createPage(int pageNumber, boolean isBlank) { + return pageProvider.getPage(isBlank, + pageNumber, PageProvider.RELTO_PAGE_SEQUENCE); } - /** - * This returns the first PageViewport that contains an id trait - * matching the idref argument, or null if no such PV exists. - * - * @param idref the idref trait needing to be resolved - * @return the first PageViewport that contains the ID trait - */ - public PageViewport getFirstPVWithID(String idref) { - List list = idTracker.getPageViewportsContainingID(idref); - if (list != null && list.size() > 0) { - return (PageViewport) list.get(0); - } - return null; - } - - /** - * This returns the last PageViewport that contains an id trait - * matching the idref argument, or null if no such PV exists. - * - * @param idref the idref trait needing to be resolved - * @return the last PageViewport that contains the ID trait - */ - public PageViewport getLastPVWithID(String idref) { - List list = idTracker.getPageViewportsContainingID(idref); - if (list != null && list.size() > 0) { - return (PageViewport) list.get(list.size() - 1); - } - return null; - } - - /** - * Add an ID reference to the current page. - * When adding areas the area adds its ID reference. - * For the page layout manager it adds the id reference - * with the current page to the area tree. - * - * @param id the ID reference to add - */ - public void addIDToPage(String id) { - if (id != null && id.length() > 0) { - idTracker.associateIDWithPageViewport(id, curPage.getPageViewport()); - } - } - - /** - * Add an id reference of the layout manager in the AreaTreeHandler, - * if the id hasn't been resolved yet - * @param id the id to track - * @return a boolean indicating if the id has already been resolved - * TODO Maybe give this a better name - */ - public boolean associateLayoutManagerID(String id) { - if (log.isDebugEnabled()) { - log.debug("associateLayoutManagerID(" + id + ")"); - } - if (!idTracker.alreadyResolvedID(id)) { - idTracker.signalPendingID(id); - return false; - } else { - return true; - } - } - - /** - * Notify the areaTreeHandler that the LayoutManagers containing - * idrefs have finished creating areas - * @param id the id for which layout has finished - */ - public void notifyEndOfLayout(String id) { - idTracker.signalIDProcessed(id); - } - - /** - * Identify an unresolved area (one needing an idref to be - * resolved, e.g. the internal-destination of an fo:basic-link) - * for both the AreaTreeHandler and PageViewport object. - * - * The IDTracker keeps a document-wide list of idref's - * and the PV's needing them to be resolved. It uses this to - * send notifications to the PV's when an id has been resolved. - * - * The PageViewport keeps lists of id's needing resolving, along - * with the child areas (page-number-citation, basic-link, etc.) - * of the PV needing their resolution. - * - * @param id the ID reference to add - * @param res the resolvable object that needs resolving - */ - public void addUnresolvedArea(String id, Resolvable res) { - curPage.getPageViewport().addUnresolvedIDRef(id, res); - idTracker.addUnresolvedIDRef(id, curPage.getPageViewport()); - } - - /** - * Bind the RetrieveMarker to the corresponding Marker subtree. - * If the boundary is page then it will only check the - * current page. For page-sequence and document it will - * lookup preceding pages from the area tree and try to find - * a marker. - * If we retrieve a marker from a preceding page, - * then the containing page does not have a qualifying area, - * and all qualifying areas have ended. - * Therefore we use last-ending-within-page (Constants.EN_LEWP) - * as the position. - * - * @param rm the RetrieveMarker instance whose properties are to - * used to find the matching Marker. - * @return a bound RetrieveMarker instance, or null if no Marker - * could be found. - */ - public RetrieveMarker resolveRetrieveMarker(RetrieveMarker rm) { - AreaTreeModel areaTreeModel = areaTreeHandler.getAreaTreeModel(); - String name = rm.getRetrieveClassName(); - int pos = rm.getRetrievePosition(); - int boundary = rm.getRetrieveBoundary(); - - // get marker from the current markers on area tree - Marker mark = (Marker)getCurrentPV().getMarker(name, pos); - if (mark == null && boundary != EN_PAGE) { - // go back over pages until mark found - // if document boundary then keep going - boolean doc = boundary == EN_DOCUMENT; - int seq = areaTreeModel.getPageSequenceCount(); - int page = areaTreeModel.getPageCount(seq) - 1; - while (page < 0 && doc && seq > 1) { - seq--; - page = areaTreeModel.getPageCount(seq) - 1; - } - while (page >= 0) { - PageViewport pv = areaTreeModel.getPage(seq, page); - mark = (Marker)pv.getMarker(name, Constants.EN_LEWP); - if (mark != null) { - break; - } - page--; - if (page < 0 && doc && seq > 1) { - seq--; - page = areaTreeModel.getPageCount(seq) - 1; - } - } - } - - if (mark == null) { - log.debug("found no marker with name: " + name); - return null; - } else { - rm.bindMarker(mark); - return rm; - } - } - - /** - * Makes a new page - * - * @param bIsBlank whether this page is blank or not - * @param bIsLast whether this page is the last page or not - * @return a new page - */ - protected Page makeNewPage(boolean bIsBlank, boolean bIsLast) { - if (curPage != null) { - finishPage(); - } - - currentPageNum++; - - curPage = pageProvider.getPage(bIsBlank, - currentPageNum, PageProvider.RELTO_PAGE_SEQUENCE); - - if (log.isDebugEnabled()) { - log.debug("[" + curPage.getPageViewport().getPageNumberString() - + (bIsBlank ? "*" : "") + "]"); - } - - addIDToPage(pageSeq.getId()); - return curPage; - } - private void layoutSideRegion(int regionID) { SideRegion reg = (SideRegion)curPage.getSimplePageMaster().getRegion(regionID); if (reg == null) { return; } - StaticContent sc = pageSeq.getStaticContent(reg.getRegionName()); + StaticContent sc = getPageSequence().getStaticContent(reg.getRegionName()); if (sc == null) { return; } @@ -406,94 +150,15 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { lm.doLayout(); } - private void finishPage() { - if (log.isTraceEnabled()) { - curPage.getPageViewport().dumpMarkers(); - } + /** {@inheritDoc} */ + protected void finishPage() { // Layout side regions layoutSideRegion(FO_REGION_BEFORE); layoutSideRegion(FO_REGION_AFTER); layoutSideRegion(FO_REGION_START); layoutSideRegion(FO_REGION_END); - // Try to resolve any unresolved IDs for the current page. - // - idTracker.tryIDResolution(curPage.getPageViewport()); - // Queue for ID resolution and rendering - areaTreeHandler.getAreaTreeModel().addPage(curPage.getPageViewport()); - if (log.isDebugEnabled()) { - log.debug("page finished: " + curPage.getPageViewport().getPageNumberString() - + ", current num: " + currentPageNum); - } - curPage = null; + super.finishPage(); } - /** - * Act upon the force-page-count trait, - * in relation to the initial-page-number trait of the following page-sequence. - * @param nextPageSeqInitialPageNumber initial-page-number trait of next page-sequence - */ - public void doForcePageCount(Numeric nextPageSeqInitialPageNumber) { - - int forcePageCount = pageSeq.getForcePageCount(); - - // xsl-spec version 1.0 (15.oct 2001) - // auto | even | odd | end-on-even | end-on-odd | no-force | inherit - // auto: - // Force the last page in this page-sequence to be an odd-page - // if the initial-page-number of the next page-sequence is even. - // Force it to be an even-page - // if the initial-page-number of the next page-sequence is odd. - // If there is no next page-sequence - // or if the value of its initial-page-number is "auto" do not force any page. - - // if force-page-count is auto then set the value of forcePageCount - // depending on the initial-page-number of the next page-sequence - if (nextPageSeqInitialPageNumber != null && forcePageCount == Constants.EN_AUTO) { - if (nextPageSeqInitialPageNumber.getEnum() != 0) { - // auto | auto-odd | auto-even - int nextPageSeqPageNumberType = nextPageSeqInitialPageNumber.getEnum(); - if (nextPageSeqPageNumberType == Constants.EN_AUTO_ODD) { - forcePageCount = Constants.EN_END_ON_EVEN; - } else if (nextPageSeqPageNumberType == Constants.EN_AUTO_EVEN) { - forcePageCount = Constants.EN_END_ON_ODD; - } else { // auto - forcePageCount = Constants.EN_NO_FORCE; - } - } else { // for explicit page number - int nextPageSeqPageStart = nextPageSeqInitialPageNumber.getValue(); - // spec rule - nextPageSeqPageStart = (nextPageSeqPageStart > 0) ? nextPageSeqPageStart : 1; - if (nextPageSeqPageStart % 2 == 0) { // explicit even startnumber - forcePageCount = Constants.EN_END_ON_ODD; - } else { // explicit odd startnumber - forcePageCount = Constants.EN_END_ON_EVEN; - } - } - } - - if (forcePageCount == Constants.EN_EVEN) { - if ((currentPageNum - startPageNum + 1) % 2 != 0) { // we have an odd number of pages - curPage = makeNewPage(true, false); - } - } else if (forcePageCount == Constants.EN_ODD) { - if ((currentPageNum - startPageNum + 1) % 2 == 0) { // we have an even number of pages - curPage = makeNewPage(true, false); - } - } else if (forcePageCount == Constants.EN_END_ON_EVEN) { - if (currentPageNum % 2 != 0) { // we are now on an odd page - curPage = makeNewPage(true, false); - } - } else if (forcePageCount == Constants.EN_END_ON_ODD) { - if (currentPageNum % 2 == 0) { // we are now on an even page - curPage = makeNewPage(true, false); - } - } else if (forcePageCount == Constants.EN_NO_FORCE) { - // i hope: nothing special at all - } - - if (curPage != null) { - finishPage(); - } - } } diff --git a/src/java/org/apache/fop/layoutmgr/TopLevelLayoutManager.java b/src/java/org/apache/fop/layoutmgr/TopLevelLayoutManager.java new file mode 100644 index 000000000..63c8ac158 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/TopLevelLayoutManager.java @@ -0,0 +1,50 @@ +/* + * 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.layoutmgr; + +import org.apache.fop.datatypes.Numeric; + +/** + * This interface is implemented by top-level layout managers such as the ones for fo:page-sequence + * and fox:external-document. + */ +public interface TopLevelLayoutManager { + + /** + * Activate the layout of this page sequence. + * PageViewports corresponding to each page generated by this + * page sequence will be created and sent to the AreaTreeModel + * for rendering. + */ + public void activateLayout(); + + /** + * Act upon the force-page-count trait, + * in relation to the initial-page-number trait of the following page-sequence. + * @param nextPageSeqInitialPageNumber initial-page-number trait of next page-sequence + */ + public void doForcePageCount(Numeric nextPageSeqInitialPageNumber); + + /** + * Finished the page-sequence and notifies everyone about it. + */ + public void finishPageSequence(); + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index 75f852e06..6426f15db 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -19,12 +19,12 @@ package org.apache.fop.layoutmgr.inline; -import java.awt.geom.Rectangle2D; +import java.awt.Dimension; +import java.awt.Rectangle; import java.util.LinkedList; import org.apache.fop.area.Area; import org.apache.fop.area.inline.Viewport; -import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.fo.FObj; import org.apache.fop.fo.flow.AbstractGraphics; @@ -57,180 +57,29 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage * @return the viewport inline area */ private Viewport getInlineArea() { + Dimension intrinsicSize = new Dimension( + fobj.getIntrinsicWidth(), + fobj.getIntrinsicHeight()); - // viewport size is determined by block-progression-dimension - // and inline-progression-dimension + //TODO Investigate if the line-height property has to be taken into the calculation + //somehow. There was some code here that hints in this direction but it was disabled. - // if replaced then use height then ignore block-progression-dimension - //int h = this.propertyList.get("height").getLength().mvalue(); - - // use specified line-height then ignore dimension in height direction - boolean hasLH = false; //propertyList.get("line-height").getSpecifiedValue() != null; - - Length len; - - int bpd = -1; - int ipd = -1; - if (hasLH) { - bpd = fobj.getLineHeight().getOptimum(this).getLength().getValue(this); - } else { - // this property does not apply when the line-height applies - // isn't the block-progression-dimension always in the same - // direction as the line height? - len = fobj.getBlockProgressionDimension().getOptimum(this).getLength(); - if (len.getEnum() != EN_AUTO) { - bpd = len.getValue(this); - } else { - len = fobj.getHeight(); - if (len.getEnum() != EN_AUTO) { - bpd = len.getValue(this); - } - } - } - - len = fobj.getInlineProgressionDimension().getOptimum(this).getLength(); - if (len.getEnum() != EN_AUTO) { - ipd = len.getValue(this); - } else { - len = fobj.getWidth(); - if (len.getEnum() != EN_AUTO) { - ipd = len.getValue(this); - } - } - - // if auto then use the intrinsic size of the content scaled - // to the content-height and content-width - int cwidth = -1; - int cheight = -1; - len = fobj.getContentWidth(); - if (len.getEnum() != EN_AUTO) { - switch (len.getEnum()) { - case EN_SCALE_TO_FIT: - if (ipd != -1) { - cwidth = ipd; - } - break; - case EN_SCALE_DOWN_TO_FIT: - if (ipd != -1 && fobj.getIntrinsicWidth() > ipd) { - cwidth = ipd; - } - break; - case EN_SCALE_UP_TO_FIT: - if (ipd != -1 && fobj.getIntrinsicWidth() < ipd) { - cwidth = ipd; - } - break; - default: - cwidth = len.getValue(this); - } - } - len = fobj.getContentHeight(); - if (len.getEnum() != EN_AUTO) { - switch (len.getEnum()) { - case EN_SCALE_TO_FIT: - if (bpd != -1) { - cheight = bpd; - } - break; - case EN_SCALE_DOWN_TO_FIT: - if (bpd != -1 && fobj.getIntrinsicHeight() > bpd) { - cheight = bpd; - } - break; - case EN_SCALE_UP_TO_FIT: - if (bpd != -1 && fobj.getIntrinsicHeight() < bpd) { - cheight = bpd; - } - break; - default: - cheight = len.getValue(this); - } - } - - int scaling = fobj.getScaling(); - if ((scaling == EN_UNIFORM) || (cwidth == -1) || cheight == -1) { - if (cwidth == -1 && cheight == -1) { - cwidth = fobj.getIntrinsicWidth(); - cheight = fobj.getIntrinsicHeight(); - } else if (cwidth == -1) { - if (fobj.getIntrinsicHeight() == 0) { - cwidth = 0; - } else { - cwidth = (int)(fobj.getIntrinsicWidth() * (double)cheight - / fobj.getIntrinsicHeight()); - } - } else if (cheight == -1) { - if (fobj.getIntrinsicWidth() == 0) { - cheight = 0; - } else { - cheight = (int)(fobj.getIntrinsicHeight() * (double)cwidth - / fobj.getIntrinsicWidth()); - } - } else { - // adjust the larger - if (fobj.getIntrinsicWidth() == 0 || fobj.getIntrinsicHeight() == 0) { - cwidth = 0; - cheight = 0; - } else { - double rat1 = (double) cwidth / fobj.getIntrinsicWidth(); - double rat2 = (double) cheight / fobj.getIntrinsicHeight(); - if (rat1 < rat2) { - // reduce cheight - cheight = (int)(rat1 * fobj.getIntrinsicHeight()); - } else if (rat1 > rat2) { - cwidth = (int)(rat2 * fobj.getIntrinsicWidth()); - } - } - } - } - - if (ipd == -1) { - ipd = cwidth; - } - if (bpd == -1) { - bpd = cheight; - } - - boolean clip = false; - if (cwidth > ipd || cheight > bpd) { - int overflow = fobj.getOverflow(); - if (overflow == EN_HIDDEN) { - clip = true; - } else if (overflow == EN_ERROR_IF_OVERFLOW) { - log.error("Object overflows the viewport: clipping"); - clip = true; - } - } - - int xoffset = fobj.computeXOffset(ipd, cwidth); - int yoffset = fobj.computeYOffset(bpd, cheight); + ImageLayout imageLayout = new ImageLayout(fobj, this, intrinsicSize); + Rectangle placement = imageLayout.getPlacement(); CommonBorderPaddingBackground borderProps = fobj.getCommonBorderPaddingBackground(); - //Determine extra BPD from borders etc. + //Determine extra BPD from borders and padding int beforeBPD = borderProps.getPadding(CommonBorderPaddingBackground.BEFORE, false, this); - beforeBPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.BEFORE, - false); - int afterBPD = borderProps.getPadding(CommonBorderPaddingBackground.AFTER, false, this); - afterBPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.AFTER, false); + beforeBPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.BEFORE, false); - yoffset += beforeBPD; - //bpd += beforeBPD; - //bpd += afterBPD; + placement.y += beforeBPD; - //Determine extra IPD from borders etc. - int startIPD = borderProps.getPadding(CommonBorderPaddingBackground.START, - false, this); - startIPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.START, - false); - int endIPD = borderProps.getPadding(CommonBorderPaddingBackground.END, false, this); - endIPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.END, false); + //Determine extra IPD from borders and padding + int startIPD = borderProps.getPadding(CommonBorderPaddingBackground.START, false, this); + startIPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.START, false); - xoffset += startIPD; - //ipd += startIPD; - //ipd += endIPD; - - Rectangle2D placement = new Rectangle2D.Float(xoffset, yoffset, cwidth, cheight); + placement.x += startIPD; Area viewportArea = getChildArea(); TraitSetter.setProducerID(viewportArea, fobj.getId()); @@ -238,10 +87,10 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage Viewport vp = new Viewport(viewportArea); TraitSetter.setProducerID(vp, fobj.getId()); - vp.setIPD(ipd); - vp.setBPD(bpd); + vp.setIPD(imageLayout.getViewportSize().width); + vp.setBPD(imageLayout.getViewportSize().height); vp.setContentPosition(placement); - vp.setClip(clip); + vp.setClip(imageLayout.isClipped()); vp.setOffset(0); // Common Border, Padding, and Background Properties @@ -254,9 +103,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage return vp; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { Viewport areaCurrent = getInlineArea(); @@ -264,9 +111,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage return super.getNextKnuthElements(context, alignment); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected AlignmentContext makeAlignmentContext(LayoutContext context) { return new AlignmentContext( get(context).getAllocBPD() diff --git a/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java b/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java new file mode 100644 index 000000000..b3ccea628 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java @@ -0,0 +1,262 @@ +/* + * 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.layoutmgr.inline; + +import java.awt.Dimension; +import java.awt.Rectangle; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.GraphicsProperties; + +public class ImageLayout implements Constants { + + /** logging instance */ + protected static Log log = LogFactory.getLog(ImageLayout.class); + + //Input + private GraphicsProperties props; + private PercentBaseContext percentBaseContext; + private Dimension intrinsicSize; + + //Output + private Rectangle placement; + private Dimension viewportSize = new Dimension(-1, -1); + private boolean clip; + + public ImageLayout(GraphicsProperties props, PercentBaseContext percentBaseContext, + Dimension intrinsicSize) { + this.props = props; + this.percentBaseContext = percentBaseContext; + this.intrinsicSize = intrinsicSize; + + doLayout(); + } + + protected void doLayout() { + Length len; + + int bpd = -1; + int ipd = -1; + + len = props.getBlockProgressionDimension().getOptimum(percentBaseContext).getLength(); + if (len.getEnum() != EN_AUTO) { + bpd = len.getValue(percentBaseContext); + } else { + len = props.getHeight(); + if (len.getEnum() != EN_AUTO) { + bpd = len.getValue(percentBaseContext); + } + } + + len = props.getInlineProgressionDimension().getOptimum(percentBaseContext).getLength(); + if (len.getEnum() != EN_AUTO) { + ipd = len.getValue(percentBaseContext); + } else { + len = props.getWidth(); + if (len.getEnum() != EN_AUTO) { + ipd = len.getValue(percentBaseContext); + } + } + + // if auto then use the intrinsic size of the content scaled + // to the content-height and content-width + int cwidth = -1; + int cheight = -1; + len = props.getContentWidth(); + if (len.getEnum() != EN_AUTO) { + switch (len.getEnum()) { + case EN_SCALE_TO_FIT: + if (ipd != -1) { + cwidth = ipd; + } + break; + case EN_SCALE_DOWN_TO_FIT: + if (ipd != -1 && intrinsicSize.width > ipd) { + cwidth = ipd; + } + break; + case EN_SCALE_UP_TO_FIT: + if (ipd != -1 && intrinsicSize.width < ipd) { + cwidth = ipd; + } + break; + default: + cwidth = len.getValue(percentBaseContext); + } + } + len = props.getContentHeight(); + if (len.getEnum() != EN_AUTO) { + switch (len.getEnum()) { + case EN_SCALE_TO_FIT: + if (bpd != -1) { + cheight = bpd; + } + break; + case EN_SCALE_DOWN_TO_FIT: + if (bpd != -1 && intrinsicSize.height > bpd) { + cheight = bpd; + } + break; + case EN_SCALE_UP_TO_FIT: + if (bpd != -1 && intrinsicSize.height < bpd) { + cheight = bpd; + } + break; + default: + cheight = len.getValue(percentBaseContext); + } + } + + int scaling = props.getScaling(); + if ((scaling == EN_UNIFORM) || (cwidth == -1) || cheight == -1) { + if (cwidth == -1 && cheight == -1) { + cwidth = intrinsicSize.width; + cheight = intrinsicSize.height; + } else if (cwidth == -1) { + if (intrinsicSize.height == 0) { + cwidth = 0; + } else { + cwidth = (int)(intrinsicSize.width * (double)cheight + / intrinsicSize.height); + } + } else if (cheight == -1) { + if (intrinsicSize.width == 0) { + cheight = 0; + } else { + cheight = (int)(intrinsicSize.height * (double)cwidth + / intrinsicSize.width); + } + } else { + // adjust the larger + if (intrinsicSize.width == 0 || intrinsicSize.height == 0) { + cwidth = 0; + cheight = 0; + } else { + double rat1 = (double) cwidth / intrinsicSize.width; + double rat2 = (double) cheight / intrinsicSize.height; + if (rat1 < rat2) { + // reduce cheight + cheight = (int)(rat1 * intrinsicSize.height); + } else if (rat1 > rat2) { + cwidth = (int)(rat2 * intrinsicSize.width); + } + } + } + } + + if (ipd == -1) { + ipd = cwidth; + } + if (bpd == -1) { + bpd = cheight; + } + + this.clip = false; + if (cwidth > ipd || cheight > bpd) { + int overflow = props.getOverflow(); + if (overflow == EN_HIDDEN) { + this.clip = true; + } else if (overflow == EN_ERROR_IF_OVERFLOW) { + //TODO Don't use logging to report error! + log.error("Object overflows the viewport: clipping"); + this.clip = true; + } + } + + int xoffset = computeXOffset(ipd, cwidth); + int yoffset = computeYOffset(bpd, cheight); + + //Build calculation results + this.viewportSize.setSize(ipd, bpd); + this.placement = new Rectangle(xoffset, yoffset, cwidth, cheight); + } + + /** + * Given the ipd and the content width calculates the + * required x offset based on the text-align property + * @param ipd the inline-progression-dimension of the object + * @param cwidth the calculated content width of the object + * @return the X offset + */ + public int computeXOffset (int ipd, int cwidth) { + int xoffset = 0; + switch (props.getTextAlign()) { + case EN_CENTER: + xoffset = (ipd - cwidth) / 2; + break; + case EN_END: + xoffset = ipd - cwidth; + break; + case EN_START: + break; + case EN_JUSTIFY: + default: + break; + } + return xoffset; + } + + /** + * Given the bpd and the content height calculates the + * required y offset based on the display-align property + * @param bpd the block-progression-dimension of the object + * @param cheight the calculated content height of the object + * @return the Y offset + */ + public int computeYOffset(int bpd, int cheight) { + int yoffset = 0; + switch (props.getDisplayAlign()) { + case EN_BEFORE: + break; + case EN_AFTER: + yoffset = bpd - cheight; + break; + case EN_CENTER: + yoffset = (bpd - cheight) / 2; + break; + case EN_AUTO: + default: + break; + } + return yoffset; + } + + public Rectangle getPlacement() { + return this.placement; + } + + public Dimension getViewportSize() { + return this.viewportSize; + } + + public Dimension getIntrinsicSize() { + return this.intrinsicSize; + } + + public boolean isClipped() { + return this.clip; + } + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 36fbc235a..eb50a3ea7 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -199,7 +199,8 @@ public class RTFHandler extends FOEventHandler { log.warn("Using default simple-page-master from page-sequence-master..."); PageSequenceMaster master = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(reference); - this.pagemaster = master.getNextSimplePageMaster(false, false, false, false); + this.pagemaster = master.getNextSimplePageMaster( + false, false, false, false, false); } } diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 9e5fd8dbc..b969afac1 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -524,7 +524,9 @@ public class XMLRenderer extends PrintRenderer { addAttribute("key", page.getKey()); addAttribute("nr", page.getPageNumber()); addAttribute("formatted-nr", page.getPageNumberString()); - addAttribute("simple-page-master-name", page.getSimplePageMasterName()); + if (page.getSimplePageMasterName() != null) { + addAttribute("simple-page-master-name", page.getSimplePageMasterName()); + } if (page.isBlank()) { addAttribute("blank", "true"); } diff --git a/status.xml b/status.xml index 0537ad75d..ff1069164 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,11 @@ + + Added new extension element: fox:external-document. It allows to add whole documents + such as multi-page TIFF images to be inserted as peers to a page-sequence. Each image + will make up an entire page. See the documentation for details. + Added support for scale-down-to-fit and scale-up-to-fit (introduced in XSL 1.1). diff --git a/test/layoutengine/standard-testcases/fox_external-document_1.xml b/test/layoutengine/standard-testcases/fox_external-document_1.xml new file mode 100644 index 000000000..ca73806e8 --- /dev/null +++ b/test/layoutengine/standard-testcases/fox_external-document_1.xml @@ -0,0 +1,53 @@ + + + + + +

+ This test checks the basics of fox:external-document. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/standard-testcases/fox_external-document_2.xml b/test/layoutengine/standard-testcases/fox_external-document_2.xml new file mode 100644 index 000000000..5bce78f35 --- /dev/null +++ b/test/layoutengine/standard-testcases/fox_external-document_2.xml @@ -0,0 +1,81 @@ + + + + + +

+ This test checks fox:external-document. +

+
+ + + + + + + + + + + + Just a normal page-sequence in between... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-- cgit v1.2.3 From 2ddc94a5b97c9a7a66bb2fee45ea6e46b86030bf Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 27 Dec 2007 10:51:11 +0000 Subject: Don't just exit with no error message if the document contains no content. Pretty irritating if it does so. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@607036 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOTreeBuilder.java | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index c4ab4fdc8..980404ffd 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -21,25 +21,27 @@ package org.apache.fop.fo; import java.io.OutputStream; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.fo.extensions.ExtensionElementMapping; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FormattingResults; import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.fo.ElementMapping.Maker; +import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.pagination.Root; import org.apache.fop.image.ImageFactory; import org.apache.fop.util.ContentHandlerFactory; -import org.apache.fop.util.ContentHandlerFactory.ObjectSource; import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; +import org.apache.fop.util.ContentHandlerFactory.ObjectSource; /** * SAX Handler that passes parsed data to the various @@ -79,6 +81,7 @@ public class FOTreeBuilder extends DefaultHandler { private FOUserAgent userAgent; private boolean used = false; + private boolean empty = true; private int depth; @@ -145,6 +148,7 @@ public class FOTreeBuilder extends DefaultHandler { + " Please instantiate a new instance."); } used = true; + empty = true; rootFObj = null; // allows FOTreeBuilder to be reused if (log.isDebugEnabled()) { log.debug("Building formatting object tree"); @@ -160,6 +164,10 @@ public class FOTreeBuilder extends DefaultHandler { */ public void endDocument() throws SAXException { this.delegate.endDocument(); + if (this.rootFObj == null && empty) { + throw new ValidationException( + "Document is empty (something might be wrong with your XSLT stylesheet)."); + } rootFObj = null; if (log.isDebugEnabled()) { log.debug("Parsing of document complete"); @@ -280,6 +288,7 @@ public class FOTreeBuilder extends DefaultHandler { // Check to ensure first node encountered is an fo:root if (rootFObj == null) { + empty = false; if (!namespaceURI.equals(FOElementMapping.URI) || !localName.equals("root")) { throw new ValidationException( -- cgit v1.2.3 From 47571de516042aee166a579e6d984697ac60146c Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 4 Jan 2008 12:14:33 +0000 Subject: The fonts variable would have always had an empty Configuration node (non-null value) even if a wasn't present in the fop configuration. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@608812 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/PrintRendererConfigurator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index 3f5884a5e..0f53f2edc 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -118,7 +118,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator boolean strict, FontCache fontCache) throws FOPException { List fontInfoList = new java.util.ArrayList(); - Configuration fonts = cfg.getChild("fonts"); + Configuration fonts = cfg.getChild("fonts", false); if (fonts != null) { long start = 0; if (log.isDebugEnabled()) { -- cgit v1.2.3 From 6415c9acd2fcfeb4961d53b8b5b967ad1010dceb Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 7 Jan 2008 10:52:09 +0000 Subject: Reenabled documentation for fox:destination. Enabled intermediate format functionality for fox:destination. Added a test case to check fox:destination. Deprecated FOP's XMLizable in favor of the XML Graphics Commons variant (and extend that variant). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@609567 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/extensions.xml | 7 ++- src/java/org/apache/fop/area/AreaTreeParser.java | 40 +++++++++++--- src/java/org/apache/fop/area/DestinationData.java | 17 +++--- .../fop/render/afp/extensions/AFPPageSetup.java | 6 ++- .../ps/extensions/PSExtensionAttachment.java | 6 ++- .../fop/render/ps/extensions/PSSetPageDevice.java | 2 +- .../org/apache/fop/render/xml/XMLRenderer.java | 29 ++++++++-- src/java/org/apache/fop/util/XMLizable.java | 13 +---- .../standard-testcases/fox_destination_1.xml | 61 ++++++++++++++++++++++ 9 files changed, 142 insertions(+), 39 deletions(-) create mode 100644 test/layoutengine/standard-testcases/fox_destination_1.xml (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/extensions.xml b/src/documentation/content/xdocs/trunk/extensions.xml index 288695286..f54afea00 100644 --- a/src/documentation/content/xdocs/trunk/extensions.xml +++ b/src/documentation/content/xdocs/trunk/extensions.xml @@ -63,8 +63,7 @@
Anchors or Named Destinations -

This extension element hasn't been reimplemented for the redesigned code, yet.

- +fox:destination.
Table Continuation Label @@ -136,7 +135,7 @@ to following pages. Here is an example of FO code creating such a table-header:<

- (layout-master-set, declarations?, bookmark-tree?, (page-sequence|page-sequence-wrapper|fox:external-document)+) + (layout-master-set, declarations?, bookmark-tree?, (page-sequence|page-sequence-wrapper|fox:external-document|fox:destination)+)

diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index aa499338b..b4a804712 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -36,16 +36,25 @@ import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.area.Trait.InternalLink; import org.apache.fop.area.Trait.Background; -import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.Trait.InternalLink; import org.apache.fop.area.inline.AbstractTextArea; import org.apache.fop.area.inline.Character; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; +import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineBlockParent; import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.inline.Leader; @@ -68,12 +77,6 @@ import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactoryRegistry; import org.apache.fop.util.DefaultErrorListener; import org.apache.fop.util.QName; -import org.w3c.dom.DOMImplementation; -import org.w3c.dom.Document; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; /** * This is a parser for the area tree XML (intermediate format) which is used to reread an area @@ -179,6 +182,7 @@ public class AreaTreeParser { makers.put("foreignObject", new ForeignObjectMaker()); makers.put("bookmarkTree", new BookmarkTreeMaker()); makers.put("bookmark", new BookmarkMaker()); + makers.put("destination", new DestinationMaker()); } private static Rectangle2D parseRect(String rect) { @@ -922,6 +926,26 @@ public class AreaTreeParser { } } + private class DestinationMaker extends AbstractMaker { + + public void startElement(Attributes attributes) { + String[] linkdata + = InternalLink.parseXMLAttribute(lastAttributes.getValue("internal-link")); + PageViewport pv = (PageViewport) pageViewportsByKey.get(linkdata[0]); + DestinationData dest = new DestinationData(linkdata[1]); + List pages = new java.util.ArrayList(); + pages.add(pv); + dest.resolveIDRef(linkdata[1], pages); + areaStack.push(dest); + } + + public void endElement() { + Object tos = areaStack.pop(); + assertObjectOfClass(tos, DestinationData.class); + treeModel.handleOffDocumentItem((DestinationData) tos); + } + } + // ==================================================================== diff --git a/src/java/org/apache/fop/area/DestinationData.java b/src/java/org/apache/fop/area/DestinationData.java index b23605972..2cff02ef4 100644 --- a/src/java/org/apache/fop/area/DestinationData.java +++ b/src/java/org/apache/fop/area/DestinationData.java @@ -22,7 +22,6 @@ package org.apache.fop.area; import java.util.List; import org.apache.fop.fo.extensions.destination.Destination; -import org.apache.fop.area.PageViewport; /** * An instance of this class is named destination from fox:destination */ @@ -46,10 +45,18 @@ public class DestinationData extends AbstractOffDocumentItem implements Resolvab * @param destination the fo:bookmark object */ public DestinationData(Destination destination) { - idRef = destination.getInternalDestination(); - idRefs = new String[] {idRef}; + this(destination.getInternalDestination()); } + /** + * Create a new named destination. + * @param idRef the id reference of the destination + */ + public DestinationData(String idRef) { + this.idRef = idRef; + this.idRefs = new String[] {idRef}; + } + /** * Get the idref for this destination * @@ -99,9 +106,7 @@ public class DestinationData extends AbstractOffDocumentItem implements Resolvab // TODO get rect area of id on page } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getName() { return "Destination"; } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java index ca568028e..91ab2dfa5 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java @@ -21,12 +21,14 @@ package org.apache.fop.render.afp.extensions; import java.io.Serializable; -import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.apache.fop.util.XMLizable; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; +import org.apache.xmlgraphics.util.XMLizable; + +import org.apache.fop.fo.extensions.ExtensionAttachment; + /** * This is the pass-through value object for the PostScript extension. */ diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java index 0fb623bdc..80a2aeee3 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java @@ -19,12 +19,14 @@ package org.apache.fop.render.ps.extensions; -import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.apache.fop.util.XMLizable; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; +import org.apache.xmlgraphics.util.XMLizable; + +import org.apache.fop.fo.extensions.ExtensionAttachment; + /** * This is the pass-through value object for the PostScript extension. */ diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java index 5684ba6a3..da84f97a2 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java @@ -96,7 +96,7 @@ public class PSSetPageDevice extends PSExtensionAttachment { * Generates SAX events representing the object's state. * @param handler ContentHandler instance to send the SAX events to * @throws SAXException if there's a problem generating the SAX events - * @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler) + * @see org.apache.xmlgraphics.util.XMLizable#toSAX(org.xml.sax.ContentHandler) */ public void toSAX(ContentHandler handler) throws SAXException { AttributesImpl atts = new AttributesImpl(); diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index b969afac1..213cba58d 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -41,7 +41,8 @@ import org.xml.sax.SAXException; import org.xml.sax.ext.LexicalHandler; import org.xml.sax.helpers.AttributesImpl; -import org.apache.fop.util.QName; +import org.apache.xmlgraphics.util.XMLizable; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; @@ -51,21 +52,22 @@ import org.apache.fop.area.BeforeFloat; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; +import org.apache.fop.area.BookmarkData; import org.apache.fop.area.CTM; +import org.apache.fop.area.DestinationData; import org.apache.fop.area.Footnote; import org.apache.fop.area.LineArea; import org.apache.fop.area.MainReference; import org.apache.fop.area.NormalFlow; import org.apache.fop.area.OffDocumentExtensionAttachment; import org.apache.fop.area.OffDocumentItem; -import org.apache.fop.area.BookmarkData; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Span; import org.apache.fop.area.Trait; -import org.apache.fop.area.Trait.InternalLink; import org.apache.fop.area.Trait.Background; +import org.apache.fop.area.Trait.InternalLink; import org.apache.fop.area.inline.Container; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; @@ -87,7 +89,7 @@ import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.XMLHandler; import org.apache.fop.util.ColorUtil; -import org.apache.fop.util.XMLizable; +import org.apache.fop.util.QName; /** * Renderer that renders areas to XML for debugging purposes. @@ -419,6 +421,8 @@ public class XMLRenderer extends PrintRenderer { public void processOffDocumentItem(OffDocumentItem oDI) { if (oDI instanceof BookmarkData) { renderBookmarkTree((BookmarkData) oDI); + } else if (oDI instanceof DestinationData) { + renderDestination((DestinationData) oDI); } else if (oDI instanceof OffDocumentExtensionAttachment) { ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment(); if (extensionAttachments == null) { @@ -466,8 +470,23 @@ public class XMLRenderer extends PrintRenderer { } /** - * {@inheritDoc} + * Renders a DestinationData object (named destination) + * @param destination the destination object */ + protected void renderDestination(DestinationData destination) { + if (destination.getWhenToProcess() == OffDocumentItem.END_OF_DOC) { + endPageSequence(); + } + atts.clear(); + PageViewport pv = destination.getPageViewport(); + String pvKey = pv == null ? null : pv.getKey(); + addAttribute("internal-link", + InternalLink.makeXMLAttribute(pvKey, destination.getIDRef())); + startElement("destination", atts); + endElement("destination"); + } + + /** {@inheritDoc} */ public void startRenderer(OutputStream outputStream) throws IOException { log.debug("Rendering areas to Area Tree XML"); diff --git a/src/java/org/apache/fop/util/XMLizable.java b/src/java/org/apache/fop/util/XMLizable.java index c1213638b..a16131989 100644 --- a/src/java/org/apache/fop/util/XMLizable.java +++ b/src/java/org/apache/fop/util/XMLizable.java @@ -25,20 +25,11 @@ package org.apache.fop.util; * src/java/org/apache/excalibur/xml/sax/XMLizable.java */ -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; - /** * This interface can be implemented by classes willing to provide an XML representation * of their current state as SAX events. + * @deprecated Use the interface in Apache XML Graphics Commons instead. */ -public interface XMLizable { - - /** - * Generates SAX events representing the object's state. - * @param handler ContentHandler instance to send the SAX events to - * @throws SAXException if there's a problem generating the SAX events - */ - void toSAX(ContentHandler handler) throws SAXException; +public interface XMLizable extends org.apache.xmlgraphics.util.XMLizable { } diff --git a/test/layoutengine/standard-testcases/fox_destination_1.xml b/test/layoutengine/standard-testcases/fox_destination_1.xml new file mode 100644 index 000000000..a5c6b15f7 --- /dev/null +++ b/test/layoutengine/standard-testcases/fox_destination_1.xml @@ -0,0 +1,61 @@ + + + + + +

+ This test checks the basics of fox:destination. +

+
+ + + + + + + + + + + + + + Chapter 1 + Blah blah bla. + Chapter 2 + Blah blah bla. + Section 1 + Blah blah bla. + Section 2 + Blah blah bla. + + + + + + + + + + + + + + +
-- cgit v1.2.3 From eb93b9ef5345d734f6204c75e3171255833ac9f8 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 7 Jan 2008 15:06:24 +0000 Subject: Bugzilla #44176: Support for custom fonts in Java2DRenderer and derived renderers. Submitted by: Patrick Jaromin Patch modified slightly by jeremias. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@609627 13f79535-47bb-0310-9956-ffa450edef68 --- .../render/bitmap/TIFFRendererConfigurator.java | 1 + .../fop/render/java2d/CustomFontMetricsMapper.java | 205 +++++++++++++++++++++ .../fop/render/java2d/FontMetricsMapper.java | 174 +---------------- .../org/apache/fop/render/java2d/FontSetup.java | 115 +++++++++--- .../apache/fop/render/java2d/Java2DRenderer.java | 2 +- .../render/java2d/Java2DRendererConfigurator.java | 1 + .../fop/render/java2d/SystemFontMetricsMapper.java | 194 +++++++++++++++++++ .../org/apache/fop/render/pcl/PCLRenderer.java | 8 +- .../fop/render/pcl/PCLRendererConfigurator.java | 2 + status.xml | 3 + 10 files changed, 513 insertions(+), 192 deletions(-) create mode 100644 src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java create mode 100644 src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java (limited to 'src') diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java b/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java index 41b05ecd7..14e6734dd 100644 --- a/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java +++ b/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java @@ -68,5 +68,6 @@ public class TIFFRendererConfigurator extends PrintRendererConfigurator { log.info("TIFF compression set to " + name); } } + super.configure(renderer); } } diff --git a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java new file mode 100644 index 000000000..968ed7b71 --- /dev/null +++ b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java @@ -0,0 +1,205 @@ +/* + * 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.render.java2d; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.Set; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +import org.apache.fop.fonts.CustomFont; +import org.apache.fop.fonts.FontType; +import org.apache.fop.fonts.LazyFont; +import org.apache.fop.fonts.Typeface; + +/** + * FontMetricsMapper that delegates most methods to an underlying + * FontMetrics instance. This class was designed to allow + * the underlying java.awt.Font to be loaded from a + * user-configured file not registered in the current graphics environment. + */ +public class CustomFontMetricsMapper extends Typeface implements FontMetricsMapper { + + /** + * Font metrics for the font this class models. + */ + private Typeface typeface; + + /** + * The font required by the Java2D renderer. + */ + private java.awt.Font font; + + /** + * Maintains the most recently requested size. + */ + private float size = 1; + + /** + * Construction of this class results in the immediate construction. + * of the underlying java.awt.Font + * @param fontMetrics + * @throws FontFormatException + * @throws IOException + */ + public CustomFontMetricsMapper(final CustomFont fontMetrics) + throws FontFormatException, IOException { + this.typeface = fontMetrics; + initialize(fontMetrics.getEmbedFileSource()); + } + + /** + * Construction of this class results in the immediate construction + * of the underlying java.awt.Font + * @param fontMetrics + * @throws FontFormatException + * @throws IOException + */ + public CustomFontMetricsMapper(final LazyFont fontMetrics, final Source fontSource) + throws FontFormatException, IOException { + this.typeface = fontMetrics; + initialize(fontSource); + } + + private static final int TYPE1_FONT = 1; //Defined in Java 1.5 + + /** + * Loads the java.awt.Font + * @param source + * @throws FontFormatException + * @throws IOException + */ + private void initialize(final Source source) + throws FontFormatException, IOException { + int type = Font.TRUETYPE_FONT; + if (FontType.TYPE1.equals(typeface.getFontType())) { + type = TYPE1_FONT; //Font.TYPE1_FONT; only available in Java 1.5 + } + + InputStream is = null; + if (source instanceof StreamSource) { + is = ((StreamSource) source).getInputStream(); + } else if (source.getSystemId() != null) { + is = new java.net.URL(source.getSystemId()).openStream(); + } else { + throw new IllegalArgumentException("No font source provided."); + } + + this.font = Font.createFont(type, is); + is.close(); + + } + + /** {@inheritDoc} */ + public final String getEncoding() { + return null; //Not applicable to Java2D rendering + } + + /** {@inheritDoc} */ + public final boolean hasChar(final char c) { + return font.canDisplay(c); + } + + /** {@inheritDoc} */ + public final char mapChar(final char c) { + return typeface.mapChar(c); + } + + /** {@inheritDoc} */ + public final Font getFont(final int size) { + if (this.size == size) { + return font; + } + + this.size = size / 1000f; + font = font.deriveFont(this.size); + return font; + } + + /** {@inheritDoc} */ + public final int getAscender(final int size) { + return typeface.getAscender(size); + } + + /** {@inheritDoc} */ + public final int getCapHeight(final int size) { + return typeface.getCapHeight(size); + } + + /** {@inheritDoc} */ + public final int getDescender(final int size) { + return typeface.getDescender(size); + } + + /** {@inheritDoc} */ + public final String getEmbedFontName() { + return typeface.getEmbedFontName(); + } + + /** {@inheritDoc} */ + public final Set getFamilyNames() { + return typeface.getFamilyNames(); + } + + /** {@inheritDoc} */ + public final String getFontName() { + return typeface.getFontName(); + } + + /** {@inheritDoc} */ + public final FontType getFontType() { + return typeface.getFontType(); + } + + /** {@inheritDoc} */ + public final String getFullName() { + return typeface.getFullName(); + } + + /** {@inheritDoc} */ + public final Map getKerningInfo() { + return typeface.getKerningInfo(); + } + + /** {@inheritDoc} */ + public final int getWidth(final int i, final int size) { + return typeface.getWidth(i, size); + } + + /** {@inheritDoc} */ + public final int[] getWidths() { + return typeface.getWidths(); + } + + /** {@inheritDoc} */ + public final int getXHeight(final int size) { + return typeface.getXHeight(size); + } + + /** {@inheritDoc} */ + public final boolean hasKerningInfo() { + return typeface.hasKerningInfo(); + } + +} diff --git a/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java index 19ecf1020..ff246af2b 100644 --- a/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java @@ -16,183 +16,23 @@ */ /* $Id$ */ - -package org.apache.fop.render.java2d; -// Java -import java.awt.Graphics2D; -import java.util.Map; -import java.util.Set; +package org.apache.fop.render.java2d; import org.apache.fop.fonts.FontMetrics; -import org.apache.fop.fonts.FontType; -import org.apache.fop.fonts.Typeface; - /** - * This class implements org.apache.fop.layout.FontMetrics and - * is added to the hash table in FontInfo. It deferes the - * actual calculation of the metrics to - * Java2DFontMetrics. It only keeps the java name and - * style as member varibles + * Adds method to retrieve the actual java.awt.Font + * for use by Java2DRenderers. */ - -public class FontMetricsMapper extends Typeface implements FontMetrics { - - /** - * This is a Java2DFontMetrics that does the real calculation. - * It is only one class that dynamically determines the font-size. - */ - private static Java2DFontMetrics metric = null; - - /** - * The java name of the font. - * # Make the family name immutable. - */ - private final String family; - - /** - * The java style of the font. - * # Make the style immutable. - */ - private final int style; - - /** - * Constructs a new Font-metrics. - * @param family the family name of the font (java value) - * @param style the java type style value of the font - * @param graphics a Graphics2D object - this is needed so - * that we can get an instance of java.awt.FontMetrics - */ - public FontMetricsMapper(String family, int style, Graphics2D graphics) { - this.family = family; - this.style = style; - if (metric == null) { - metric = new Java2DFontMetrics(graphics); - } - } - - /** {@inheritDoc} */ - public String getFontName() { - return family; - } - - /** {@inheritDoc} */ - public String getEmbedFontName() { - return getFontName(); - } - - /** {@inheritDoc} */ - public String getFullName() { - return getFontName(); - } - - /** {@inheritDoc} */ - public Set getFamilyNames() { - Set s = new java.util.HashSet(); - s.add(this.family); - return s; - } - - /** - * {@inheritDoc} - */ - public FontType getFontType() { - return FontType.OTHER; - } - - /** - * {@inheritDoc} - */ - public int getMaxAscent(int size) { - return metric.getMaxAscent(family, style, size); - } - - /** - * {@inheritDoc} - */ - public int getAscender(int size) { - return metric.getAscender(family, style, size); - } - - /** - * {@inheritDoc} - */ - public int getCapHeight(int size) { - return metric.getCapHeight(family, style, size); - } - - /** - * {@inheritDoc} - */ - public int getDescender(int size) { - return metric.getDescender(family, style, size); - } - - /** - * {@inheritDoc} - */ - public int getXHeight(int size) { - return metric.getXHeight(family, style, size); - } - - /** - * {@inheritDoc} - */ - public int getWidth(int i, int size) { - return metric.width(i, family, style, size); - } - - - /** - * {@inheritDoc} - */ - public int[] getWidths() { - return metric.getWidths(family, style, Java2DFontMetrics.FONT_SIZE); - } +public interface FontMetricsMapper extends FontMetrics { /** * Gets a Font instance of the Font that this * FontMetrics describes in the desired size. * @param size font size - * @return font with the desired characeristics. - */ - public java.awt.Font getFont(int size) { - return metric.getFont(family, style, size); - } - - /** - * {@inheritDoc} - */ - public Map getKerningInfo() { - return java.util.Collections.EMPTY_MAP; - } - - /** - * {@inheritDoc} + * @return font with the desired characteristics. */ - public boolean hasKerningInfo() { - return false; - } - - /** {@inheritDoc} */ - public String getEncoding() { - return null; //Not applicable to Java2D rendering - } - - /** {@inheritDoc} */ - public char mapChar(char c) { - return c; - } - - /** {@inheritDoc} */ - public boolean hasChar(char c) { - return metric.hasChar(family, style, Java2DFontMetrics.FONT_SIZE, c); - } - + java.awt.Font getFont(int size); + } - - - - - diff --git a/src/java/org/apache/fop/render/java2d/FontSetup.java b/src/java/org/apache/fop/render/java2d/FontSetup.java index bd53c20d7..6cdf01521 100644 --- a/src/java/org/apache/fop/render/java2d/FontSetup.java +++ b/src/java/org/apache/fop/render/java2d/FontSetup.java @@ -5,9 +5,9 @@ * 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. @@ -22,14 +22,23 @@ package org.apache.fop.render.java2d; // FOP import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; +import java.util.List; import java.util.Set; +import javax.xml.transform.Source; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.fop.fonts.CustomFont; +import org.apache.fop.fonts.EmbedFontInfo; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontLoader; +import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.FontUtil; +import org.apache.fop.fonts.LazyFont; /** * Sets up the Java2D/AWT fonts. It is similar to @@ -70,10 +79,13 @@ public class FontSetup { * triplets for lookup. * * @param fontInfo the font info object to set up - * @param graphics needed for acces to font metrics + * @param configuredFontList of fop config fonts + * @param resolver for resolving the font file URI + * @param graphics needed for access to font metrics */ - public static void setup(FontInfo fontInfo, Graphics2D graphics) { - FontMetricsMapper metric; + public static void setup(FontInfo fontInfo, List configuredFontList, + FontResolver resolver, Graphics2D graphics) { + FontMetricsMapper metric; int normal, bold, bolditalic, italic; /* @@ -87,47 +99,47 @@ public class FontSetup { italic = java.awt.Font.ITALIC; bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC; - metric = new FontMetricsMapper("SansSerif", normal, graphics); + metric = new SystemFontMetricsMapper("SansSerif", normal, graphics); // --> goes to F1 fontInfo.addMetrics("F1", metric); - metric = new FontMetricsMapper("SansSerif", italic, graphics); + metric = new SystemFontMetricsMapper("SansSerif", italic, graphics); // --> goes to F2 fontInfo.addMetrics("F2", metric); - metric = new FontMetricsMapper("SansSerif", bold, graphics); + metric = new SystemFontMetricsMapper("SansSerif", bold, graphics); // --> goes to F3 fontInfo.addMetrics("F3", metric); - metric = new FontMetricsMapper("SansSerif", bolditalic, graphics); + metric = new SystemFontMetricsMapper("SansSerif", bolditalic, graphics); // --> goes to F4 fontInfo.addMetrics("F4", metric); - metric = new FontMetricsMapper("Serif", normal, graphics); + metric = new SystemFontMetricsMapper("Serif", normal, graphics); // --> goes to F5 fontInfo.addMetrics("F5", metric); - metric = new FontMetricsMapper("Serif", italic, graphics); + metric = new SystemFontMetricsMapper("Serif", italic, graphics); // --> goes to F6 fontInfo.addMetrics("F6", metric); - metric = new FontMetricsMapper("Serif", bold, graphics); + metric = new SystemFontMetricsMapper("Serif", bold, graphics); // --> goes to F7 fontInfo.addMetrics("F7", metric); - metric = new FontMetricsMapper("Serif", bolditalic, graphics); + metric = new SystemFontMetricsMapper("Serif", bolditalic, graphics); // --> goes to F8 fontInfo.addMetrics("F8", metric); - metric = new FontMetricsMapper("MonoSpaced", normal, graphics); + metric = new SystemFontMetricsMapper("MonoSpaced", normal, graphics); // --> goes to F9 fontInfo.addMetrics("F9", metric); - metric = new FontMetricsMapper("MonoSpaced", italic, graphics); + metric = new SystemFontMetricsMapper("MonoSpaced", italic, graphics); // --> goes to F10 fontInfo.addMetrics("F10", metric); - metric = new FontMetricsMapper("MonoSpaced", bold, graphics); + metric = new SystemFontMetricsMapper("MonoSpaced", bold, graphics); // --> goes to F11 fontInfo.addMetrics("F11", metric); - metric = new FontMetricsMapper("MonoSpaced", bolditalic, graphics); + metric = new SystemFontMetricsMapper("MonoSpaced", bolditalic, graphics); // --> goes to F12 fontInfo.addMetrics("F12", metric); - metric = new FontMetricsMapper("Serif", normal, graphics); + metric = new SystemFontMetricsMapper("Serif", normal, graphics); //"Symbol" doesn't seem to work here, but "Serif" does the job just fine. *shrug* // --> goes to F13 and F14 fontInfo.addMetrics("F13", metric); @@ -207,10 +219,11 @@ public class FontSetup { fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", "normal", Font.WEIGHT_NORMAL); - configureInstalledAWTFonts(fontInfo, graphics, LAST_PREDEFINED_FONT_NUMBER + 1); + int lastNum = configureInstalledAWTFonts(fontInfo, graphics, LAST_PREDEFINED_FONT_NUMBER + 1); + addConfiguredFonts(fontInfo, configuredFontList, resolver, lastNum++); } - private static void configureInstalledAWTFonts(FontInfo fontInfo, Graphics2D graphics, + private static int configureInstalledAWTFonts(FontInfo fontInfo, Graphics2D graphics, int startNumber) { int num = startNumber; GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); @@ -250,9 +263,69 @@ public class FontSetup { guessedStyle, guessedWeight, fontKey); } } + return num; + + } + + /** + * Add fonts from configuration file starting with internal name F. + * + * @param fontInfo the font info object to set up + * @param fontList a list of EmbedFontInfo objects + * @param num starting index for internal font numbering + * @param resolver the font resolver + */ + private static void addConfiguredFonts(FontInfo fontInfo, List fontList, FontResolver resolver, int num) { + + if (fontList == null || fontList.size() < 1) { + log.debug("No user configured fonts found."); + return; + } + if (resolver == null) { + // Ensure that we have minimal font resolution capabilities + resolver = org.apache.fop.fonts.FontSetup + .createMinimalFontResolver(); + } + String internalName = null; + + for (int i = 0; i < fontList.size(); i++) { + + EmbedFontInfo configFontInfo = (EmbedFontInfo) fontList.get(i); + String fontFile = configFontInfo.getEmbedFile(); + internalName = "F" + num; + num++; + try { + FontMetricsMapper font = null; + String metricsUrl = configFontInfo.getMetricsFile(); + // If the user specified an XML-based metrics file, we'll use it + // Otherwise, calculate metrics directly from the font file. + if (metricsUrl != null) { + LazyFont fontMetrics = new LazyFont(configFontInfo, resolver); + Source fontSource = resolver.resolve(configFontInfo.getEmbedFile()); + font = new CustomFontMetricsMapper(fontMetrics, fontSource); + } else { + CustomFont fontMetrics = FontLoader.loadFont(fontFile, resolver); + font = new CustomFontMetricsMapper(fontMetrics); + } + fontInfo.addMetrics(internalName, font); + + List triplets = configFontInfo.getFontTriplets(); + for (int c = 0; c < triplets.size(); c++) { + FontTriplet triplet = (FontTriplet) triplets.get(c); + + if (log.isDebugEnabled()) { + log.debug("Registering: " + triplet + " under " + internalName); + } + fontInfo.addFontProperties(internalName, triplet); + } + } catch (Exception e) { + log.warn("Unable to load custom font from file '" + fontFile + "'", e); + } + } } + private static void addFontTriplet(FontInfo fontInfo, String fontName, String fontStyle, int fontWeight, String fontKey) { FontTriplet triplet = FontInfo.createFontKey(fontName, fontStyle, fontWeight); @@ -261,7 +334,7 @@ public class FontSetup { private static void addFontMetricsMapper(FontInfo fontInfo, String family, String fontKey, Graphics2D graphics, int style) { - FontMetricsMapper metric = new FontMetricsMapper(family, style, graphics); + FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, graphics); fontInfo.addMetrics(fontKey, metric); } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index aa9b0337a..eededf13b 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -179,7 +179,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem //The next line is important to get accurate font metrics! g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - FontSetup.setup(fontInfo, g); + FontSetup.setup(fontInfo, fontList, fontResolver, g); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java b/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java index 6732a10fe..cc8d3d07f 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java @@ -53,5 +53,6 @@ public class Java2DRendererConfigurator extends PrintRendererConfigurator { java2dRenderer.setTransparentPageBackground("true".equalsIgnoreCase(value)); } } + super.configure(renderer); } } diff --git a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java new file mode 100644 index 000000000..ed7391383 --- /dev/null +++ b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java @@ -0,0 +1,194 @@ +/* + * 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.render.java2d; + +// Java +import java.awt.Graphics2D; +import java.util.Map; +import java.util.Set; + +import org.apache.fop.fonts.FontType; +import org.apache.fop.fonts.Typeface; + + +/** + * This class implements org.apache.fop.layout.FontMetrics and + * is added to the hash table in FontInfo. It deferes the + * actual calculation of the metrics to + * Java2DFontMetrics. It only keeps the java name and + * style as member varibles + */ + +public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapper { + + /** + * This is a Java2DFontMetrics that does the real calculation. + * It is only one class that dynamically determines the font-size. + */ + private static Java2DFontMetrics metric = null; + + /** + * The java name of the font. + * # Make the family name immutable. + */ + private final String family; + + /** + * The java style of the font. + * # Make the style immutable. + */ + private final int style; + + /** + * Constructs a new Font-metrics. + * @param family the family name of the font (java value) + * @param style the java type style value of the font + * @param graphics a Graphics2D object - this is needed so + * that we can get an instance of java.awt.FontMetrics + */ + public SystemFontMetricsMapper(String family, int style, Graphics2D graphics) { + this.family = family; + this.style = style; + if (metric == null) { + metric = new Java2DFontMetrics(graphics); + } + } + + /** {@inheritDoc} */ + public String getFontName() { + return family; + } + + /** {@inheritDoc} */ + public String getEmbedFontName() { + return getFontName(); + } + + /** {@inheritDoc} */ + public String getFullName() { + return getFontName(); + } + + /** {@inheritDoc} */ + public Set getFamilyNames() { + Set s = new java.util.HashSet(); + s.add(this.family); + return s; + } + + /** + * {@inheritDoc} + */ + public FontType getFontType() { + return FontType.OTHER; + } + + /** + * {@inheritDoc} + */ + public int getMaxAscent(int size) { + return metric.getMaxAscent(family, style, size); + } + + /** + * {@inheritDoc} + */ + public int getAscender(int size) { + return metric.getAscender(family, style, size); + } + + /** + * {@inheritDoc} + */ + public int getCapHeight(int size) { + return metric.getCapHeight(family, style, size); + } + + /** + * {@inheritDoc} + */ + public int getDescender(int size) { + return metric.getDescender(family, style, size); + } + + /** + * {@inheritDoc} + */ + public int getXHeight(int size) { + return metric.getXHeight(family, style, size); + } + + /** + * {@inheritDoc} + */ + public int getWidth(int i, int size) { + return metric.width(i, family, style, size); + } + + + /** + * {@inheritDoc} + */ + public int[] getWidths() { + return metric.getWidths(family, style, Java2DFontMetrics.FONT_SIZE); + } + + /** + * {@inheritDoc} + */ + public java.awt.Font getFont(int size) { + return metric.getFont(family, style, size); + } + + /** + * {@inheritDoc} + */ + public Map getKerningInfo() { + return java.util.Collections.EMPTY_MAP; + } + + /** + * {@inheritDoc} + */ + public boolean hasKerningInfo() { + return false; + } + + /** {@inheritDoc} */ + public String getEncoding() { + return null; //Not applicable to Java2D rendering + } + + /** {@inheritDoc} */ + public char mapChar(char c) { + return c; + } + + /** {@inheritDoc} */ + public boolean hasChar(char c) { + return metric.hasChar(family, style, Java2DFontMetrics.FONT_SIZE, c); + } + +} + + + + + diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 095c3bba7..732ce0f8f 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -48,8 +48,12 @@ import java.util.List; import java.util.Map; import java.util.Stack; +import org.w3c.dom.Document; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.java2d.GraphicContext; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.MimeConstants; import org.apache.fop.area.Area; @@ -86,8 +90,6 @@ import org.apache.fop.render.pcl.extensions.PCLElementMapping; import org.apache.fop.traits.BorderProps; import org.apache.fop.util.QName; import org.apache.fop.util.UnitConv; -import org.apache.xmlgraphics.java2d.GraphicContext; -import org.w3c.dom.Document; /** * Renderer for the PCL 5 printer language. It also uses HP GL/2 for certain graphic elements. @@ -182,7 +184,7 @@ public class PCLRenderer extends PrintRenderer { //The next line is important to get accurate font metrics! g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - FontSetup.setup(fontInfo, g); + FontSetup.setup(fontInfo, fontList, fontResolver, g); } /** diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java index 1330a46ac..03b60f316 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java @@ -20,6 +20,7 @@ package org.apache.fop.render.pcl; import org.apache.avalon.framework.configuration.Configuration; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.render.PrintRendererConfigurator; @@ -73,5 +74,6 @@ public class PCLRendererConfigurator extends PrintRendererConfigurator { pclRenderer.setPJLDisabled(cfg.getChild("disable-pjl").getValueAsBoolean(false)); } + super.configure(renderer); } } diff --git a/status.xml b/status.xml index ff1069164..1c2f18b4b 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Added support for custom fonts in Java2DRenderer and derived renderers. + Added new extension element: fox:external-document. It allows to add whole documents such as multi-page TIFF images to be inserted as peers to a page-sequence. Each image -- cgit v1.2.3 From 292aace6a143ee656e148e45ca79c42800b678ee Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 8 Jan 2008 15:27:02 +0000 Subject: cleaned up git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610020 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java b/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java index 5c1c66dbc..129a3f5a1 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java @@ -30,7 +30,6 @@ import org.apache.fop.render.afp.tools.BinaryUtils; * The Map Page Overlay structured field maps a Resource Local ID to the name of * a Begin Overlay structured field. A Map Page Overlay structured field may * contain from one to 254 repeating groups. - * */ public class MapPageOverlay extends AbstractAFPObject { @@ -68,15 +67,10 @@ public class MapPageOverlay extends AbstractAFPObject { log.debug("addOverlay():: adding overlay " + name); } - byte[] data; - try { - - data = name.getBytes(AFPConstants.EBCIDIC_ENCODING); + byte[] data = name.getBytes(AFPConstants.EBCIDIC_ENCODING); overLays.add(data); - } catch (UnsupportedEncodingException usee) { - log.error("addOverlay():: UnsupportedEncodingException translating the name " + name); } @@ -117,7 +111,6 @@ public class MapPageOverlay extends AbstractAFPObject { byte olayref = 0x00; for (int i = 0; i < oLayCount; i++) { - olayref = (byte) (olayref + 1); data[++pos] = 0x00; -- cgit v1.2.3 From d424cf5ce41b7dbd80385e1669f47b05a4c6d4a6 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 8 Jan 2008 15:28:56 +0000 Subject: Appears to be unused/referenced and superceeded by PageGroup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610021 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/render/afp/modca/EndPageGroup.java | 79 ---------------------- 1 file changed, 79 deletions(-) delete mode 100644 src/java/org/apache/fop/render/afp/modca/EndPageGroup.java (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/modca/EndPageGroup.java b/src/java/org/apache/fop/render/afp/modca/EndPageGroup.java deleted file mode 100644 index 25fc006ce..000000000 --- a/src/java/org/apache/fop/render/afp/modca/EndPageGroup.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.afp.modca; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * The End Named Page Group (ENG) structured field terminates a page group that was - * initiated by a Begin Named Page Group structured field. - * - * Note :This object will be used to represent an ENG - * structured field. It is necessary as you can't end - * a PageGroup because you don't know where the group - * will end (as this is controlled by the tags in the FO). - *

- * - */ -public class EndPageGroup extends AbstractNamedAFPObject { - - /** - * Main constructor - * @param groupId the group id - */ - public EndPageGroup(String groupId) { - - super(groupId); - - if (log.isDebugEnabled()) { - log.debug("A ENG is being created for group: " + groupId); - } - } - - /** - * Accessor method to write the AFP datastream for the End Page Group. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xAD; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - } - -} -- cgit v1.2.3 From 298d3dc816fb589c7d7789705bbea45b09559fed Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 8 Jan 2008 15:34:07 +0000 Subject: cleaned up git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610022 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/render/afp/modca/IncludePageOverlay.java | 39 +++++++++------------- 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java b/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java index 754679385..7c52fe0a2 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java @@ -42,12 +42,12 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { /** * The x coordinate */ - private int xCoor = 0; + private int x = 0; /** * The y coordinate */ - private int yCoor = 0; + private int y = 0; /** * The orientation @@ -62,11 +62,9 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { * @param orientation The orientation */ public IncludePageOverlay(String overlayName, int x, int y, int orientation) { - super(overlayName); - - xCoor = x; - yCoor = y; + this.x = x; + this.y = y; setOrientation(orientation); } @@ -77,7 +75,6 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { * The orientation (0,90, 180, 270) */ public void setOrientation(int orientation) { - if (orientation == 0 || orientation == 90 || orientation == 180 || orientation == 270) { this.orientation = orientation; @@ -85,7 +82,6 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { throw new IllegalArgumentException( "The orientation must be one of the values 0, 90, 180, 270"); } - } /** @@ -101,9 +97,9 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { data[0] = 0x5A; // Set the total record length - byte[] rl1 = BinaryUtils.convert(24, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; + byte[] len = BinaryUtils.convert(24, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; // Structured field ID for a IPO data[3] = (byte) 0xD3; @@ -115,20 +111,18 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { data[8] = 0x00; // Reserved for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - byte[] r2 = BinaryUtils.convert(xCoor, 3); - data[17] = r2[0]; // x coordinate - data[18] = r2[1]; - data[19] = r2[2]; + byte[] xcoord = BinaryUtils.convert(x, 3); + data[17] = xcoord[0]; // x coordinate + data[18] = xcoord[1]; + data[19] = xcoord[2]; - byte[] r3 = BinaryUtils.convert(yCoor, 3); - data[20] = r3[0]; // y coordinate - data[21] = r3[1]; - data[22] = r3[2]; + byte[] ycoord = BinaryUtils.convert(y, 3); + data[20] = ycoord[0]; // y coordinate + data[21] = ycoord[1]; + data[22] = ycoord[2]; switch (orientation) { case 90: @@ -148,9 +142,6 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { data[24] = 0x00; break; } - os.write(data); - } - } \ No newline at end of file -- cgit v1.2.3 From fa80d556ca5bcad58ba32a151936d480c3ff6246 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 8 Jan 2008 15:35:18 +0000 Subject: fixed javadoc git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610023 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java b/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java index 30e2e94b2..7dd210a1e 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java @@ -38,8 +38,8 @@ public class ImageSizeParameter extends AbstractAFPObject { * resolution, hsize and vsize. * @param hresol The horizontal resolution of the image. * @param vresol The vertical resolution of the image. - * @param hsize The hsize of the image. - * @param vsize The vsize of the vsize. + * @param hsize The horizontal size of the image. + * @param vsize The vertical size of the image. */ public ImageSizeParameter(int hresol, int vresol, int hsize, int vsize) { this.hRes = hresol; -- cgit v1.2.3 From 5044438b501528cdc603f9ad431ac95c055b5db1 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 9 Jan 2008 11:02:08 +0000 Subject: Fixed checkstyle issues: tabs and trailing spaces git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610337 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/render/java2d/CustomFontMetricsMapper.java | 6 ++-- .../org/apache/fop/render/java2d/FontSetup.java | 40 +++++++++++----------- 2 files changed, 23 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java index 968ed7b71..208bc303a 100644 --- a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java @@ -64,7 +64,7 @@ public class CustomFontMetricsMapper extends Typeface implements FontMetricsMapp * @throws IOException */ public CustomFontMetricsMapper(final CustomFont fontMetrics) - throws FontFormatException, IOException { + throws FontFormatException, IOException { this.typeface = fontMetrics; initialize(fontMetrics.getEmbedFileSource()); } @@ -77,13 +77,13 @@ public class CustomFontMetricsMapper extends Typeface implements FontMetricsMapp * @throws IOException */ public CustomFontMetricsMapper(final LazyFont fontMetrics, final Source fontSource) - throws FontFormatException, IOException { + throws FontFormatException, IOException { this.typeface = fontMetrics; initialize(fontSource); } private static final int TYPE1_FONT = 1; //Defined in Java 1.5 - + /** * Loads the java.awt.Font * @param source diff --git a/src/java/org/apache/fop/render/java2d/FontSetup.java b/src/java/org/apache/fop/render/java2d/FontSetup.java index 6cdf01521..752335521 100644 --- a/src/java/org/apache/fop/render/java2d/FontSetup.java +++ b/src/java/org/apache/fop/render/java2d/FontSetup.java @@ -50,18 +50,18 @@ public class FontSetup { /** logging instance */ protected static Log log = LogFactory.getLog(FontSetup.class); - + private static final int LAST_PREDEFINED_FONT_NUMBER = 14; private static final Set HARDCODED_FONT_NAMES; - + static { HARDCODED_FONT_NAMES = new java.util.HashSet(); HARDCODED_FONT_NAMES.add("any"); HARDCODED_FONT_NAMES.add("sans-serif"); HARDCODED_FONT_NAMES.add("serif"); HARDCODED_FONT_NAMES.add("monospace"); - + HARDCODED_FONT_NAMES.add("Helvetica"); HARDCODED_FONT_NAMES.add("Times"); HARDCODED_FONT_NAMES.add("Courier"); @@ -71,7 +71,7 @@ public class FontSetup { HARDCODED_FONT_NAMES.add("Times-Roman"); HARDCODED_FONT_NAMES.add("Computer-Modern-Typewriter"); } - + /** * Sets up the font info object. * @@ -85,7 +85,7 @@ public class FontSetup { */ public static void setup(FontInfo fontInfo, List configuredFontList, FontResolver resolver, Graphics2D graphics) { - FontMetricsMapper metric; + FontMetricsMapper metric; int normal, bold, bolditalic, italic; /* @@ -218,32 +218,32 @@ public class FontSetup { fontInfo.addFontProperties("F8", "Times Roman", "italic", Font.WEIGHT_BOLD); fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", "normal", Font.WEIGHT_NORMAL); - - int lastNum = configureInstalledAWTFonts(fontInfo, graphics, LAST_PREDEFINED_FONT_NUMBER + 1); - addConfiguredFonts(fontInfo, configuredFontList, resolver, lastNum++); + + int lastNum = configureInstalledAWTFonts(fontInfo, graphics, LAST_PREDEFINED_FONT_NUMBER + 1); + addConfiguredFonts(fontInfo, configuredFontList, resolver, lastNum++); } - private static int configureInstalledAWTFonts(FontInfo fontInfo, Graphics2D graphics, + private static int configureInstalledAWTFonts(FontInfo fontInfo, Graphics2D graphics, int startNumber) { int num = startNumber; GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - + java.awt.Font[] fonts = env.getAllFonts(); for (int i = 0; i < fonts.length; i++) { java.awt.Font f = fonts[i]; if (HARDCODED_FONT_NAMES.contains(f.getName())) { continue; //skip } - + if (log.isTraceEnabled()) { - log.trace("AWT Font: " + f.getFontName() - + ", family: " + f.getFamily() - + ", PS: " + f.getPSName() + log.trace("AWT Font: " + f.getFontName() + + ", family: " + f.getFamily() + + ", PS: " + f.getPSName() + ", Name: " + f.getName() + ", Angle: " + f.getItalicAngle() + ", Style: " + f.getStyle()); } - + String searchName = FontUtil.stripWhiteSpace(f.getName()).toLowerCase(); String guessedStyle = FontUtil.guessStyle(searchName); int guessedWeight = FontUtil.guessWeight(searchName); @@ -252,7 +252,7 @@ public class FontSetup { String fontKey = "F" + num; int style = convertToAWTFontStyle(guessedStyle, guessedWeight); addFontMetricsMapper(fontInfo, f.getName(), fontKey, graphics, style); - + //Register appropriate font triplets matching the font. Two different strategies: //Example: "Arial Bold", normal, normal addFontTriplet(fontInfo, f.getName(), @@ -320,12 +320,12 @@ public class FontSetup { fontInfo.addFontProperties(internalName, triplet); } } catch (Exception e) { - log.warn("Unable to load custom font from file '" + fontFile + "'", e); + log.warn("Unable to load custom font from file '" + fontFile + "'", e); } } } - + private static void addFontTriplet(FontInfo fontInfo, String fontName, String fontStyle, int fontWeight, String fontKey) { FontTriplet triplet = FontInfo.createFontKey(fontName, fontStyle, fontWeight); @@ -334,7 +334,7 @@ public class FontSetup { private static void addFontMetricsMapper(FontInfo fontInfo, String family, String fontKey, Graphics2D graphics, int style) { - FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, graphics); + FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, graphics); fontInfo.addMetrics(fontKey, metric); } @@ -348,6 +348,6 @@ public class FontSetup { } return style; } - + } -- cgit v1.2.3 From b59f42a3208bb67205e36e5ef4e95811b58de3e4 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 9 Jan 2008 12:01:21 +0000 Subject: keep-together is an inherited property git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610355 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 1fe9a32c4..695eddc07 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1802,7 +1802,7 @@ public final class FOPropertyMapping implements Constants { // keep-together m = new KeepProperty.Maker(PR_KEEP_TOGETHER); m.useGeneric(genericKeep); - m.setInherited(false); + m.setInherited(true); m.setDefault("auto"); m.addShorthand(s_generics[PR_PAGE_BREAK_INSIDE]); addPropertyMaker("keep-together", m); -- cgit v1.2.3 From 1ab3e8a6a95b9ce900740a603bd978b2581eb1bb Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 9 Jan 2008 15:40:25 +0000 Subject: cleanup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610420 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/render/afp/modca/IncludePageSegment.java | 31 +++++++++------------- 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java b/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java index 518904878..7792a7162 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java @@ -45,24 +45,24 @@ public class IncludePageSegment extends AbstractNamedAFPObject { /** * The x position where we need to put this object on the page */ - private byte[] xCoor; + private byte[] x; /** * The y position where we need to put this object on the page */ - private byte[] yCoor; + private byte[] y; /** * Constructor for the Include Page Segment * @param name Name of the page segment - * @param xVal The x position - * @param yVal The y position + * @param x The x position + * @param y The y position */ - public IncludePageSegment(String name, int xVal, int yVal) { + public IncludePageSegment(String name, int x, int y) { super(name); - this.xCoor = BinaryUtils.convert(xVal, 3); - this.yCoor = BinaryUtils.convert(yVal, 3); + this.x = BinaryUtils.convert(x, 3); + this.y = BinaryUtils.convert(y, 3); } @@ -93,22 +93,17 @@ public class IncludePageSegment extends AbstractNamedAFPObject { data[8] = 0x00; // Reserved for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - data[17] = xCoor[0]; // x coordinate - data[18] = xCoor[1]; - data[19] = xCoor[2]; + data[17] = x[0]; // x coordinate + data[18] = x[1]; + data[19] = x[2]; - data[20] = yCoor[0]; // y coordinate - data[21] = yCoor[1]; - data[22] = yCoor[2]; + data[20] = y[0]; // y coordinate + data[21] = y[1]; + data[22] = y[2]; os.write(data); - } - - } -- cgit v1.2.3 From e9693885fd98f2f0cb77cb9527708edfdfbe7a7b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 10 Jan 2008 07:38:47 +0000 Subject: Added basic support for PDF page labels. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610704 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFDictionary.java | 18 +- src/java/org/apache/fop/pdf/PDFFactory.java | 11 ++ src/java/org/apache/fop/pdf/PDFNumberTreeNode.java | 121 +++++++++++++ src/java/org/apache/fop/pdf/PDFNumsArray.java | 94 ++++++++++ src/java/org/apache/fop/pdf/PDFPageLabels.java | 48 ++++++ src/java/org/apache/fop/pdf/PDFRoot.java | 189 +++++++++++---------- .../org/apache/fop/render/pdf/PDFRenderer.java | 15 ++ status.xml | 3 + 8 files changed, 404 insertions(+), 95 deletions(-) create mode 100644 src/java/org/apache/fop/pdf/PDFNumberTreeNode.java create mode 100644 src/java/org/apache/fop/pdf/PDFNumsArray.java create mode 100644 src/java/org/apache/fop/pdf/PDFPageLabels.java (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFDictionary.java b/src/java/org/apache/fop/pdf/PDFDictionary.java index 71393cace..c183871b5 100644 --- a/src/java/org/apache/fop/pdf/PDFDictionary.java +++ b/src/java/org/apache/fop/pdf/PDFDictionary.java @@ -101,16 +101,26 @@ public class PDFDictionary extends PDFObject { */ protected void writeDictionary(StringBuffer sb) { sb.append("<<"); + boolean compact = (this.order.size() <= 2); Iterator iter = this.order.iterator(); while (iter.hasNext()) { String key = (String)iter.next(); - sb.append("\n /"); - sb.append(key); - sb.append(" "); + if (compact) { + sb.append(' '); + } else { + sb.append("\n "); + } + sb.append('/').append(key); + sb.append(' '); Object obj = this.entries.get(key); formatObject(obj, sb); } - sb.append("\n>>\n"); + if (compact) { + sb.append(' '); + } else { + sb.append('\n'); + } + sb.append(">>\n"); } } diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index e1546baed..f851abae7 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -848,6 +848,17 @@ public class PDFFactory { return names; } + /** + * Make a names dictionary (the /PageLabels object). + * @return the new PDFPageLabels object + */ + public PDFPageLabels makePageLabels() { + PDFPageLabels pageLabels = new PDFPageLabels(); + getDocument().assignObjectNumber(pageLabels); + getDocument().addTrailerObject(pageLabels); + return pageLabels; + } + /** * Make a the head object of the name dictionary (the /Dests object). * diff --git a/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java b/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java new file mode 100644 index 000000000..4e69c01d4 --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java @@ -0,0 +1,121 @@ +/* + * 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.pdf; + +/** + * Class representing a PDF number tree node. + */ +public class PDFNumberTreeNode extends PDFDictionary { + + private static final String KIDS = "Kids"; + private static final String NUMS = "Nums"; + private static final String LIMITS = "Limits"; + + /** + * create a named destination + */ + public PDFNumberTreeNode() { + /* generic creation of PDF object */ + super(); + } + + /** + * Sets the Kids array. + * @param kids the Kids array + */ + public void setKids(PDFArray kids) { + put(KIDS, kids); + } + + /** + * Returns the Kids array. + * @return the Kids array + */ + public PDFArray getKids() { + return (PDFArray)get(KIDS); + } + + /** + * Sets the Nums array. + * @param nums the Nums array + */ + public void setNums(PDFNumsArray nums) { + put(NUMS, nums); + } + + /** + * Returns the Nums array. + * @return the Nums array + */ + public PDFNumsArray getNums() { + return (PDFNumsArray)get(NUMS); + } + + /** + * Sets the lower limit value of the Limits array. + * @param key the lower limit value + */ + public void setLowerLimit(Integer key) { + PDFArray limits = prepareLimitsArray(); + limits.set(0, key); + } + + /** + * Returns the lower limit value of the Limits array. + * @return the lower limit value + */ + public Integer getLowerLimit() { + PDFArray limits = prepareLimitsArray(); + return (Integer)limits.get(0); + } + + /** + * Sets the upper limit value of the Limits array. + * @param key the upper limit value + */ + public void setUpperLimit(Integer key) { + PDFArray limits = prepareLimitsArray(); + limits.set(1, key); + } + + /** + * Returns the upper limit value of the Limits array. + * @return the upper limit value + */ + public Integer getUpperLimit() { + PDFArray limits = prepareLimitsArray(); + return (Integer)limits.get(1); + } + + + private PDFArray prepareLimitsArray() { + PDFArray limits = (PDFArray)get(LIMITS); + if (limits == null) { + limits = new PDFArray(new Object[2]); + put(LIMITS, limits); + } + if (limits.length() != 2) { + throw new IllegalStateException("Limits array must have 2 entries"); + } + return limits; + } + +} + diff --git a/src/java/org/apache/fop/pdf/PDFNumsArray.java b/src/java/org/apache/fop/pdf/PDFNumsArray.java new file mode 100644 index 000000000..55f973ccd --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFNumsArray.java @@ -0,0 +1,94 @@ +/* + * 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: PDFArray.java 588547 2007-10-26 07:48:14Z jeremias $ */ + +package org.apache.fop.pdf; + +import java.util.Iterator; +import java.util.Map; +import java.util.SortedMap; + +/** + * Class representing an "Nums" array object (for Number Trees). + */ +public class PDFNumsArray extends PDFObject { + + /** Sorted Map holding the values of this array. */ + protected SortedMap map = new java.util.TreeMap(); + + /** + * Create a new, empty array object + */ + public PDFNumsArray() { + /* generic creation of PDF object */ + super(); + } + + /** + * Returns the length of the array + * @return the length of the array + */ + public int length() { + return this.map.size(); + } + + /** + * Sets an entry. + * @param key the key of the value to set + * @param obj the new value + */ + public void put(int key, Object obj) { + this.map.put(new Integer(key), obj); + } + + /** + * Gets an entry. + * @param key the key of requested value + * @return the requested value + */ + public Object get(int key) { + return this.map.get(new Integer(key)); + } + + /** {@inheritDoc} */ + public String toPDFString() { + StringBuffer p = new StringBuffer(64); + if (hasObjectNumber()) { + p.append(getObjectID()); + } + p.append("["); + boolean first = true; + Iterator iter = this.map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry)iter.next(); + if (!first) { + p.append(" "); + } + first = false; + formatObject(entry.getKey(), p); + p.append(" "); + formatObject(entry.getValue(), p); + } + p.append("]"); + if (hasObjectNumber()) { + p.append("\nendobj\n"); + } + return p.toString(); + } + +} diff --git a/src/java/org/apache/fop/pdf/PDFPageLabels.java b/src/java/org/apache/fop/pdf/PDFPageLabels.java new file mode 100644 index 000000000..bb02a3c7e --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFPageLabels.java @@ -0,0 +1,48 @@ +/* + * 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.pdf; + +/** + * Class representing a PDF /PageLabels dictionary. + */ +public class PDFPageLabels extends PDFNumberTreeNode { + + /** + * Create the /PageLabels dictionary + */ + public PDFPageLabels() { + super(); + } + + /** + * Returns the Nums object + * @return the Nums object (an empty PDFNumsArray for the "/Nums" entry is created + * if it doesn't exist) + */ + public PDFNumsArray getNums() { + PDFNumsArray nums = super.getNums(); + if (nums == null) { + nums = new PDFNumsArray(); + setNums(nums); + } + return nums; + } + +} diff --git a/src/java/org/apache/fop/pdf/PDFRoot.java b/src/java/org/apache/fop/pdf/PDFRoot.java index 64103df22..1a54a209f 100644 --- a/src/java/org/apache/fop/pdf/PDFRoot.java +++ b/src/java/org/apache/fop/pdf/PDFRoot.java @@ -19,12 +19,10 @@ package org.apache.fop.pdf; -import java.util.List; - /** - * class representing a Root (/Catalog) object + * Class representing a Root (/Catalog) object. */ -public class PDFRoot extends PDFObject { +public class PDFRoot extends PDFDictionary { /** * Use no page mode setting, default @@ -46,27 +44,13 @@ public class PDFRoot extends PDFObject { */ public static final int PAGEMODE_FULLSCREEN = 3; - /** - * the /Pages object that is root of the Pages hierarchy - */ - protected PDFPages rootPages; - - /** - * Root outline object - */ - private PDFOutline outline; - - /** Optional Metadata object */ - private PDFMetadata metadata; + private static final PDFName[] PAGEMODE_NAMES = new PDFName[] { + new PDFName("UseNone"), + new PDFName("UseOutlines"), + new PDFName("UseThumbs"), + new PDFName("FullScreen"), + }; - /** The array of OutputIntents */ - private List outputIntents; - - /** the /Dests object, if this PDF has a Names Dictionary */ - private PDFNames names; - - private int pageMode = PAGEMODE_USENONE; - /** * create a Root (/Catalog) object. NOTE: The PDFRoot * object must be created before the PDF document is @@ -80,25 +64,45 @@ public class PDFRoot extends PDFObject { public PDFRoot(int objnum, PDFPages pages) { super(); setObjectNumber(objnum); + put("Type", new PDFName("Catalog")); setRootPages(pages); } /** * Set the page mode for the PDF document. * - * @param mode the page mode + * @param mode the page mode (one of PAGEMODE_*) */ public void setPageMode(int mode) { - pageMode = mode; + put("PageMode", PAGEMODE_NAMES[mode]); } + /** + * Returns the currently active /PageMode. + * @return the /PageMode (one of PAGEMODE_*) + */ + public int getPageMode() { + PDFName mode = (PDFName)get("PageMode"); + if (mode != null) { + for (int i = 0; i < PAGEMODE_NAMES.length; i++) { + if (PAGEMODE_NAMES[i].equals(mode)) { + return i; + } + } + throw new IllegalStateException("Unknown /PageMode encountered: " + mode); + } else { + return PAGEMODE_USENONE; + } + } + /** * add a /Page object to the root /Pages object * * @param page the /Page object to add */ public void addPage(PDFPage page) { - this.rootPages.addPage(page); + PDFPages pages = getRootPages(); + pages.addPage(page); } /** @@ -107,16 +111,50 @@ public class PDFRoot extends PDFObject { * @param pages the /Pages object to set as root */ public void setRootPages(PDFPages pages) { - this.rootPages = pages; + put("Pages", pages.makeReference()); } + /** + * Returns the /PageLabels object. + * @return the /PageLabels object if set, null otherwise. + * @since PDF 1.3 + */ + public PDFPages getRootPages() { + PDFReference ref = (PDFReference)get("Pages"); + return (ref != null ? (PDFPages)ref.getObject() : null); + } + + /** + * Sets the /PageLabels object. + * @param pageLabels the /PageLabels object + */ + public void setPageLabels(PDFPageLabels pageLabels) { + put("PageLabels", pageLabels.makeReference()); + } + + /** + * Returns the /PageLabels object. + * @return the /PageLabels object if set, null otherwise. + * @since PDF 1.3 + */ + public PDFPageLabels getPageLabels() { + PDFReference ref = (PDFReference)get("PageLabels"); + return (ref != null ? (PDFPageLabels)ref.getObject() : null); + } + /** * Set the root outline for the PDF document. * * @param out the root PDF Outline */ public void setRootOutline(PDFOutline out) { - outline = out; + put("Outlines", out.makeReference()); + + //Set /PageMode to /UseOutlines by default if no other mode has been set + PDFName mode = (PDFName)get("PageMode"); + if (mode == null) { + setPageMode(PAGEMODE_USEOUTLINES); + } } /** @@ -125,24 +163,27 @@ public class PDFRoot extends PDFObject { * @return the root PDF Outline */ public PDFOutline getRootOutline() { - return outline; + PDFReference ref = (PDFReference)get("Outlines"); + return (ref != null ? (PDFOutline)ref.getObject() : null); } /** - * Set the Names object. + * Set the /Names object. * @param names the Names object * @since PDF 1.2 */ public void setNames(PDFNames names) { - this.names = names; + put("Names", names.makeReference()); } /** + * Returns the /Names object. * @return the Names object if set, null otherwise. * @since PDF 1.2 */ public PDFNames getNames() { - return this.names; + PDFReference ref = (PDFReference)get("Names"); + return (ref != null ? (PDFNames)ref.getObject() : null); } /** @@ -151,78 +192,44 @@ public class PDFRoot extends PDFObject { * @since PDF 1.4 */ public void setMetadata(PDFMetadata meta) { - this.metadata = meta; + if (getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) { + put("Metadata", meta.makeReference()); + } } /** - * @return the Metadata object if set, null otherwise. + * Returns the /Metadata object + * @return the /Metadata object if set, null otherwise. * @since PDF 1.4 */ public PDFMetadata getMetadata() { - return this.metadata; + PDFReference ref = (PDFReference)get("Metadata"); + return (ref != null ? (PDFMetadata)ref.getObject() : null); } /** - * Adds an OutputIntent to the PDF - * @param outputIntent the OutputIntent dictionary + * Returns the /OutputIntents array. + * @return the /OutputIntents array or null if it doesn't exist + * @since PDF 1.4 */ - public void addOutputIntent(PDFOutputIntent outputIntent) { - if (this.outputIntents == null) { - this.outputIntents = new java.util.ArrayList(); - } - this.outputIntents.add(outputIntent); + public PDFArray getOutputIntents() { + return (PDFArray)get("OutputIntents"); } /** - * {@inheritDoc} - */ - public String toPDFString() { - StringBuffer p = new StringBuffer(128); - p.append(getObjectID()); - p.append("<< /Type /Catalog\n /Pages " - + this.rootPages.referencePDF() - + "\n"); - if (outline != null) { - p.append(" /Outlines " + outline.referencePDF() + "\n"); - p.append(" /PageMode /UseOutlines\n"); - } else { - switch (pageMode) { - case PAGEMODE_USEOUTLINES: - p.append(" /PageMode /UseOutlines\n"); - break; - case PAGEMODE_USETHUMBS: - p.append(" /PageMode /UseThumbs\n"); - break; - case PAGEMODE_FULLSCREEN: - p.append(" /PageMode /FullScreen\n"); - break; - case PAGEMODE_USENONE: - default: - break; - } - } - if (getDocumentSafely().hasDestinations() && getNames() != null) { - p.append(" /Names " + getNames().referencePDF() + "\n"); - } - if (getMetadata() != null - && getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) { - p.append(" /Metadata " + getMetadata().referencePDF() + "\n"); - } - if (this.outputIntents != null - && this.outputIntents.size() > 0 - && getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) { - p.append(" /OutputIntents ["); - for (int i = 0, c = this.outputIntents.size(); i < c; i++) { - PDFOutputIntent outputIntent = (PDFOutputIntent)this.outputIntents.get(i); - if (i > 0) { - p.append(" "); - } - p.append(outputIntent.referencePDF()); + * Adds an OutputIntent to the PDF + * @param outputIntent the OutputIntent dictionary + * @since PDF 1.4 + */ + public void addOutputIntent(PDFOutputIntent outputIntent) { + if (getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) { + PDFArray outputIntents = getOutputIntents(); + if (outputIntents == null) { + outputIntents = new PDFArray(); + put("OutputIntents", outputIntents); } - p.append("]\n"); + outputIntents.add(outputIntent); } - p.append(">>\nendobj\n"); - return p.toString(); } - + } diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index a03179692..2d8e7d5ba 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -73,6 +73,7 @@ import org.apache.fop.pdf.PDFAction; import org.apache.fop.pdf.PDFAnnotList; import org.apache.fop.pdf.PDFColor; import org.apache.fop.pdf.PDFConformanceException; +import org.apache.fop.pdf.PDFDictionary; import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFEncryptionManager; import org.apache.fop.pdf.PDFEncryptionParams; @@ -88,6 +89,7 @@ import org.apache.fop.pdf.PDFNumber; import org.apache.fop.pdf.PDFOutline; import org.apache.fop.pdf.PDFOutputIntent; import org.apache.fop.pdf.PDFPage; +import org.apache.fop.pdf.PDFPageLabels; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; import org.apache.fop.pdf.PDFState; @@ -715,6 +717,19 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { page.getPageIndex()); pageReferences.put(page.getKey(), currentPage.referencePDF()); pvReferences.put(page.getKey(), page); + + //Produce page labels + PDFPageLabels pageLabels = this.pdfDoc.getRoot().getPageLabels(); + if (pageLabels == null) { + //Set up PageLabels + pageLabels = this.pdfDoc.getFactory().makePageLabels(); + this.pdfDoc.getRoot().setPageLabels(pageLabels); + } + PDFDictionary dict = new PDFDictionary(); + dict.put("P", page.getPageNumberString()); + //TODO If the sequence of generated page numbers were inspected, this could be + //expressed in a more space-efficient way + pageLabels.getNums().put(page.getPageIndex(), dict); } /** diff --git a/status.xml b/status.xml index 1c2f18b4b..3b8881211 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Added support for PDF page labels. + Added support for custom fonts in Java2DRenderer and derived renderers. -- cgit v1.2.3 From e8fd5b3999e6bfbda9453017012266951db71c83 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 10 Jan 2008 10:13:21 +0000 Subject: PostScript output now generates the bounding box DSC comments for the whole document. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610739 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/ps/PSRenderer.java | 36 ++++++++++++++++------ .../org/apache/fop/render/ps/ResourceHandler.java | 21 ++++++++++--- status.xml | 3 ++ 3 files changed, 46 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index 3befb0738..7580bd0d5 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -35,9 +35,22 @@ import java.util.Map; import javax.xml.transform.Source; +import org.w3c.dom.Document; + import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.ps.DSCConstants; +import org.apache.xmlgraphics.ps.PSGenerator; +import org.apache.xmlgraphics.ps.PSProcSets; +import org.apache.xmlgraphics.ps.PSResource; +import org.apache.xmlgraphics.ps.PSState; +import org.apache.xmlgraphics.ps.dsc.DSCException; +import org.apache.xmlgraphics.ps.dsc.ResourceTracker; +import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox; +import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; @@ -75,14 +88,6 @@ import org.apache.fop.render.ps.extensions.PSExtensionAttachment; import org.apache.fop.render.ps.extensions.PSSetPageDevice; import org.apache.fop.render.ps.extensions.PSSetupCode; import org.apache.fop.util.CharUtilities; -import org.apache.xmlgraphics.ps.DSCConstants; -import org.apache.xmlgraphics.ps.PSGenerator; -import org.apache.xmlgraphics.ps.PSProcSets; -import org.apache.xmlgraphics.ps.PSResource; -import org.apache.xmlgraphics.ps.PSState; -import org.apache.xmlgraphics.ps.dsc.DSCException; -import org.apache.xmlgraphics.ps.dsc.ResourceTracker; -import org.w3c.dom.Document; /** * Renderer that renders to PostScript. @@ -152,6 +157,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda /** Whether or not Dublin Core Standard (dsc) compliant output is enforced */ private boolean dscCompliant = true; + /** Is used to determine the document's bounding box */ + private Rectangle2D documentBoundingBox; + /** This is a collection holding all document header comments */ private Collection headerComments; @@ -776,6 +784,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda gen.writeDSCComment(DSCConstants.CREATION_DATE, new Object[] {new java.util.Date()}); gen.writeDSCComment(DSCConstants.LANGUAGE_LEVEL, new Integer(gen.getPSLevel())); gen.writeDSCComment(DSCConstants.PAGES, new Object[] {DSCConstants.ATEND}); + gen.writeDSCComment(DSCConstants.BBOX, DSCConstants.ATEND); + gen.writeDSCComment(DSCConstants.HIRES_BBOX, DSCConstants.ATEND); + this.documentBoundingBox = new Rectangle2D.Double(); gen.writeDSCComment(DSCConstants.DOCUMENT_SUPPLIED_RESOURCES, new Object[] {DSCConstants.ATEND}); if (headerComments != null) { @@ -833,6 +844,8 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda footerComments.clear(); } gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.currentPageNumber)); + new DSCCommentBoundingBox(this.documentBoundingBox).generate(gen); + new DSCCommentHiResBoundingBox(this.documentBoundingBox).generate(gen); gen.getResourceTracker().writeResources(false, gen); gen.writeDSCComment(DSCConstants.EOF); gen.flush(); @@ -863,7 +876,8 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda try { try { ResourceHandler.process(this.userAgent, in, this.outputStream, - this.fontInfo, resTracker, this.formResources, this.currentPageNumber); + this.fontInfo, resTracker, this.formResources, + this.currentPageNumber, this.documentBoundingBox); this.outputStream.flush(); } catch (DSCException e) { throw new RuntimeException(e.getMessage()); @@ -1031,7 +1045,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda log.error(e.getMessage()); } final Integer zero = new Integer(0); + Rectangle2D pageBoundingBox = new Rectangle2D.Double(); if (rotate) { + pageBoundingBox.setRect(0, 0, pageHeight, pageWidth); gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] { zero, zero, new Long(Math.round(pageHeight)), new Long(Math.round(pageWidth)) }); @@ -1040,6 +1056,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda new Double(pageWidth) }); gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape"); } else { + pageBoundingBox.setRect(0, 0, pageWidth, pageHeight); gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] { zero, zero, new Long(Math.round(pageWidth)), new Long(Math.round(pageHeight)) }); @@ -1051,6 +1068,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda "Portrait"); } } + this.documentBoundingBox.add(pageBoundingBox); gen.writeDSCComment(DSCConstants.PAGE_RESOURCES, new Object[] {DSCConstants.ATEND}); diff --git a/src/java/org/apache/fop/render/ps/ResourceHandler.java b/src/java/org/apache/fop/render/ps/ResourceHandler.java index f187e619a..a0762e6e0 100644 --- a/src/java/org/apache/fop/render/ps/ResourceHandler.java +++ b/src/java/org/apache/fop/render/ps/ResourceHandler.java @@ -19,6 +19,7 @@ package org.apache.fop.render.ps; +import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -26,10 +27,6 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; import org.apache.xmlgraphics.ps.DSCConstants; import org.apache.xmlgraphics.ps.PSGenerator; import org.apache.xmlgraphics.ps.dsc.DSCException; @@ -39,8 +36,10 @@ import org.apache.xmlgraphics.ps.dsc.DSCParserConstants; import org.apache.xmlgraphics.ps.dsc.DefaultNestedDocumentHandler; import org.apache.xmlgraphics.ps.dsc.ResourceTracker; import org.apache.xmlgraphics.ps.dsc.events.DSCComment; +import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox; import org.apache.xmlgraphics.ps.dsc.events.DSCCommentDocumentNeededResources; import org.apache.xmlgraphics.ps.dsc.events.DSCCommentDocumentSuppliedResources; +import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox; import org.apache.xmlgraphics.ps.dsc.events.DSCCommentLanguageLevel; import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPage; import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPages; @@ -49,6 +48,11 @@ import org.apache.xmlgraphics.ps.dsc.events.DSCHeaderComment; import org.apache.xmlgraphics.ps.dsc.events.PostScriptComment; import org.apache.xmlgraphics.ps.dsc.tools.DSCTools; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.image.FopImage; +import org.apache.fop.image.ImageFactory; + /** * This class is used when two-pass production is used to generate the PostScript file (setting * "optimize-resources"). It uses the DSC parser from XML Graphics Commons to go over the @@ -67,11 +71,14 @@ public class ResourceHandler implements DSCParserConstants { * @param resTracker the resource tracker to use * @param formResources Contains all forms used by this document (maintained by PSRenderer) * @param pageCount the number of pages (given here because PSRenderer writes an "(atend)") + * @param documentBoundingBox the document's bounding box + * (given here because PSRenderer writes an "(atend)") * @throws DSCException If there's an error in the DSC structure of the PS file * @throws IOException In case of an I/O error */ public static void process(FOUserAgent userAgent, InputStream in, OutputStream out, - FontInfo fontInfo, ResourceTracker resTracker, Map formResources, int pageCount) + FontInfo fontInfo, ResourceTracker resTracker, Map formResources, + int pageCount, Rectangle2D documentBoundingBox) throws DSCException, IOException { DSCParser parser = new DSCParser(in); PSGenerator gen = new PSGenerator(out); @@ -86,6 +93,8 @@ public class ResourceHandler implements DSCParserConstants { { //We rewrite those as part of the processing filtered.add(DSCConstants.PAGES); + filtered.add(DSCConstants.BBOX); + filtered.add(DSCConstants.HIRES_BBOX); filtered.add(DSCConstants.DOCUMENT_NEEDED_RESOURCES); filtered.add(DSCConstants.DOCUMENT_SUPPLIED_RESOURCES); } @@ -109,6 +118,8 @@ public class ResourceHandler implements DSCParserConstants { //Set number of pages DSCCommentPages pages = new DSCCommentPages(pageCount); pages.generate(gen); + new DSCCommentBoundingBox(documentBoundingBox).generate(gen); + new DSCCommentHiResBoundingBox(documentBoundingBox).generate(gen); PSFontUtils.determineSuppliedFonts(resTracker, fontInfo, fontInfo.getUsedFonts()); registerSuppliedForms(resTracker, formResources); diff --git a/status.xml b/status.xml index 3b8881211..829a76a66 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + PostScript output now generates the bounding box DSC comments for the whole document. + Added support for PDF page labels. -- cgit v1.2.3 From 8fb6ba565df16744165598c9a74d3dcc5ac85795 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 10 Jan 2008 15:53:20 +0000 Subject: - renamed variables for clarity - moved the computation of a cell's content length in PrimaryGridUnit - better javadoc for getHeight method in EffRow git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610821 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/EffRow.java | 11 +++- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 9 ++-- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 59 ++++++++++------------ 3 files changed, 39 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java index 17ab67f98..03012aa3c 100644 --- a/src/java/org/apache/fop/fo/flow/table/EffRow.java +++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java @@ -80,13 +80,20 @@ public class EffRow { return getGridUnit(0).getRow(); } - /** @return the calculated height for this EffRow. */ + /** + * Returns the calculated height for this EffRow, including the cells' + * bpds/paddings/borders, and the table's border-separation. + * + * @return the row's height + */ public MinOptMax getHeight() { return this.height; } /** - * Sets the calculated height for this EffRow. + * Sets the calculated height for this EffRow, including everything (cells' bpds, + * paddings, borders, and border-separation). + * * @param mom the calculated height */ public void setHeight(MinOptMax mom) { diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 2f2cd940e..ae8db7ba7 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.table.TableCellLayoutManager; /** @@ -142,13 +143,11 @@ public class PrimaryGridUnit extends GridUnit { return getHalfMaxBeforeBorderWidth() + getHalfMaxAfterBorderWidth(); } - /** @param value The length of the cell content to remember. */ - public void setContentLength(int value) { - this.contentLength = value; - } - /** @return the length of the cell content. */ public int getContentLength() { + if (contentLength < 0) { + contentLength = ElementListUtils.calcContentLength(elements); + } return contentLength; } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 028d60bf3..3fa40a8fd 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -148,9 +148,9 @@ class RowGroupLayoutManager { TableRow tableRow = null; // The row's minimum content height; 0 if the row's height is auto, otherwise // the .minimum component of the explicitly specified value - int minContentHeight = 0; - int maxCellHeight = 0; - int effRowContentHeight = 0; + int minRowBPD = 0; + // The BPD of the biggest cell in the row + int maxCellBPD = 0; for (int j = 0; j < row.getGridUnits().size(); j++) { assert maxColumnCount == 0 || maxColumnCount == row.getGridUnits().size(); maxColumnCount = Math.max(maxColumnCount, row.getGridUnits().size()); @@ -168,14 +168,12 @@ class RowGroupLayoutManager { tableRow = primary.getRow(); //Check for bpd on row, see CSS21, 17.5.3 Table height algorithms - LengthRangeProperty bpd = tableRow.getBlockProgressionDimension(); - if (!bpd.getMinimum(tableLM).isAuto()) { - minContentHeight = Math.max( - minContentHeight, - bpd.getMinimum( - tableLM).getLength().getValue(tableLM)); + LengthRangeProperty rowBPD = tableRow.getBlockProgressionDimension(); + if (!rowBPD.getMinimum(tableLM).isAuto()) { + minRowBPD = Math.max(minRowBPD, + rowBPD.getMinimum(tableLM).getLength().getValue(tableLM)); } - MinOptMaxUtil.restrict(explicitRowHeights[rgi], bpd, tableLM); + MinOptMaxUtil.restrict(explicitRowHeights[rgi], rowBPD, tableLM); } @@ -218,31 +216,27 @@ class RowGroupLayoutManager { } } - - //Calculate height of cell contents - primary.setContentLength(ElementListUtils.calcContentLength( - primary.getElements())); - maxCellHeight = Math.max(maxCellHeight, primary.getContentLength()); - //Calculate height of row, see CSS21, 17.5.3 Table height algorithms if (gu.isLastGridUnitRowSpan()) { - int effCellContentHeight = minContentHeight; - LengthRangeProperty bpd = primary.getCell().getBlockProgressionDimension(); - if (!bpd.getMinimum(tableLM).isAuto()) { - effCellContentHeight = Math.max( - effCellContentHeight, - bpd.getMinimum(tableLM).getLength().getValue(tableLM)); + // The effective cell's bpd, after taking into account bpd + // (possibly explicitly) set on the row or on the cell, and the + // cell's content length + int effectiveCellBPD = minRowBPD; + LengthRangeProperty cellBPD = primary.getCell() + .getBlockProgressionDimension(); + if (!cellBPD.getMinimum(tableLM).isAuto()) { + effectiveCellBPD = Math.max(effectiveCellBPD, + cellBPD.getMinimum(tableLM).getLength().getValue(tableLM)); } - if (!bpd.getOptimum(tableLM).isAuto()) { - effCellContentHeight = Math.max( - effCellContentHeight, - bpd.getOptimum(tableLM).getLength().getValue(tableLM)); + if (!cellBPD.getOptimum(tableLM).isAuto()) { + effectiveCellBPD = Math.max(effectiveCellBPD, + cellBPD.getOptimum(tableLM).getLength().getValue(tableLM)); } if (gu.getRowSpanIndex() == 0) { //TODO ATM only non-row-spanned cells are taken for this - MinOptMaxUtil.restrict(explicitRowHeights[rgi], bpd, tableLM); + MinOptMaxUtil.restrict(explicitRowHeights[rgi], cellBPD, tableLM); } - effCellContentHeight = Math.max(effCellContentHeight, + effectiveCellBPD = Math.max(effectiveCellBPD, primary.getContentLength()); int borderWidths; @@ -253,13 +247,12 @@ class RowGroupLayoutManager { borderWidths = primary.getHalfMaxBorderWidth(); } int padding = 0; - effRowContentHeight = Math.max(effRowContentHeight, - effCellContentHeight); + maxCellBPD = Math.max(maxCellBPD, effectiveCellBPD); CommonBorderPaddingBackground cbpb = primary.getCell().getCommonBorderPaddingBackground(); padding += cbpb.getPaddingBefore(false, primary.getCellLM()); padding += cbpb.getPaddingAfter(false, primary.getCellLM()); - int effRowHeight = effCellContentHeight + int effRowHeight = effectiveCellBPD + padding + borderWidths + 2 * tableLM.getHalfBorderSeparationBPD(); for (int previous = 0; previous < gu.getRowSpanIndex(); previous++) { @@ -279,13 +272,13 @@ class RowGroupLayoutManager { row.setHeight(rowHeights[rgi]); row.setExplicitHeight(explicitRowHeights[rgi]); - if (effRowContentHeight > row.getExplicitHeight().max) { + if (maxCellBPD > row.getExplicitHeight().max) { log.warn(FONode.decorateWithContextInfo( "The contents of row " + (row.getIndex() + 1) + " are taller than they should be (there is a" + " block-progression-dimension or height constraint on the indicated row)." + " Due to its contents the row grows" - + " to " + effRowContentHeight + " millipoints, but the row shouldn't get" + + " to " + maxCellBPD + " millipoints, but the row shouldn't get" + " any taller than " + row.getExplicitHeight() + " millipoints.", row.getTableRow())); } -- cgit v1.2.3 From 29e6465b7caefae6fc6beb04ff63c5d65eeb5504 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 10 Jan 2008 17:41:52 +0000 Subject: No need to check if the end of the cell is reached when creating the areas for a row git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610848 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 6d2568afb..3df06e482 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -170,8 +170,7 @@ class RowPainter { for (int i = 0; i < primaryGridUnits.length; i++) { GridUnit currentGU = lastRow.getGridUnit(i); if (primaryGridUnits[i] != null) { - if (forcedFlush || ((end[i] == primaryGridUnits[i].getElements().size() - 1) - && currentGU.isLastGridUnitRowSpan())) { + if (forcedFlush || currentGU.isLastGridUnitRowSpan()) { //the last line in the "if" above is to avoid a premature end of a //row-spanned cell because no CellParts are generated after a cell is //finished with its content. -- cgit v1.2.3 From 8c267304cbe4be06ff567b297b9f93364875b595 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 10 Jan 2008 17:54:16 +0000 Subject: Simplified addAreasAndFlushRow git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610853 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/RowPainter.java | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 3df06e482..f31076537 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -169,27 +169,11 @@ class RowPainter { tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), yoffset); for (int i = 0; i < primaryGridUnits.length; i++) { GridUnit currentGU = lastRow.getGridUnit(i); - if (primaryGridUnits[i] != null) { - if (forcedFlush || currentGU.isLastGridUnitRowSpan()) { - //the last line in the "if" above is to avoid a premature end of a - //row-spanned cell because no CellParts are generated after a cell is - //finished with its content. - //See table-cell_number-rows-spanned_bug38397.xml - addAreasForCell(primaryGridUnits[i], start[i], end[i], lastRow, partBPD[i], - actualRowHeight); - primaryGridUnits[i] = null; - start[i] = 0; - end[i] = -1; - partBPD[i] = 0; - } - } else if (!currentGU.isEmpty() - && currentGU.getColSpanIndex() == 0 + if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 && (forcedFlush || currentGU.isLastGridUnitRowSpan())) { - //A row-spanned cell has finished contributing content on the previous page - //and now still has to cause grid units to be painted. - //See table-cell_page-break_span.xml addAreasForCell(currentGU.getPrimary(), start[i], end[i], lastRow, partBPD[i], actualRowHeight); + primaryGridUnits[i] = null; start[i] = 0; end[i] = -1; partBPD[i] = 0; -- cgit v1.2.3 From 2282c3ce2e807a2dfbf205f2d2cf6ae98442f474 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 10 Jan 2008 19:23:56 +0000 Subject: Removed endPart() method and moved its content into addAreasAndFlushRow() git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610886 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 9 +++------ .../apache/fop/layoutmgr/table/TableContentLayoutManager.java | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index f31076537..1af05cc99 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -187,8 +187,10 @@ class RowPainter { // (header, footer, body) has been reached, and the next row will anyway be // different from the current one, and this is unnecessary to recall this // method in the first lines of handleTableContentPosition, so we may reset - // lastRow + // the following variables lastRow = null; + firstRowIndex = -1; + rowOffsets.clear(); } return actualRowHeight; } @@ -358,9 +360,4 @@ class RowPainter { private int getRowOffset(int rowIndex) { return ((Integer) rowOffsets.get(rowIndex - firstRowIndex)).intValue(); } - - void endPart() { - firstRowIndex = -1; - rowOffsets.clear(); - } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 308b2cca7..57972078e 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -418,7 +418,6 @@ public class TableContentLayoutManager implements PercentBaseContext { handleMarkersAndPositions(lst, body, firstPos, false, painter); } painter.addAreasAndFlushRow(true); - painter.endPart(); } private void handleMarkersAndPositions(List positions, TableBody body, boolean firstPos, -- cgit v1.2.3 From f8dea60c1848c1eea105d7133e258366caf658a1 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 10 Jan 2008 19:34:13 +0000 Subject: Removed accumulatedBPD which is redundant with yoffset git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610891 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 1af05cc99..59a7c9dc5 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -43,7 +43,6 @@ class RowPainter { private TableRow rowFO = null; private int colCount; private int yoffset = 0; - private int accumulatedBPD = 0; /** Currently handled row (= last encountered row). */ private EffRow lastRow = null; private LayoutContext layoutContext; @@ -91,7 +90,7 @@ class RowPainter { } int getAccumulatedBPD() { - return this.accumulatedBPD; + return yoffset; } /** @@ -180,7 +179,6 @@ class RowPainter { } } yoffset += actualRowHeight; - accumulatedBPD += actualRowHeight; if (forcedFlush) { // Either the end of the page is reached, then this was the last call of this // method and we no longer care about lastRow; or the end of a table-part -- cgit v1.2.3 From 6d0258a999b480b52639256d0f8b4b88ee73ec5b Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 10 Jan 2008 19:35:24 +0000 Subject: The return value of addAreasAndFlushRow is never used, changed it to void git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610893 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 59a7c9dc5..228ae333b 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -145,9 +145,8 @@ class RowPainter { * @param forcedFlush true if the elements must be drawn even if the row isn't * finished yet (last row on the page), or if the row is the last of the current table * part - * @return the height of the (grid) row */ - int addAreasAndFlushRow(boolean forcedFlush) { + void addAreasAndFlushRow(boolean forcedFlush) { int actualRowHeight = 0; if (log.isDebugEnabled()) { @@ -190,7 +189,6 @@ class RowPainter { firstRowIndex = -1; rowOffsets.clear(); } - return actualRowHeight; } /** -- cgit v1.2.3 From 25d54cbe272b847655d66cff12b2af171233a723 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 10 Jan 2008 19:57:29 +0000 Subject: Renamed lastRow into currentRow and yoffset into currentRowOffset git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@610905 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/RowPainter.java | 52 +++++++++++----------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 228ae333b..9a79d7744 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -42,9 +42,9 @@ class RowPainter { /** The fo:table-row containing the currently handled grid rows. */ private TableRow rowFO = null; private int colCount; - private int yoffset = 0; + private int currentRowOffset = 0; /** Currently handled row (= last encountered row). */ - private EffRow lastRow = null; + private EffRow currentRow = null; private LayoutContext layoutContext; /** * Index of the first row of the current part present on the current page. @@ -90,7 +90,7 @@ class RowPainter { } int getAccumulatedBPD() { - return yoffset; + return currentRowOffset; } /** @@ -100,16 +100,16 @@ class RowPainter { * @param tcpos a position representing the row fragment */ void handleTableContentPosition(TableContentPosition tcpos) { - if (lastRow != tcpos.row && lastRow != null) { + if (tcpos.row != currentRow && currentRow != null) { addAreasAndFlushRow(false); } if (log.isDebugEnabled()) { log.debug("===handleTableContentPosition(" + tcpos); } rowFO = tcpos.row.getTableRow(); - lastRow = tcpos.row; + currentRow = tcpos.row; if (firstRowIndex < 0) { - firstRowIndex = lastRow.getIndex(); + firstRowIndex = currentRow.getIndex(); } Iterator partIter = tcpos.cellParts.iterator(); //Iterate over all grid units in the current step @@ -150,9 +150,10 @@ class RowPainter { int actualRowHeight = 0; if (log.isDebugEnabled()) { - log.debug("Remembering yoffset for row " + lastRow.getIndex() + ": " + yoffset); + log.debug("Remembering yoffset for row " + currentRow.getIndex() + ": " + + currentRowOffset); } - recordRowOffset(lastRow.getIndex(), yoffset); + recordRowOffset(currentRow.getIndex(), currentRowOffset); for (int i = 0; i < primaryGridUnits.length; i++) { if ((primaryGridUnits[i] != null) @@ -164,12 +165,13 @@ class RowPainter { actualRowHeight += 2 * tclm.getTableLM().getHalfBorderSeparationBPD(); //Add areas for row - tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), yoffset); + tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), + currentRowOffset); for (int i = 0; i < primaryGridUnits.length; i++) { - GridUnit currentGU = lastRow.getGridUnit(i); + GridUnit currentGU = currentRow.getGridUnit(i); if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 && (forcedFlush || currentGU.isLastGridUnitRowSpan())) { - addAreasForCell(currentGU.getPrimary(), start[i], end[i], lastRow, partBPD[i], + addAreasForCell(currentGU.getPrimary(), start[i], end[i], currentRow, partBPD[i], actualRowHeight); primaryGridUnits[i] = null; start[i] = 0; @@ -177,15 +179,15 @@ class RowPainter { partBPD[i] = 0; } } - yoffset += actualRowHeight; + currentRowOffset += actualRowHeight; if (forcedFlush) { // Either the end of the page is reached, then this was the last call of this - // method and we no longer care about lastRow; or the end of a table-part + // method and we no longer care about currentRow; or the end of a table-part // (header, footer, body) has been reached, and the next row will anyway be // different from the current one, and this is unnecessary to recall this // method in the first lines of handleTableContentPosition, so we may reset // the following variables - lastRow = null; + currentRow = null; firstRowIndex = -1; rowOffsets.clear(); } @@ -194,8 +196,7 @@ class RowPainter { /** * Computes the total height of the part of the given cell spanning on the current * active row, including borders and paddings. The bpd is also stored in partBPD, and - * it is ensured that the cell's or row's explicit height is respected. yoffset is - * updated accordingly. + * it is ensured that the cell's or row's explicit height is respected. * * @param pgu primary grid unit corresponding to the cell * @param start index of the first element of the cell occuring on the current page @@ -271,7 +272,7 @@ class RowPainter { len += pgu.getHalfMaxAfterBorderWidth(); } int cellOffset = getRowOffset(Math.max(pgu.getStartRow(), firstRowIndex)); - len -= yoffset - cellOffset; + len -= currentRowOffset - cellOffset; return len; } @@ -279,7 +280,7 @@ class RowPainter { EffRow row, int contentHeight, int rowHeight) { //Determine the first row in this sequence int startRowIndex = Math.max(pgu.getStartRow(), firstRowIndex); - int lastRowIndex = lastRow.getIndex(); + int currentRowIndex = currentRow.getIndex(); // In collapsing-border model, if the cell spans over several columns/rows then // dedicated areas will be created for each grid unit to hold the corresponding @@ -287,23 +288,24 @@ class RowPainter { // grid row spanned over by the cell int[] spannedGridRowHeights = null; if (!tclm.getTableLM().getTable().isSeparateBorderModel() && pgu.hasSpanning()) { - spannedGridRowHeights = new int[lastRowIndex - startRowIndex + 1]; + spannedGridRowHeights = new int[currentRowIndex - startRowIndex + 1]; int prevOffset = getRowOffset(startRowIndex); - for (int i = 0; i < lastRowIndex - startRowIndex; i++) { + for (int i = 0; i < currentRowIndex - startRowIndex; i++) { int newOffset = getRowOffset(startRowIndex + i + 1); spannedGridRowHeights[i] = newOffset - prevOffset; prevOffset = newOffset; } - spannedGridRowHeights[lastRowIndex - startRowIndex] = rowHeight; + spannedGridRowHeights[currentRowIndex - startRowIndex] = rowHeight; } int cellOffset = getRowOffset(startRowIndex); int effCellHeight = rowHeight; - effCellHeight += yoffset - cellOffset; + effCellHeight += currentRowOffset - cellOffset; if (log.isDebugEnabled()) { log.debug("Creating area for cell:"); log.debug(" current row: " + row.getIndex()); - log.debug(" start row: " + pgu.getStartRow() + " " + yoffset + " " + cellOffset); + log.debug(" start row: " + pgu.getStartRow() + " " + currentRowOffset + " " + + cellOffset); log.debug(" contentHeight: " + contentHeight + " rowHeight=" + rowHeight + " effCellHeight=" + effCellHeight); } @@ -320,7 +322,7 @@ class RowPainter { } cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(), startPos, endPos + 1), layoutContext, spannedGridRowHeights, startRowIndex - pgu.getStartRow(), - lastRowIndex - pgu.getStartRow() + 1); + currentRowIndex - pgu.getStartRow() + 1); } /** @@ -338,7 +340,7 @@ class RowPainter { * TableContentPosition will be created for this row. Thus its index will never be * recorded by the #handleTableContentPosition method. * - * The yoffset for such a row is the same as the next non-empty row. It's needed + * The offset of such a row is the same as the next non-empty row. It's needed * to correctly offset blocks for cells starting on this row. Hence the loop * below. */ -- cgit v1.2.3 From db4f3b282c3c02db5e4a712a40eff4c897a85b13 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 11 Jan 2008 09:04:28 +0000 Subject: Bugfix: Some string objects were not encrypted (for example in named destinations) I had to refactor the PDF library a little bit but since it only affects the inner API it shouldn't be a problem that I removed some methods which caused trouble because a didn't think about encryption when I worked on the PDF library last year. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@611114 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/AbstractPDFStream.java | 41 ++-- src/java/org/apache/fop/pdf/BitmapImage.java | 9 - src/java/org/apache/fop/pdf/PDFArray.java | 72 +++--- src/java/org/apache/fop/pdf/PDFDestination.java | 40 ++-- src/java/org/apache/fop/pdf/PDFDests.java | 2 +- src/java/org/apache/fop/pdf/PDFDictionary.java | 64 ++++-- src/java/org/apache/fop/pdf/PDFDocument.java | 19 +- src/java/org/apache/fop/pdf/PDFEncryptionJCE.java | 27 ++- src/java/org/apache/fop/pdf/PDFFactory.java | 13 +- src/java/org/apache/fop/pdf/PDFFilterList.java | 4 +- src/java/org/apache/fop/pdf/PDFFormXObject.java | 6 +- src/java/org/apache/fop/pdf/PDFImage.java | 5 +- src/java/org/apache/fop/pdf/PDFImageXObject.java | 7 +- src/java/org/apache/fop/pdf/PDFName.java | 13 +- src/java/org/apache/fop/pdf/PDFNameTreeNode.java | 2 +- src/java/org/apache/fop/pdf/PDFNull.java | 10 +- src/java/org/apache/fop/pdf/PDFNumberTreeNode.java | 242 ++++++++++----------- src/java/org/apache/fop/pdf/PDFNumsArray.java | 198 +++++++++-------- src/java/org/apache/fop/pdf/PDFObject.java | 91 ++++++-- src/java/org/apache/fop/pdf/PDFPageLabels.java | 96 ++++---- src/java/org/apache/fop/pdf/PDFReference.java | 9 +- src/java/org/apache/fop/pdf/PDFRoot.java | 2 +- src/java/org/apache/fop/pdf/PDFWritable.java | 16 +- .../org/apache/fop/render/pdf/FopPDFImage.java | 6 +- .../org/apache/fop/render/pdf/PDFRenderer.java | 20 +- status.xml | 3 + 26 files changed, 564 insertions(+), 453 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/AbstractPDFStream.java b/src/java/org/apache/fop/pdf/AbstractPDFStream.java index 0ade68f89..16190da99 100644 --- a/src/java/org/apache/fop/pdf/AbstractPDFStream.java +++ b/src/java/org/apache/fop/pdf/AbstractPDFStream.java @@ -21,8 +21,10 @@ package org.apache.fop.pdf; import java.io.IOException; import java.io.OutputStream; +import java.io.Writer; import org.apache.commons.io.output.CountingOutputStream; + import org.apache.fop.util.CloseBlockerOutputStream; /** @@ -169,8 +171,12 @@ public abstract class AbstractPDFStream extends PDFDictionary { * {@inheritDoc} */ protected int output(OutputStream stream) throws IOException { - int length = 0; setupFilterList(); + + CountingOutputStream cout = new CountingOutputStream(stream); + Writer writer = PDFDocument.getWriterFor(cout); + writer.write(getObjectID()); + //int length = 0; StreamCache encodedStream = null; PDFNumber refLength = null; @@ -184,38 +190,21 @@ public abstract class AbstractPDFStream extends PDFDictionary { lengthEntry = new Integer(encodedStream.getSize() + 1); } - byte[] p = encode(buildStreamDict(lengthEntry)); - stream.write(p); - length += p.length; + populateStreamDict(lengthEntry); + writeDictionary(cout, writer); //Send encoded stream to target OutputStream + writer.flush(); if (encodedStream == null) { - int bytesWritten = encodeAndWriteStream(stream, refLength); - length += bytesWritten; + encodeAndWriteStream(cout, refLength); } else { - length += outputStreamData(encodedStream, stream); + outputStreamData(encodedStream, cout); encodedStream.clear(); //Encoded stream can now be discarded } - p = encode("\nendobj\n"); - stream.write(p); - length += p.length; - return length; - } - - /** - * Constructs the dictionary for the stream. Override this method if you - * need additional entries. - * @param lengthEntry value for the /Length entry - * @return the newly constructed dictionary - */ - protected String buildStreamDict(Object lengthEntry) { - StringBuffer sb = new StringBuffer(); - sb.append(getObjectID()); - populateStreamDict(lengthEntry); - - writeDictionary(sb); - return sb.toString(); + writer.write("\nendobj\n"); + writer.flush(); + return cout.getCount(); } /** diff --git a/src/java/org/apache/fop/pdf/BitmapImage.java b/src/java/org/apache/fop/pdf/BitmapImage.java index 461ec0a64..34c78ffe3 100644 --- a/src/java/org/apache/fop/pdf/BitmapImage.java +++ b/src/java/org/apache/fop/pdf/BitmapImage.java @@ -163,15 +163,6 @@ public class BitmapImage implements PDFImage { return null; } - /** - * Get the soft mask reference for this image. - * - * @return the soft mask reference if any - */ - public String getSoftMask() { - return maskRef.toInlinePDFString(); - } - /** {@inheritDoc} */ public PDFReference getSoftMaskReference() { return maskRef; diff --git a/src/java/org/apache/fop/pdf/PDFArray.java b/src/java/org/apache/fop/pdf/PDFArray.java index 2dd68ad8b..2cb2adb1d 100644 --- a/src/java/org/apache/fop/pdf/PDFArray.java +++ b/src/java/org/apache/fop/pdf/PDFArray.java @@ -19,9 +19,14 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; import java.util.Collection; import java.util.List; +import org.apache.commons.io.output.CountingOutputStream; + /** * Class representing an array object. */ @@ -33,20 +38,21 @@ public class PDFArray extends PDFObject { /** * Create a new, empty array object + * @param parent the array's parent if any */ - public PDFArray() { + public PDFArray(PDFObject parent) { /* generic creation of PDF object */ - super(); + super(parent); } /** - * Create the array object - * + * Create an array object. + * @param parent the array's parent if any * @param values the actual array wrapped by this object */ - public PDFArray(int[] values) { + public PDFArray(PDFObject parent, int[] values) { /* generic creation of PDF object */ - super(); + super(parent); for (int i = 0, c = values.length; i < c; i++) { this.values.add(new Integer(values[i])); @@ -54,25 +60,25 @@ public class PDFArray extends PDFObject { } /** - * Create the array object - * + * Create an array object. + * @param parent the array's parent if any * @param values the actual values wrapped by this object */ - public PDFArray(Collection values) { + public PDFArray(PDFObject parent, Collection values) { /* generic creation of PDF object */ - super(); + super(parent); this.values.addAll(values); } /** * Create the array object - * + * @param parent the array's parent if any * @param values the actual array wrapped by this object */ - public PDFArray(Object[] values) { + public PDFArray(PDFObject parent, Object[] values) { /* generic creation of PDF object */ - super(); + super(parent); for (int i = 0, c = values.length; i < c; i++) { this.values.add(values[i]); @@ -114,6 +120,17 @@ public class PDFArray extends PDFObject { return this.values.get(index); } + /** + * Adds a new value to the array. + * @param obj the value + */ + public void add(PDFObject obj) { + if (obj != null) { + obj.setParent(this); + } + this.values.add(obj); + } + /** * Adds a new value to the array. * @param obj the value @@ -130,27 +147,30 @@ public class PDFArray extends PDFObject { this.values.add(new Double(value)); } - /** - * {@inheritDoc} - */ - public String toPDFString() { - StringBuffer p = new StringBuffer(64); + /** {@inheritDoc} */ + protected int output(OutputStream stream) throws IOException { + CountingOutputStream cout = new CountingOutputStream(stream); + Writer writer = PDFDocument.getWriterFor(cout); if (hasObjectNumber()) { - p.append(getObjectID()); + writer.write(getObjectID()); } - p.append("["); + + writer.write('['); for (int i = 0; i < values.size(); i++) { if (i > 0) { - p.append(" "); + writer.write(' '); } Object obj = this.values.get(i); - formatObject(obj, p); + formatObject(obj, cout, writer); } - p.append("]"); + writer.write(']'); + if (hasObjectNumber()) { - p.append("\nendobj\n"); + writer.write("\nendobj\n"); } - return p.toString(); + + writer.flush(); + return cout.getCount(); } - + } diff --git a/src/java/org/apache/fop/pdf/PDFDestination.java b/src/java/org/apache/fop/pdf/PDFDestination.java index c59b20cfc..eaf38449d 100644 --- a/src/java/org/apache/fop/pdf/PDFDestination.java +++ b/src/java/org/apache/fop/pdf/PDFDestination.java @@ -19,6 +19,12 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + +import org.apache.commons.io.output.CountingOutputStream; + /** * class representing a named destination */ @@ -40,30 +46,24 @@ public class PDFDestination extends PDFObject { * @param goToRef Object reference to the GoTo Action */ public PDFDestination(String idRef, Object goToRef) { + super(); this.goToReference = goToRef; this.idRef = idRef; } - /** - * Creates the key/value pair for this destination entry for the name tree. - * @return the formatted key/value pair - */ - public String toKeyValuePair() { - StringBuffer sb = new StringBuffer(); - sb.append("(").append(getIDRef()).append(") "); - if (goToReference instanceof PDFWritable) { - sb.append(((PDFWritable)goToReference).toInlinePDFString()); - } else { - sb.append(goToReference); - } - return sb.toString(); - } - /** {@inheritDoc} */ - protected String toPDFString() { - return toKeyValuePair(); + protected int output(OutputStream stream) throws IOException { + CountingOutputStream cout = new CountingOutputStream(stream); + Writer writer = PDFDocument.getWriterFor(cout); + + formatObject(getIDRef(), cout, writer); + writer.write(' '); + formatObject(goToReference, cout, writer); + + writer.flush(); + return cout.getCount(); } - + /** * Sets the GoToReference in the associated DestinationData object. * @@ -124,9 +124,7 @@ public class PDFDestination extends PDFObject { return false; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int hashCode() { return getIDRef().hashCode(); } diff --git a/src/java/org/apache/fop/pdf/PDFDests.java b/src/java/org/apache/fop/pdf/PDFDests.java index 463ef8d7e..ff2d6a237 100644 --- a/src/java/org/apache/fop/pdf/PDFDests.java +++ b/src/java/org/apache/fop/pdf/PDFDests.java @@ -40,7 +40,7 @@ public class PDFDests extends PDFNameTreeNode { */ public PDFDests(List destinationList) { this(); - setNames(new PDFArray(destinationList)); + setNames(new PDFArray(this, destinationList)); } } diff --git a/src/java/org/apache/fop/pdf/PDFDictionary.java b/src/java/org/apache/fop/pdf/PDFDictionary.java index c183871b5..49d48312c 100644 --- a/src/java/org/apache/fop/pdf/PDFDictionary.java +++ b/src/java/org/apache/fop/pdf/PDFDictionary.java @@ -19,10 +19,15 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; import java.util.Iterator; import java.util.List; import java.util.Map; +import org.apache.commons.io.output.CountingOutputStream; + /** * Class representing a PDF dictionary object */ @@ -40,13 +45,20 @@ public class PDFDictionary extends PDFObject { protected List order = new java.util.ArrayList(); /** - * Create the dictionary object + * Create a new dictionary object. */ public PDFDictionary() { - /* generic creation of PDF object */ super(); } + /** + * Create a new dictionary object. + * @param parent the object's parent if any + */ + public PDFDictionary(PDFObject parent) { + super(parent); + } + /** * Puts a new name/value pair. * @param name the name @@ -80,47 +92,53 @@ public class PDFDictionary extends PDFObject { return this.entries.get(name); } - /** - * {@inheritDoc} - */ - public String toPDFString() { - StringBuffer p = new StringBuffer(64); + /** {@inheritDoc} */ + protected int output(OutputStream stream) throws IOException { + CountingOutputStream cout = new CountingOutputStream(stream); + Writer writer = PDFDocument.getWriterFor(cout); if (hasObjectNumber()) { - p.append(getObjectID()); + writer.write(getObjectID()); } - writeDictionary(p); + + writeDictionary(cout, writer); + if (hasObjectNumber()) { - p.append("endobj\n"); + writer.write("\nendobj\n"); } - return p.toString(); + + writer.flush(); + return cout.getCount(); } - + /** * Writes the contents of the dictionary to a StringBuffer. - * @param sb the target StringBuffer + * @param out the OutputStream (for binary content) + * @param writer the Writer (for text content, wraps the above OutputStream) + * @throws IOException if an I/O error occurs */ - protected void writeDictionary(StringBuffer sb) { - sb.append("<<"); + protected void writeDictionary(OutputStream out, Writer writer) throws IOException { + writer.write("<<"); boolean compact = (this.order.size() <= 2); Iterator iter = this.order.iterator(); while (iter.hasNext()) { String key = (String)iter.next(); if (compact) { - sb.append(' '); + writer.write(' '); } else { - sb.append("\n "); + writer.write("\n "); } - sb.append('/').append(key); - sb.append(' '); + writer.write('/'); + writer.write(key); + writer.write(' '); Object obj = this.entries.get(key); - formatObject(obj, sb); + formatObject(obj, out, writer); } if (compact) { - sb.append(' '); + writer.write(' '); } else { - sb.append('\n'); + writer.write('\n'); } - sb.append(">>\n"); + writer.write(">>\n"); } } diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index 045d52173..bd44595fb 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -24,15 +24,16 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; +import java.io.Writer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Iterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -316,6 +317,22 @@ public class PDFDocument { } } + /** + * Creates and returns a Writer object wrapping the given OutputStream. The Writer is + * buffered to reduce the number of calls to the encoding converter so don't forget + * to flush() the Writer after use or before writing directly to the + * underlying OutputStream. + * @param out the OutputStream to write to + * @return the requested Writer + */ + public static Writer getWriterFor(OutputStream out) { + try { + return new java.io.BufferedWriter(new java.io.OutputStreamWriter(out, ENCODING)); + } catch (UnsupportedEncodingException uee) { + throw new Error("JVM doesn't support " + ENCODING + " encoding!"); + } + } + /** * set the producer of the document * diff --git a/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java b/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java index 203ca90e1..5da37076c 100644 --- a/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java +++ b/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java @@ -20,20 +20,20 @@ package org.apache.fop.pdf; // Java +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.IOException; +import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.InvalidKeyException; +import java.util.Random; + +import javax.crypto.BadPaddingException; import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; import javax.crypto.CipherOutputStream; import javax.crypto.IllegalBlockSizeException; -import javax.crypto.BadPaddingException; import javax.crypto.NoSuchPaddingException; - -import java.util.Random; +import javax.crypto.spec.SecretKeySpec; /** * class representing a /Filter /Standard object. @@ -358,17 +358,20 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { if (this.encryptionKey == null) { throw new IllegalStateException("PDF Encryption has not been initialized"); } - log.debug("encrypting with for " + number + " " + generation); - byte[] hash = calcHash(number, generation); return encryptWithHash(data, hash, hash.length); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public byte[] encrypt(byte[] data, PDFObject refObj) { - return encryptData(data, refObj.getObjectNumber(), refObj.getGeneration()); + PDFObject o = refObj; + while (o != null && !o.hasObjectNumber()) { + o = o.getParent(); + } + if (o == null) { + throw new IllegalStateException("No object number could be obtained for a PDF object"); + } + return encryptData(data, o.getObjectNumber(), o.getGeneration()); } private byte[] calcHash(int number, int generation) { diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index f851abae7..f3069e85e 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -39,6 +39,9 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.xmp.Metadata; + import org.apache.fop.fonts.CIDFont; import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.FontDescriptor; @@ -51,7 +54,6 @@ import org.apache.fop.fonts.truetype.FontFileReader; import org.apache.fop.fonts.truetype.TTFSubSetFile; import org.apache.fop.fonts.type1.PFBData; import org.apache.fop.fonts.type1.PFBParser; -import org.apache.xmlgraphics.xmp.Metadata; /** * This class provides method to create and register PDF objects. @@ -872,7 +874,7 @@ public class PDFFactory { //true for a "deep" structure (one node per entry), true for a "flat" structure if (deep) { dests = new PDFDests(); - PDFArray kids = new PDFArray(); + PDFArray kids = new PDFArray(dests); Iterator iter = destinationList.iterator(); while (iter.hasNext()) { PDFDestination dest = (PDFDestination)iter.next(); @@ -880,8 +882,9 @@ public class PDFFactory { getDocument().registerObject(node); node.setLowerLimit(dest.getIDRef()); node.setUpperLimit(dest.getIDRef()); - node.setNames(new PDFArray()); - node.getNames().add(dest); + node.setNames(new PDFArray(node)); + PDFArray names = node.getNames(); + names.add(dest); kids.add(node); } dests.setLowerLimit(((PDFNameTreeNode)kids.get(0)).getLowerLimit()); @@ -1527,7 +1530,7 @@ public class PDFFactory { * @return the PDF Array with the int values */ public PDFArray makeArray(int[] values) { - PDFArray array = new PDFArray(values); + PDFArray array = new PDFArray(null, values); getDocument().registerObject(array); return array; diff --git a/src/java/org/apache/fop/pdf/PDFFilterList.java b/src/java/org/apache/fop/pdf/PDFFilterList.java index e866fc88e..607ae174b 100644 --- a/src/java/org/apache/fop/pdf/PDFFilterList.java +++ b/src/java/org/apache/fop/pdf/PDFFilterList.java @@ -277,7 +277,7 @@ public class PDFFilterList { } private void putFilterEntries(PDFDictionary dict, List names) { - PDFArray array = new PDFArray(); + PDFArray array = new PDFArray(dict); for (int i = 0, c = names.size(); i < c; i++) { final String name = (String)names.get(i); if (name.length() > 0) { @@ -323,7 +323,7 @@ public class PDFFilterList { private void putDecodeParams(PDFDictionary dict, List parms) { boolean needParmsEntry = false; - PDFArray array = new PDFArray(); + PDFArray array = new PDFArray(dict); for (int i = 0, c = parms.size(); i < c; i++) { Object obj = parms.get(i); if (obj != null) { diff --git a/src/java/org/apache/fop/pdf/PDFFormXObject.java b/src/java/org/apache/fop/pdf/PDFFormXObject.java index 456419f80..6ccf76c6c 100644 --- a/src/java/org/apache/fop/pdf/PDFFormXObject.java +++ b/src/java/org/apache/fop/pdf/PDFFormXObject.java @@ -63,7 +63,7 @@ public class PDFFormXObject extends PDFXObject { public void setBBox(Rectangle2D bbox) { PDFArray array = (PDFArray)get("BBox"); if (array == null) { - array = new PDFArray(); + array = new PDFArray(this); array.add(bbox.getX()); array.add(bbox.getY()); array.add(bbox.getWidth()); @@ -105,7 +105,7 @@ public class PDFFormXObject extends PDFXObject { double[] m = new double[6]; at.getMatrix(m); if (array == null) { - array = new PDFArray(); + array = new PDFArray(this); array.add(m[0]); array.add(m[1]); array.add(m[2]); @@ -170,7 +170,7 @@ public class PDFFormXObject extends PDFXObject { /** {@inheritDoc} */ protected void populateStreamDict(Object lengthEntry) { if (get("Matrix") == null) { - put("Matrix", new PDFArray(new int[] {1, 0, 0, 1, 0, 0})); + put("Matrix", new PDFArray(this, new int[] {1, 0, 0, 1, 0, 0})); } put("Resources", resRef); super.populateStreamDict(lengthEntry); diff --git a/src/java/org/apache/fop/pdf/PDFImage.java b/src/java/org/apache/fop/pdf/PDFImage.java index dd24240b5..f880fa6ac 100644 --- a/src/java/org/apache/fop/pdf/PDFImage.java +++ b/src/java/org/apache/fop/pdf/PDFImage.java @@ -105,11 +105,8 @@ public interface PDFImage { /** * Get the PDF reference for a soft mask. - * - * @return the PDF reference for a soft mask image + * @return the PDF reference for a soft mask image (or null if there's no soft mask) */ - String getSoftMask(); - PDFReference getSoftMaskReference(); /** @return true for CMYK images generated by Adobe Photoshop */ diff --git a/src/java/org/apache/fop/pdf/PDFImageXObject.java b/src/java/org/apache/fop/pdf/PDFImageXObject.java index 4cc174100..35f3e543d 100644 --- a/src/java/org/apache/fop/pdf/PDFImageXObject.java +++ b/src/java/org/apache/fop/pdf/PDFImageXObject.java @@ -94,7 +94,8 @@ public class PDFImageXObject extends PDFXObject { PDFICCStream pdfICCStream = pdfimage.getICCStream(); if (pdfICCStream != null) { - put("ColorSpace", new PDFArray(new Object[] {new PDFName("ICCBased"), pdfICCStream})); + put("ColorSpace", new PDFArray(this, + new Object[] {new PDFName("ICCBased"), pdfICCStream})); } else { PDFDeviceColorSpace cs = pdfimage.getColorSpace(); put("ColorSpace", new PDFName(cs.getName())); @@ -107,7 +108,7 @@ public class PDFImageXObject extends PDFXObject { */ final Float zero = new Float(0.0f); final Float one = new Float(1.0f); - PDFArray decode = new PDFArray(); + PDFArray decode = new PDFArray(this); for (int i = 0, c = pdfimage.getColorSpace().getNumComponents(); i < c; i++) { decode.add(one); decode.add(zero); @@ -117,7 +118,7 @@ public class PDFImageXObject extends PDFXObject { if (pdfimage.isTransparent()) { PDFColor transp = pdfimage.getTransparentColor(); - PDFArray mask = new PDFArray(); + PDFArray mask = new PDFArray(this); mask.add(new Integer(transp.red255())); mask.add(new Integer(transp.red255())); mask.add(new Integer(transp.green255())); diff --git a/src/java/org/apache/fop/pdf/PDFName.java b/src/java/org/apache/fop/pdf/PDFName.java index 4c3c3d003..8c626d53f 100644 --- a/src/java/org/apache/fop/pdf/PDFName.java +++ b/src/java/org/apache/fop/pdf/PDFName.java @@ -19,6 +19,10 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + /** * Class representing a PDF name object. */ @@ -65,15 +69,14 @@ public class PDFName implements PDFWritable { sb.append(DIGITS[ch & 0x0F]); } - /** {@inheritDoc} */ - public String toInlinePDFString() { + public String toString() { return this.name; } - + /** {@inheritDoc} */ - public String toString() { - return toInlinePDFString(); + public void outputInline(OutputStream out, Writer writer) throws IOException { + writer.write(toString()); } } diff --git a/src/java/org/apache/fop/pdf/PDFNameTreeNode.java b/src/java/org/apache/fop/pdf/PDFNameTreeNode.java index 476cfc7a2..4dcf0e03e 100644 --- a/src/java/org/apache/fop/pdf/PDFNameTreeNode.java +++ b/src/java/org/apache/fop/pdf/PDFNameTreeNode.java @@ -108,7 +108,7 @@ public class PDFNameTreeNode extends PDFDictionary { private PDFArray prepareLimitsArray() { PDFArray limits = (PDFArray)get(LIMITS); if (limits == null) { - limits = new PDFArray(new Object[2]); + limits = new PDFArray(this, new Object[2]); put(LIMITS, limits); } if (limits.length() != 2) { diff --git a/src/java/org/apache/fop/pdf/PDFNull.java b/src/java/org/apache/fop/pdf/PDFNull.java index e3fb44a8d..b1af30dc0 100644 --- a/src/java/org/apache/fop/pdf/PDFNull.java +++ b/src/java/org/apache/fop/pdf/PDFNull.java @@ -19,6 +19,10 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + /** * Class representing a PDF name object. */ @@ -35,13 +39,13 @@ public final class PDFNull implements PDFWritable { } /** {@inheritDoc} */ - public String toInlinePDFString() { + public String toString() { return "null"; } /** {@inheritDoc} */ - public String toString() { - return toInlinePDFString(); + public void outputInline(OutputStream out, Writer writer) throws IOException { + writer.write(toString()); } } diff --git a/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java b/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java index 4e69c01d4..ef1ccb452 100644 --- a/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java +++ b/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java @@ -1,121 +1,121 @@ -/* - * 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.pdf; - -/** - * Class representing a PDF number tree node. - */ -public class PDFNumberTreeNode extends PDFDictionary { - - private static final String KIDS = "Kids"; - private static final String NUMS = "Nums"; - private static final String LIMITS = "Limits"; - - /** - * create a named destination - */ - public PDFNumberTreeNode() { - /* generic creation of PDF object */ - super(); - } - - /** - * Sets the Kids array. - * @param kids the Kids array - */ - public void setKids(PDFArray kids) { - put(KIDS, kids); - } - - /** - * Returns the Kids array. - * @return the Kids array - */ - public PDFArray getKids() { - return (PDFArray)get(KIDS); - } - - /** - * Sets the Nums array. - * @param nums the Nums array - */ - public void setNums(PDFNumsArray nums) { - put(NUMS, nums); - } - - /** - * Returns the Nums array. - * @return the Nums array - */ - public PDFNumsArray getNums() { - return (PDFNumsArray)get(NUMS); - } - - /** - * Sets the lower limit value of the Limits array. - * @param key the lower limit value - */ - public void setLowerLimit(Integer key) { - PDFArray limits = prepareLimitsArray(); - limits.set(0, key); - } - - /** - * Returns the lower limit value of the Limits array. - * @return the lower limit value - */ - public Integer getLowerLimit() { - PDFArray limits = prepareLimitsArray(); - return (Integer)limits.get(0); - } - - /** - * Sets the upper limit value of the Limits array. - * @param key the upper limit value - */ - public void setUpperLimit(Integer key) { - PDFArray limits = prepareLimitsArray(); - limits.set(1, key); - } - - /** - * Returns the upper limit value of the Limits array. - * @return the upper limit value - */ - public Integer getUpperLimit() { - PDFArray limits = prepareLimitsArray(); - return (Integer)limits.get(1); - } - - - private PDFArray prepareLimitsArray() { - PDFArray limits = (PDFArray)get(LIMITS); - if (limits == null) { - limits = new PDFArray(new Object[2]); - put(LIMITS, limits); - } - if (limits.length() != 2) { - throw new IllegalStateException("Limits array must have 2 entries"); - } - return limits; - } - -} - +/* + * 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.pdf; + +/** + * Class representing a PDF number tree node. + */ +public class PDFNumberTreeNode extends PDFDictionary { + + private static final String KIDS = "Kids"; + private static final String NUMS = "Nums"; + private static final String LIMITS = "Limits"; + + /** + * create a named destination + */ + public PDFNumberTreeNode() { + /* generic creation of PDF object */ + super(); + } + + /** + * Sets the Kids array. + * @param kids the Kids array + */ + public void setKids(PDFArray kids) { + put(KIDS, kids); + } + + /** + * Returns the Kids array. + * @return the Kids array + */ + public PDFArray getKids() { + return (PDFArray)get(KIDS); + } + + /** + * Sets the Nums array. + * @param nums the Nums array + */ + public void setNums(PDFNumsArray nums) { + put(NUMS, nums); + } + + /** + * Returns the Nums array. + * @return the Nums array + */ + public PDFNumsArray getNums() { + return (PDFNumsArray)get(NUMS); + } + + /** + * Sets the lower limit value of the Limits array. + * @param key the lower limit value + */ + public void setLowerLimit(Integer key) { + PDFArray limits = prepareLimitsArray(); + limits.set(0, key); + } + + /** + * Returns the lower limit value of the Limits array. + * @return the lower limit value + */ + public Integer getLowerLimit() { + PDFArray limits = prepareLimitsArray(); + return (Integer)limits.get(0); + } + + /** + * Sets the upper limit value of the Limits array. + * @param key the upper limit value + */ + public void setUpperLimit(Integer key) { + PDFArray limits = prepareLimitsArray(); + limits.set(1, key); + } + + /** + * Returns the upper limit value of the Limits array. + * @return the upper limit value + */ + public Integer getUpperLimit() { + PDFArray limits = prepareLimitsArray(); + return (Integer)limits.get(1); + } + + + private PDFArray prepareLimitsArray() { + PDFArray limits = (PDFArray)get(LIMITS); + if (limits == null) { + limits = new PDFArray(this, new Object[2]); + put(LIMITS, limits); + } + if (limits.length() != 2) { + throw new IllegalStateException("Limits array must have 2 entries"); + } + return limits; + } + +} + diff --git a/src/java/org/apache/fop/pdf/PDFNumsArray.java b/src/java/org/apache/fop/pdf/PDFNumsArray.java index 55f973ccd..0a86754e8 100644 --- a/src/java/org/apache/fop/pdf/PDFNumsArray.java +++ b/src/java/org/apache/fop/pdf/PDFNumsArray.java @@ -1,94 +1,104 @@ -/* - * 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: PDFArray.java 588547 2007-10-26 07:48:14Z jeremias $ */ - -package org.apache.fop.pdf; - -import java.util.Iterator; -import java.util.Map; -import java.util.SortedMap; - -/** - * Class representing an "Nums" array object (for Number Trees). - */ -public class PDFNumsArray extends PDFObject { - - /** Sorted Map holding the values of this array. */ - protected SortedMap map = new java.util.TreeMap(); - - /** - * Create a new, empty array object - */ - public PDFNumsArray() { - /* generic creation of PDF object */ - super(); - } - - /** - * Returns the length of the array - * @return the length of the array - */ - public int length() { - return this.map.size(); - } - - /** - * Sets an entry. - * @param key the key of the value to set - * @param obj the new value - */ - public void put(int key, Object obj) { - this.map.put(new Integer(key), obj); - } - - /** - * Gets an entry. - * @param key the key of requested value - * @return the requested value - */ - public Object get(int key) { - return this.map.get(new Integer(key)); - } - - /** {@inheritDoc} */ - public String toPDFString() { - StringBuffer p = new StringBuffer(64); - if (hasObjectNumber()) { - p.append(getObjectID()); - } - p.append("["); - boolean first = true; - Iterator iter = this.map.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = (Map.Entry)iter.next(); - if (!first) { - p.append(" "); - } - first = false; - formatObject(entry.getKey(), p); - p.append(" "); - formatObject(entry.getValue(), p); - } - p.append("]"); - if (hasObjectNumber()) { - p.append("\nendobj\n"); - } - return p.toString(); - } - -} +/* + * 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.pdf; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.util.Iterator; +import java.util.Map; +import java.util.SortedMap; + +import org.apache.commons.io.output.CountingOutputStream; + +/** + * Class representing an "Nums" array object (for Number Trees). + */ +public class PDFNumsArray extends PDFObject { + + /** Sorted Map holding the values of this array. */ + protected SortedMap map = new java.util.TreeMap(); + + /** + * Create a new, empty array object. + * @param parent the object's parent if any + */ + public PDFNumsArray(PDFObject parent) { + super(parent); + } + + /** + * Returns the length of the array + * @return the length of the array + */ + public int length() { + return this.map.size(); + } + + /** + * Sets an entry. + * @param key the key of the value to set + * @param obj the new value + */ + public void put(int key, Object obj) { + this.map.put(new Integer(key), obj); + } + + /** + * Gets an entry. + * @param key the key of requested value + * @return the requested value + */ + public Object get(int key) { + return this.map.get(new Integer(key)); + } + + /** {@inheritDoc} */ + protected int output(OutputStream stream) throws IOException { + CountingOutputStream cout = new CountingOutputStream(stream); + Writer writer = PDFDocument.getWriterFor(cout); + if (hasObjectNumber()) { + writer.write(getObjectID()); + } + + writer.write('['); + boolean first = true; + Iterator iter = this.map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry)iter.next(); + if (!first) { + writer.write(" "); + } + first = false; + formatObject(entry.getKey(), cout, writer); + writer.write(" "); + formatObject(entry.getValue(), cout, writer); + } + writer.write(']'); + + if (hasObjectNumber()) { + writer.write("\nendobj\n"); + } + + writer.flush(); + return cout.getCount(); + } + +} diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java index cab6b75f2..f53183574 100644 --- a/src/java/org/apache/fop/pdf/PDFObject.java +++ b/src/java/org/apache/fop/pdf/PDFObject.java @@ -22,6 +22,7 @@ package org.apache.fop.pdf; // Java import java.io.IOException; import java.io.OutputStream; +import java.io.Writer; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -57,6 +58,9 @@ public abstract class PDFObject implements PDFWritable { */ private PDFDocument document; + /** the parent PDFObject (may be null and may not always be set, needed for encryption) */ + private PDFObject parent; + /** * Returns the object's number. * @return the PDF Object number @@ -68,6 +72,21 @@ public abstract class PDFObject implements PDFWritable { return this.objnum; } + /** + * Default constructor. + */ + public PDFObject() { + //nop + } + + /** + * Constructor for direct objects. + * @param parent the containing PDFObject instance + */ + public PDFObject(PDFObject parent) { + setParent(parent); + } + /** * Indicates whether this PDFObject has already been assigned an * object number. @@ -102,7 +121,13 @@ public abstract class PDFObject implements PDFWritable { * has not been assigned) */ public final PDFDocument getDocument() { - return this.document; + if (this.document != null) { + return this.document; + } else if (getParent() != null) { + return getParent().getDocument(); + } else { + return null; + } } /** @@ -127,6 +152,22 @@ public abstract class PDFObject implements PDFWritable { this.document = doc; } + /** + * Returns this objects's parent. The parent is null if it is a "direct object". + * @return the parent or null if there's no parent (or it hasn't been set) + */ + public PDFObject getParent() { + return this.parent; + } + + /** + * Sets the direct parent object. + * @param parent the direct parent + */ + public void setParent(PDFObject parent) { + this.parent = parent; + } + /** * Returns the PDF representation of the Object ID. * @return the Object ID @@ -169,6 +210,16 @@ public abstract class PDFObject implements PDFWritable { return pdf.length; } + /** {@inheritDoc} */ + public void outputInline(OutputStream out, Writer writer) throws IOException { + if (hasObjectNumber()) { + writer.write(referencePDF()); + } else { + writer.flush(); + output(out); + } + } + /** * Encodes the object as a byte array for output to a PDF file. * @@ -184,7 +235,9 @@ public abstract class PDFObject implements PDFWritable { * is normally converted/encoded to a byte array by toPDF(). Only use * this method to implement the serialization if the object can be fully * represented as text. If the PDF representation of the object contains - * binary content use toPDF() or output(OutputStream) instead. + * binary content use toPDF() or output(OutputStream) instead. This applies + * to any object potentially containing a string object because string object + * are encrypted and therefore need to be binary. * @return String the String representation */ protected String toPDFString() { @@ -192,20 +245,6 @@ public abstract class PDFObject implements PDFWritable { + "Use output(OutputStream) instead."); } - /** - * Returns a representation of this object for in-object placement, i.e. if the object - * has an object number its reference is returned. Otherwise, its PDF representation is - * returned. - * @return the String representation - */ - public String toInlinePDFString() { - if (hasObjectNumber()) { - return referencePDF(); - } else { - return toPDFString(); - } - } - /** * Converts text to a byte array for writing to a PDF file. * @param text text to convert/encode @@ -250,23 +289,27 @@ public abstract class PDFObject implements PDFWritable { /** * Formats an object for serialization to PDF. * @param obj the object - * @param sb the StringBuffer to write to + * @param out the OutputStream to write to + * @param writer a Writer for text content (will always be a wrapper around the above + * OutputStream. Make sure flush is called when mixing calls) + * @throws IOException If an I/O error occurs */ - protected void formatObject(Object obj, StringBuffer sb) { + protected void formatObject(Object obj, OutputStream out, Writer writer) throws IOException { if (obj == null) { - sb.append("null"); + writer.write("null"); } else if (obj instanceof PDFWritable) { - sb.append(((PDFWritable)obj).toInlinePDFString()); + ((PDFWritable)obj).outputInline(out, writer); } else if (obj instanceof Number) { if (obj instanceof Double || obj instanceof Float) { - sb.append(PDFNumber.doubleOut(((Number)obj).doubleValue())); + writer.write(PDFNumber.doubleOut(((Number)obj).doubleValue())); } else { - sb.append(obj); + writer.write(obj.toString()); } } else if (obj instanceof Boolean) { - sb.append(obj); + writer.write(obj.toString()); } else { - sb.append("(").append(obj).append(")"); + writer.flush(); + out.write(encodeText(obj.toString())); } } diff --git a/src/java/org/apache/fop/pdf/PDFPageLabels.java b/src/java/org/apache/fop/pdf/PDFPageLabels.java index bb02a3c7e..1a51c4155 100644 --- a/src/java/org/apache/fop/pdf/PDFPageLabels.java +++ b/src/java/org/apache/fop/pdf/PDFPageLabels.java @@ -1,48 +1,48 @@ -/* - * 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.pdf; - -/** - * Class representing a PDF /PageLabels dictionary. - */ -public class PDFPageLabels extends PDFNumberTreeNode { - - /** - * Create the /PageLabels dictionary - */ - public PDFPageLabels() { - super(); - } - - /** - * Returns the Nums object - * @return the Nums object (an empty PDFNumsArray for the "/Nums" entry is created - * if it doesn't exist) - */ - public PDFNumsArray getNums() { - PDFNumsArray nums = super.getNums(); - if (nums == null) { - nums = new PDFNumsArray(); - setNums(nums); - } - return nums; - } - -} +/* + * 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.pdf; + +/** + * Class representing a PDF /PageLabels dictionary. + */ +public class PDFPageLabels extends PDFNumberTreeNode { + + /** + * Create the /PageLabels dictionary + */ + public PDFPageLabels() { + super(); + } + + /** + * Returns the Nums object + * @return the Nums object (an empty PDFNumsArray for the "/Nums" entry is created + * if it doesn't exist) + */ + public PDFNumsArray getNums() { + PDFNumsArray nums = super.getNums(); + if (nums == null) { + nums = new PDFNumsArray(this); + setNums(nums); + } + return nums; + } + +} diff --git a/src/java/org/apache/fop/pdf/PDFReference.java b/src/java/org/apache/fop/pdf/PDFReference.java index ed1a8c016..3b615735a 100644 --- a/src/java/org/apache/fop/pdf/PDFReference.java +++ b/src/java/org/apache/fop/pdf/PDFReference.java @@ -19,6 +19,9 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; import java.lang.ref.Reference; import java.lang.ref.SoftReference; @@ -68,13 +71,13 @@ public class PDFReference implements PDFWritable { } /** {@inheritDoc} */ - public String toInlinePDFString() { + public String toString() { return this.indirectReference; } /** {@inheritDoc} */ - public String toString() { - return toInlinePDFString(); + public void outputInline(OutputStream out, Writer writer) throws IOException { + writer.write(toString()); } } diff --git a/src/java/org/apache/fop/pdf/PDFRoot.java b/src/java/org/apache/fop/pdf/PDFRoot.java index 1a54a209f..54cadf616 100644 --- a/src/java/org/apache/fop/pdf/PDFRoot.java +++ b/src/java/org/apache/fop/pdf/PDFRoot.java @@ -225,7 +225,7 @@ public class PDFRoot extends PDFDictionary { if (getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) { PDFArray outputIntents = getOutputIntents(); if (outputIntents == null) { - outputIntents = new PDFArray(); + outputIntents = new PDFArray(this); put("OutputIntents", outputIntents); } outputIntents.add(outputIntent); diff --git a/src/java/org/apache/fop/pdf/PDFWritable.java b/src/java/org/apache/fop/pdf/PDFWritable.java index 23bcf9ad8..4f024fb92 100644 --- a/src/java/org/apache/fop/pdf/PDFWritable.java +++ b/src/java/org/apache/fop/pdf/PDFWritable.java @@ -19,6 +19,10 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + /** * This interface is implemented by classes that can be serialized to a PDF file either by * serializing the object or by writing a indirect reference to the actual object. @@ -26,11 +30,13 @@ package org.apache.fop.pdf; public interface PDFWritable { /** - * Returns a representation of this object for in-object placement, i.e. if the object - * has an object number its reference is returned. Otherwise, its PDF representation is - * returned. - * @return the String representation + * Writes a "direct object" (inline object) representation to the stream. A Writer is given + * for optimized encoding of text content. Since the Writer is buffered, make sure + * flush() is called before any direct calls to out are made. + * @param out the OutputStream (for binary content) + * @param writer the Writer (for text content, wraps the above OutputStream) + * @throws IOException if an I/O error occurs */ - String toInlinePDFString(); + void outputInline(OutputStream out, Writer writer) throws IOException; } diff --git a/src/java/org/apache/fop/render/pdf/FopPDFImage.java b/src/java/org/apache/fop/render/pdf/FopPDFImage.java index c9b0e3a7b..e60c207d6 100644 --- a/src/java/org/apache/fop/render/pdf/FopPDFImage.java +++ b/src/java/org/apache/fop/render/pdf/FopPDFImage.java @@ -25,6 +25,7 @@ import java.io.OutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.image.EPSImage; import org.apache.fop.image.FopImage; import org.apache.fop.image.TIFFImage; @@ -237,11 +238,6 @@ public class FopPDFImage implements PDFImage { return maskRef; } - /** {@inheritDoc} */ - public String getSoftMask() { - return softMask.toInlinePDFString(); - } - /** {@inheritDoc} */ public PDFReference getSoftMaskReference() { return softMask; diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 2d8e7d5ba..f4aa5ee90 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -37,7 +37,15 @@ import java.util.Map; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; +import org.w3c.dom.Document; + import org.apache.commons.io.IOUtils; +import org.apache.commons.io.output.CountingOutputStream; + +import org.apache.xmlgraphics.xmp.Metadata; +import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter; +import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; @@ -86,6 +94,7 @@ import org.apache.fop.pdf.PDFInfo; import org.apache.fop.pdf.PDFLink; import org.apache.fop.pdf.PDFMetadata; import org.apache.fop.pdf.PDFNumber; +import org.apache.fop.pdf.PDFNumsArray; import org.apache.fop.pdf.PDFOutline; import org.apache.fop.pdf.PDFOutputIntent; import org.apache.fop.pdf.PDFPage; @@ -102,10 +111,6 @@ import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.RendererContext; import org.apache.fop.util.CharUtilities; import org.apache.fop.util.ColorProfileUtil; -import org.apache.xmlgraphics.xmp.Metadata; -import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter; -import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema; -import org.w3c.dom.Document; /** * Renderer that renders areas to PDF. @@ -357,7 +362,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { this.pdfDoc.getInfo().setTitle(userAgent.getTitle()); this.pdfDoc.getInfo().setKeywords(userAgent.getKeywords()); this.pdfDoc.setFilterMap(filterMap); - this.pdfDoc.outputHeader(stream); + this.pdfDoc.outputHeader(ostream); //Setup encryption if necessary PDFEncryptionManager.setupPDFEncryption(encryptionParams, this.pdfDoc); @@ -725,11 +730,12 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { pageLabels = this.pdfDoc.getFactory().makePageLabels(); this.pdfDoc.getRoot().setPageLabels(pageLabels); } - PDFDictionary dict = new PDFDictionary(); + PDFNumsArray nums = pageLabels.getNums(); + PDFDictionary dict = new PDFDictionary(nums); dict.put("P", page.getPageNumberString()); //TODO If the sequence of generated page numbers were inspected, this could be //expressed in a more space-efficient way - pageLabels.getNums().put(page.getPageIndex(), dict); + nums.put(page.getPageIndex(), dict); } /** diff --git a/status.xml b/status.xml index 829a76a66..e66635844 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Fixed generation of named destinations so it works when the PDF document is encrypted. + PostScript output now generates the bounding box DSC comments for the whole document. -- cgit v1.2.3 From 44c5761c1a801f4b6ae91ae7afb8006e8bb9c7fe Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 11 Jan 2008 19:50:53 +0000 Subject: Merged branch https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImagePackageRedesign (revs 594558 to 611138) into Trunk: A new image loading framework has been introduced to fix various problems with external graphics and improve performance. Switched to Batik 1.7. Added xml-apis-ext.jar as needed by Batik 1.7. Updated to latest XML Graphics Commons snapshot. Changelog of branch: ------------------------------------------------------------------------ r594558 | jeremias | 2007-11-13 16:04:56 +0100 (Di, 13 Nov 2007) | 1 line Branch for image package redesign ------------------------------------------------------------------------ r594560 | jeremias | 2007-11-13 16:10:35 +0100 (Di, 13 Nov 2007) | 1 line Implementation of Dijkstra's algorithm for finding the shortest path. Used in the new image package to find the best combination of image loaders and image converters to provide an image in the optimal form for a renderer. ------------------------------------------------------------------------ r594848 | jeremias | 2007-11-14 13:12:50 +0100 (Mi, 14 Nov 2007) | 3 lines Initial upload of what I have already for the image package redesign. For now, it's in a parallel package (image2). The final package name is TBD. The code isn't hooked into the renderers, yet, and there's no image cache. This is still all work in progress. ------------------------------------------------------------------------ r594851 | jeremias | 2007-11-14 13:20:12 +0100 (Mi, 14 Nov 2007) | 1 line Test cases and additional test files for the new image package. ------------------------------------------------------------------------ r595305 | jeremias | 2007-11-15 15:01:37 +0100 (Do, 15 Nov 2007) | 1 line Small mistake while reimplementing JPEG. ------------------------------------------------------------------------ r595308 | jeremias | 2007-11-15 15:13:36 +0100 (Do, 15 Nov 2007) | 5 lines Introduced a usage penalty for ImageLoaders so we can calculate an overall penalty for a pipeline. Multiple image flavors can be passed to ImageManager.getImage() if the caller supports multiple formats. The image package chooses the best pipeline. Implemented a converter from RenderedImage to PNG. Implemented loaders for raw formats (EMF, JPEG and PNG). Hooked the new image package into the RTF handler as first real proof-of-concept. ------------------------------------------------------------------------ r596240 | jeremias | 2007-11-19 11:02:13 +0100 (Mo, 19 Nov 2007) | 1 line Fixed bug in pipeline selection. ------------------------------------------------------------------------ r596242 | jeremias | 2007-11-19 11:03:06 +0100 (Mo, 19 Nov 2007) | 1 line MIME type in parentheses behind the URI makes more sense. ------------------------------------------------------------------------ r599430 | jeremias | 2007-11-29 14:08:01 +0100 (Do, 29 Nov 2007) | 1 line Support for baseline information (needed by at least MathML). ------------------------------------------------------------------------ r599433 | jeremias | 2007-11-29 14:09:04 +0100 (Do, 29 Nov 2007) | 1 line Bugfix: BMP don't all have resolution information. ------------------------------------------------------------------------ r599434 | jeremias | 2007-11-29 14:10:54 +0100 (Do, 29 Nov 2007) | 1 line Change MIME type ------------------------------------------------------------------------ r599436 | jeremias | 2007-11-29 14:17:14 +0100 (Do, 29 Nov 2007) | 3 lines Started integrating into Java2D and PostScript renderers and ExternalGraphic. Added support for EPS graphics. Added support for raw embedding of JPEG images (for PostScript). ------------------------------------------------------------------------ r600821 | jeremias | 2007-12-04 08:51:06 +0100 (Di, 04 Dez 2007) | 5 lines Clean up Javadocs Generally make more useful. Reuse FOProcessor instance for the whole run to actually feel the effect of an image cache attached to the FopFactory. Add option to prompt the user before actually starting (in order to connect a VM monitor). ------------------------------------------------------------------------ r600870 | jeremias | 2007-12-04 11:27:51 +0100 (Di, 04 Dez 2007) | 14 lines Note: The API of the new image package has changed a bit. (it became necessary when I introduced caching) The direct dependency on FOUserAgent has been removed to make the image package more universally usable. Instead an ImageContext (provided by FopFactory in FOP) and ImageSessionContext (provided by FOUserAgent in FOP) was introduced. Introduced image caching with soft references (I didn't reintroduce the FOUserAgent lock, yet, because it doesn't help much) ImageInfo doesn't carry the Source for the image anymore. The Source is provided by the new ImageSessionContext.java and only shared within the same thread to make things simpler and to avoid complex synchronization and cleanup. Image instances now indicate whether they are cacheable (not all Image instances are cacheable, for example when they just carry an InputStream). Moved the converter pipeline functionality into its own subpackage to keep "spi" clean. Added checks in ImageSize to detect incomplete Preloaders. ImageSource can now indicate whether its a fast source (loading from local file) or a slow source (loading over the network). (but this isn't used, yet) Fixed a bug in WMF and SVG preloaders: they didn't close their Sources after fully loading the images. Bugfix in ImageRawJPEG: it illegally reported being an EPS file ImageRawStream got an "InputStreamFactory" so it is possible to reuse raw images if they have been loaded into memory (or to a local file which hasn't been implemented, yet). The pipeline code now converts single-use raw images to reusable raw images when possible. But there's nothing built in to restrict the image size to a maximum, yet. Improved JPEG preloader so it can stop early an deal with images that have to APP0 segment. Images from digicams are such an example. They carry the resolution info in the EXIF block which is currently not interpreted. Fallback is to the configured source resolution. ------------------------------------------------------------------------ r600930 | jeremias | 2007-12-04 14:25:43 +0100 (Di, 04 Dez 2007) | 1 line Package HTML Files. ------------------------------------------------------------------------ r600934 | jeremias | 2007-12-04 14:34:41 +0100 (Di, 04 Dez 2007) | 1 line Javadoc fixes ------------------------------------------------------------------------ r602023 | jeremias | 2007-12-07 09:46:56 +0100 (Fr, 07 Dez 2007) | 2 lines Bugfix for bug in SVG preloader which didn't calculate the size of an SVG correctly when there's no explicit size. ------------------------------------------------------------------------ r602024 | jeremias | 2007-12-07 09:49:49 +0100 (Fr, 07 Dez 2007) | 1 line Some small javadoc and logging improvements/refinements. ------------------------------------------------------------------------ r602025 | jeremias | 2007-12-07 09:50:22 +0100 (Fr, 07 Dez 2007) | 1 line Enable assert keyword for javadoc production. ------------------------------------------------------------------------ r602032 | jeremias | 2007-12-07 09:59:10 +0100 (Fr, 07 Dez 2007) | 11 lines Added color space information and an optional ICC color profile to the basic Image interface. Reimplemented transparency support (for now only for ImageIO loader and PDF output) ImageIO preloader passes the already loaded metadata to the ImageIO loader through the "custom objects" so it doesn't have to load them again. PDF library: Corrected the naming of the method indicating the "bits per component" (bits per component != bits per pixel) PDF library: Added a method which lets a user override values in an XObject's dictionary after the major values have been set (useful not to make the PDFImage interface more complicated). PDF library: Support for gray transparent colors. PDF library: Added a convenience class for alpha channel bitmaps (AlphaRasterImage) Integration of the new image package into the PDFRenderer (currently supports all previous embedding methods except deprecated EPS embedding and CCITT embedding, now supports even more transparency options than before) ------------------------------------------------------------------------ r602033 | jeremias | 2007-12-07 09:59:57 +0100 (Fr, 07 Dez 2007) | 1 line Small optimization from my failed experiments to support native PNG embedding. ------------------------------------------------------------------------ r602034 | jeremias | 2007-12-07 10:01:34 +0100 (Fr, 07 Dez 2007) | 1 line Don't use "content" filter for ICC profiles. Instead compress using "default". "content" is for page content. ------------------------------------------------------------------------ r602036 | jeremias | 2007-12-07 10:02:25 +0100 (Fr, 07 Dez 2007) | 1 line Added general key for precompressed content of any kind. ------------------------------------------------------------------------ r602037 | jeremias | 2007-12-07 10:03:39 +0100 (Fr, 07 Dez 2007) | 1 line Various variants of the FOP logo for testing. Some of them have transparency info. ------------------------------------------------------------------------ r602228 | jeremias | 2007-12-07 22:30:17 +0100 (Fr, 07 Dez 2007) | 4 lines Discarded PreloaderPNG in favor of PreloaderImageIO which now supports all formats supported by ImageIO (meaning that you can uses JPEG-2000 images if you have a suitable ImageIO codec installed). ImagePreloader.getMimeType() removed because it isn't really used in the new setup. ImagePreloader.getPriority() introduced which allows to prioritize preloaders and thus gives the opportunity to tweak the order in which the preloaders are checked when an image is inspected. ImageLoaderImageIO can now use multiple Readers if one fails (one codec may not support all format variants, for example). ------------------------------------------------------------------------ r602229 | jeremias | 2007-12-07 22:30:48 +0100 (Fr, 07 Dez 2007) | 1 line Added a toString() impl for debugging. ------------------------------------------------------------------------ r602442 | jeremias | 2007-12-08 11:36:32 +0100 (Sa, 08 Dez 2007) | 6 lines Support handling images with no associated URI (from instream-foreign-object). These images are not cached. Add support for plain image conversion (i.e. with no loading) for instream-foreign-object. Add convenience writeTo() methods in ImageRawStream to save a few lines of code. Support for instream-foreign-object in RTF output. Teach RTF library to handle images without an associated URL. ------------------------------------------------------------------------ r603191 | jeremias | 2007-12-11 11:03:32 +0100 (Di, 11 Dez 2007) | 2 lines Bugfix: Graphics2DAdapter didn't do the graphics state save correct so subsequent images may have been painted with the wrong transformation matrix. Bugfix: bitmap images didn't scale correctly when the resolutions were changed. ------------------------------------------------------------------------ r603207 | jeremias | 2007-12-11 12:08:36 +0100 (Di, 11 Dez 2007) | 1 line Convenience method for obtaining the image size in points. ------------------------------------------------------------------------ r603208 | jeremias | 2007-12-11 12:12:50 +0100 (Di, 11 Dez 2007) | 3 lines Precisely define the expectations for the area parameter in Graphics2DImagePainter. New ImageConverter: Bitmap -> Graphics2D ------------------------------------------------------------------------ r603209 | jeremias | 2007-12-11 12:15:49 +0100 (Di, 11 Dez 2007) | 3 lines Refine pipeline building: Expose a method to allow the PS Renderer to predict what kind of pipeline will be selected (because it doesn't support all image types as PostScript forms) If there are multiple candidate pipelines for one conversion type, choose the one with the lowest penalty, not just the one that happens to be first. ------------------------------------------------------------------------ r603250 | jeremias | 2007-12-11 15:17:32 +0100 (Di, 11 Dez 2007) | 1 line Removing failed experiment: raw PNG embedding didn't work out. ------------------------------------------------------------------------ r603254 | jeremias | 2007-12-11 15:29:48 +0100 (Di, 11 Dez 2007) | 2 lines Plugged new image package into form generation for PostScript. XML images and EPS files are currently supported as forms. They are added inline. ------------------------------------------------------------------------ r603256 | jeremias | 2007-12-11 15:34:52 +0100 (Di, 11 Dez 2007) | 1 line Embedding EPS in PDF is no longer implemented as it is a deprecated feature in PDF. Therefore, this test is not needed anymore. The PDF renderer will say: "Cannot load image (no suitable loader/converter combination available) for myfile.eps (application/postscript)" ------------------------------------------------------------------------ r603266 | jeremias | 2007-12-11 16:16:22 +0100 (Di, 11 Dez 2007) | 1 line Size calculation for images can be slightly different after the redesign due to different rounding. Give a little tolerance. ------------------------------------------------------------------------ r603271 | jeremias | 2007-12-11 16:24:08 +0100 (Di, 11 Dez 2007) | 1 line Bugfix: Only generate the FixedLength if there is baseline information. ------------------------------------------------------------------------ r603358 | jeremias | 2007-12-11 22:13:22 +0100 (Di, 11 Dez 2007) | 1 line Switched background images to new image package. ------------------------------------------------------------------------ r603632 | jeremias | 2007-12-12 15:52:09 +0100 (Mi, 12 Dez 2007) | 1 line Switch to new image package for PDF/SVG support. ------------------------------------------------------------------------ r603642 | jeremias | 2007-12-12 16:30:16 +0100 (Mi, 12 Dez 2007) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-594557" from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ------------------------------------------------------------------------ r603656 | jeremias | 2007-12-12 17:13:06 +0100 (Mi, 12 Dez 2007) | 307 lines Merged revisions 594558-603642 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r594571 | vhennebert | 2007-11-13 17:24:32 +0100 (Di, 13 Nov 2007) | 7 lines Moved the creation of grid units to the FO tree building stage. Brought a few improvements along with the move: - bugfix: border-resolution for border-end on row-spanning cells was wrong - bugfix: in case of missing cells the border-end of the table was applied to an inner cell, instead of the cell in the last column (but missing cells aren't painted yet :-\) - bugfix: in collapsing-border model, border-before and -after specified on table-column were applied to every cell of the column, instead of only the first and the last ones - border resolution is now made progressively when possible, and no longer triggers the fetching of all the rows of the table Added testcases for the border conflict resolution (between the various elements of a table and not only the cells) ........ r594578 | vhennebert | 2007-11-13 17:50:09 +0100 (Di, 13 Nov 2007) | 2 lines Moved *GridUnit from layoutmgr/table to fo/flow/table ........ r594579 | vhennebert | 2007-11-13 17:55:54 +0100 (Di, 13 Nov 2007) | 2 lines Changed back visibility of fields from public to package-private, due to the move of *GridUnit in the fo.flow.table package ........ r594584 | vhennebert | 2007-11-13 18:13:19 +0100 (Di, 13 Nov 2007) | 2 lines Use a singleton for a default BorderInfo of style none, instead of every time a new instance ........ r594592 | vhennebert | 2007-11-13 18:39:17 +0100 (Di, 13 Nov 2007) | 2 lines Cleaned up RowGroupLayoutManager and TableRowIterator ........ r594821 | vhennebert | 2007-11-14 11:18:45 +0100 (Mi, 14 Nov 2007) | 2 lines Moved EffRow to the fo.flow.table package ........ r594829 | vhennebert | 2007-11-14 11:41:52 +0100 (Mi, 14 Nov 2007) | 2 lines Reduced visibility of some methods and constructors from public to package-private, as a consequence of the move of *GridUnit to the fo.flow.table package ........ r594836 | vhennebert | 2007-11-14 12:14:03 +0100 (Mi, 14 Nov 2007) | 2 lines Restored the setting of the parent table-row element on grid units ........ r594852 | vhennebert | 2007-11-14 13:21:53 +0100 (Mi, 14 Nov 2007) | 2 lines Restored the setting of rowIndex on primary grid units (although testcases were already working...) ........ r595297 | jeremias | 2007-11-15 14:28:58 +0100 (Do, 15 Nov 2007) | 2 lines Bugzilla #43143: Had to remove the Expert(Subset) Encoding detection as this caused problems with a barcode font that used dfCharset=2 but was not using ExpertSubset encoding. To detect Expert(Subset)Encoding, the AFM needs to be parsed. And since we don't support that encoding, yet, the fallback to WinAnsiEncoding should work well enough. ........ r595637 | acumiskey | 2007-11-16 13:12:52 +0100 (Fr, 16 Nov 2007) | 3 lines This should improve the ability of the FontLoader when resolving PFM files for Type 1 fonts on case sensitive Unix systems. ........ r596072 | jeremias | 2007-11-18 11:48:53 +0100 (So, 18 Nov 2007) | 4 lines ApacheCon US is over. OSSSummit was cancelled/postponed. Added example for total page count using XSL 1.1 Adjusted total page count example to new FOP API. (Thanks to Miroslav Gregan for the hint) ........ r596097 | jeremias | 2007-11-18 17:56:09 +0100 (So, 18 Nov 2007) | 6 lines Bugzilla #43605: Added methods for page-number-citation and page-number-citation-last in FOEventHandler.java Submitted by: V. Schappert Patch modified by Jeremias: Bugfix: FOEventHandler.startPageNumberCitation() was also called in the case of a page-number-citation-last. Introduced abstract base classes to avoid this. ........ r596100 | jeremias | 2007-11-18 18:17:24 +0100 (So, 18 Nov 2007) | 1 line Added sample as suggested by Kumar Puppala. ........ r596390 | vhennebert | 2007-11-19 19:25:27 +0100 (Mo, 19 Nov 2007) | 2 lines Bugzilla #43766: breaks generated by the merging algorithm for table rows containing empty cells has always a penalty of 900 ........ r596554 | jeremias | 2007-11-20 08:14:33 +0100 (Di, 20 Nov 2007) | 2 lines Bugzilla #43904: Buffer the OutputStreams in our transcoders if the users forget. ........ r596600 | jeremias | 2007-11-20 11:20:29 +0100 (Di, 20 Nov 2007) | 3 lines Bugzilla #43910: Avoid a NullPointerException in AreaTreeHandler.endDocument(). Submitted by: David Delbecq ........ r596724 | jeremias | 2007-11-20 16:56:33 +0100 (Di, 20 Nov 2007) | 3 lines Bugfix: Bugfix for URI resolution: Make StreamSources without system identifier work again. Bugfix: Close streams opened by test font resolution in font configuration (the font URIs will be resolved again later anyway). Better error message when the loading of font metric files doesn't work due to missing information in the returned Source instances. ........ r596727 | vhennebert | 2007-11-20 17:07:32 +0100 (Di, 20 Nov 2007) | 2 lines Bugfix in tables: wrong element generation by the merging algorithm when glues must be produced to cope with conditional spaces. The corresponding length was added twice: one in the glue itself and one in the following box. ........ r596739 | cbowditch | 2007-11-20 17:49:13 +0100 (Di, 20 Nov 2007) | 1 line bug fix: memory leak in PropertyCache. Fix provided by Jeremias. There are still some thread synchronization issues to be addressed in the PropertyCache. See the following thread for details: http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200711.mbox/%3cBAY117-DAV109E36CC066889386AB917FB870@phx.gbl%3e ........ r596742 | vhennebert | 2007-11-20 18:08:46 +0100 (Di, 20 Nov 2007) | 2 lines Added a news entry about Max Berger becoming a committer. Welcome Max! ........ r596776 | vhennebert | 2007-11-20 19:47:39 +0100 (Di, 20 Nov 2007) | 2 lines Bugzilla #43803: table cells having no children are allowed in relaxed validation mode. ........ r597052 | vhennebert | 2007-11-21 13:23:59 +0100 (Mi, 21 Nov 2007) | 2 lines Bugfix: the last element generated by the merging algorithm may now be a glue ........ r597448 | jeremias | 2007-11-22 17:13:05 +0100 (Do, 22 Nov 2007) | 2 lines First draft of a possible new intermediate format for Apache FOP. Details on: http://wiki.apache.org/xmlgraphics-fop/AreaTreeIntermediateXml/NewDesign ........ r598558 | jeremias | 2007-11-27 09:36:23 +0100 (Di, 27 Nov 2007) | 6 lines Bugzilla #40230: Bugfix: no empty page is generated anymore if there's no content after a break-after. Bugzilla #43917: Bugfix for border-after painting and element list generation when a forced break is involved. ........ r599536 | vhennebert | 2007-11-29 19:31:13 +0100 (Do, 29 Nov 2007) | 4 lines Added fixes-bug attributes for: - wrong element generation in table when glues are produced - border-resolution on row-spanning cells ........ r599746 | jeremias | 2007-11-30 10:04:54 +0100 (Fr, 30 Nov 2007) | 2 lines Bugzilla #37993: Bugfix: allow multiple bookmarks to point at the same destination. ........ r600195 | adelmelle | 2007-12-01 22:11:53 +0100 (Sa, 01 Dez 2007) | 1 line Correction and simplification of the PropertyCache: subclass WeakReference and remove internal threading ........ r600467 | jeremias | 2007-12-03 11:16:27 +0100 (Mo, 03 Dez 2007) | 2 lines Log RuntimeExceptions during rendering so that they are at least visible somewhere if someone doesn't set an ErrorListener on the XSLT processor (this could lead to exceptions being swallowed). This is a temporary measure until we have time to improve the exception handling in FOP. The original problem that led to this change was: "The number of this PDFNumber must not be empty" while producing a PDF/A with customized filter entries in the PDF configuration. The exception was a follow-up exception after a PDFConformanceException that was swallowed by a default ErrorListener. ........ r600521 | jeremias | 2007-12-03 14:21:06 +0100 (Mo, 03 Dez 2007) | 1 line Added a possibility to rerun the whole run a defined number of times to test for possible issues outside a single rendering run. ........ r600529 | jeremias | 2007-12-03 14:32:04 +0100 (Mo, 03 Dez 2007) | 1 line Oops. ........ r601413 | vhennebert | 2007-12-05 17:56:47 +0100 (Mi, 05 Dez 2007) | 2 lines Typo in property: svn:kewords -> svn:keywords ........ r601415 | acumiskey | 2007-12-05 18:11:44 +0100 (Mi, 05 Dez 2007) | 2 lines Corrected javadocs ........ r601416 | acumiskey | 2007-12-05 18:12:54 +0100 (Mi, 05 Dez 2007) | 2 lines Corrected javadoc ........ r601417 | acumiskey | 2007-12-05 18:13:31 +0100 (Mi, 05 Dez 2007) | 2 lines Corrected javadoc ........ r601419 | acumiskey | 2007-12-05 18:15:46 +0100 (Mi, 05 Dez 2007) | 2 lines Improved use of logging ........ r601423 | acumiskey | 2007-12-05 18:19:43 +0100 (Mi, 05 Dez 2007) | 2 lines Corrected javadoc, fixed checkstyle issues, and now also correctly caters for negative number conversions ........ r601424 | acumiskey | 2007-12-05 18:21:15 +0100 (Mi, 05 Dez 2007) | 2 lines Fixed checkstyle issues ........ r601426 | acumiskey | 2007-12-05 18:24:15 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601427 | acumiskey | 2007-12-05 18:25:07 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601428 | acumiskey | 2007-12-05 18:25:58 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601429 | acumiskey | 2007-12-05 18:27:06 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601430 | acumiskey | 2007-12-05 18:28:03 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601431 | acumiskey | 2007-12-05 18:28:48 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601432 | acumiskey | 2007-12-05 18:29:31 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601433 | acumiskey | 2007-12-05 18:30:04 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601434 | acumiskey | 2007-12-05 18:31:20 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601435 | acumiskey | 2007-12-05 18:32:29 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601436 | acumiskey | 2007-12-05 18:34:44 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601437 | acumiskey | 2007-12-05 18:35:31 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601438 | acumiskey | 2007-12-05 18:36:12 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes and cleanup ........ r601439 | acumiskey | 2007-12-05 18:37:40 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601440 | acumiskey | 2007-12-05 18:39:54 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601442 | acumiskey | 2007-12-05 18:42:13 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601443 | acumiskey | 2007-12-05 18:42:48 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601444 | acumiskey | 2007-12-05 18:43:46 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601445 | acumiskey | 2007-12-05 18:44:36 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601446 | acumiskey | 2007-12-05 18:45:20 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601447 | acumiskey | 2007-12-05 18:47:44 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601448 | acumiskey | 2007-12-05 18:48:56 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601449 | acumiskey | 2007-12-05 18:49:46 +0100 (Mi, 05 Dez 2007) | 2 lines Checkstyle fixes ........ r601712 | acumiskey | 2007-12-06 12:57:14 +0100 (Do, 06 Dez 2007) | 2 lines Temporary fix to the build ........ r602045 | jeremias | 2007-12-07 10:20:28 +0100 (Fr, 07 Dez 2007) | 1 line Avoid a NPE in toString(). ........ r602125 | maxberger | 2007-12-07 16:36:53 +0100 (Fr, 07 Dez 2007) | 6 lines Updated xmlgraphics from SVN Added autodetection of fonts in jar files (x-font and x-font-truetype) Added files needed for testcase Please note: Actual testcase is still missing! ........ r602898 | maxberger | 2007-12-10 14:35:33 +0100 (Mo, 10 Dez 2007) | 2 lines Added documentation for font-in-jar-files ........ r603590 | acumiskey | 2007-12-12 13:24:10 +0100 (Mi, 12 Dez 2007) | 4 lines * Added an SVG handler and Graphics2D implementation for AFP which injects AFP GOCA structured fields into the AFPDataStream. * Fixed many checkstyle problems. * Updated xmlgraphics-commons-1.3svn.jar to include changes to TextHandler ........ r603592 | acumiskey | 2007-12-12 13:26:39 +0100 (Mi, 12 Dez 2007) | 2 lines Updated status with SVG support for AFP. ........ ------------------------------------------------------------------------ r603661 | jeremias | 2007-12-12 17:20:09 +0100 (Mi, 12 Dez 2007) | 1 line Fix javadoc ------------------------------------------------------------------------ r603886 | jeremias | 2007-12-13 12:15:48 +0100 (Do, 13 Dez 2007) | 1 line Copy/paste programming is dangerous. :-) ------------------------------------------------------------------------ r603902 | jeremias | 2007-12-13 13:17:56 +0100 (Do, 13 Dez 2007) | 2 lines Factored out all image handling code in the PDFRenderer into PDFImageHandler classes. The interface was introduced to handle PDF-in-PDF images. The PDFImageHandler interface changes in a backwards-incompatible way but since the PDF-in-PDF plug-in probably has the only implementation, that's not very problematic. I'll release a new version as soon as the image stuff is merged back into Trunk. ------------------------------------------------------------------------ r603937 | jeremias | 2007-12-13 16:20:46 +0100 (Do, 13 Dez 2007) | 1 line Some cleanup ------------------------------------------------------------------------ r603938 | jeremias | 2007-12-13 16:23:23 +0100 (Do, 13 Dez 2007) | 2 lines Switch PCL renderer to new image package. Add an option to force a color canvas (RGB) instead of a gray canvas. Set this to true for all SVG graphics since Batik does not seem to support gradients on a grayscale canvas (IllegalArgumentException). ------------------------------------------------------------------------ r604122 | jeremias | 2007-12-14 08:58:56 +0100 (Fr, 14 Dez 2007) | 1 line Stupid copy/paste again. ------------------------------------------------------------------------ r604135 | jeremias | 2007-12-14 10:04:43 +0100 (Fr, 14 Dez 2007) | 1 line Preliminary changes to switch to the new image library. TIFF optimizations still missing. Untested. ------------------------------------------------------------------------ r604144 | jeremias | 2007-12-14 11:12:41 +0100 (Fr, 14 Dez 2007) | 1 line Switch to new image package. At some point we will probably want to remove this example as JEuclid has a better plug-in now. ------------------------------------------------------------------------ r604150 | jeremias | 2007-12-14 11:27:39 +0100 (Fr, 14 Dez 2007) | 1 line Old JEuclid doesn't notice itself if no MathML document is loaded. ------------------------------------------------------------------------ r604155 | jeremias | 2007-12-14 11:48:07 +0100 (Fr, 14 Dez 2007) | 2 lines Switched to new image package. The preloader simply loads the full document and converts it to SVG. That's the only way to determine the intrinsic size of the image. ------------------------------------------------------------------------ r604157 | jeremias | 2007-12-14 11:51:21 +0100 (Fr, 14 Dez 2007) | 1 line No longer needed. ------------------------------------------------------------------------ r604214 | jeremias | 2007-12-14 17:07:30 +0100 (Fr, 14 Dez 2007) | 1 line Added work-around for decoding CMYK JPEGs with ImageIO (no guarantees for color fidelity but it's better than not being able to use CMYK images). ------------------------------------------------------------------------ r604297 | jeremias | 2007-12-14 22:14:12 +0100 (Fr, 14 Dez 2007) | 68 lines Merged revisions 603643-604293 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r603890 | vhennebert | 2007-12-13 12:35:17 +0100 (Do, 13 Dez 2007) | 2 lines Fixed @throws statements in javadoc ........ r603926 | adelmelle | 2007-12-13 15:43:08 +0100 (Do, 13 Dez 2007) | 4 lines Minor tweaks: * only add text to a fo:wrapper if it is not a direct flow-descendant * error if an fo:wrapper that is a direct flow-descendant contains inline-level children ........ r603943 | vhennebert | 2007-12-13 16:55:29 +0100 (Do, 13 Dez 2007) | 2 lines Removed calls to removeLegalBreaks since they aren't necessary (the whole content is put in a single box anyway) and the method is buggy. ........ r603945 | vhennebert | 2007-12-13 17:10:32 +0100 (Do, 13 Dez 2007) | 2 lines Implemented the resolution of collapsing borders in the FO tree, for every situation (normal, cell at the top of a page, cell broken), taking conditionality, headers and footers into account. ........ r603959 | vhennebert | 2007-12-13 18:21:24 +0100 (Do, 13 Dez 2007) | 2 lines Reverted change accidentally introduced in the previous commit. A proper fix needs to be found for this one. ........ r603961 | vhennebert | 2007-12-13 18:31:26 +0100 (Do, 13 Dez 2007) | 2 lines Ok, now /really/ revert the previous commit :-\ ........ r603962 | vhennebert | 2007-12-13 18:32:43 +0100 (Do, 13 Dez 2007) | 2 lines Style only: removed trailing white spaces ........ r603968 | vhennebert | 2007-12-13 19:28:56 +0100 (Do, 13 Dez 2007) | 2 lines Fixed the handling of columns in the border resolution, especially in case of column-spanning cells ........ r603975 | vhennebert | 2007-12-13 19:52:48 +0100 (Do, 13 Dez 2007) | 2 lines Removed parameter from the endPart method, since the part is already passed as a parameter of the previously called startPart method ........ r603979 | vhennebert | 2007-12-13 19:57:25 +0100 (Do, 13 Dez 2007) | 2 lines Removed parameter from the endTablePart method, as the part is already passed as as a parameter of the previously called startTablePart method ........ r603990 | vhennebert | 2007-12-13 20:17:12 +0100 (Do, 13 Dez 2007) | 2 lines Throw a ValidationException if table-footer is put after table-body and the table uses the collapsing border model. The footer must be known to properly resolve borders. ........ r604171 | vhennebert | 2007-12-14 12:32:51 +0100 (Fr, 14 Dez 2007) | 2 lines Clean up: removed all reset and resetPosition methods, which pre-date the Knuth era and are no longer needed ........ r604180 | vhennebert | 2007-12-14 13:23:10 +0100 (Fr, 14 Dez 2007) | 2 lines Reduced visibility of methods from public to package-private ........ r604185 | acumiskey | 2007-12-14 14:16:06 +0100 (Fr, 14 Dez 2007) | 2 lines Fixed copy constructor ........ r604293 | jeremias | 2007-12-14 21:58:53 +0100 (Fr, 14 Dez 2007) | 2 lines Bugfix: DecodeParms -> DecodeParams (introduced when I changed to generic PDF structures) (fixes CCITT encoded images) ........ ------------------------------------------------------------------------ r604301 | jeremias | 2007-12-14 22:26:27 +0100 (Fr, 14 Dez 2007) | 9 lines Merged revisions 604294-604299 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r604299 | jeremias | 2007-12-14 22:24:14 +0100 (Fr, 14 Dez 2007) | 1 line Don't hack when you're tired! Reverting r604293 and instead fixing the right value. It's DecodeParams -> DecodeParms! ........ ------------------------------------------------------------------------ r604930 | jeremias | 2007-12-17 18:05:47 +0100 (Mo, 17 Dez 2007) | 2 lines Dispose ImageReader when done reading. Don't close streams as some codecs appear to do "late reading" of the image, i.e. only when the rasters are accessed, at which point they still seek on the stream. For this, the streams must remain open. I hope the codecs all properly close the streams once they don't need them anymore. The javadocs are not clear enough in this regards, IMO. ------------------------------------------------------------------------ r604968 | jeremias | 2007-12-17 20:03:45 +0100 (Mo, 17 Dez 2007) | 3 lines Added an isSupported() method to ImageLoaderFactory so we can check early if an ImageLoader may or may not support a particular subformat. This is used to allow optimized loading of CCITT compressed TIFF images. Support for undecoded embedding of single-strip CCITT compressed images for PDF, PostScript and AFP. Added a fallback mechanism for ImageLoaders: if one ImageLoader cannot load a particular image, try equivalent others registered for the same format. ------------------------------------------------------------------------ r604972 | jeremias | 2007-12-17 20:07:43 +0100 (Mo, 17 Dez 2007) | 1 line Update Commons ------------------------------------------------------------------------ r605138 | jeremias | 2007-12-18 09:42:41 +0100 (Di, 18 Dez 2007) | 2 lines Support for specifying a particular page number of a multi-page image (such as TIFF). Format: http://localhost/images/scan1.tif#page=3 ------------------------------------------------------------------------ r605479 | jeremias | 2007-12-19 10:18:33 +0100 (Mi, 19 Dez 2007) | 3 lines Removed new image package after the copying it to XML Graphics Commons. Adjusted to use the Commons' version. Batik-dependent plugins remain but will eventually need a different resting place. ------------------------------------------------------------------------ r605486 | jeremias | 2007-12-19 10:39:33 +0100 (Mi, 19 Dez 2007) | 1 line Adjust the (pre)loader registration for the demo extensions. ------------------------------------------------------------------------ r605567 | jeremias | 2007-12-19 16:03:25 +0100 (Mi, 19 Dez 2007) | 1 line Fixed scaling and translation (didn't work correctly in certain situations) ------------------------------------------------------------------------ r607034 | jeremias | 2007-12-27 11:47:12 +0100 (Do, 27 Dez 2007) | 71 lines Merged revisions 604300-607033 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r604475 | vhennebert | 2007-12-15 19:16:01 +0100 (Sa, 15 Dez 2007) | 2 lines Testcase for the resolution of collapsed and conditional borders in the FO tree ........ r604678 | adelmelle | 2007-12-16 20:54:00 +0100 (So, 16 Dez 2007) | 8 lines Streamlining/Correction of the changes made in r603926 - delegate validation of the fo:wrapper's children to the parent: added static FONode.validateChildNode() - narrow the condition for processing text-childnodes: this is not only constrained to fo:flow and fo:static-content, but the same goes for a fo:wrapper that is a direct descendant of a fo:block-container or fo:inline-container, which only allow block-level content (interpretation) - minor javadoc fixups/improvements ........ r604814 | vhennebert | 2007-12-17 11:21:04 +0100 (Mo, 17 Dez 2007) | 2 lines Organized imports ........ r604965 | vhennebert | 2007-12-17 19:56:46 +0100 (Mo, 17 Dez 2007) | 2 lines Renaming GridUnitPart into the more accurate CellPart. Moreover I was always making the confusion between gup and pgu ........ r604970 | vhennebert | 2007-12-17 20:05:27 +0100 (Mo, 17 Dez 2007) | 2 lines Simplified addAreasAndFlushRow: there can no longer be null GridUnits, every hole in the grid is now filled with an EmptyGridUnit ........ r605195 | vhennebert | 2007-12-18 12:56:38 +0100 (Di, 18 Dez 2007) | 2 lines Reset previousRowsLength before a new row-group is handled ........ r605246 | vhennebert | 2007-12-18 17:48:03 +0100 (Di, 18 Dez 2007) | 2 lines Simplification in RowPainter: avoid the use of an array to store rowOffsets and firstRow index for each part of the table (header, footer, body). One at a time is enough. ........ r605253 | vhennebert | 2007-12-18 18:01:45 +0100 (Di, 18 Dez 2007) | 2 lines Renamed firstRow into firstRowIndex and moved its initialization into handeTableContentPosition ........ r605295 | vhennebert | 2007-12-18 19:58:29 +0100 (Di, 18 Dez 2007) | 2 lines Streamlined the recording of row offsets, by replacing Map with a List. Fixed bug #43633 in the same time. ........ r605297 | vhennebert | 2007-12-18 20:02:02 +0100 (Di, 18 Dez 2007) | 3 lines SVG support for AFP is an important addition IMO. IIUC it will have to be advertised in the next release as "Support for SVG images using primitive AFP graphics commands instead of bitmap images", or something like that? ........ r605517 | vhennebert | 2007-12-19 12:47:38 +0100 (Mi, 19 Dez 2007) | 2 lines I said currentGU can no longer be null ........ r605978 | jeremias | 2007-12-20 18:00:46 +0100 (Do, 20 Dez 2007) | 1 line Remove commented code. ........ r606004 | jeremias | 2007-12-20 20:19:19 +0100 (Do, 20 Dez 2007) | 1 line Added support for scale-down-to-fit and scale-up-to-fit. ........ r607032 | jeremias | 2007-12-27 11:34:15 +0100 (Do, 27 Dez 2007) | 4 lines Added new extension element: fox:external-document. It allows to add whole documents such as multi-page TIFF images to be inserted as peers to a page-sequence. Each image will make up an entire page. See the documentation for details. ATM, only single pages are possible. Multi-page images will be supported with the new image package. Some preparations for page-position="only" but the implementation is incomplete and "only" has no effect, yet. (Just uploaded some stuff I once started) Some javadoc cleanups. ........ ------------------------------------------------------------------------ r607091 | jeremias | 2007-12-27 18:13:45 +0100 (Do, 27 Dez 2007) | 1 line Avoid cutting away the URI fragment when building URLs from filenames. ------------------------------------------------------------------------ r607092 | jeremias | 2007-12-27 18:15:49 +0100 (Do, 27 Dez 2007) | 3 lines Switched fox:external-document to new image package. Added multi-page support for fox:external-document. Changed multi-page.tiff: page 4 is now bigger than all other pages. (to make sure that individually sized pages are handled properly) ------------------------------------------------------------------------ r607188 | jeremias | 2007-12-28 09:38:26 +0100 (Fr, 28 Dez 2007) | 2 lines Throwing IllegalStateException causes a prior exception to be swallowed by Xalan-J. Need to throw a SAXException instead. Instead of logging an error about the element mismatch throw a SAXException because the logging only confuses the user as it's practically always a follow-up exception of an exception happening earlier in the respective startElement() event. ------------------------------------------------------------------------ r607249 | jeremias | 2007-12-28 15:27:39 +0100 (Fr, 28 Dez 2007) | 1 line Metadata didn't get transported to the renderer when only fox:external-document is used. ------------------------------------------------------------------------ r607256 | jeremias | 2007-12-28 16:06:35 +0100 (Fr, 28 Dez 2007) | 1 line Corrected content model. ------------------------------------------------------------------------ r607261 | jeremias | 2007-12-28 16:11:56 +0100 (Fr, 28 Dez 2007) | 1 line Added -imagein to command-line so (multi-page) images such as TIFF files can be converted to PDF and other formats supported by FOP. The default stylesheet can be overwritten (with -xslt) if desired. ------------------------------------------------------------------------ r609530 | jeremias | 2008-01-07 09:16:09 +0100 (Mo, 07 Jan 2008) | 1 line Fixed copy/paste mistake. Thanks for spotting it, Vincent. ------------------------------------------------------------------------ r609600 | jeremias | 2008-01-07 14:28:53 +0100 (Mo, 07 Jan 2008) | 1 line Removed "image2" package again and moved the Batik-dependent implementations under the old "image" package. In this form, the deprecated code doesn't conflict with the new implementations anymore. ------------------------------------------------------------------------ r610029 | jeremias | 2008-01-08 16:48:53 +0100 (Di, 08 Jan 2008) | 3 lines Added minimal support for the .minimum/.maximum components of block/inline-progression-dimension on fo:external-graphic and fo:instream-foreign-object. This will only constrain the image itself but not allow the layout engine itself to resize the image as seen fit. Added missing Javadocs in ImageLayout.java. ------------------------------------------------------------------------ r611120 | jeremias | 2008-01-11 10:20:57 +0100 (Fr, 11 Jan 2008) | 100 lines Merged revisions 607034-611115 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r607036 | jeremias | 2007-12-27 11:51:11 +0100 (Do, 27 Dez 2007) | 1 line Don't just exit with no error message if the document contains no content. Pretty irritating if it does so. ........ r608812 | acumiskey | 2008-01-04 13:14:33 +0100 (Fr, 04 Jan 2008) | 3 lines The fonts variable would have always had an empty Configuration node (non-null value) even if a wasn't present in the fop configuration. ........ r609567 | jeremias | 2008-01-07 11:52:09 +0100 (Mo, 07 Jan 2008) | 4 lines Reenabled documentation for fox:destination. Enabled intermediate format functionality for fox:destination. Added a test case to check fox:destination. Deprecated FOP's XMLizable in favor of the XML Graphics Commons variant (and extend that variant). ........ r609627 | jeremias | 2008-01-07 16:06:24 +0100 (Mo, 07 Jan 2008) | 5 lines Bugzilla #44176: Support for custom fonts in Java2DRenderer and derived renderers. Submitted by: Patrick Jaromin Patch modified slightly by jeremias. ........ r610020 | acumiskey | 2008-01-08 16:27:02 +0100 (Di, 08 Jan 2008) | 2 lines cleaned up ........ r610021 | acumiskey | 2008-01-08 16:28:56 +0100 (Di, 08 Jan 2008) | 2 lines Appears to be unused/referenced and superceeded by PageGroup ........ r610022 | acumiskey | 2008-01-08 16:34:07 +0100 (Di, 08 Jan 2008) | 2 lines cleaned up ........ r610023 | acumiskey | 2008-01-08 16:35:18 +0100 (Di, 08 Jan 2008) | 2 lines fixed javadoc ........ r610337 | vhennebert | 2008-01-09 12:02:08 +0100 (Mi, 09 Jan 2008) | 2 lines Fixed checkstyle issues: tabs and trailing spaces ........ r610355 | vhennebert | 2008-01-09 13:01:21 +0100 (Mi, 09 Jan 2008) | 2 lines keep-together is an inherited property ........ r610420 | acumiskey | 2008-01-09 16:40:25 +0100 (Mi, 09 Jan 2008) | 2 lines cleanup ........ r610704 | jeremias | 2008-01-10 08:38:47 +0100 (Do, 10 Jan 2008) | 1 line Added basic support for PDF page labels. ........ r610739 | jeremias | 2008-01-10 11:13:21 +0100 (Do, 10 Jan 2008) | 1 line PostScript output now generates the bounding box DSC comments for the whole document. ........ r610821 | vhennebert | 2008-01-10 16:53:20 +0100 (Do, 10 Jan 2008) | 4 lines - renamed variables for clarity - moved the computation of a cell's content length in PrimaryGridUnit - better javadoc for getHeight method in EffRow ........ r610848 | vhennebert | 2008-01-10 18:41:52 +0100 (Do, 10 Jan 2008) | 2 lines No need to check if the end of the cell is reached when creating the areas for a row ........ r610853 | vhennebert | 2008-01-10 18:54:16 +0100 (Do, 10 Jan 2008) | 2 lines Simplified addAreasAndFlushRow ........ r610886 | vhennebert | 2008-01-10 20:23:56 +0100 (Do, 10 Jan 2008) | 2 lines Removed endPart() method and moved its content into addAreasAndFlushRow() ........ r610891 | vhennebert | 2008-01-10 20:34:13 +0100 (Do, 10 Jan 2008) | 2 lines Removed accumulatedBPD which is redundant with yoffset ........ r610893 | vhennebert | 2008-01-10 20:35:24 +0100 (Do, 10 Jan 2008) | 2 lines The return value of addAreasAndFlushRow is never used, changed it to void ........ r610905 | vhennebert | 2008-01-10 20:57:29 +0100 (Do, 10 Jan 2008) | 2 lines Renamed lastRow into currentRow and yoffset into currentRowOffset ........ r611114 | jeremias | 2008-01-11 10:04:28 +0100 (Fr, 11 Jan 2008) | 2 lines Bugfix: Some string objects were not encrypted (for example in named destinations) I had to refactor the PDF library a little bit but since it only affects the inner API it shouldn't be a problem that I removed some methods which caused trouble because a didn't think about encryption when I worked on the PDF library last year. ........ ------------------------------------------------------------------------ r611133 | jeremias | 2008-01-11 11:45:01 +0100 (Fr, 11 Jan 2008) | 4 lines Fixed merge problems. Fixed a NPE when a mask is null in BitmapImage.java Add support for properly encoding binary data as a hexadecimal string object (including encryption). Adjust palette generation for indexed bitmaps to work correctly with encryption. ------------------------------------------------------------------------ r611138 | jeremias | 2008-01-11 11:59:27 +0100 (Fr, 11 Jan 2008) | 1 line Removed empty package. ------------------------------------------------------------------------ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@611278 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 1 + ...xmlgraphics.image.loader.spi.ImageLoaderFactory | 1 + ...che.xmlgraphics.image.loader.spi.ImagePreloader | 1 + .../fop/mathml/ImageLoaderFactoryMathML.java | 66 ++++ .../org/apache/fop/mathml/ImageLoaderMathML.java | 71 ++++ .../src/org/apache/fop/mathml/MathMLElement.java | 27 +- .../apache/fop/mathml/MathMLElementMapping.java | 53 +-- .../src/org/apache/fop/mathml/MathMLObj.java | 4 +- .../src/org/apache/fop/mathml/PreloaderMathML.java | 189 +++++++++++ ...che.xmlgraphics.image.loader.spi.ImagePreloader | 1 + .../plan/src/org/apache/fop/plan/PlanElement.java | 23 +- .../org/apache/fop/plan/PlanElementMapping.java | 34 +- examples/plan/src/org/apache/fop/plan/PlanObj.java | 4 +- .../src/org/apache/fop/plan/PreloaderPlan.java | 114 +++++++ fop.bat | 3 +- lib/README.txt | 13 + lib/batik-all-1.6.jar | Bin 2623953 -> 0 bytes lib/batik-all-1.7.jar | Bin 0 -> 3318083 bytes lib/batik.NOTICE.txt | 16 +- lib/xml-apis-ext.jar | Bin 0 -> 85686 bytes lib/xmlgraphics-commons-1.3svn.jar | Bin 370762 -> 498867 bytes .../org.apache.fop.render.pdf.PDFImageHandler | 5 + ...che.xmlgraphics.image.loader.spi.ImageConverter | 2 + ...xmlgraphics.image.loader.spi.ImageLoaderFactory | 2 + ...che.xmlgraphics.image.loader.spi.ImagePreloader | 2 + src/java/org/apache/fop/apps/FOURIResolver.java | 21 +- src/java/org/apache/fop/apps/FOUserAgent.java | 31 +- src/java/org/apache/fop/apps/FopFactory.java | 24 +- src/java/org/apache/fop/area/AreaTreeHandler.java | 22 +- src/java/org/apache/fop/area/AreaTreeParser.java | 33 +- src/java/org/apache/fop/area/Trait.java | 19 +- .../org/apache/fop/cli/CommandLineOptions.java | 48 ++- src/java/org/apache/fop/cli/ImageInputHandler.java | 60 ++++ src/java/org/apache/fop/cli/InputHandler.java | 33 +- src/java/org/apache/fop/cli/image2fo.xsl | 45 +++ src/java/org/apache/fop/fo/FOTreeBuilder.java | 15 +- .../org/apache/fop/fo/flow/ExternalGraphic.java | 43 ++- src/java/org/apache/fop/fo/pagination/Root.java | 14 +- .../properties/CommonBorderPaddingBackground.java | 35 +- .../apache/fop/image/loader/batik/BatikUtil.java | 41 +++ .../image/loader/batik/ImageConverterSVG2G2D.java | 120 +++++++ .../image/loader/batik/ImageConverterWMF2G2D.java | 107 ++++++ .../image/loader/batik/ImageLoaderFactorySVG.java | 63 ++++ .../image/loader/batik/ImageLoaderFactoryWMF.java | 62 ++++ .../fop/image/loader/batik/ImageLoaderSVG.java | 78 +++++ .../fop/image/loader/batik/ImageLoaderWMF.java | 70 ++++ .../apache/fop/image/loader/batik/ImageWMF.java | 69 ++++ .../fop/image/loader/batik/PreloaderSVG.java | 182 ++++++++++ .../fop/image/loader/batik/PreloaderWMF.java | 142 ++++++++ .../org/apache/fop/image/loader/batik/package.html | 26 ++ .../layoutmgr/ExternalDocumentLayoutManager.java | 105 ++++-- src/java/org/apache/fop/layoutmgr/TraitSetter.java | 17 +- .../apache/fop/layoutmgr/inline/ImageLayout.java | 190 ++++++++--- src/java/org/apache/fop/pdf/AlphaRasterImage.java | 181 ++++++++++ src/java/org/apache/fop/pdf/BitmapImage.java | 27 +- src/java/org/apache/fop/pdf/FlateFilter.java | 8 +- src/java/org/apache/fop/pdf/PDFFactory.java | 3 - src/java/org/apache/fop/pdf/PDFFilterList.java | 5 + src/java/org/apache/fop/pdf/PDFICCStream.java | 4 +- src/java/org/apache/fop/pdf/PDFImage.java | 14 +- src/java/org/apache/fop/pdf/PDFImageXObject.java | 21 +- src/java/org/apache/fop/pdf/PDFObject.java | 26 +- src/java/org/apache/fop/pdf/PDFReference.java | 3 + src/java/org/apache/fop/pdf/PDFText.java | 26 +- .../fop/render/AbstractGenericSVGHandler.java | 26 +- .../fop/render/AbstractGraphics2DAdapter.java | 6 +- .../fop/render/AbstractPathOrientedRenderer.java | 88 +++-- .../org/apache/fop/render/Graphics2DAdapter.java | 2 +- .../apache/fop/render/Graphics2DImagePainter.java | 21 +- .../fop/render/afp/AFPGraphics2DAdapter.java | 3 +- .../org/apache/fop/render/afp/AFPRenderer.java | 184 +++++++--- .../fop/render/java2d/Java2DGraphics2DAdapter.java | 32 +- .../apache/fop/render/java2d/Java2DRenderer.java | 141 ++++---- .../fop/render/pcl/PCLGraphics2DAdapter.java | 9 +- .../org/apache/fop/render/pcl/PCLRenderer.java | 255 +++++++------- .../apache/fop/render/pcl/PCLRendererContext.java | 17 + .../render/pcl/PCLRendererContextConstants.java | 32 ++ .../org/apache/fop/render/pcl/PCLSVGHandler.java | 8 + .../fop/render/pdf/AbstractImageAdapter.java | 200 +++++++++++ .../org/apache/fop/render/pdf/FopPDFImage.java | 374 --------------------- .../fop/render/pdf/ImageRawCCITTFaxAdapter.java | 110 ++++++ .../apache/fop/render/pdf/ImageRawJPEGAdapter.java | 96 ++++++ .../fop/render/pdf/ImageRenderedAdapter.java | 249 ++++++++++++++ .../fop/render/pdf/PDFGraphics2DAdapter.java | 3 +- .../org/apache/fop/render/pdf/PDFImageHandler.java | 44 ++- .../fop/render/pdf/PDFImageHandlerGraphics2D.java | 68 ++++ .../fop/render/pdf/PDFImageHandlerRawCCITTFax.java | 83 +++++ .../fop/render/pdf/PDFImageHandlerRawJPEG.java | 83 +++++ .../fop/render/pdf/PDFImageHandlerRegistry.java | 84 ++++- .../render/pdf/PDFImageHandlerRenderedImage.java | 84 +++++ .../apache/fop/render/pdf/PDFImageHandlerXML.java | 74 ++++ .../org/apache/fop/render/pdf/PDFRenderer.java | 160 ++++----- .../fop/render/pdf/PDFRendererConfigurator.java | 2 +- .../org/apache/fop/render/pdf/PDFSVGHandler.java | 51 +-- .../apache/fop/render/ps/ImageEncoderCCITTFax.java | 71 ++++ .../org/apache/fop/render/ps/ImageEncoderJPEG.java | 51 +++ .../apache/fop/render/ps/PSGraphics2DAdapter.java | 34 +- .../org/apache/fop/render/ps/PSImageUtils.java | 100 +----- src/java/org/apache/fop/render/ps/PSRenderer.java | 232 ++++++++++--- .../apache/fop/render/ps/PSSupportedFlavors.java | 67 ++++ .../org/apache/fop/render/ps/ResourceHandler.java | 149 +++++++- src/java/org/apache/fop/render/rtf/RTFHandler.java | 188 +++++------ .../rtf/rtflib/rtfdoc/RtfExternalGraphic.java | 26 +- src/java/org/apache/fop/svg/PDFBridgeContext.java | 45 ++- src/java/org/apache/fop/svg/PDFGraphics2D.java | 17 +- .../org/apache/fop/svg/PDFImageElementBridge.java | 209 +++++++----- src/java/org/apache/fop/svg/PDFTranscoder.java | 57 +++- .../fop/util/dijkstra/DefaultEdgeDirectory.java | 109 ++++++ .../fop/util/dijkstra/DijkstraAlgorithm.java | 215 ++++++++++++ src/java/org/apache/fop/util/dijkstra/Edge.java | 47 +++ .../apache/fop/util/dijkstra/EdgeDirectory.java | 45 +++ src/java/org/apache/fop/util/dijkstra/Vertex.java | 32 ++ status.xml | 10 +- .../image/loader/batik/ImageLoaderTestCase.java | 118 +++++++ .../image/loader/batik/ImagePreloaderTestCase.java | 109 ++++++ test/java/org/apache/fop/memory/MemoryEater.java | 5 +- .../fop/render/pdf/PDFAConformanceTestCase.java | 14 - test/java/org/apache/fop/threading/FOPTestbed.java | 39 ++- .../java/org/apache/fop/threading/FOProcessor.java | 19 +- .../org/apache/fop/threading/FOProcessorImpl.java | 57 ++-- test/java/org/apache/fop/threading/Main.java | 20 ++ test/java/org/apache/fop/threading/sample.cfg.xml | 11 +- test/java/org/apache/fop/util/dijkstra/City.java | 57 ++++ .../apache/fop/util/dijkstra/DijkstraTestCase.java | 139 ++++++++ test/java/org/apache/fop/util/dijkstra/Mode.java | 51 +++ .../org/apache/fop/util/dijkstra/TrainRoute.java | 67 ++++ test/java/org/apache/fop/visual/BatchDiffer.java | 31 +- .../standard-testcases/external-graphic_bmp.xml | 16 +- .../standard-testcases/external-graphic_emf.xml | 8 +- .../standard-testcases/external-graphic_eps.xml | 8 +- .../standard-testcases/external-graphic_png.xml | 16 +- .../standard-testcases/external-graphic_size_1.xml | 121 +++++++ .../standard-testcases/external-graphic_tiff.xml | 32 +- .../standard-testcases/fox_external-document_1.xml | 16 +- .../standard-testcases/fox_external-document_2.xml | 16 +- .../standard-testcases/fox_external-document_3.xml | 53 +++ .../standard-testcases/inline_vertical-align_2.xml | 44 +-- test/resources/images/fop-logo-color-24bit.png | Bin 0 -> 36816 bytes .../images/fop-logo-color-palette-2bit.png | Bin 0 -> 9160 bytes .../images/fop-logo-color-palette-4bit.png | Bin 0 -> 11990 bytes .../images/fop-logo-color-palette-8bit.png | Bin 0 -> 17912 bytes test/resources/images/fop-logo-gray-8bit.png | Bin 0 -> 18447 bytes test/resources/images/fop-logo-mono-1bit.png | Bin 0 -> 11190 bytes test/resources/images/img-with-tiff-preview.eps | Bin 0 -> 13926 bytes test/resources/images/multi-page.tiff | Bin 0 -> 12339 bytes test/resources/images/no-resolution.bmp | Bin 0 -> 7654 bytes test/resources/images/no-resolution.tif | Bin 0 -> 314 bytes test/resources/images/testChart.wmf | Bin 0 -> 4200 bytes test/resources/images/tiff_group3-1d.tif | Bin 0 -> 9823 bytes test/resources/images/tiff_group3-2d.tif | Bin 0 -> 6976 bytes test/resources/images/tiff_group3-multi-strip.tif | Bin 0 -> 8596 bytes test/xml/pdf-a/with-eps.fo | 14 - 152 files changed, 6266 insertions(+), 1773 deletions(-) create mode 100644 examples/mathml/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory create mode 100644 examples/mathml/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader create mode 100644 examples/mathml/src/org/apache/fop/mathml/ImageLoaderFactoryMathML.java create mode 100644 examples/mathml/src/org/apache/fop/mathml/ImageLoaderMathML.java create mode 100644 examples/mathml/src/org/apache/fop/mathml/PreloaderMathML.java create mode 100644 examples/plan/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader create mode 100644 examples/plan/src/org/apache/fop/plan/PreloaderPlan.java delete mode 100644 lib/batik-all-1.6.jar create mode 100644 lib/batik-all-1.7.jar create mode 100644 lib/xml-apis-ext.jar create mode 100644 src/java/META-INF/services/org.apache.fop.render.pdf.PDFImageHandler create mode 100644 src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageConverter create mode 100644 src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory create mode 100644 src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader create mode 100644 src/java/org/apache/fop/cli/ImageInputHandler.java create mode 100644 src/java/org/apache/fop/cli/image2fo.xsl create mode 100644 src/java/org/apache/fop/image/loader/batik/BatikUtil.java create mode 100644 src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java create mode 100644 src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java create mode 100644 src/java/org/apache/fop/image/loader/batik/ImageLoaderFactorySVG.java create mode 100644 src/java/org/apache/fop/image/loader/batik/ImageLoaderFactoryWMF.java create mode 100644 src/java/org/apache/fop/image/loader/batik/ImageLoaderSVG.java create mode 100644 src/java/org/apache/fop/image/loader/batik/ImageLoaderWMF.java create mode 100644 src/java/org/apache/fop/image/loader/batik/ImageWMF.java create mode 100644 src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java create mode 100644 src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java create mode 100644 src/java/org/apache/fop/image/loader/batik/package.html create mode 100644 src/java/org/apache/fop/pdf/AlphaRasterImage.java create mode 100644 src/java/org/apache/fop/render/pcl/PCLRendererContextConstants.java create mode 100644 src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java delete mode 100644 src/java/org/apache/fop/render/pdf/FopPDFImage.java create mode 100644 src/java/org/apache/fop/render/pdf/ImageRawCCITTFaxAdapter.java create mode 100644 src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java create mode 100644 src/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java create mode 100644 src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java create mode 100644 src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java create mode 100644 src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java create mode 100644 src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java create mode 100644 src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java create mode 100644 src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java create mode 100644 src/java/org/apache/fop/render/ps/ImageEncoderJPEG.java create mode 100644 src/java/org/apache/fop/render/ps/PSSupportedFlavors.java create mode 100644 src/java/org/apache/fop/util/dijkstra/DefaultEdgeDirectory.java create mode 100644 src/java/org/apache/fop/util/dijkstra/DijkstraAlgorithm.java create mode 100644 src/java/org/apache/fop/util/dijkstra/Edge.java create mode 100644 src/java/org/apache/fop/util/dijkstra/EdgeDirectory.java create mode 100644 src/java/org/apache/fop/util/dijkstra/Vertex.java create mode 100644 test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java create mode 100644 test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java create mode 100644 test/java/org/apache/fop/util/dijkstra/City.java create mode 100644 test/java/org/apache/fop/util/dijkstra/DijkstraTestCase.java create mode 100644 test/java/org/apache/fop/util/dijkstra/Mode.java create mode 100644 test/java/org/apache/fop/util/dijkstra/TrainRoute.java create mode 100644 test/layoutengine/standard-testcases/external-graphic_size_1.xml create mode 100644 test/layoutengine/standard-testcases/fox_external-document_3.xml create mode 100644 test/resources/images/fop-logo-color-24bit.png create mode 100644 test/resources/images/fop-logo-color-palette-2bit.png create mode 100644 test/resources/images/fop-logo-color-palette-4bit.png create mode 100644 test/resources/images/fop-logo-color-palette-8bit.png create mode 100644 test/resources/images/fop-logo-gray-8bit.png create mode 100644 test/resources/images/fop-logo-mono-1bit.png create mode 100644 test/resources/images/img-with-tiff-preview.eps create mode 100644 test/resources/images/multi-page.tiff create mode 100644 test/resources/images/no-resolution.bmp create mode 100644 test/resources/images/no-resolution.tif create mode 100644 test/resources/images/testChart.wmf create mode 100644 test/resources/images/tiff_group3-1d.tif create mode 100644 test/resources/images/tiff_group3-2d.tif create mode 100644 test/resources/images/tiff_group3-multi-strip.tif delete mode 100644 test/xml/pdf-a/with-eps.fo (limited to 'src') diff --git a/build.xml b/build.xml index add212d3e..dd68ecdda 100644 --- a/build.xml +++ b/build.xml @@ -1018,6 +1018,7 @@ NOTE: overview="${src.dir}/java/org/apache/fop/overview.html" use="true" failonerror="true" + source="${javac.source}" public="${javadoc.public}" package="${javadoc.package}" private="${javadoc.private}"> diff --git a/examples/mathml/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory b/examples/mathml/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory new file mode 100644 index 000000000..ab58234d4 --- /dev/null +++ b/examples/mathml/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory @@ -0,0 +1 @@ +org.apache.fop.mathml.ImageLoaderFactoryMathML diff --git a/examples/mathml/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader b/examples/mathml/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader new file mode 100644 index 000000000..870684c8f --- /dev/null +++ b/examples/mathml/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader @@ -0,0 +1 @@ +org.apache.fop.mathml.PreloaderMathML diff --git a/examples/mathml/src/org/apache/fop/mathml/ImageLoaderFactoryMathML.java b/examples/mathml/src/org/apache/fop/mathml/ImageLoaderFactoryMathML.java new file mode 100644 index 000000000..b0e94222a --- /dev/null +++ b/examples/mathml/src/org/apache/fop/mathml/ImageLoaderFactoryMathML.java @@ -0,0 +1,66 @@ +/* + * 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.mathml; + +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoaderFactory; +import org.apache.xmlgraphics.image.loader.spi.ImageLoader; + +/** + * Factory class for the ImageLoader for MathML. + */ +public class ImageLoaderFactoryMathML extends AbstractImageLoaderFactory { + + /** MathML MIME type */ + public static final String MIME_MATHML = "text/mathml"; + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.GRAPHICS2D}; + + private static final String[] MIMES = new String[] { + MIME_MATHML}; + + /** {@inheritDoc} */ + public String[] getSupportedMIMETypes() { + return MIMES; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedFlavors(String mime) { + return FLAVORS; + } + + /** {@inheritDoc} */ + public ImageLoader newImageLoader(ImageFlavor targetFlavor) { + return new ImageLoaderMathML(targetFlavor); + } + + /** {@inheritDoc} */ + public int getUsagePenalty(String mime, ImageFlavor flavor) { + return 0; + } + + /** {@inheritDoc} */ + public boolean isAvailable() { + //TODO Refine! + return true; + } + +} diff --git a/examples/mathml/src/org/apache/fop/mathml/ImageLoaderMathML.java b/examples/mathml/src/org/apache/fop/mathml/ImageLoaderMathML.java new file mode 100644 index 000000000..900b9d614 --- /dev/null +++ b/examples/mathml/src/org/apache/fop/mathml/ImageLoaderMathML.java @@ -0,0 +1,71 @@ +/* + * 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.mathml; + +import java.io.IOException; +import java.util.Map; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoader; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; + +/** + * ImageLoader for MathML (using JEuclid). + */ +public class ImageLoaderMathML extends AbstractImageLoader { + + private ImageFlavor targetFlavor; + + /** + * Main constructor. + * @param targetFlavor the target flavor + */ + public ImageLoaderMathML(ImageFlavor targetFlavor) { + if (!(ImageFlavor.GRAPHICS2D.equals(targetFlavor))) { + throw new IllegalArgumentException("Unsupported target ImageFlavor: " + targetFlavor); + } + this.targetFlavor = targetFlavor; + } + + /** {@inheritDoc} */ + public ImageFlavor getTargetFlavor() { + return this.targetFlavor; + } + + /** {@inheritDoc} */ + public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) + throws ImageException, IOException { + if (!ImageLoaderFactoryMathML.MIME_MATHML.equals(info.getMimeType())) { + throw new IllegalArgumentException("ImageInfo must be from an MathML image"); + } + Image img = info.getOriginalImage(); + if (!(img instanceof ImageGraphics2D)) { + throw new IllegalArgumentException( + "ImageInfo was expected to contain the MathML document as Graphics2D image"); + } + ImageGraphics2D g2dImage = (ImageGraphics2D)img; + return g2dImage; + } + +} diff --git a/examples/mathml/src/org/apache/fop/mathml/MathMLElement.java b/examples/mathml/src/org/apache/fop/mathml/MathMLElement.java index f4c4bc329..82bd85a17 100644 --- a/examples/mathml/src/org/apache/fop/mathml/MathMLElement.java +++ b/examples/mathml/src/org/apache/fop/mathml/MathMLElement.java @@ -23,9 +23,9 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.geom.Point2D; -import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; +import net.sourceforge.jeuclid.DOMMathBuilder; +import net.sourceforge.jeuclid.MathBase; + import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -34,11 +34,12 @@ import org.w3c.dom.Node; import org.xml.sax.Attributes; import org.xml.sax.Locator; -import org.apache.batik.svggen.SVGGraphics2D; import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.svggen.SVGGraphics2D; -import net.sourceforge.jeuclid.MathBase; -import net.sourceforge.jeuclid.DOMMathBuilder; +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; /** * Defines the top-level element for MathML. @@ -57,9 +58,7 @@ public class MathMLElement extends MathMLObj { super(parent); } - /** - * @see org.apache.fop.fo.FONode#processNode - */ + /** {@inheritDoc} */ public void processNode(String elementName, Locator locator, Attributes attlist, @@ -141,15 +140,13 @@ public class MathMLElement extends MathMLObj { } - /** @see org.apache.fop.fo.XMLObj#getDOMDocument() */ + /** {@inheritDoc} */ public Document getDOMDocument() { convertToSVG(); return doc; } - /** - * @see org.apache.fop.fo.FONode#getNamespaceURI() - */ + /** {@inheritDoc} */ public String getNamespaceURI() { if (svgDoc == null) { return MathMLElementMapping.NAMESPACE; @@ -157,9 +154,7 @@ public class MathMLElement extends MathMLObj { return "http://www.w3.org/2000/svg"; } - /** - * @see org.apache.fop.fo.XMLObj#getDimension(Point2D) - */ + /** {@inheritDoc} */ public Point2D getDimension(Point2D view) { convertToSVG(); return new Point2D.Float(width, height); diff --git a/examples/mathml/src/org/apache/fop/mathml/MathMLElementMapping.java b/examples/mathml/src/org/apache/fop/mathml/MathMLElementMapping.java index 050004392..fdfa0b5c7 100644 --- a/examples/mathml/src/org/apache/fop/mathml/MathMLElementMapping.java +++ b/examples/mathml/src/org/apache/fop/mathml/MathMLElementMapping.java @@ -19,17 +19,12 @@ package org.apache.fop.mathml; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ElementMapping; -import org.apache.fop.image.analyser.XMLReader; -import org.apache.fop.image.FopImage; -import org.w3c.dom.DOMImplementation; -import org.w3c.dom.Document; - import java.util.HashMap; -import net.sourceforge.jeuclid.MathBase; -import net.sourceforge.jeuclid.DOMMathBuilder; +import org.w3c.dom.DOMImplementation; + +import org.apache.fop.fo.ElementMapping; +import org.apache.fop.fo.FONode; /** * This class provides the element mapping for FOP. @@ -44,19 +39,17 @@ public class MathMLElementMapping extends ElementMapping { this.namespaceURI = NAMESPACE; } - /** @see org.apache.fop.fo.ElementMapping#getDOMImplementation() */ + /** {@inheritDoc} */ public DOMImplementation getDOMImplementation() { return getDefaultDOMImplementation(); } - /** @see org.apache.fop.fo.ElementMapping#initialize() */ + /** {@inheritDoc} */ protected void initialize() { if (foObjs == null) { foObjs = new HashMap(); foObjs.put("math", new ME()); foObjs.put(DEFAULT, new MathMLMaker()); - - XMLReader.setConverter(this.namespaceURI, new MathMLConverter()); } } @@ -72,38 +65,4 @@ public class MathMLElementMapping extends ElementMapping { } } - static class MathMLConverter implements XMLReader.Converter { - public FopImage.ImageInfo convert(Document doc) { - try { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - String fontname = "Helvetica"; - int fontstyle = 0; - int inlinefontstyle = 0; - int inlinefontsize = 12; - int displayfontsize = 12; - - MathBase base = new MathBase( - (new DOMMathBuilder(doc)).getMathRootElement(), - fontname, fontstyle, inlinefontsize, - displayfontsize); - - base.setDebug(false); - - info.data = MathMLElement.createSVG(base); - - info.width = base.getWidth(); - info.height = base.getHeight(); - - info.mimeType = "image/svg+xml"; - info.str = "http://www.w3.org/2000/svg"; - - return info; - } catch (Throwable t) { - /**@todo log that properly */ - } - return null; - - } - } - } diff --git a/examples/mathml/src/org/apache/fop/mathml/MathMLObj.java b/examples/mathml/src/org/apache/fop/mathml/MathMLObj.java index b7a6d1732..9d2b78047 100644 --- a/examples/mathml/src/org/apache/fop/mathml/MathMLObj.java +++ b/examples/mathml/src/org/apache/fop/mathml/MathMLObj.java @@ -35,12 +35,12 @@ public class MathMLObj extends XMLObj { super(parent); } - /** @see org.apache.fop.fo.FONode#getNamespaceURI() */ + /** {@inheritDoc} */ public String getNamespaceURI() { return MathMLElementMapping.NAMESPACE; } - /** @see org.apache.fop.fo.FONode#getNormalNamespacePrefix() */ + /** {@inheritDoc} */ public String getNormalNamespacePrefix() { return "mathml"; } diff --git a/examples/mathml/src/org/apache/fop/mathml/PreloaderMathML.java b/examples/mathml/src/org/apache/fop/mathml/PreloaderMathML.java new file mode 100644 index 000000000..3015462ce --- /dev/null +++ b/examples/mathml/src/org/apache/fop/mathml/PreloaderMathML.java @@ -0,0 +1,189 @@ +/* + * 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.mathml; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamSource; + +import net.sourceforge.jeuclid.MathBase; +import net.sourceforge.jeuclid.SAXMathBuilder; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageContext; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + +import org.apache.fop.util.UnclosableInputStream; + +/** + * Image preloader for MathML images. + */ +public class PreloaderMathML extends AbstractImagePreloader { + + /** Logger instance */ + private static Log log = LogFactory.getLog(PreloaderMathML.class); + + private boolean jeuclidAvailable = true; + + /** {@inheritDoc} */ + public ImageInfo preloadImage(String uri, Source src, ImageContext context) + throws IOException { + if (!ImageUtil.hasInputStream(src)) { + //TODO Remove this and support DOMSource and possibly SAXSource + return null; + } + ImageInfo info = null; + if (jeuclidAvailable) { + try { + Loader loader = new Loader(); + info = loader.getImage(uri, src, context); + } catch (NoClassDefFoundError e) { + jeuclidAvailable = false; + log.warn("JEuclid not in class path", e); + return null; + } + } + if (info != null) { + ImageUtil.closeQuietly(src); //Image is fully read + } + return info; + } + + /** + * This method is put in another class so that the class loader does not + * attempt to load JEuclid related classes when constructing the MathMLPreloader + * class. + */ + class Loader { + + private ImageInfo getImage(String uri, Source src, ImageContext context) { + + InputStream in = new UnclosableInputStream(ImageUtil.needInputStream(src)); + try { + int length = in.available(); + in.mark(length + 1); + + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(); + Source source = new StreamSource(in); + SAXMathBuilder mathBuilder = new SAXMathBuilder(); + SAXResult res = new SAXResult(mathBuilder); + transformer.transform(source, res); + + String fontname = "Helvetica"; + int fontstyle = 0; + int displayfontsize = 12; + int inlinefontsize = 12; + + if (mathBuilder.getMathRootElement() == null) { + //not a MathML document + try { + in.reset(); + } catch (IOException ioe) { + log.error("Error while resetting ImageInputStream", ioe); + } + return null; + } + final MathBase base = new MathBase( + mathBuilder.getMathRootElement(), + fontname, fontstyle, inlinefontsize, + displayfontsize); + + ImageInfo info = new ImageInfo(uri, "text/mathml"); + final ImageSize size = new ImageSize(); + size.setSizeInMillipoints( + Math.round(base.getWidth() * 1000), + Math.round(base.getHeight() * 1000)); + //Set the resolution to that of the FOUserAgent + size.setResolution(context.getSourceResolution()); + size.calcPixelsFromSize(); + info.setSize(size); + + Graphics2DImagePainter painter = new Graphics2DImagePainter() { + + public Dimension getImageSize() { + return size.getDimensionMpt(); + } + + public void paint(Graphics2D g2d, Rectangle2D area) { + base.paint(g2d); + } + + }; + + //The whole image had to be loaded for this, so keep it + Image image = new ImageGraphics2D(info, painter); + info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, image); + + return info; + } catch (NoClassDefFoundError ncdfe) { + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } + jeuclidAvailable = false; + log.warn("JEuclid not in class path", ncdfe); + return null; + } catch (IOException e) { + // If the MathML is invalid then it throws an IOException + // so there is no way of knowing if it is an svg document + + log.debug("Error while trying to load stream as an MathML file: " + + e.getMessage()); + // assuming any exception means this document is not svg + // or could not be loaded for some reason + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } + return null; + } catch (TransformerException e) { + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } + log.debug("Error while trying to parsing a MathML file: " + + e.getMessage()); + return null; + } + } + } + +} diff --git a/examples/plan/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader b/examples/plan/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader new file mode 100644 index 000000000..444080090 --- /dev/null +++ b/examples/plan/resources/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader @@ -0,0 +1 @@ +org.apache.fop.plan.PreloaderPlan diff --git a/examples/plan/src/org/apache/fop/plan/PlanElement.java b/examples/plan/src/org/apache/fop/plan/PlanElement.java index 9e4f7bb16..d910076c6 100644 --- a/examples/plan/src/org/apache/fop/plan/PlanElement.java +++ b/examples/plan/src/org/apache/fop/plan/PlanElement.java @@ -21,14 +21,15 @@ package org.apache.fop.plan; import java.awt.geom.Point2D; -import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; - import org.w3c.dom.Document; + import org.xml.sax.Attributes; import org.xml.sax.Locator; +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; + /** * This class defines the plan element. */ @@ -46,9 +47,7 @@ public class PlanElement extends PlanObj { super(parent); } - /** - * @see org.apache.fop.fo.FONode#processNode - */ + /** {@inheritDoc} */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException { @@ -79,15 +78,13 @@ public class PlanElement extends PlanObj { } - /** - * @see org.apache.fop.fo.XMLObj#getDOMDocument() - */ + /** {@inheritDoc} */ public Document getDOMDocument() { convertToSVG(); return doc; } - /** @see org.apache.fop.fo.FONode#getNamespaceURI() */ + /** {@inheritDoc} */ public String getNamespaceURI() { if (svgDoc == null) { return PlanElementMapping.NAMESPACE; @@ -95,9 +92,7 @@ public class PlanElement extends PlanObj { return "http://www.w3.org/2000/svg"; } - /** - * @see org.apache.fop.fo.XMLObj#getDimension(Point2D) - */ + /** {@inheritDoc} */ public Point2D getDimension(Point2D view) { convertToSVG(); return new Point2D.Float(width, height); diff --git a/examples/plan/src/org/apache/fop/plan/PlanElementMapping.java b/examples/plan/src/org/apache/fop/plan/PlanElementMapping.java index 556518d42..c33c25edf 100644 --- a/examples/plan/src/org/apache/fop/plan/PlanElementMapping.java +++ b/examples/plan/src/org/apache/fop/plan/PlanElementMapping.java @@ -19,12 +19,10 @@ package org.apache.fop.plan; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ElementMapping; -import org.apache.fop.image.analyser.XMLReader; -import org.apache.fop.image.FopImage; import org.w3c.dom.DOMImplementation; -import org.w3c.dom.Document; + +import org.apache.fop.fo.ElementMapping; +import org.apache.fop.fo.FONode; /** * This class provides the element mapping for FOP. @@ -39,19 +37,17 @@ public class PlanElementMapping extends ElementMapping { this.namespaceURI = NAMESPACE; } - /** @see org.apache.fop.fo.ElementMapping#getDOMImplementation() */ + /** {@inheritDoc} */ public DOMImplementation getDOMImplementation() { return getDefaultDOMImplementation(); } - /** @see org.apache.fop.fo.ElementMapping#initialize() */ + /** {@inheritDoc} */ protected void initialize() { if (foObjs == null) { foObjs = new java.util.HashMap(); foObjs.put("plan", new PE()); foObjs.put(DEFAULT, new PlanMaker()); - - XMLReader.setConverter(this.namespaceURI, new PlanConverter()); } } @@ -67,24 +63,4 @@ public class PlanElementMapping extends ElementMapping { } } - static class PlanConverter implements XMLReader.Converter { - public FopImage.ImageInfo convert(Document doc) { - try { - PlanRenderer pr = new PlanRenderer(); - pr.setFontInfo("Helvetica", 12); - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.data = pr.createSVGDocument(doc); - info.width = (int)pr.getWidth(); - info.height = (int)pr.getHeight(); - info.mimeType = "image/svg+xml"; - info.str = "http://www.w3.org/2000/svg"; - - return info; - } catch (Throwable t) { - /**@todo Log this properly! */ - } - return null; - } - } - } diff --git a/examples/plan/src/org/apache/fop/plan/PlanObj.java b/examples/plan/src/org/apache/fop/plan/PlanObj.java index 32ad522b1..36f3243a6 100644 --- a/examples/plan/src/org/apache/fop/plan/PlanObj.java +++ b/examples/plan/src/org/apache/fop/plan/PlanObj.java @@ -38,12 +38,12 @@ public class PlanObj extends XMLObj { super(parent); } - /** @see org.apache.fop.fo.FONode#getNamespaceURI() */ + /** {@inheritDoc} */ public String getNamespaceURI() { return PlanElementMapping.NAMESPACE; } - /** @see org.apache.fop.fo.FONode#getNormalNamespacePrefix() */ + /** {@inheritDoc} */ public String getNormalNamespacePrefix() { return "plan"; } diff --git a/examples/plan/src/org/apache/fop/plan/PreloaderPlan.java b/examples/plan/src/org/apache/fop/plan/PreloaderPlan.java new file mode 100644 index 000000000..58d5be477 --- /dev/null +++ b/examples/plan/src/org/apache/fop/plan/PreloaderPlan.java @@ -0,0 +1,114 @@ +/* + * 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.plan; + +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.w3c.dom.Document; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageContext; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; + +import org.apache.fop.util.UnclosableInputStream; + +/** + * Image preloader for Plan images. + */ +public class PreloaderPlan extends AbstractImagePreloader { + + /** Logger instance */ + private static Log log = LogFactory.getLog(PreloaderPlan.class); + + /** {@inheritDoc} */ + public ImageInfo preloadImage(String uri, Source src, ImageContext context) + throws IOException { + if (!ImageUtil.hasInputStream(src)) { + //TODO Remove this and support DOMSource and possibly SAXSource + return null; + } + ImageInfo info = getImage(uri, src, context); + if (info != null) { + ImageUtil.closeQuietly(src); //Image is fully read + } + return info; + } + + private ImageInfo getImage(String uri, Source src, ImageContext context) { + + InputStream in = new UnclosableInputStream(ImageUtil.needInputStream(src)); + try { + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(); + Source source = new StreamSource(in); + DOMResult res = new DOMResult(); + transformer.transform(source, res); + + //Have to render the plan to know its size + PlanRenderer pr = new PlanRenderer(); + Document svgDoc = pr.createSVGDocument((Document)res.getNode()); + float width = pr.getWidth(); + float height = pr.getHeight(); + + //Return converted SVG image + ImageInfo info = new ImageInfo(uri, "image/svg+xml"); + final ImageSize size = new ImageSize(); + size.setSizeInMillipoints( + Math.round(width * 1000), + Math.round(height * 1000)); + //Set the resolution to that of the FOUserAgent + size.setResolution(context.getSourceResolution()); + size.calcPixelsFromSize(); + info.setSize(size); + + //The whole image had to be loaded for this, so keep it + Image image = new ImageXMLDOM(info, svgDoc, + svgDoc.getDocumentElement().getNamespaceURI()); + info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, image); + + return info; + } catch (TransformerException e) { + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } + log.debug("Error while trying to parsing a Plan file: " + + e.getMessage()); + return null; + } + } + +} diff --git a/fop.bat b/fop.bat index 0f92b9915..95086ba96 100644 --- a/fop.bat +++ b/fop.bat @@ -56,10 +56,11 @@ set LOCALCLASSPATH=%LOCAL_FOP_HOME%build\fop.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LOCAL_FOP_HOME%build\fop-sandbox.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LOCAL_FOP_HOME%build\fop-hyph.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xml-apis-1.3.02.jar +set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xml-apis-ext.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xercesImpl-2.7.1.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xalan-2.7.0.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\serializer-2.7.0.jar -set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\batik-all-1.6.jar +set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\batik-all-1.7svn.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xmlgraphics-commons-1.3svn.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\avalon-framework-4.2.0.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-io-1.3.1.jar diff --git a/lib/README.txt b/lib/README.txt index 88993f656..8d6356eaa 100644 --- a/lib/README.txt +++ b/lib/README.txt @@ -51,6 +51,19 @@ Normal Dependencies Apache License v2.0 +- Apache XML Commons Externals + + xml-apis-ext-*.jar + http://xml.apache.org/commons/components/external/ + (additional DOM APIs from W3C, like SVG, SMIL and Simple API for CSS) + + Apache License v2.0 (applies to the distribution) + W3C Software Notice and License (applies to the various DOM Java bindings) + W3C Document License (applies to the DOM documentation) + http://www.w3.org/Consortium/Legal/copyright-software + http://www.w3.org/Consortium/Legal/copyright-documents + http://www.w3.org/Consortium/Legal/ + Special Dependencies diff --git a/lib/batik-all-1.6.jar b/lib/batik-all-1.6.jar deleted file mode 100644 index 7b59021db..000000000 Binary files a/lib/batik-all-1.6.jar and /dev/null differ diff --git a/lib/batik-all-1.7.jar b/lib/batik-all-1.7.jar new file mode 100644 index 000000000..589328581 Binary files /dev/null and b/lib/batik-all-1.7.jar differ diff --git a/lib/batik.NOTICE.txt b/lib/batik.NOTICE.txt index 6feaadad8..662188f35 100644 --- a/lib/batik.NOTICE.txt +++ b/lib/batik.NOTICE.txt @@ -1,8 +1,18 @@ -This product includes software developed by +Apache Batik +Copyright 1999-2007 The Apache Software Foundation + +This product includes software developed at The Apache Software Foundation (http://www.apache.org/). This software contains code from the World Wide Web Consortium (W3C) for the Document Object Model API (DOM API) and SVG Document Type Definition (DTD). -This software contains code from the International Organisation for Standardization -for the definition of character entities used in the software's documentation. +This software contains code from the International Organisation for +Standardization for the definition of character entities used in the software's +documentation. + +This product includes images from the Tango Desktop Project +(http://tango.freedesktop.org/). + +This product includes images from the Pasodoble Icon Theme +(http://www.jesusda.com/projects/pasodoble). diff --git a/lib/xml-apis-ext.jar b/lib/xml-apis-ext.jar new file mode 100644 index 000000000..a7869d68a Binary files /dev/null and b/lib/xml-apis-ext.jar differ diff --git a/lib/xmlgraphics-commons-1.3svn.jar b/lib/xmlgraphics-commons-1.3svn.jar index 0b63c1815..cc3c3c6da 100644 Binary files a/lib/xmlgraphics-commons-1.3svn.jar and b/lib/xmlgraphics-commons-1.3svn.jar differ diff --git a/src/java/META-INF/services/org.apache.fop.render.pdf.PDFImageHandler b/src/java/META-INF/services/org.apache.fop.render.pdf.PDFImageHandler new file mode 100644 index 000000000..b72796c2d --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.render.pdf.PDFImageHandler @@ -0,0 +1,5 @@ +org.apache.fop.render.pdf.PDFImageHandlerRawJPEG +org.apache.fop.render.pdf.PDFImageHandlerRawCCITTFax +org.apache.fop.render.pdf.PDFImageHandlerGraphics2D +org.apache.fop.render.pdf.PDFImageHandlerRenderedImage +org.apache.fop.render.pdf.PDFImageHandlerXML \ No newline at end of file diff --git a/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageConverter b/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageConverter new file mode 100644 index 000000000..c3c688a2c --- /dev/null +++ b/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageConverter @@ -0,0 +1,2 @@ +org.apache.fop.image.loader.batik.ImageConverterSVG2G2D +org.apache.fop.image.loader.batik.ImageConverterWMF2G2D diff --git a/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory b/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory new file mode 100644 index 000000000..b607a5e64 --- /dev/null +++ b/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory @@ -0,0 +1,2 @@ +org.apache.fop.image.loader.batik.ImageLoaderFactorySVG +org.apache.fop.image.loader.batik.ImageLoaderFactoryWMF \ No newline at end of file diff --git a/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader b/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader new file mode 100644 index 000000000..c64d899b7 --- /dev/null +++ b/src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader @@ -0,0 +1,2 @@ +org.apache.fop.image.loader.batik.PreloaderWMF +org.apache.fop.image.loader.batik.PreloaderSVG diff --git a/src/java/org/apache/fop/apps/FOURIResolver.java b/src/java/org/apache/fop/apps/FOURIResolver.java index d68905e4c..f38be542a 100644 --- a/src/java/org/apache/fop/apps/FOURIResolver.java +++ b/src/java/org/apache/fop/apps/FOURIResolver.java @@ -32,13 +32,13 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; -// commons logging import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.util.DataURIResolver; import org.apache.xmlgraphics.util.io.Base64EncodeStream; +import org.apache.fop.util.DataURIResolver; + /** * Provides FOP specific URI resolution. This is the default URIResolver * {@link FOUserAgent} will use unless overidden. @@ -132,10 +132,23 @@ public class FOURIResolver implements javax.xml.transform.URIResolver { // Fallback to default resolution mechanism if (source == null) { URL absoluteURL = null; - File file = new File(href); + int hashPos = href.indexOf('#'); + String fileURL, fragment; + if (hashPos >= 0) { + fileURL = href.substring(0, hashPos); + fragment = href.substring(hashPos); + } else { + fileURL = href; + fragment = null; + } + File file = new File(fileURL); if (file.canRead() && file.isFile()) { try { - absoluteURL = file.toURL(); + if (fragment != null) { + absoluteURL = new URL(file.toURL().toExternalForm() + fragment); + } else { + absoluteURL = file.toURL(); + } } catch (MalformedURLException mfue) { handleException(mfue, "Could not convert filename '" + href + "' to URL", throwExceptions); diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index 07928fef2..966e227fe 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -23,15 +23,18 @@ package org.apache.fop.apps; import java.io.File; import java.util.Date; import java.util.Map; + import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; -// commons logging import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -// FOP +import org.apache.xmlgraphics.image.loader.ImageContext; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext; + import org.apache.fop.Version; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.pdf.PDFEncryptionParams; @@ -110,6 +113,22 @@ public class FOUserAgent { /** Set of keywords applicable to this document. */ protected String keywords = null; + private ImageSessionContext imageSessionContext = new AbstractImageSessionContext() { + + public ImageContext getParentContext() { + return getFactory(); + } + + public float getTargetResolution() { + return FOUserAgent.this.getTargetResolution(); + } + + public Source resolveURI(String uri) { + return FOUserAgent.this.resolveURI(uri); + } + + }; + /** * Default constructor * @see org.apache.fop.apps.FopFactory @@ -442,6 +461,14 @@ public class FOUserAgent { setTargetResolution((float)dpi); } + /** + * Returns the image session context for the image package. + * @return the ImageSessionContext instance for this rendering run + */ + public ImageSessionContext getImageSessionContext() { + return this.imageSessionContext; + } + // ---------------------------------------------- environment-level stuff // (convenience access to FopFactory methods) diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index c87a3041b..dc94d92fb 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.util.Collection; import java.util.Collections; @@ -36,10 +37,12 @@ import javax.xml.transform.URIResolver; import org.xml.sax.SAXException; import org.apache.avalon.framework.configuration.Configuration; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.image.loader.ImageContext; +import org.apache.xmlgraphics.image.loader.ImageManager; + import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.ElementMappingRegistry; import org.apache.fop.fonts.FontCache; @@ -57,7 +60,7 @@ import org.apache.fop.util.ContentHandlerFactoryRegistry; * Information that may potentially be different for each rendering run can be * found and managed in the FOUserAgent. */ -public class FopFactory { +public class FopFactory implements ImageContext { /** logger instance */ private static Log log = LogFactory.getLog(FopFactory.class); @@ -83,6 +86,9 @@ public class FopFactory { /** Image factory for creating fop image objects */ private ImageFactory imageFactory; + /** Image manager for loading and caching image objects */ + private ImageManager imageManager; + /** Configuration layer used to configure fop */ private FopFactoryConfigurator config = null; @@ -150,7 +156,8 @@ public class FopFactory { this.elementMappingRegistry = new ElementMappingRegistry(this); this.foURIResolver = new FOURIResolver(validateUserConfigStrictly()); this.colorSpaceCache = new ColorSpaceCache(foURIResolver); - this.imageFactory = new ImageFactory(); + this.imageFactory = new ImageFactory(); + this.imageManager = new ImageManager(this); this.rendererFactory = new RendererFactory(); this.xmlHandlers = new XMLHandlerRegistry(); this.ignoredNamespaces = new java.util.HashSet(); @@ -292,6 +299,14 @@ public class FopFactory { return this.imageFactory; } + /** + * Returns the image manager. + * @return the image manager + */ + public ImageManager getImageManager() { + return this.imageManager; + } + /** * Add the element mapping with the given class name. * @param elementMapping the class name representing the element mapping. @@ -748,5 +763,6 @@ public class FopFactory { */ public ColorSpace getColorSpace(String baseUri, String iccProfileSrc) { return colorSpaceCache.get(baseUri, iccProfileSrc); - } + } + } diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java index a107da833..7454f4667 100644 --- a/src/java/org/apache/fop/area/AreaTreeHandler.java +++ b/src/java/org/apache/fop/area/AreaTreeHandler.java @@ -189,12 +189,12 @@ public class AreaTreeHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - * @param pageSequence - * is the pageSequence being started - */ + /** {@inheritDoc} */ public void startPageSequence(PageSequence pageSequence) { + startAbstractPageSequence(pageSequence); + } + + private void startAbstractPageSequence(AbstractPageSequence pageSequence) { rootFObj = pageSequence.getRoot(); finishPrevPageSequence(pageSequence.getInitialPageNumber()); pageSequence.initPageNumber(); @@ -238,18 +238,12 @@ public class AreaTreeHandler extends FOEventHandler { } } - /** - * @see org.apache.fop.fo.FOEventHandler#startExternalDocument(org.apache.fop.fo.extensions.ExternalDocument) - */ + /** {@inheritDoc} */ public void startExternalDocument(ExternalDocument document) { - rootFObj = document.getRoot(); - finishPrevPageSequence(document.getInitialPageNumber()); - document.initPageNumber(); + startAbstractPageSequence(document); } - /** - * @see org.apache.fop.fo.FOEventHandler#endExternalDocument(org.apache.fop.fo.extensions.ExternalDocument) - */ + /** {@inheritDoc} */ public void endExternalDocument(ExternalDocument document) { if (statistics != null) { statistics.end(); diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index b4a804712..d4cdf5239 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -47,6 +47,10 @@ import org.xml.sax.helpers.DefaultHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Trait.Background; import org.apache.fop.area.Trait.InternalLink; @@ -69,8 +73,6 @@ import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; import org.apache.fop.traits.BorderProps; import org.apache.fop.util.ColorUtil; import org.apache.fop.util.ContentHandlerFactory; @@ -1048,22 +1050,19 @@ public class AreaTreeParser { } catch (PropertyException e) { throw new IllegalArgumentException(e.getMessage()); } - String url = attributes.getValue("bkg-img"); - if (url != null) { - bkg.setURL(url); - - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage img = fact.getImage(url, userAgent); - if (img == null) { - log.error("Background image not available: " + url); - } else { - // load dimensions - if (!img.load(FopImage.DIMENSIONS)) { - log.error("Cannot read background image dimensions: " - + url); - } + String uri = attributes.getValue("bkg-img"); + if (uri != null) { + bkg.setURL(uri); + + try { + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageSessionContext sessionContext + = userAgent.getImageSessionContext(); + ImageInfo info = manager.getImageInfo(uri, sessionContext); + bkg.setImageInfo(info); + } catch (Exception e) { + log.error("Background image not available: " + uri, e); } - bkg.setFopImage(img); String repeat = attributes.getValue("bkg-repeat"); if (repeat != null) { diff --git a/src/java/org/apache/fop/area/Trait.java b/src/java/org/apache/fop/area/Trait.java index b3c3d3947..98bed098c 100644 --- a/src/java/org/apache/fop/area/Trait.java +++ b/src/java/org/apache/fop/area/Trait.java @@ -22,9 +22,10 @@ package org.apache.fop.area; import java.awt.Color; import java.io.Serializable; +import org.apache.xmlgraphics.image.loader.ImageInfo; + import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontTriplet; -import org.apache.fop.image.FopImage; import org.apache.fop.traits.BorderProps; import org.apache.fop.util.ColorUtil; @@ -559,7 +560,7 @@ public class Trait implements Serializable { private String url = null; /** The background image if any. */ - private FopImage fopimage = null; + private ImageInfo imageInfo = null; /** Background repeat enum for images. */ private int repeat; @@ -603,11 +604,11 @@ public class Trait implements Serializable { } /** - * Returns the FopImage representing the background image + * Returns the ImageInfo object representing the background image * @return the background image, null if n/a */ - public FopImage getFopImage() { - return fopimage; + public ImageInfo getImageInfo() { + return imageInfo; } /** @@ -659,11 +660,11 @@ public class Trait implements Serializable { } /** - * Sets the FopImage to use as the background image. - * @param fopimage The FopImage to use + * Sets the ImageInfo of the image to use as the background image. + * @param info The background image's info object */ - public void setFopImage(FopImage fopimage) { - this.fopimage = fopimage; + public void setImageInfo(ImageInfo info) { + this.imageInfo = info; } /** diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index 63a817071..3bb0aae7f 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -29,6 +29,11 @@ import java.util.Vector; import javax.swing.UIManager; +import org.xml.sax.SAXException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.fop.Version; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; @@ -38,19 +43,12 @@ import org.apache.fop.pdf.PDFAMode; import org.apache.fop.pdf.PDFEncryptionManager; import org.apache.fop.pdf.PDFEncryptionParams; import org.apache.fop.pdf.PDFXMode; -import org.apache.fop.render.awt.AWTRenderer; import org.apache.fop.render.Renderer; +import org.apache.fop.render.awt.AWTRenderer; import org.apache.fop.render.pdf.PDFRenderer; import org.apache.fop.render.xml.XMLRenderer; import org.apache.fop.util.CommandLineLogger; -// commons logging -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -// SAX -import org.xml.sax.SAXException; - /** * Options parses the commandline arguments */ @@ -71,6 +69,8 @@ public class CommandLineOptions { public static final int XSLT_INPUT = 2; /** input: Area Tree XML file */ public static final int AREATREE_INPUT = 3; + /** input: Image file */ + public static final int IMAGE_INPUT = 4; /* show configuration information */ private Boolean showConfiguration = Boolean.FALSE; @@ -86,6 +86,8 @@ public class CommandLineOptions { private File xmlfile = null; /* area tree input file */ private File areatreefile = null; + /* area tree input file */ + private File imagefile = null; /* output file */ private File outfile = null; /* input mode */ @@ -249,6 +251,8 @@ public class CommandLineOptions { i = i + parseXMLInputOption(args, i); } else if (args[i].equals("-atin")) { i = i + parseAreaTreeInputOption(args, i); + } else if (args[i].equals("-imagein")) { + i = i + parseImageInputOption(args, i); } else if (args[i].equals("-awt")) { i = i + parseAWTOutputOption(args, i); } else if (args[i].equals("-pdf")) { @@ -594,6 +598,17 @@ public class CommandLineOptions { } } + private int parseImageInputOption(String[] args, int i) throws FOPException { + inputmode = IMAGE_INPUT; + if ((i + 1 == args.length) + || (args[i + 1].charAt(0) == '-')) { + throw new FOPException("you must specify the image file for the '-imagein' option"); + } else { + imagefile = new File(args[i + 1]); + return 1; + } + } + private PDFEncryptionParams getPDFEncryptionParams() throws FOPException { PDFEncryptionParams params = (PDFEncryptionParams)renderingOptions.get( PDFRenderer.ENCRYPTION_PARAMS); @@ -768,6 +783,20 @@ public class CommandLineOptions { + areatreefile.getAbsolutePath() + " not found "); } + } else if (inputmode == IMAGE_INPUT) { + if (outputmode.equals(MimeConstants.MIME_XSL_FO)) { + throw new FOPException( + "FO output mode is only available if you use -xml and -xsl"); + } + if (xmlfile != null) { + log.warn("image input mode, but XML file is set:"); + log.error("XML file: " + xmlfile.toString()); + } + if (!imagefile.exists()) { + throw new FileNotFoundException("Error: image file " + + imagefile.getAbsolutePath() + + " not found "); + } } } // end checkSettings @@ -814,6 +843,8 @@ public class CommandLineOptions { return new AreaTreeInputHandler(areatreefile); case XSLT_INPUT: return new InputHandler(xmlfile, xsltfile, xsltParams); + case IMAGE_INPUT: + return new ImageInputHandler(imagefile, xsltfile, xsltParams); default: throw new IllegalArgumentException("Error creating InputHandler object."); } @@ -920,6 +951,7 @@ public class CommandLineOptions { + " -fo infile xsl:fo input file \n" + " -xml infile xml input file, must be used together with -xsl \n" + " -atin infile area tree input file \n" + + " -imagein infile image input file \n" + " -xsl stylesheet xslt stylesheet \n \n" + " -param name value to use for parameter in xslt stylesheet\n" + " (repeat '-param name value' for each parameter)\n \n" diff --git a/src/java/org/apache/fop/cli/ImageInputHandler.java b/src/java/org/apache/fop/cli/ImageInputHandler.java new file mode 100644 index 000000000..fe3d5021f --- /dev/null +++ b/src/java/org/apache/fop/cli/ImageInputHandler.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.cli; + +import java.io.File; +import java.io.StringReader; +import java.util.Vector; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +/** + * InputHandler for the images (for example TIFF) as input. + */ +public class ImageInputHandler extends InputHandler { + + /** + * Main constructor. + * @param imagefile the image file + * @param xsltfile XSLT file (may be null in which case the default stylesheet is used) + * @param params Vector of command-line parameters (name, value, + * name, value, ...) for XSL stylesheet, null if none + */ + public ImageInputHandler(File imagefile, File xsltfile, Vector params) { + super(imagefile, xsltfile, params); + } + + /** {@inheritDoc} */ + protected Source createMainSource() { + return new StreamSource(new StringReader( + "" + this.sourcefile.toURI().toASCIIString() + "")); + } + + /** {@inheritDoc} */ + protected Source createXSLTSource() { + Source src = super.createXSLTSource(); + if (src == null) { + src = new StreamSource(getClass().getResource("image2fo.xsl").toExternalForm()); + } + return src; + } + +} diff --git a/src/java/org/apache/fop/cli/InputHandler.java b/src/java/org/apache/fop/cli/InputHandler.java index bfbce269d..89977beb7 100644 --- a/src/java/org/apache/fop/cli/InputHandler.java +++ b/src/java/org/apache/fop/cli/InputHandler.java @@ -24,7 +24,6 @@ import java.io.File; import java.io.OutputStream; import java.util.Vector; -// Imported TraX classes import javax.xml.transform.ErrorListener; import javax.xml.transform.Result; import javax.xml.transform.Source; @@ -37,6 +36,7 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; @@ -50,7 +50,8 @@ import org.apache.fop.render.awt.viewer.Renderable; */ public class InputHandler implements ErrorListener, Renderable { - private File sourcefile = null; // either FO or XML/XSLT usage + /** original source file */ + protected File sourcefile = null; private File stylesheet = null; // for XML/XSLT usage private Vector xsltParams = null; // for XML/XSLT usage @@ -131,6 +132,26 @@ public class InputHandler implements ErrorListener, Renderable { transformTo(res); } + /** + * Creates a Source for the main input file. + * @return the Source for the main input file + */ + protected Source createMainSource() { + return new StreamSource(this.sourcefile); + } + + /** + * Creates a Source for the selected stylesheet. + * @return the Source for the selected stylesheet or null if there's no stylesheet + */ + protected Source createXSLTSource() { + if (this.stylesheet != null) { + return new StreamSource(this.stylesheet); + } else { + return null; + } + } + /** * Transforms the input document to the input format expected by FOP using XSLT. * @param result the Result object where the result of the XSL transformation is sent to @@ -142,11 +163,11 @@ public class InputHandler implements ErrorListener, Renderable { TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer; - if (stylesheet == null) { // FO Input + Source xsltSource = createXSLTSource(); + if (xsltSource == null) { // FO Input transformer = factory.newTransformer(); } else { // XML/XSLT input - transformer = factory.newTransformer(new StreamSource( - stylesheet)); + transformer = factory.newTransformer(xsltSource); // Set the value of parameters, if any, defined for stylesheet if (xsltParams != null) { @@ -159,7 +180,7 @@ public class InputHandler implements ErrorListener, Renderable { transformer.setErrorListener(this); // Create a SAXSource from the input Source file - Source src = new StreamSource(sourcefile); + Source src = createMainSource(); // Start XSLT transformation and FOP processing transformer.transform(src, result); diff --git a/src/java/org/apache/fop/cli/image2fo.xsl b/src/java/org/apache/fop/cli/image2fo.xsl new file mode 100644 index 000000000..3a2610230 --- /dev/null +++ b/src/java/org/apache/fop/cli/image2fo.xsl @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index 980404ffd..63fc5cb5b 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -276,9 +276,7 @@ public class FOTreeBuilder extends DefaultHandler { */ private int nestedMarkerDepth = 0; - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startElement(String namespaceURI, String localName, String rawName, Attributes attlist) throws SAXException { @@ -359,19 +357,16 @@ public class FOTreeBuilder extends DefaultHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endElement(String uri, String localName, String rawName) throws SAXException { if (currentFObj == null) { - throw new IllegalStateException( + throw new SAXException( "endElement() called for " + rawName + " where there is no current element."); - } else - if (!currentFObj.getLocalName().equals(localName) + } else if (!currentFObj.getLocalName().equals(localName) || !currentFObj.getNamespaceURI().equals(uri)) { - log.warn("Mismatch: " + currentFObj.getLocalName() + throw new SAXException("Mismatch: " + currentFObj.getLocalName() + " (" + currentFObj.getNamespaceURI() + ") vs. " + localName + " (" + uri + ")"); } diff --git a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java index f0285e6f4..dd45f585c 100644 --- a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java +++ b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java @@ -19,15 +19,22 @@ package org.apache.fop.fo.flow; +import java.io.IOException; + +import org.xml.sax.Locator; + +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.xml.sax.Locator; +import org.apache.fop.fo.properties.FixedLength; /** * Class modelling the fo:external-graphic object. @@ -63,21 +70,25 @@ public class ExternalGraphic extends AbstractGraphics { super.bind(pList); src = pList.get(PR_SRC).getString(); - //Additional processing: preload image - url = ImageFactory.getURL(getSrc()); + //Additional processing: obtain the image's intrinsic size and baseline information + url = URISpecification.getURL(src); FOUserAgent userAgent = getUserAgent(); - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage fopimage = fact.getImage(url, userAgent); - if (fopimage == null) { - log.error("Image not available: " + getSrc()); - } else { - // load dimensions - if (!fopimage.load(FopImage.DIMENSIONS)) { - log.error("Cannot read image dimensions: " + getSrc()); + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageInfo info = null; + try { + info = manager.getImageInfo(url, userAgent.getImageSessionContext()); + } catch (ImageException e) { + log.error("Image not available: " + e.getMessage()); + } catch (IOException ioe) { + log.error("I/O error while loading image: " + ioe.getMessage()); + } + if (info != null) { + this.intrinsicWidth = info.getSize().getWidthMpt(); + this.intrinsicHeight = info.getSize().getHeightMpt(); + int baseline = info.getSize().getBaselinePositionFromBottom(); + if (baseline != 0) { + this.intrinsicAlignmentAdjust = new FixedLength(-baseline); } - this.intrinsicWidth = fopimage.getIntrinsicWidth(); - this.intrinsicHeight = fopimage.getIntrinsicHeight(); - this.intrinsicAlignmentAdjust = fopimage.getIntrinsicAlignmentAdjust(); } //TODO Report to caller so he can decide to throw an exception } diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java index 139f7606a..6e079cf47 100644 --- a/src/java/org/apache/fop/fo/pagination/Root.java +++ b/src/java/org/apache/fop/fo/pagination/Root.java @@ -31,8 +31,8 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.pagination.bookmarks.BookmarkTree; import org.apache.fop.fo.extensions.destination.Destination; +import org.apache.fop.fo.pagination.bookmarks.BookmarkTree; /** * The fo:root formatting object. Contains page masters, page-sequences. @@ -73,20 +73,16 @@ public class Root extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { mediaUsage = pList.get(PR_MEDIA_USAGE).getEnum(); } - /** - * Signal end of this xml element. - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (!pageSequenceFound || layoutMasterSet == null) { - missingChildElementError("(layout-master-set, declarations?, " + - "bookmark-tree?, (page-sequence+|fox:external-document))"); + missingChildElementError("(layout-master-set, declarations?, " + + "bookmark-tree?, (page-sequence|fox:external-document)+)"); } } diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index 866a020e2..68d4bcab1 100755 --- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java +++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java @@ -21,13 +21,16 @@ package org.apache.fop.fo.properties; import java.awt.Color; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; -import org.apache.fop.image.FopImage; import org.apache.fop.image.ImageFactory; /** @@ -66,7 +69,7 @@ public class CommonBorderPaddingBackground { public Length backgroundPositionVertical; - private FopImage fopimage; + private ImageInfo backgroundImageInfo; /** the "before" edge */ @@ -232,18 +235,16 @@ public class CommonBorderPaddingBackground { Constants.PR_BACKGROUND_POSITION_VERTICAL).getLength(); //Additional processing: preload image - String url = ImageFactory.getURL(backgroundImage); + String uri = ImageFactory.getURL(backgroundImage); FOUserAgent userAgent = pList.getFObj().getUserAgent(); - ImageFactory fact = userAgent.getFactory().getImageFactory(); - fopimage = fact.getImage(url, userAgent); - if (fopimage == null) { - Property.log.error("Background image not available: " + backgroundImage); - } else { - // load dimensions - if (!fopimage.load(FopImage.DIMENSIONS)) { - Property.log.error("Cannot read background image dimensions: " - + backgroundImage); - } + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageSessionContext sessionContext = userAgent.getImageSessionContext(); + ImageInfo info; + try { + info = manager.getImageInfo(uri, sessionContext); + this.backgroundImageInfo = info; + } catch (Exception e) { + Property.log.error("Background image not available: " + uri); } //TODO Report to caller so he can decide to throw an exception } @@ -315,11 +316,11 @@ public class CommonBorderPaddingBackground { } /** - * @return the background image as a preloaded FopImage, null if there is + * @return the background image info object, null if there is * no background image. */ - public FopImage getFopImage() { - return this.fopimage; + public ImageInfo getImageInfo() { + return this.backgroundImageInfo; } /** @@ -455,7 +456,7 @@ public class CommonBorderPaddingBackground { * @return true if there is any kind of background to be painted */ public boolean hasBackground() { - return ((backgroundColor != null || getFopImage() != null)); + return ((backgroundColor != null || getImageInfo() != null)); } /** @return true if border is non-zero. */ diff --git a/src/java/org/apache/fop/image/loader/batik/BatikUtil.java b/src/java/org/apache/fop/image/loader/batik/BatikUtil.java new file mode 100644 index 000000000..1ae2a9917 --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/BatikUtil.java @@ -0,0 +1,41 @@ +/* + * 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.image.loader.batik; + +/** + * Helper utilities for Apache Batik. + */ +public class BatikUtil { + + /** + * Checks whether Apache Batik is available in the classpath. + * @return true if Apache Batik is available + */ + public static boolean isBatikAvailable() { + try { + Class.forName("org.apache.batik.dom.svg.SVGDOMImplementation"); + return true; + } catch (Exception e) { + //ignore + } + return false; + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java new file mode 100644 index 000000000..81b3b4c07 --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -0,0 +1,120 @@ +/* + * 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.image.loader.batik; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.util.Map; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.GVTBuilder; +import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.gvt.GraphicsNode; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageProcessingHints; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageConverter; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.xmlgraphics.util.UnitConv; + +import org.apache.fop.svg.SVGUserAgent; + +/** + * This ImageConverter converts SVG images to Java2D. + *

+ * Note: The target flavor is "generic" Java2D. No Batik-specific bridges are hooked into the + * conversion process. Specialized renderers may want to provide specialized adapters to profit + * from target-format features (for example with PDF or PS). This converter is mainly for formats + * which only support bitmap images or rudimentary Java2D support. + */ +public class ImageConverterSVG2G2D extends AbstractImageConverter { + + /** {@inheritDoc} */ + public Image convert(Image src, Map hints) throws ImageException { + checkSourceFlavor(src); + final ImageXMLDOM svg = (ImageXMLDOM)src; + if (!SVGDOMImplementation.SVG_NAMESPACE_URI.equals(svg.getRootNamespace())) { + throw new IllegalArgumentException("XML DOM is not in the SVG namespace: " + + svg.getRootNamespace()); + } + + //Prepare + float pxToMillimeter = (float)UnitConv.mm2in(72); //default: 72dpi + Number ptm = (Number)hints.get(ImageProcessingHints.SOURCE_RESOLUTION); + if (ptm != null) { + pxToMillimeter = (float)UnitConv.mm2in(ptm.doubleValue()); + } + SVGUserAgent ua = new SVGUserAgent( + pxToMillimeter, + new AffineTransform()); + GVTBuilder builder = new GVTBuilder(); + final BridgeContext ctx = new BridgeContext(ua); + + //Build the GVT tree + final GraphicsNode root; + try { + root = builder.build(ctx, svg.getDocument()); + } catch (Exception e) { + throw new ImageException("GVT tree could not be built for SVG graphic", e); + } + + //Create the painter + Graphics2DImagePainter painter = new Graphics2DImagePainter() { + + public void paint(Graphics2D g2d, Rectangle2D area) { + // If no viewbox is defined in the svg file, a viewbox of 100x100 is + // assumed, as defined in SVGUserAgent.getViewportSize() + float iw = (float) ctx.getDocumentSize().getWidth(); + float ih = (float) ctx.getDocumentSize().getHeight(); + float w = (float) area.getWidth(); + float h = (float) area.getHeight(); + g2d.translate(area.getX(), area.getY()); + g2d.scale(w / iw, h / ih); + + root.paint(g2d); + } + + public Dimension getImageSize() { + return new Dimension(svg.getSize().getWidthMpt(), svg.getSize().getHeightMpt()); + } + + }; + + ImageGraphics2D g2dImage = new ImageGraphics2D(src.getInfo(), painter); + return g2dImage; + } + + /** {@inheritDoc} */ + public ImageFlavor getSourceFlavor() { + return ImageFlavor.XML_DOM; + } + + /** {@inheritDoc} */ + public ImageFlavor getTargetFlavor() { + return ImageFlavor.GRAPHICS2D; + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java new file mode 100644 index 000000000..6babe4523 --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java @@ -0,0 +1,107 @@ +/* + * 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.image.loader.batik; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.util.Map; + +import org.apache.batik.transcoder.wmf.tosvg.WMFPainter; +import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageConverter; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + +/** + * This ImageConverter converts WMF (Windows Metafile) images (represented by Batik's + * WMFRecordStore) to Java2D. + */ +public class ImageConverterWMF2G2D extends AbstractImageConverter { + + /** logger */ + private static Log log = LogFactory.getLog(ImageConverterWMF2G2D.class); + + /** {@inheritDoc} */ + public Image convert(Image src, Map hints) { + checkSourceFlavor(src); + ImageWMF wmf = (ImageWMF)src; + + Graphics2DImagePainter painter; + painter = new Graphics2DImagePainterWMF(wmf); + + ImageGraphics2D g2dImage = new ImageGraphics2D(src.getInfo(), painter); + return g2dImage; + } + + /** {@inheritDoc} */ + public ImageFlavor getSourceFlavor() { + return ImageWMF.WMF_IMAGE; + } + + /** {@inheritDoc} */ + public ImageFlavor getTargetFlavor() { + return ImageFlavor.GRAPHICS2D; + } + + private static class Graphics2DImagePainterWMF implements Graphics2DImagePainter { + + private ImageWMF wmf; + + public Graphics2DImagePainterWMF(ImageWMF wmf) { + this.wmf = wmf; + } + + /** {@inheritDoc} */ + public Dimension getImageSize() { + return wmf.getSize().getDimensionMpt(); + } + + /** {@inheritDoc} */ + public void paint(Graphics2D g2d, Rectangle2D area) { + WMFRecordStore wmfStore = wmf.getRecordStore(); + double w = area.getWidth(); + double h = area.getHeight(); + + //Fit in paint area + g2d.translate(area.getX(), area.getY()); + double sx = w / wmfStore.getWidthPixels(); + double sy = h / wmfStore.getHeightPixels(); + if (sx != 1.0 || sy != 1.0) { + g2d.scale(sx, sy); + } + + WMFPainter painter = new WMFPainter(wmfStore, 1.0f); + long start = System.currentTimeMillis(); + painter.paint(g2d); + if (log.isDebugEnabled()) { + long duration = System.currentTimeMillis() - start; + log.debug("Painting WMF took " + duration + " ms."); + } + } + + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/ImageLoaderFactorySVG.java b/src/java/org/apache/fop/image/loader/batik/ImageLoaderFactorySVG.java new file mode 100644 index 000000000..fa58d8e4a --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/ImageLoaderFactorySVG.java @@ -0,0 +1,63 @@ +/* + * 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.image.loader.batik; + +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoaderFactory; +import org.apache.xmlgraphics.image.loader.spi.ImageLoader; +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * Factory class for the ImageLoader for SVG. + */ +public class ImageLoaderFactorySVG extends AbstractImageLoaderFactory { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.XML_DOM}; + + private static final String[] MIMES = new String[] { + MimeConstants.MIME_SVG}; + + /** {@inheritDoc} */ + public String[] getSupportedMIMETypes() { + return MIMES; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedFlavors(String mime) { + return FLAVORS; + } + + /** {@inheritDoc} */ + public ImageLoader newImageLoader(ImageFlavor targetFlavor) { + return new ImageLoaderSVG(targetFlavor); + } + + /** {@inheritDoc} */ + public int getUsagePenalty(String mime, ImageFlavor flavor) { + return 0; + } + + /** {@inheritDoc} */ + public boolean isAvailable() { + return BatikUtil.isBatikAvailable(); + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/ImageLoaderFactoryWMF.java b/src/java/org/apache/fop/image/loader/batik/ImageLoaderFactoryWMF.java new file mode 100644 index 000000000..bfa004d7e --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/ImageLoaderFactoryWMF.java @@ -0,0 +1,62 @@ +/* + * 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.image.loader.batik; + +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoaderFactory; +import org.apache.xmlgraphics.image.loader.spi.ImageLoader; + +/** + * Factory class for the ImageLoader for WMF (Windows Metafile). + */ +public class ImageLoaderFactoryWMF extends AbstractImageLoaderFactory { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageWMF.WMF_IMAGE}; + + private static final String[] MIMES = new String[] { + ImageWMF.MIME_WMF}; + + /** {@inheritDoc} */ + public String[] getSupportedMIMETypes() { + return MIMES; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedFlavors(String mime) { + return FLAVORS; + } + + /** {@inheritDoc} */ + public ImageLoader newImageLoader(ImageFlavor targetFlavor) { + return new ImageLoaderWMF(targetFlavor); + } + + /** {@inheritDoc} */ + public int getUsagePenalty(String mime, ImageFlavor flavor) { + return 0; + } + + /** {@inheritDoc} */ + public boolean isAvailable() { + return BatikUtil.isBatikAvailable(); + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/ImageLoaderSVG.java b/src/java/org/apache/fop/image/loader/batik/ImageLoaderSVG.java new file mode 100644 index 000000000..64aff962b --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/ImageLoaderSVG.java @@ -0,0 +1,78 @@ +/* + * 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.image.loader.batik; + +import java.io.IOException; +import java.util.Map; + +import org.apache.batik.dom.svg.SVGDOMImplementation; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoader; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * ImageLoader for SVG (using Apache Batik). + */ +public class ImageLoaderSVG extends AbstractImageLoader { + + private ImageFlavor targetFlavor; + + /** + * Main constructor. + * @param targetFlavor the target flavor + */ + public ImageLoaderSVG(ImageFlavor targetFlavor) { + if (!(ImageFlavor.XML_DOM.equals(targetFlavor))) { + throw new IllegalArgumentException("Unsupported target ImageFlavor: " + targetFlavor); + } + this.targetFlavor = targetFlavor; + } + + /** {@inheritDoc} */ + public ImageFlavor getTargetFlavor() { + return this.targetFlavor; + } + + /** {@inheritDoc} */ + public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) + throws ImageException, IOException { + if (!MimeConstants.MIME_SVG.equals(info.getMimeType())) { + throw new IllegalArgumentException("ImageInfo must be from an SVG image"); + } + Image img = info.getOriginalImage(); + if (!(img instanceof ImageXMLDOM)) { + throw new IllegalArgumentException( + "ImageInfo was expected to contain the SVG document as DOM"); + } + ImageXMLDOM svgImage = (ImageXMLDOM)img; + if (!SVGDOMImplementation.SVG_NAMESPACE_URI.equals(svgImage.getRootNamespace())) { + throw new IllegalArgumentException( + "The Image is not in the SVG namespace: " + svgImage.getRootNamespace()); + } + return svgImage; + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/ImageLoaderWMF.java b/src/java/org/apache/fop/image/loader/batik/ImageLoaderWMF.java new file mode 100644 index 000000000..e7f3e0f0a --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/ImageLoaderWMF.java @@ -0,0 +1,70 @@ +/* + * 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.image.loader.batik; + +import java.io.IOException; +import java.util.Map; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoader; + +/** + * ImageLoader for WMF (Windows Metafile). Depends on the WMF preloader based on Apache Batik. + */ +public class ImageLoaderWMF extends AbstractImageLoader { + + private ImageFlavor targetFlavor; + + /** + * Main constructor. + * @param targetFlavor the target flavor + */ + public ImageLoaderWMF(ImageFlavor targetFlavor) { + if (!(ImageWMF.WMF_IMAGE.equals(targetFlavor))) { + throw new IllegalArgumentException("Unsupported target ImageFlavor: " + targetFlavor); + } + this.targetFlavor = targetFlavor; + } + + /** {@inheritDoc} */ + public ImageFlavor getTargetFlavor() { + return this.targetFlavor; + } + + /** {@inheritDoc} */ + public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) + throws ImageException, IOException { + if (!ImageWMF.MIME_WMF.equals(info.getMimeType())) { + throw new IllegalArgumentException("ImageInfo must be from a WMF image"); + } + Image img = info.getOriginalImage(); + if (!(img instanceof ImageWMF)) { + throw new IllegalArgumentException( + "ImageInfo was expected to contain the Windows Metafile (WMF)"); + } + ImageWMF wmfImage = (ImageWMF)img; + return wmfImage; + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/ImageWMF.java b/src/java/org/apache/fop/image/loader/batik/ImageWMF.java new file mode 100644 index 000000000..f785d27cc --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/ImageWMF.java @@ -0,0 +1,69 @@ +/* + * 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.image.loader.batik; + +import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore; + +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.impl.AbstractImage; + +/** + * This class is an implementation of the Image interface exposing a RenderedImage. + */ +public class ImageWMF extends AbstractImage { + + /** MIME type for WMF */ + public static final String MIME_WMF = "image/x-wmf"; + + /** ImageFlavor for Batik's WMFRecordStore */ + public static final ImageFlavor WMF_IMAGE = new ImageFlavor("WMFRecordStore"); + + private WMFRecordStore store; + + /** + * Main constructor. + * @param info the image info object + * @param store the WMF record store containing the loaded WMF file + */ + public ImageWMF(ImageInfo info, WMFRecordStore store) { + super(info); + this.store = store; + } + + /** {@inheritDoc} */ + public ImageFlavor getFlavor() { + return WMF_IMAGE; + } + + /** {@inheritDoc} */ + public boolean isCacheable() { + return true; + } + + /** + * Returns the contained WMF record store. + * @return the WMFRecordStore + */ + public WMFRecordStore getRecordStore() { + return this.store; + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java new file mode 100644 index 000000000..e83a302da --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -0,0 +1,182 @@ +/* + * 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.image.loader.batik; + +import java.awt.geom.AffineTransform; +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Source; + +import org.w3c.dom.Element; +import org.w3c.dom.svg.SVGDocument; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.UnitProcessor; +import org.apache.batik.dom.svg.SAXSVGDocumentFactory; +import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.dom.svg.SVGOMDocument; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.ImageContext; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; +import org.apache.xmlgraphics.util.MimeConstants; + +import org.apache.fop.svg.SVGUserAgent; +import org.apache.fop.util.UnclosableInputStream; + +/** + * Image preloader for SVG images. + */ +public class PreloaderSVG extends AbstractImagePreloader { + + /** Logger instance */ + private static Log log = LogFactory.getLog(PreloaderSVG.class); + + private boolean batikAvailable = true; + + /** {@inheritDoc} */ + public ImageInfo preloadImage(String uri, Source src, ImageContext context) + throws IOException { + if (!ImageUtil.hasInputStream(src)) { + //TODO Remove this and support DOMSource and possibly SAXSource + return null; + } + ImageInfo info = null; + if (batikAvailable) { + try { + Loader loader = new Loader(); + info = loader.getImage(uri, src, context); + } catch (NoClassDefFoundError e) { + batikAvailable = false; + log.warn("Batik not in class path", e); + return null; + } + } + if (info != null) { + ImageUtil.closeQuietly(src); //Image is fully read + } + return info; + } + + /** + * Returns the fully qualified classname of an XML parser for + * Batik classes that apparently need it (error messages, perhaps) + * @return an XML parser classname + */ + public static String getParserName() { + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + return factory.newSAXParser().getXMLReader().getClass().getName(); + } catch (Exception e) { + return null; + } + } + + /** + * This method is put in another class so that the class loader does not + * attempt to load Batik related classes when constructing the SVGPreloader + * class. + */ + class Loader { + private ImageInfo getImage(String uri, Source src, + ImageContext context) { + // parse document and get the size attributes of the svg element + + InputStream in = new UnclosableInputStream(ImageUtil.needInputStream(src)); + try { + int length = in.available(); + in.mark(length + 1); + SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( + getParserName()); + SVGDocument doc = (SVGDocument) factory.createSVGDocument(src.getSystemId(), in); + + Element e = doc.getRootElement(); + float pxUnitToMillimeter = 25.4f / context.getSourceResolution(); + SVGUserAgent userAg = new SVGUserAgent(pxUnitToMillimeter, + new AffineTransform()); + BridgeContext ctx = new BridgeContext(userAg); + UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); + + String s; + // 'width' attribute - default is 100% + s = e.getAttributeNS(null, SVGOMDocument.SVG_WIDTH_ATTRIBUTE); + if (s.length() == 0) { + s = SVGOMDocument.SVG_SVG_WIDTH_DEFAULT_VALUE; + } + float width = UnitProcessor.svgHorizontalLengthToUserSpace( + s, SVGOMDocument.SVG_WIDTH_ATTRIBUTE, uctx); + + // 'height' attribute - default is 100% + s = e.getAttributeNS(null, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE); + if (s.length() == 0) { + s = SVGOMDocument.SVG_SVG_HEIGHT_DEFAULT_VALUE; + } + float height = UnitProcessor.svgVerticalLengthToUserSpace( + s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx); + + ImageInfo info = new ImageInfo(uri, MimeConstants.MIME_SVG); + ImageSize size = new ImageSize(); + size.setSizeInMillipoints(Math.round(width * 1000), Math.round(height * 1000)); + //Set the resolution to that of the FOUserAgent + size.setResolution(context.getSourceResolution()); + size.calcPixelsFromSize(); + info.setSize(size); + + //The whole image had to be loaded for this, so keep it + ImageXMLDOM xmlImage = new ImageXMLDOM(info, + doc, SVGDOMImplementation.SVG_NAMESPACE_URI); + info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, xmlImage); + + return info; + } catch (NoClassDefFoundError ncdfe) { + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } + batikAvailable = false; + log.warn("Batik not in class path", ncdfe); + return null; + } catch (IOException e) { + // If the svg is invalid then it throws an IOException + // so there is no way of knowing if it is an svg document + + log.debug("Error while trying to load stream as an SVG file: " + + e.getMessage()); + // assuming any exception means this document is not svg + // or could not be loaded for some reason + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } + return null; + } + } + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java b/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java new file mode 100644 index 000000000..abb740411 --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java @@ -0,0 +1,142 @@ +/* + * 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.image.loader.batik; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.transform.Source; + +import org.apache.batik.transcoder.wmf.WMFConstants; +import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore; +import org.apache.commons.io.EndianUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.ImageContext; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; + +import org.apache.fop.util.UnclosableInputStream; + +/** + * Image preloader for WMF images (Windows Metafile). + */ +public class PreloaderWMF extends AbstractImagePreloader { + + /** Logger instance */ + private static Log log = LogFactory.getLog(PreloaderWMF.class); + + private boolean batikAvailable = true; + + /** {@inheritDoc} */ + public ImageInfo preloadImage(String uri, Source src, ImageContext context) + throws IOException { + if (!ImageUtil.hasInputStream(src)) { + return null; + } + ImageInfo info = null; + if (batikAvailable) { + try { + Loader loader = new Loader(); + info = loader.getImage(uri, src, context); + } catch (NoClassDefFoundError e) { + batikAvailable = false; + log.warn("Batik not in class path", e); + return null; + } + } + if (info != null) { + ImageUtil.closeQuietly(src); //Image is fully read + } + return info; + } + + /** + * This method is put in another class so that the class loader does not + * attempt to load Batik related classes when constructing the WMFPreloader + * class. + */ + class Loader { + private ImageInfo getImage(String uri, Source src, + ImageContext context) { + // parse document and get the size attributes of the svg element + + InputStream in = new UnclosableInputStream(ImageUtil.needInputStream(src)); + try { + in.mark(4 + 1); + + DataInputStream din = new DataInputStream(in); + int magic = EndianUtils.swapInteger(din.readInt()); + din.reset(); + if (magic != WMFConstants.META_ALDUS_APM) { + return null; //Not a WMF file + } + + WMFRecordStore wmfStore = new WMFRecordStore(); + wmfStore.read(din); + IOUtils.closeQuietly(din); + + int width = wmfStore.getWidthUnits(); + int height = wmfStore.getHeightUnits(); + int dpi = wmfStore.getMetaFileUnitsPerInch(); + + ImageInfo info = new ImageInfo(uri, "image/x-wmf"); + ImageSize size = new ImageSize(); + size.setSizeInPixels(width, height); + size.setResolution(dpi); + size.calcSizeFromPixels(); + info.setSize(size); + ImageWMF img = new ImageWMF(info, wmfStore); + info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, img); + + return info; + } catch (NoClassDefFoundError ncdfe) { + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } + batikAvailable = false; + log.warn("Batik not in class path", ncdfe); + return null; + } catch (IOException e) { + // If the svg is invalid then it throws an IOException + // so there is no way of knowing if it is an svg document + + log.debug("Error while trying to load stream as an WMF file: " + + e.getMessage()); + // assuming any exception means this document is not svg + // or could not be loaded for some reason + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } + return null; + } + } + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/package.html b/src/java/org/apache/fop/image/loader/batik/package.html new file mode 100644 index 000000000..f664913d7 --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/package.html @@ -0,0 +1,26 @@ + + + +org.apache.fop.image2.impl.batik Package + +

+ Contains implementations of image loaders and converters which are dependent + on Apache Batik (SVG and WMF). +

+ + \ No newline at end of file diff --git a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java index 5668f81ef..0e51517f2 100644 --- a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java @@ -21,10 +21,18 @@ package org.apache.fop.layoutmgr; import java.awt.Dimension; import java.awt.Rectangle; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.area.Block; @@ -38,8 +46,6 @@ import org.apache.fop.area.inline.Viewport; import org.apache.fop.datatypes.FODimension; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExternalDocument; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; import org.apache.fop.layoutmgr.inline.ImageLayout; /** @@ -51,14 +57,13 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan private static Log log = LogFactory.getLog(ExternalDocumentLayoutManager.class); - private FopImage image; private ImageLayout imageLayout; /** * Constructor * * @param ath the area tree handler object - * @param pseq fo:page-sequence to process + * @param document fox:external-document to process */ public ExternalDocumentLayoutManager(AreaTreeHandler ath, ExternalDocument document) { super(ath, document); @@ -80,38 +85,78 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan public void activateLayout() { initialize(); - String uri = getExternalDocument().getSrc(); FOUserAgent userAgent = pageSeq.getUserAgent(); - ImageFactory fact = userAgent.getFactory().getImageFactory(); - this.image = fact.getImage(uri, userAgent); - if (this.image == null) { - log.error("Image not available: " + uri); - return; - } else { - // load dimensions - if (!this.image.load(FopImage.DIMENSIONS)) { - log.error("Cannot read image dimensions: " + uri); - return; - } - } - Dimension intrinsicSize = new Dimension( - image.getIntrinsicWidth(), - image.getIntrinsicHeight()); - this.imageLayout = new ImageLayout(getExternalDocument(), this, intrinsicSize); + ImageManager imageManager = userAgent.getFactory().getImageManager(); - areaTreeHandler.getAreaTreeModel().startPageSequence(null); - if (log.isDebugEnabled()) { - log.debug("Starting layout"); + String uri = getExternalDocument().getSrc(); + Integer firstPageIndex = ImageUtil.getPageIndexFromURI(uri); + boolean hasPageIndex = (firstPageIndex != null); + + try { + ImageInfo info = imageManager.getImageInfo(uri, userAgent.getImageSessionContext()); + + Object moreImages = info.getCustomObjects().get(ImageInfo.HAS_MORE_IMAGES); + boolean hasMoreImages = moreImages != null && !Boolean.FALSE.equals(moreImages); + + Dimension intrinsicSize = info.getSize().getDimensionMpt(); + ImageLayout layout = new ImageLayout(getExternalDocument(), this, intrinsicSize); + + areaTreeHandler.getAreaTreeModel().startPageSequence(null); + if (log.isDebugEnabled()) { + log.debug("Starting layout"); + } + + makePageForImage(info, layout); + + if (!hasPageIndex && hasMoreImages) { + if (log.isTraceEnabled()) { + log.trace("Starting multi-page processing..."); + } + URI originalURI; + try { + originalURI = new URI(uri); + int pageIndex = 1; + while (hasMoreImages) { + URI tempURI = new URI(originalURI.getScheme(), + originalURI.getSchemeSpecificPart(), + "page=" + Integer.toString(pageIndex + 1)); + if (log.isTraceEnabled()) { + log.trace("Subimage: " + tempURI.toASCIIString()); + } + ImageInfo subinfo = imageManager.getImageInfo( + tempURI.toASCIIString(), userAgent.getImageSessionContext()); + + moreImages = subinfo.getCustomObjects().get(ImageInfo.HAS_MORE_IMAGES); + hasMoreImages = moreImages != null && !Boolean.FALSE.equals(moreImages); + + intrinsicSize = subinfo.getSize().getDimensionMpt(); + layout = new ImageLayout( + getExternalDocument(), this, intrinsicSize); + + makePageForImage(subinfo, layout); + + pageIndex++; + } + } catch (URISyntaxException e) { + log.error("Error parsing or constructing URIs based on URI: " + uri); + return; + } + } + } catch (IOException ioe) { + log.error("Image not available: " + uri, ioe); + } catch (ImageException ie) { + log.error("Error while inspecting image: " + uri + " (" + ie.getMessage() + ")"); } + } + private void makePageForImage(ImageInfo info, ImageLayout layout) { + this.imageLayout = layout; curPage = makeNewPage(false, false); - - fillPage(); //TODO Implement multi-page documents (using new image package) - + fillPage(info.getOriginalURI()); finishPage(); } - - private void fillPage() { + + private void fillPage(String uri) { Dimension imageSize = this.imageLayout.getViewportSize(); @@ -119,7 +164,7 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan blockArea.setIPD(imageSize.width); LineArea lineArea = new LineArea(); - Image imageArea = new Image(getExternalDocument().getSrc()); + Image imageArea = new Image(uri); TraitSetter.setProducerID(imageArea, fobj.getId()); transferForeignAttributes(imageArea); diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java index b50167b16..f1e5ffdc6 100644 --- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java +++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java @@ -21,20 +21,19 @@ package org.apache.fop.layoutmgr; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.traits.BorderProps; -import org.apache.fop.traits.MinOptMax; + import org.apache.fop.area.Area; import org.apache.fop.area.Trait; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.datatypes.SimplePercentBaseContext; import org.apache.fop.fo.Constants; -import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fonts.Font; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.traits.BorderProps; +import org.apache.fop.traits.MinOptMax; /** * This is a helper class used for setting common traits on areas. @@ -303,9 +302,9 @@ public class TraitSetter { Trait.Background back = new Trait.Background(); back.setColor(backProps.backgroundColor); - if (backProps.getFopImage() != null) { + if (backProps.getImageInfo() != null) { back.setURL(backProps.backgroundImage); - back.setFopImage(backProps.getFopImage()); + back.setImageInfo(backProps.getImageInfo()); back.setRepeat(backProps.backgroundRepeat); if (backProps.backgroundPositionHorizontal != null) { if (back.getRepeat() == Constants.EN_NOREPEAT @@ -317,7 +316,7 @@ public class TraitSetter { back.setHoriz(backProps.backgroundPositionHorizontal.getValue( new SimplePercentBaseContext(context, LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, - (width - back.getFopImage().getIntrinsicWidth()) + (width - back.getImageInfo().getSize().getHeightMpt()) ) )); } else { @@ -338,7 +337,7 @@ public class TraitSetter { back.setVertical(backProps.backgroundPositionVertical.getValue( new SimplePercentBaseContext(context, LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL, - (height - back.getFopImage().getIntrinsicHeight()) + (height - back.getImageInfo().getSize().getHeightMpt()) ) )); } else { diff --git a/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java b/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java index b3ccea628..60247af39 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java @@ -29,7 +29,11 @@ import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.GraphicsProperties; +import org.apache.fop.fo.properties.LengthRangeProperty; +/** + * Helper class which calculates the size and position in the viewport of an image. + */ public class ImageLayout implements Constants { /** logging instance */ @@ -45,6 +49,12 @@ public class ImageLayout implements Constants { private Dimension viewportSize = new Dimension(-1, -1); private boolean clip; + /** + * Main constructor + * @param props the properties for the image + * @param percentBaseContext the context object for percentage calculations + * @param intrinsicSize the image's intrinsic size + */ public ImageLayout(GraphicsProperties props, PercentBaseContext percentBaseContext, Dimension intrinsicSize) { this.props = props; @@ -54,6 +64,9 @@ public class ImageLayout implements Constants { doLayout(); } + /** + * Does the actual calculations for the image. + */ protected void doLayout() { Length len; @@ -63,25 +76,26 @@ public class ImageLayout implements Constants { len = props.getBlockProgressionDimension().getOptimum(percentBaseContext).getLength(); if (len.getEnum() != EN_AUTO) { bpd = len.getValue(percentBaseContext); - } else { - len = props.getHeight(); - if (len.getEnum() != EN_AUTO) { - bpd = len.getValue(percentBaseContext); - } + } + len = props.getBlockProgressionDimension().getMinimum(percentBaseContext).getLength(); + if (bpd == -1 && len.getEnum() != EN_AUTO) { + //Establish minimum viewport size + bpd = len.getValue(percentBaseContext); } len = props.getInlineProgressionDimension().getOptimum(percentBaseContext).getLength(); if (len.getEnum() != EN_AUTO) { ipd = len.getValue(percentBaseContext); - } else { - len = props.getWidth(); - if (len.getEnum() != EN_AUTO) { - ipd = len.getValue(percentBaseContext); - } + } + len = props.getInlineProgressionDimension().getMinimum(percentBaseContext).getLength(); + if (ipd == -1 && len.getEnum() != EN_AUTO) { + //Establish minimum viewport size + ipd = len.getValue(percentBaseContext); } // if auto then use the intrinsic size of the content scaled // to the content-height and content-width + boolean constrainIntrinsicSize = false; int cwidth = -1; int cheight = -1; len = props.getContentWidth(); @@ -91,16 +105,19 @@ public class ImageLayout implements Constants { if (ipd != -1) { cwidth = ipd; } + constrainIntrinsicSize = true; break; case EN_SCALE_DOWN_TO_FIT: if (ipd != -1 && intrinsicSize.width > ipd) { cwidth = ipd; } + constrainIntrinsicSize = true; break; case EN_SCALE_UP_TO_FIT: if (ipd != -1 && intrinsicSize.width < ipd) { cwidth = ipd; } + constrainIntrinsicSize = true; break; default: cwidth = len.getValue(percentBaseContext); @@ -113,64 +130,43 @@ public class ImageLayout implements Constants { if (bpd != -1) { cheight = bpd; } + constrainIntrinsicSize = true; break; case EN_SCALE_DOWN_TO_FIT: if (bpd != -1 && intrinsicSize.height > bpd) { cheight = bpd; } + constrainIntrinsicSize = true; break; case EN_SCALE_UP_TO_FIT: if (bpd != -1 && intrinsicSize.height < bpd) { cheight = bpd; } + constrainIntrinsicSize = true; break; default: cheight = len.getValue(percentBaseContext); } } - int scaling = props.getScaling(); - if ((scaling == EN_UNIFORM) || (cwidth == -1) || cheight == -1) { - if (cwidth == -1 && cheight == -1) { - cwidth = intrinsicSize.width; - cheight = intrinsicSize.height; - } else if (cwidth == -1) { - if (intrinsicSize.height == 0) { - cwidth = 0; - } else { - cwidth = (int)(intrinsicSize.width * (double)cheight - / intrinsicSize.height); - } - } else if (cheight == -1) { - if (intrinsicSize.width == 0) { - cheight = 0; - } else { - cheight = (int)(intrinsicSize.height * (double)cwidth - / intrinsicSize.width); - } - } else { - // adjust the larger - if (intrinsicSize.width == 0 || intrinsicSize.height == 0) { - cwidth = 0; - cheight = 0; - } else { - double rat1 = (double) cwidth / intrinsicSize.width; - double rat2 = (double) cheight / intrinsicSize.height; - if (rat1 < rat2) { - // reduce cheight - cheight = (int)(rat1 * intrinsicSize.height); - } else if (rat1 > rat2) { - cwidth = (int)(rat2 * intrinsicSize.width); - } - } - } + Dimension constrainedIntrinsicSize; + if (constrainIntrinsicSize) { + constrainedIntrinsicSize = constrain(intrinsicSize); + } else { + constrainedIntrinsicSize = intrinsicSize; } + + //Derive content extents where not explicit + Dimension adjustedDim = adjustContentSize(cwidth, cheight, constrainedIntrinsicSize); + cwidth = adjustedDim.width; + cheight = adjustedDim.height; + //Adjust viewport if not explicit if (ipd == -1) { - ipd = cwidth; + ipd = constrainExtent(cwidth, props.getInlineProgressionDimension()); } if (bpd == -1) { - bpd = cheight; + bpd = constrainExtent(cheight, props.getBlockProgressionDimension()); } this.clip = false; @@ -193,6 +189,90 @@ public class ImageLayout implements Constants { this.placement = new Rectangle(xoffset, yoffset, cwidth, cheight); } + private int constrainExtent(int extent, LengthRangeProperty range) { + Length len; + len = range.getMaximum(percentBaseContext).getLength(); + if (len.getEnum() != EN_AUTO) { + int max = len.getValue(percentBaseContext); + if (max != -1) { + extent = Math.min(extent, max); + } + } + len = range.getMinimum(percentBaseContext).getLength(); + if (len.getEnum() != EN_AUTO) { + int min = len.getValue(percentBaseContext); + if (min != -1) { + extent = Math.max(extent, min); + } + } + return extent; + } + + private Dimension constrain(Dimension size) { + Dimension adjusted = new Dimension(size); + int effWidth = constrainExtent(size.width, props.getInlineProgressionDimension()); + int effHeight = constrainExtent(size.height, props.getBlockProgressionDimension()); + int scaling = props.getScaling(); + if (scaling == EN_UNIFORM) { + double rat1 = (double)effWidth / size.width; + double rat2 = (double)effHeight / size.height; + if (rat1 < rat2) { + adjusted.width = effWidth; + adjusted.height = (int)(rat1 * size.height); + } else if (rat1 > rat2) { + adjusted.width = (int)(rat2 * size.width); + adjusted.height = effHeight; + } + } else { + adjusted.width = effWidth; + adjusted.height = effHeight; + } + return adjusted; + } + + private Dimension adjustContentSize( + final int cwidth, final int cheight, + Dimension defaultSize) { + Dimension dim = new Dimension(cwidth, cheight); + int scaling = props.getScaling(); + if ((scaling == EN_UNIFORM) || (cwidth == -1) || cheight == -1) { + if (cwidth == -1 && cheight == -1) { + dim.width = defaultSize.width; + dim.height = defaultSize.height; + } else if (cwidth == -1) { + if (defaultSize.height == 0) { + dim.width = 0; + } else { + dim.width = (int)(defaultSize.width * (double)cheight + / defaultSize.height); + } + } else if (cheight == -1) { + if (defaultSize.width == 0) { + dim.height = 0; + } else { + dim.height = (int)(defaultSize.height * (double)cwidth + / defaultSize.width); + } + } else { + // adjust the larger + if (defaultSize.width == 0 || defaultSize.height == 0) { + dim.width = 0; + dim.height = 0; + } else { + double rat1 = (double)cwidth / defaultSize.width; + double rat2 = (double)cheight / defaultSize.height; + if (rat1 < rat2) { + // reduce height + dim.height = (int)(rat1 * defaultSize.height); + } else if (rat1 > rat2) { + dim.width = (int)(rat2 * defaultSize.width); + } + } + } + } + return dim; + } + /** * Given the ipd and the content width calculates the * required x offset based on the text-align property @@ -243,18 +323,34 @@ public class ImageLayout implements Constants { return yoffset; } + /** + * Returns the placement of the image inside the viewport. + * @return the placement of the image inside the viewport (coordinates in millipoints) + */ public Rectangle getPlacement() { return this.placement; } + /** + * Returns the size of the image's viewport. + * @return the viewport size (in millipoints) + */ public Dimension getViewportSize() { return this.viewportSize; } + /** + * Returns the size of the image's intrinsic (natural) size. + * @return the intrinsic size (in millipoints) + */ public Dimension getIntrinsicSize() { return this.intrinsicSize; } + /** + * Indicates whether the image is clipped. + * @return true if the image shall be clipped + */ public boolean isClipped() { return this.clip; } diff --git a/src/java/org/apache/fop/pdf/AlphaRasterImage.java b/src/java/org/apache/fop/pdf/AlphaRasterImage.java new file mode 100644 index 000000000..be476bdb2 --- /dev/null +++ b/src/java/org/apache/fop/pdf/AlphaRasterImage.java @@ -0,0 +1,181 @@ +/* + * 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.pdf; + +import java.awt.image.DataBuffer; +import java.awt.image.Raster; +import java.awt.image.RenderedImage; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.xmlgraphics.image.GraphicsUtil; + +/** + * PDFImage implementation for alpha channel "images". + */ +public class AlphaRasterImage implements PDFImage { + + private int bitsPerComponent; + private PDFDeviceColorSpace colorSpace; + private Raster alpha; + private String key; + + /** + * Create a alpha channel image. + * Creates a new bitmap image with the given data. + * + * @param k the key to be used to lookup the image + * @param alpha the alpha channel raster + */ + public AlphaRasterImage(String k, Raster alpha) { + this.key = k; + this.bitsPerComponent = 8; + this.colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_GRAY); + if (alpha == null) { + throw new NullPointerException("Parameter alpha must not be null"); + } + this.alpha = alpha; + } + + /** + * Create a alpha channel image. + * Extracts the alpha channel from the RenderedImage and creates a new bitmap image + * with the given data. + * + * @param k the key to be used to lookup the image + * @param image the image (must have an alpha channel) + */ + public AlphaRasterImage(String k, RenderedImage image) { + this(k, GraphicsUtil.getAlphaRaster(image)); + } + + /** {@inheritDoc} */ + public void setup(PDFDocument doc) { + //nop + } + + /** {@inheritDoc} */ + public String getKey() { + return key; + } + + /** {@inheritDoc} */ + public int getWidth() { + return alpha.getWidth(); + } + + /** {@inheritDoc} */ + public int getHeight() { + return alpha.getHeight(); + } + + /** {@inheritDoc} */ + public PDFDeviceColorSpace getColorSpace() { + return colorSpace; + } + + /** {@inheritDoc} */ + public int getBitsPerComponent() { + return bitsPerComponent; + } + + /** {@inheritDoc} */ + public boolean isTransparent() { + return false; + } + + /** {@inheritDoc} */ + public PDFColor getTransparentColor() { + return null; + } + + /** {@inheritDoc} */ + public String getMask() { + return null; + } + + /** {@inheritDoc} */ + public String getSoftMask() { + return null; + } + + /** {@inheritDoc} */ + public PDFReference getSoftMaskReference() { + return null; + } + + /** {@inheritDoc} */ + public boolean isInverted() { + return false; + } + + /** {@inheritDoc} */ + public void outputContents(OutputStream out) throws IOException { + int w = getWidth(); + int h = getHeight(); + + //Check Raster + int nbands = alpha.getNumBands(); + if (nbands != 1) { + throw new UnsupportedOperationException( + "Expected only one band/component for the alpha channel"); + } + int dataType = alpha.getDataBuffer().getDataType(); + if (dataType != DataBuffer.TYPE_BYTE) { + 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} */ + public void populateXObjectDictionary(PDFDictionary dict) { + //nop + } + + /** {@inheritDoc} */ + public PDFICCStream getICCStream() { + return null; + } + + /** {@inheritDoc} */ + public boolean isPS() { + return false; + } + + /** {@inheritDoc} */ + public String getFilterHint() { + return PDFFilterList.IMAGE_FILTER; + } + + /** {@inheritDoc} */ + public PDFFilter getPDFFilter() { + return null; + } + +} + + diff --git a/src/java/org/apache/fop/pdf/BitmapImage.java b/src/java/org/apache/fop/pdf/BitmapImage.java index 34c78ffe3..69b51dac3 100644 --- a/src/java/org/apache/fop/pdf/BitmapImage.java +++ b/src/java/org/apache/fop/pdf/BitmapImage.java @@ -30,7 +30,7 @@ import java.io.OutputStream; public class BitmapImage implements PDFImage { private int height; private int width; - private int bitsPerPixel; + private int bitsPerComponent; private PDFDeviceColorSpace colorSpace; private byte[] bitmaps; private PDFReference maskRef; @@ -53,10 +53,12 @@ public class BitmapImage implements PDFImage { this.key = k; this.height = height; this.width = width; - this.bitsPerPixel = 8; + this.bitsPerComponent = 8; this.colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB); this.bitmaps = data; - maskRef = new PDFReference(mask); + if (mask != null) { + maskRef = new PDFReference(mask); + } } /** @@ -117,13 +119,9 @@ public class BitmapImage implements PDFImage { return colorSpace; } - /** - * Get the number of bits per pixel. - * - * @return the number of bits per pixel - */ - public int getBitsPerPixel() { - return bitsPerPixel; + /** {@inheritDoc} */ + public int getBitsPerComponent() { + return bitsPerComponent; } /** @@ -173,13 +171,16 @@ public class BitmapImage implements PDFImage { return false; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void outputContents(OutputStream out) throws IOException { out.write(bitmaps); } + /** {@inheritDoc} */ + public void populateXObjectDictionary(PDFDictionary dict) { + //nop + } + /** * Get the ICC stream. * @return always returns null since this has no icc color space diff --git a/src/java/org/apache/fop/pdf/FlateFilter.java b/src/java/org/apache/fop/pdf/FlateFilter.java index d7dc81d1f..a652c4534 100644 --- a/src/java/org/apache/fop/pdf/FlateFilter.java +++ b/src/java/org/apache/fop/pdf/FlateFilter.java @@ -19,8 +19,8 @@ package org.apache.fop.pdf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; import org.apache.xmlgraphics.util.io.FlateEncodeOutputStream; @@ -98,13 +98,13 @@ public class FlateFilter extends PDFFilter { if (predictor > PREDICTION_NONE) { PDFDictionary dict = new PDFDictionary(); dict.put("Predictor", predictor); - if (colors > 0) { + if (colors > 1) { dict.put("Colors", colors); } - if (bitsPerComponent > 0) { + if (bitsPerComponent > 0 && bitsPerComponent != 8) { dict.put("BitsPerComponent", bitsPerComponent); } - if (columns > 0) { + if (columns > 1) { dict.put("Columns", columns); } return dict; diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index f3069e85e..d0c48ee39 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -1490,9 +1490,6 @@ public class PDFFactory { */ public PDFICCStream makePDFICCStream() { PDFICCStream iccStream = new PDFICCStream(); - iccStream.getFilterList().addDefaultFilters( - getDocument().getFilterMap(), - PDFFilterList.CONTENT_FILTER); getDocument().registerObject(iccStream); //getDocument().applyEncryption(iccStream); diff --git a/src/java/org/apache/fop/pdf/PDFFilterList.java b/src/java/org/apache/fop/pdf/PDFFilterList.java index 607ae174b..84131707b 100644 --- a/src/java/org/apache/fop/pdf/PDFFilterList.java +++ b/src/java/org/apache/fop/pdf/PDFFilterList.java @@ -34,6 +34,8 @@ public class PDFFilterList { public static final String DEFAULT_FILTER = "default"; /** Key for the filter used for normal content*/ public static final String CONTENT_FILTER = "content"; + /** Key for the filter used for precompressed content */ + public static final String PRECOMPRESSED_FILTER = "precompressed"; /** Key for the filter used for images */ public static final String IMAGE_FILTER = "image"; /** Key for the filter used for JPEG images */ @@ -178,6 +180,9 @@ public class PDFFilterList { } else if (TIFF_FILTER.equals(type)) { //CCITT-encoded images are already well compressed addFilter(new NullFilter()); + } else if (PRECOMPRESSED_FILTER.equals(type)) { + //precompressed content doesn't need further compression + addFilter(new NullFilter()); } else { // built-in default to flate addFilter(new FlateFilter()); diff --git a/src/java/org/apache/fop/pdf/PDFICCStream.java b/src/java/org/apache/fop/pdf/PDFICCStream.java index da1e8353c..f242c0cae 100644 --- a/src/java/org/apache/fop/pdf/PDFICCStream.java +++ b/src/java/org/apache/fop/pdf/PDFICCStream.java @@ -66,9 +66,7 @@ public class PDFICCStream extends PDFStream { return length; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void outputRawStreamData(OutputStream out) throws IOException { cp.write(out); } diff --git a/src/java/org/apache/fop/pdf/PDFImage.java b/src/java/org/apache/fop/pdf/PDFImage.java index f880fa6ac..e0aaa44fa 100644 --- a/src/java/org/apache/fop/pdf/PDFImage.java +++ b/src/java/org/apache/fop/pdf/PDFImage.java @@ -69,11 +69,11 @@ public interface PDFImage { PDFDeviceColorSpace getColorSpace(); /** - * Get the bits per pixel for this image. + * Get the bits per color component for this image. * - * @return the bits per pixel + * @return the bits per component */ - int getBitsPerPixel(); + int getBitsPerComponent(); /** * Check if this image is a PostScript image. @@ -129,6 +129,14 @@ public interface PDFImage { */ void outputContents(OutputStream out) throws IOException; + /** + * Populates the XObject's dictionary with additional values. The values are added to the + * dictionary after all the values obtained from other methods from this interface have + * been put into the dictionary. That allows to override certain values. + * @param dict the dictionary to fill + */ + void populateXObjectDictionary(PDFDictionary dict); + /** * Get the ICC stream for this image. * diff --git a/src/java/org/apache/fop/pdf/PDFImageXObject.java b/src/java/org/apache/fop/pdf/PDFImageXObject.java index 35f3e543d..14fbeed4d 100644 --- a/src/java/org/apache/fop/pdf/PDFImageXObject.java +++ b/src/java/org/apache/fop/pdf/PDFImageXObject.java @@ -90,7 +90,7 @@ public class PDFImageXObject extends PDFXObject { put("Subtype", new PDFName("Image")); put("Width", new Integer(pdfimage.getWidth())); put("Height", new Integer(pdfimage.getHeight())); - put("BitsPerComponent", new Integer(pdfimage.getBitsPerPixel())); + put("BitsPerComponent", new Integer(pdfimage.getBitsPerComponent())); PDFICCStream pdfICCStream = pdfimage.getICCStream(); if (pdfICCStream != null) { @@ -119,18 +119,25 @@ public class PDFImageXObject extends PDFXObject { if (pdfimage.isTransparent()) { PDFColor transp = pdfimage.getTransparentColor(); PDFArray mask = new PDFArray(this); - mask.add(new Integer(transp.red255())); - mask.add(new Integer(transp.red255())); - mask.add(new Integer(transp.green255())); - mask.add(new Integer(transp.green255())); - mask.add(new Integer(transp.blue255())); - mask.add(new Integer(transp.blue255())); + if (pdfimage.getColorSpace().isGrayColorSpace()) { + mask.add(new Integer(transp.red255())); + mask.add(new Integer(transp.red255())); + } else { + mask.add(new Integer(transp.red255())); + mask.add(new Integer(transp.red255())); + mask.add(new Integer(transp.green255())); + mask.add(new Integer(transp.green255())); + mask.add(new Integer(transp.blue255())); + mask.add(new Integer(transp.blue255())); + } put("Mask", mask); } PDFReference ref = pdfimage.getSoftMaskReference(); if (ref != null) { put("SMask", ref); } + //Important: do this at the end so previous values can be overwritten. + pdfimage.populateXObjectDictionary(this); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java index f53183574..4bfd805f4 100644 --- a/src/java/org/apache/fop/pdf/PDFObject.java +++ b/src/java/org/apache/fop/pdf/PDFObject.java @@ -276,14 +276,23 @@ public abstract class PDFObject implements PDFWritable { */ protected byte[] encodeString(String string) { return encodeText(string); - /* - final byte[] buf = encode(PDFText.escapeString(string)); + } + + /** + * Encodes binary data as hexadecimal string object. + * @param data the binary data + * @param out the OutputStream to write the encoded object to + * @throws IOException if an I/O error occurs + */ + protected void encodeBinaryToHexString(byte[] data, OutputStream out) throws IOException { + out.write('<'); if (getDocumentSafely().isEncryptionActive()) { - return PDFText.escapeByteArray( - getDocument().getEncryption().encrypt(buf, this)); - } else { - return buf; - }*/ + data = getDocument().getEncryption().encrypt(data, this); + } + String hex = PDFText.toHex(data, false); + byte[] encoded = hex.getBytes("US-ASCII"); + out.write(encoded); + out.write('>'); } /** @@ -307,6 +316,9 @@ public abstract class PDFObject implements PDFWritable { } } else if (obj instanceof Boolean) { writer.write(obj.toString()); + } else if (obj instanceof byte[]) { + writer.flush(); + encodeBinaryToHexString((byte[])obj, out); } else { writer.flush(); out.write(encodeText(obj.toString())); diff --git a/src/java/org/apache/fop/pdf/PDFReference.java b/src/java/org/apache/fop/pdf/PDFReference.java index 3b615735a..da388d368 100644 --- a/src/java/org/apache/fop/pdf/PDFReference.java +++ b/src/java/org/apache/fop/pdf/PDFReference.java @@ -51,6 +51,9 @@ public class PDFReference implements PDFWritable { * @param ref an object reference */ public PDFReference(String ref) { + if (ref == null) { + throw new NullPointerException("ref must not be null"); + } this.indirectReference = ref; } diff --git a/src/java/org/apache/fop/pdf/PDFText.java b/src/java/org/apache/fop/pdf/PDFText.java index 4c17148c1..d380ac8dd 100644 --- a/src/java/org/apache/fop/pdf/PDFText.java +++ b/src/java/org/apache/fop/pdf/PDFText.java @@ -25,12 +25,12 @@ import org.apache.avalon.framework.CascadingRuntimeException; /** * This class represents a simple number object. It also contains contains some - * utility methods for outputing numbers to PDF. + * utility methods for outputting numbers to PDF. */ public class PDFText extends PDFObject { - private static final char[] DIGITS = - {'0', '1', '2', '3', '4', '5', '6', '7', + private static final char[] DIGITS + = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; private String text; @@ -145,19 +145,33 @@ public class PDFText extends PDFObject { /** * Converts a byte array to a Hexadecimal String (3.2.3 in PDF 1.4 specs) * @param data the data to encode + * @param brackets true if enclosing brackets should be included * @return String the resulting string */ - public static final String toHex(byte[] data) { + public static final String toHex(byte[] data, boolean brackets) { final StringBuffer sb = new StringBuffer(data.length * 2); - sb.append("<"); + if (brackets) { + sb.append("<"); + } for (int i = 0; i < data.length; i++) { sb.append(DIGITS[(data[i] >>> 4) & 0x0F]); sb.append(DIGITS[data[i] & 0x0F]); } - sb.append(">"); + if (brackets) { + sb.append(">"); + } return sb.toString(); } + /** + * Converts a byte array to a Hexadecimal String (3.2.3 in PDF 1.4 specs) + * @param data the data to encode + * @return String the resulting string + */ + public static final String toHex(byte[] data) { + return toHex(data, true); + } + /** * Converts a String to UTF-16 (big endian). * @param text text to convert diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index 7d21d78c0..f74699fd5 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -26,28 +26,18 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.IOException; -// DOM import org.w3c.dom.Document; -// Batik -import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; -// FOP -import org.apache.fop.render.Graphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; -import org.apache.fop.render.RendererContextConstants; -import org.apache.fop.render.XMLHandler; -import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContext.RendererContextWrapper; import org.apache.fop.svg.SVGUserAgent; -// Commons-Logging -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** * Generic XML handler for SVG. Uses Apache Batik for SVG processing and simply paints to * a Graphics2DAdapter and thus ultimatively to Graphics2D interface that is presented. @@ -76,6 +66,7 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC */ protected void renderSVGDocument(final RendererContext context, final Document doc) throws IOException { + updateRendererContext(context); final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext(context); int x = wrappedContext.getCurrentXPosition(); int y = wrappedContext.getCurrentYPosition(); @@ -123,6 +114,15 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC x, y, wrappedContext.getWidth(), wrappedContext.getHeight()); } + /** + * Override this method to update the renderer context if it needs special settings for + * certain conditions. + * @param context the renderer context + */ + protected void updateRendererContext(RendererContext context) { + //nop + } + /** {@inheritDoc} */ public String getNamespace() { return SVGDOMImplementation.SVG_NAMESPACE_URI; diff --git a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java index b51b71d61..bc7bb95a1 100644 --- a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java @@ -33,8 +33,6 @@ import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.WritableRaster; -import org.apache.fop.render.Graphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; import org.apache.fop.render.RendererContext.RendererContextWrapper; import org.apache.fop.util.UnitConv; @@ -49,9 +47,11 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { * @param context the renderer context for the current renderer * @param resolution the requested bitmap resolution * @param gray true if the generated image should be in grayscales + * @param withAlpha true if an alpha channel should be created * @return the generated BufferedImage */ - protected BufferedImage paintToBufferedImage(Graphics2DImagePainter painter, + protected BufferedImage paintToBufferedImage( + org.apache.xmlgraphics.java2d.Graphics2DImagePainter painter, RendererContextWrapper context, int resolution, boolean gray, boolean withAlpha) { int bmw = (int)Math.ceil(UnitConv.mpt2px(context.getWidth(), resolution)); int bmh = (int)Math.ceil(UnitConv.mpt2px(context.getHeight(), resolution)); diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 4e5edece6..ac11d56d5 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -25,6 +25,10 @@ import java.awt.geom.Rectangle2D; import java.util.List; import java.util.Map; +import org.w3c.dom.Document; + +import org.apache.xmlgraphics.image.loader.ImageSize; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; @@ -36,9 +40,7 @@ import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.Viewport; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontMetrics; -import org.apache.fop.image.FopImage; import org.apache.fop.traits.BorderProps; -import org.w3c.dom.Document; /** * Abstract base class for renderers like PDF and PostScript where many painting operations @@ -151,51 +153,47 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { updateColor(back.getColor(), true); fillRect(sx, sy, paddRectWidth, paddRectHeight); } - if (back.getFopImage() != null) { - FopImage fopimage = back.getFopImage(); - if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) { - saveGraphicsState(); - clipRect(sx, sy, paddRectWidth, paddRectHeight); - int horzCount = (int)((paddRectWidth - * 1000 / fopimage.getIntrinsicWidth()) + 1.0f); - int vertCount = (int)((paddRectHeight - * 1000 / fopimage.getIntrinsicHeight()) + 1.0f); - if (back.getRepeat() == EN_NOREPEAT) { - horzCount = 1; - vertCount = 1; - } else if (back.getRepeat() == EN_REPEATX) { - vertCount = 1; - } else if (back.getRepeat() == EN_REPEATY) { - horzCount = 1; - } - //change from points to millipoints - sx *= 1000; - sy *= 1000; - if (horzCount == 1) { - sx += back.getHoriz(); - } - if (vertCount == 1) { - sy += back.getVertical(); - } - for (int x = 0; x < horzCount; x++) { - for (int y = 0; y < vertCount; y++) { - // place once - Rectangle2D pos; - // Image positions are relative to the currentIP/BP - pos = new Rectangle2D.Float(sx - currentIPPosition - + (x * fopimage.getIntrinsicWidth()), - sy - currentBPPosition - + (y * fopimage.getIntrinsicHeight()), - fopimage.getIntrinsicWidth(), - fopimage.getIntrinsicHeight()); - drawImage(back.getURL(), pos); - } + if (back.getImageInfo() != null) { + ImageSize imageSize = back.getImageInfo().getSize(); + saveGraphicsState(); + clipRect(sx, sy, paddRectWidth, paddRectHeight); + int horzCount = (int)((paddRectWidth + * 1000 / imageSize.getWidthMpt()) + 1.0f); + int vertCount = (int)((paddRectHeight + * 1000 / imageSize.getHeightMpt()) + 1.0f); + if (back.getRepeat() == EN_NOREPEAT) { + horzCount = 1; + vertCount = 1; + } else if (back.getRepeat() == EN_REPEATX) { + vertCount = 1; + } else if (back.getRepeat() == EN_REPEATY) { + horzCount = 1; + } + //change from points to millipoints + sx *= 1000; + sy *= 1000; + if (horzCount == 1) { + sx += back.getHoriz(); + } + if (vertCount == 1) { + sy += back.getVertical(); + } + for (int x = 0; x < horzCount; x++) { + for (int y = 0; y < vertCount; y++) { + // place once + Rectangle2D pos; + // Image positions are relative to the currentIP/BP + pos = new Rectangle2D.Float(sx - currentIPPosition + + (x * imageSize.getWidthMpt()), + sy - currentBPPosition + + (y * imageSize.getHeightMpt()), + imageSize.getWidthMpt(), + imageSize.getHeightMpt()); + drawImage(back.getURL(), pos); } - - restoreGraphicsState(); - } else { - log.warn("Can't find background image: " + back.getURL()); } + + restoreGraphicsState(); } } diff --git a/src/java/org/apache/fop/render/Graphics2DAdapter.java b/src/java/org/apache/fop/render/Graphics2DAdapter.java index 2509b3864..e9b00f103 100644 --- a/src/java/org/apache/fop/render/Graphics2DAdapter.java +++ b/src/java/org/apache/fop/render/Graphics2DAdapter.java @@ -43,7 +43,7 @@ public interface Graphics2DAdapter { * @param height height of the image * @throws IOException In case of an I/O error while writing the output format */ - void paintImage(Graphics2DImagePainter painter, + void paintImage(org.apache.xmlgraphics.java2d.Graphics2DImagePainter painter, RendererContext context, int x, int y, int width, int height) throws IOException; diff --git a/src/java/org/apache/fop/render/Graphics2DImagePainter.java b/src/java/org/apache/fop/render/Graphics2DImagePainter.java index 3039a72a7..9301a6962 100644 --- a/src/java/org/apache/fop/render/Graphics2DImagePainter.java +++ b/src/java/org/apache/fop/render/Graphics2DImagePainter.java @@ -19,27 +19,12 @@ package org.apache.fop.render; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.geom.Rectangle2D; - /** * This interface is used by the Graphics2DAdapter. Components that can paint using * a Graphics2D instance can implement this interface to paint themselves. + * @deprecated use {@link org.apache.xmlgraphics.java2d.Graphics2DImagePainter} directly! */ -public interface Graphics2DImagePainter { - - /** - * Called to paint the image. Implementations should scale so the image is - * painted fully inside the given area indicated by then Rectangle2D object. - * @param g2d the Graphics2D instance to paint on - * @param area the target area for the image - */ - void paint(Graphics2D g2d, Rectangle2D area); +public interface Graphics2DImagePainter + extends org.apache.xmlgraphics.java2d.Graphics2DImagePainter { - /** - * @return the dimensions of the image to be painted in millipoints - */ - Dimension getImageSize(); - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index 8fa0d0f72..687a0373e 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -22,8 +22,9 @@ package org.apache.fop.render.afp; import java.awt.image.BufferedImage; import java.io.IOException; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + import org.apache.fop.render.AbstractGraphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; import org.apache.fop.render.RendererContext; /** diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index de414fa10..cdb2f2ec8 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -20,10 +20,13 @@ package org.apache.fop.render.afp; import java.awt.Color; +import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; @@ -32,7 +35,22 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; + +import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; +import org.apache.xmlgraphics.ps.ImageEncodingHelper; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; import org.apache.fop.area.Block; @@ -49,6 +67,7 @@ import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.FontInfo; @@ -56,10 +75,6 @@ import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.base14.Courier; import org.apache.fop.fonts.base14.Helvetica; import org.apache.fop.fonts.base14.TimesRoman; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.apache.fop.image.TIFFImage; -import org.apache.fop.image.XMLImage; import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.RendererContext; @@ -74,7 +89,6 @@ import org.apache.fop.render.afp.modca.AFPConstants; import org.apache.fop.render.afp.modca.AFPDataStream; import org.apache.fop.render.afp.modca.ImageObject; import org.apache.fop.render.afp.modca.PageObject; -import org.w3c.dom.Document; /** * This is an implementation of a FOP Renderer that renders areas to AFP. @@ -735,20 +749,117 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { return context; } - /** - * {@inheritDoc} - */ - public void drawImage(String url, Rectangle2D pos, Map foreignAttributes) { + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] + {ImageFlavor.RAW_CCITTFAX, + ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE, + ImageFlavor.XML_DOM}; + + /** {@inheritDoc} */ + public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { + uri = URISpecification.getURL(uri); + Rectangle posInt = new Rectangle( + (int)pos.getX(), + (int)pos.getY(), + (int)pos.getWidth(), + (int)pos.getHeight()); + Point origin = new Point(currentIPPosition, currentBPPosition); + int x = origin.x + posInt.x; + int y = origin.y + posInt.y; + String name = null; if (pageSegmentsMap != null) { - name = (String) pageSegmentsMap.get(url); + name = (String) pageSegmentsMap.get(uri); } if (name != null) { - int x = mpts2units(pos.getX() + currentIPPosition); - int y = mpts2units(pos.getY() + currentBPPosition); - afpDataStream.createIncludePageSegment(name, x, y); + afpDataStream.createIncludePageSegment(name, mpts2units(x), mpts2units(y)); } else { - url = ImageFactory.getURL(url); + ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageInfo info = null; + try { + ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + info = manager.getImageInfo(uri, sessionContext); + + //Only now fully load/prepare the image + Map hints = ImageUtil.getDefaultHints(sessionContext); + org.apache.xmlgraphics.image.loader.Image img = manager.getImage( + info, FLAVORS, hints, sessionContext); + + //...and process the image + if (img instanceof ImageGraphics2D) { + ImageGraphics2D imageG2D = (ImageGraphics2D)img; + RendererContext context = createRendererContext( + posInt.x, posInt.y, + posInt.width, posInt.height, foreignAttributes); + getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(), + context, + origin.x + posInt.x, origin.y + posInt.y, + posInt.width, posInt.height); + } else if (img instanceof ImageRendered) { + ImageRendered imgRend = (ImageRendered)img; + RenderedImage ri = imgRend.getRenderedImage(); + + drawBufferedImage(ri, getResolution(), + posInt.x + currentIPPosition, + posInt.y + currentBPPosition, + posInt.width, + posInt.height); + } else if (img instanceof ImageRawCCITTFax) { + ImageRawCCITTFax ccitt = (ImageRawCCITTFax)img; + int afpx = mpts2units(posInt.x + currentIPPosition); + int afpy = mpts2units(posInt.y + currentBPPosition); + int afpw = mpts2units(posInt.getWidth()); + int afph = mpts2units(posInt.getHeight()); + int afpres = getResolution(); + ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph, + afpres, afpres); + io.setImageParameters( + (int) (ccitt.getSize().getDpiHorizontal() * 10), + (int) (ccitt.getSize().getDpiVertical() * 10), + ccitt.getSize().getWidthPx(), + ccitt.getSize().getHeightPx()); + int compression = ccitt.getCompression(); + switch (compression) { + case TIFFImage.COMP_FAX_G3_1D : + io.setImageEncoding((byte) 0x80); + break; + case TIFFImage.COMP_FAX_G3_2D : + io.setImageEncoding((byte) 0x81); + break; + case TIFFImage.COMP_FAX_G4_2D : + io.setImageEncoding((byte) 0x82); + break; + default: + throw new IllegalStateException( + "Invalid compression scheme: " + compression); + } + InputStream in = ccitt.createInputStream(); + try { + byte[] buf = IOUtils.toByteArray(in); + io.setImageData(buf); + } finally { + IOUtils.closeQuietly(in); + } + } else if (img instanceof ImageXMLDOM) { + ImageXMLDOM imgXML = (ImageXMLDOM)img; + renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(), + pos, foreignAttributes); + } else { + throw new UnsupportedOperationException("Unsupported image type: " + img); + } + + } catch (ImageException ie) { + log.error("Error while processing image: " + + (info != null ? info.toString() : uri), ie); + } catch (FileNotFoundException fe) { + log.error(fe.getMessage()); + } catch (IOException ioe) { + log.error("I/O error while processing image: " + + (info != null ? info.toString() : uri), ioe); + } + + /* ImageFactory fact = userAgent.getFactory().getImageFactory(); FopImage fopimage = fact.getImage(url, userAgent); if (fopimage == null) { @@ -768,6 +879,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { renderDocument(doc, ns, pos, foreignAttributes); } else if (MimeConstants.MIME_EPS.equals(mime)) { log.warn("EPS images are not supported by this renderer"); + */ /* * } else if (MimeConstants.MIME_JPEG.equals(mime)) { if * (!fopimage.load(FopImage.ORIGINAL_DATA)) { return; } @@ -785,7 +897,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * io.setImageIDESize((byte)fopimage.getBitsPerPixel()); * io.setImageEncoding((byte)0x83); * io.setImageData(fopimage.getRessourceBytes()); - */ + *//* } else if (MimeConstants.MIME_TIFF.equals(mime) && fopimage instanceof TIFFImage) { TIFFImage tiffImage = (TIFFImage) fopimage; @@ -852,43 +964,30 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { convertToGrayScaleImage(io, fopimage.getBitmaps(), fopimage .getWidth(), fopimage.getHeight(), this.bitsPerPixel); } - } + }*/ } } /** - * Writes a BufferedImage to an OutputStream as raw sRGB bitmaps. + * Writes a RenderedImage to an OutputStream as raw sRGB bitmaps. * - * @param img - * the BufferedImage + * @param image + * the RenderedImage * @param out * the OutputStream * @throws IOException * In case of an I/O error. */ - public static void writeImage(BufferedImage img, OutputStream out) + public static void writeImage(RenderedImage image, OutputStream out) throws IOException { - int w = img.getWidth(); - int h = img.getHeight(); - int[] tmpMap = img.getRGB(0, 0, w, h, null, 0, w); - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - int p = tmpMap[i * w + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - out.write((byte) (r & 0xFF)); - out.write((byte) (g & 0xFF)); - out.write((byte) (b & 0xFF)); - } - } + ImageEncodingHelper.encodeRenderedImageAsRGB(image, out); } /** * Draws a BufferedImage to AFP. * - * @param bi - * the BufferedImage + * @param image + * the RenderedImage * @param imageResolution * the resolution of the BufferedImage * @param x @@ -900,7 +999,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @param h * the height of the viewport (in mpt) */ - public void drawBufferedImage(BufferedImage bi, int imageResolution, int x, + public void drawBufferedImage(RenderedImage image, int imageResolution, int x, int y, int w, int h) { int afpx = mpts2units(x); int afpy = mpts2units(y); @@ -910,21 +1009,24 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { ByteArrayOutputStream baout = new ByteArrayOutputStream(); try { // Serialize image - writeImage(bi, baout); + //TODO Eventually, this should be changed not to buffer as this increases the + //memory consumption (see PostScript output) + writeImage(image, baout); byte[] buf = baout.toByteArray(); // Generate image ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph, afpres, afpres); io.setImageParameters(imageResolution, imageResolution, - bi.getWidth(), bi.getHeight()); + image.getWidth(), image.getHeight()); if (colorImages) { io.setImageIDESize((byte)24); io.setImageData(buf); } else { // TODO Teach it how to handle grayscale BufferedImages directly // because this is pretty inefficient - convertToGrayScaleImage(io, buf, bi.getWidth(), bi.getHeight(), this.bitsPerPixel); + convertToGrayScaleImage(io, buf, + image.getWidth(), image.getHeight(), this.bitsPerPixel); } } catch (IOException ioe) { log.error("Error while serializing bitmap: " + ioe.getMessage(), diff --git a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java index f74df6cff..1182fe42d 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java @@ -21,12 +21,14 @@ package org.apache.fop.render.java2d; import java.awt.Color; import java.awt.Dimension; +import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.IOException; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + import org.apache.fop.render.Graphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; import org.apache.fop.render.RendererContext; /** @@ -34,16 +36,6 @@ import org.apache.fop.render.RendererContext; */ public class Java2DGraphics2DAdapter implements Graphics2DAdapter { - private Java2DGraphicsState state; - - /** - * Main constructor - * @param state the state tracker for this rendering run - */ - public Java2DGraphics2DAdapter(Java2DGraphicsState state) { - this.state = state; - } - /** {@inheritDoc} */ public void paintImage(Graphics2DImagePainter painter, RendererContext context, @@ -63,26 +55,28 @@ public class Java2DGraphics2DAdapter implements Graphics2DAdapter { float sy = fheight / (float)imh; Java2DRenderer renderer = (Java2DRenderer)context.getRenderer(); - renderer.saveGraphicsState(); - state.getGraph().setColor(Color.black); - state.getGraph().setBackground(Color.black); + Java2DGraphicsState state = renderer.state; + + //Create copy and paint on that + Graphics2D g2d = (Graphics2D)state.getGraph().create(); + g2d.setColor(Color.black); + g2d.setBackground(Color.black); //TODO Clip to the image area. // transform so that the coordinates (0,0) is from the top left // and positive is down and to the right. (0,0) is where the // viewBox puts it. - state.getGraph().translate(fx, fy); + g2d.translate(fx, fy); AffineTransform at = AffineTransform.getScaleInstance(sx, sy); if (!at.isIdentity()) { - state.getGraph().transform(at); + g2d.transform(at); } Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); - painter.paint(state.getGraph(), area); + painter.paint(g2d, area); - renderer.restoreGraphicsState(); - + g2d.dispose(); } } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index eededf13b..0f73c5761 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -25,7 +25,6 @@ import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; -import java.awt.color.ColorSpace; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; @@ -33,14 +32,6 @@ import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.ComponentColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.PixelInterleavedSampleModel; -import java.awt.image.Raster; -import java.awt.image.SampleModel; -import java.awt.image.WritableRaster; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; @@ -51,7 +42,15 @@ import java.util.List; import java.util.Map; import java.util.Stack; -import org.w3c.dom.Document; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; @@ -65,13 +64,11 @@ import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.Typeface; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.apache.fop.image.XMLImage; import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.RendererContext; @@ -184,7 +181,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** {@inheritDoc} */ public Graphics2DAdapter getGraphics2DAdapter() { - return new Java2DGraphics2DAdapter(state); + return new Java2DGraphics2DAdapter(); } /** @@ -884,76 +881,58 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** * {@inheritDoc} */ - protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) { + protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { int x = currentIPPosition + (int)Math.round(pos.getX()); int y = currentBPPosition + (int)Math.round(pos.getY()); - url = ImageFactory.getURL(url); - - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage fopimage = fact.getImage(url, userAgent); - - if (fopimage == null) { - return; - } - if (!fopimage.load(FopImage.DIMENSIONS)) { - return; - } - int w = fopimage.getWidth(); - int h = fopimage.getHeight(); - String mime = fopimage.getMimeType(); - if ("text/xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - renderDocument(doc, ns, pos, foreignAttributes); - - } else if ("image/svg+xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, foreignAttributes); - } else if ("image/eps".equals(mime)) { - log.warn("EPS images are not supported by this renderer"); - } else { - if (!fopimage.load(FopImage.BITMAP)) { - log.warn("Loading of bitmap failed: " + url); - return; + uri = URISpecification.getURL(uri); + + ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageInfo info = null; + try { + ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + info = manager.getImageInfo(uri, sessionContext); + final ImageFlavor[] flavors = new ImageFlavor[] + {ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE, + ImageFlavor.XML_DOM}; + Map hints = ImageUtil.getDefaultHints(sessionContext); + org.apache.xmlgraphics.image.loader.Image img = manager.getImage( + info, flavors, hints, sessionContext); + if (img instanceof ImageGraphics2D) { + ImageGraphics2D imageG2D = (ImageGraphics2D)img; + int width = (int)pos.getWidth(); + int height = (int)pos.getHeight(); + RendererContext context = createRendererContext( + x, y, width, height, foreignAttributes); + getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(), + context, x, y, width, height); + } else if (img instanceof ImageRendered) { + ImageRendered imgRend = (ImageRendered)img; + AffineTransform at = new AffineTransform(); + at.translate(x / 1000f, y / 1000f); + double sx = pos.getWidth() / info.getSize().getWidthMpt(); + double sy = pos.getHeight() / info.getSize().getHeightMpt(); + sx *= userAgent.getSourceResolution() / info.getSize().getDpiHorizontal(); + sy *= userAgent.getSourceResolution() / info.getSize().getDpiVertical(); + at.scale(sx, sy); + state.getGraph().drawRenderedImage(imgRend.getRenderedImage(), at); + } else if (img instanceof ImageXMLDOM) { + ImageXMLDOM imgXML = (ImageXMLDOM)img; + renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(), + pos, foreignAttributes); } - - byte[] raw = fopimage.getBitmaps(); - - // TODO Hardcoded color and sample models, FIX ME! - ColorModel cm = new ComponentColorModel( - ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB), - new int[] {8, 8, 8}, - false, false, - ColorModel.OPAQUE, DataBuffer.TYPE_BYTE); - SampleModel sampleModel = new PixelInterleavedSampleModel( - DataBuffer.TYPE_BYTE, w, h, 3, w * 3, new int[] {0, 1, 2}); - DataBuffer dbuf = new DataBufferByte(raw, w * h * 3); - - WritableRaster raster = Raster.createWritableRaster(sampleModel, - dbuf, null); - - java.awt.Image awtImage; - // Combine the color model and raster into a buffered image - awtImage = new BufferedImage(cm, raster, false, null); - - state.getGraph().drawImage(awtImage, - (int)(x / 1000f), (int)(y / 1000f), - (int)(pos.getWidth() / 1000f), (int)(pos.getHeight() / 1000f), null); + } catch (ImageException ie) { + log.error("Error while processing image: " + + (info != null ? info.toString() : uri), ie); + } catch (IOException ioe) { + log.error("I/O error while processing image: " + + (info != null ? info.toString() : uri), ioe); } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected RendererContext createRendererContext(int x, int y, int width, int height, Map foreignAttributes) { RendererContext context = super.createRendererContext( @@ -962,9 +941,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem return context; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException { if (pageIndex >= getNumberOfPages()) { @@ -1004,6 +981,10 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem //not necessary in Java2D } + /** + * Controls the page background. + * @param transparentPageBackground true if the background should be transparent + */ public void setTransparentPageBackground(boolean transparentPageBackground) { this.transparentPageBackground = transparentPageBackground; } diff --git a/src/java/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java b/src/java/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java index 80c010afc..06a4d37a0 100644 --- a/src/java/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java @@ -28,11 +28,13 @@ import java.io.IOException; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + import org.apache.fop.render.AbstractGraphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; import org.apache.fop.render.RendererContext; import org.apache.fop.util.UnitConv; -import org.apache.xmlgraphics.java2d.GraphicContext; /** * Graphics2DAdapter implementation for PCL and HP GL/2. @@ -110,7 +112,8 @@ public class PCLGraphics2DAdapter extends AbstractGraphics2DAdapter { if (!painted) { //Fallback solution: Paint to a BufferedImage int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); - BufferedImage bi = paintToBufferedImage(painter, pclContext, resolution, true, false); + BufferedImage bi = paintToBufferedImage(painter, pclContext, + resolution, !pclContext.isColorCanvas(), false); pcl.setCursorPos(x, y); gen.paintBitmap(bi, new Dimension(width, height), pclContext.isSourceTransparency()); diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 732ce0f8f..b48c28089 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -24,24 +24,17 @@ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; +import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; -import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.ComponentColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.PixelInterleavedSampleModel; -import java.awt.image.Raster; import java.awt.image.RenderedImage; -import java.awt.image.SampleModel; -import java.awt.image.WritableRaster; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.util.List; @@ -52,7 +45,19 @@ import org.w3c.dom.Document; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.MimeConstants; @@ -70,16 +75,12 @@ import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.Viewport; import org.apache.fop.area.inline.WordArea; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontMetrics; -import org.apache.fop.image.EPSImage; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.apache.fop.image.XMLImage; import org.apache.fop.render.Graphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; import org.apache.fop.render.PrintRenderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; @@ -134,6 +135,13 @@ public class PCLRenderer extends PrintRenderer { */ private boolean allTextAsBitmaps = false; + /** + * Controls whether an RGB canvas is used when converting Java2D graphics to bitmaps. + * This can be used to work around problems with Apache Batik, for example, but setting + * this to true will increase memory consumption. + */ + private boolean useColorCanvas = false; + /** * Controls whether the generation of PJL commands gets disabled. */ @@ -991,87 +999,88 @@ public class PCLRenderer extends PrintRenderer { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ + protected RendererContext createRendererContext(int x, int y, int width, int height, + Map foreignAttributes) { + RendererContext context = super.createRendererContext( + x, y, width, height, foreignAttributes); + context.setProperty(PCLRendererContextConstants.PCL_COLOR_CANVAS, + Boolean.valueOf(this.useColorCanvas)); + return context; + } + + /** {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { drawImage(image.getURL(), pos, image.getForeignAttributes()); } + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] + {ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE, + ImageFlavor.XML_DOM}; /** * Draw an image at the indicated location. - * @param url the URI/URL of the image + * @param uri the URI/URL of the image * @param pos the position of the image * @param foreignAttributes an optional Map with foreign attributes, may be null */ - protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) { - url = ImageFactory.getURL(url); - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage fopimage = fact.getImage(url, userAgent); - if (fopimage == null) { - return; - } - if (!fopimage.load(FopImage.DIMENSIONS)) { - return; - } - String mime = fopimage.getMimeType(); - if ("text/xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, foreignAttributes); - } else if ("image/svg+xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, foreignAttributes); - } else if (fopimage instanceof EPSImage) { - log.warn("EPS images are not supported by this renderer"); - } else { - if (!fopimage.load(FopImage.BITMAP)) { - log.error("Bitmap image could not be processed: " + fopimage); - return; - } - byte[] imgmap = fopimage.getBitmaps(); + protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { + uri = URISpecification.getURL(uri); + Rectangle posInt = new Rectangle( + (int)pos.getX(), + (int)pos.getY(), + (int)pos.getWidth(), + (int)pos.getHeight()); + Point origin = new Point(currentIPPosition, currentBPPosition); + int x = origin.x + posInt.x; + int y = origin.y + posInt.y; + + ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageInfo info = null; + try { + ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + info = manager.getImageInfo(uri, sessionContext); - ColorModel cm = new ComponentColorModel( - ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB), - new int[] {8, 8, 8}, - false, false, - ColorModel.OPAQUE, DataBuffer.TYPE_BYTE); - int imgw = fopimage.getWidth(); - int imgh = fopimage.getHeight(); - SampleModel sampleModel = new PixelInterleavedSampleModel( - DataBuffer.TYPE_BYTE, imgw, imgh, 3, imgw * 3, new int[] {0, 1, 2}); - DataBuffer dbuf = new DataBufferByte(imgmap, imgw * imgh * 3); - - WritableRaster raster = Raster.createWritableRaster(sampleModel, - dbuf, null); - - // Combine the color model and raster into a buffered image - RenderedImage img = new BufferedImage(cm, raster, false, null); - - try { - setCursorPos(this.currentIPPosition + (int)pos.getX(), - this.currentBPPosition + (int)pos.getY()); - gen.paintBitmap(img, - new Dimension((int)pos.getWidth(), (int)pos.getHeight()), + //Only now fully load/prepare the image + Map hints = ImageUtil.getDefaultHints(sessionContext); + org.apache.xmlgraphics.image.loader.Image img = manager.getImage( + info, FLAVORS, hints, sessionContext); + + //...and process the image + if (img instanceof ImageGraphics2D) { + ImageGraphics2D imageG2D = (ImageGraphics2D)img; + RendererContext context = createRendererContext( + posInt.x, posInt.y, + posInt.width, posInt.height, foreignAttributes); + getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(), + context, x, y, posInt.width, posInt.height); + } else if (img instanceof ImageRendered) { + ImageRendered imgRend = (ImageRendered)img; + RenderedImage ri = imgRend.getRenderedImage(); + setCursorPos(x, y); + gen.paintBitmap(ri, + new Dimension(posInt.width, posInt.height), false); - } catch (IOException ioe) { - handleIOTrouble(ioe); + } else if (img instanceof ImageXMLDOM) { + ImageXMLDOM imgXML = (ImageXMLDOM)img; + renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(), + pos, foreignAttributes); + } else { + throw new UnsupportedOperationException("Unsupported image type: " + img); } + + } catch (ImageException ie) { + log.error("Error while processing image: " + + (info != null ? info.toString() : uri), ie); + } catch (FileNotFoundException fe) { + log.error(fe.getMessage()); + } catch (IOException ioe) { + handleIOTrouble(ioe); } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { Document doc = fo.getDocument(); String ns = fo.getNameSpace(); @@ -1153,52 +1162,45 @@ public class PCLRenderer extends PrintRenderer { } // background image - if (back.getFopImage() != null) { - FopImage fopimage = back.getFopImage(); - if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) { - saveGraphicsState(); - clipRect(sx, sy, paddRectWidth, paddRectHeight); - int horzCount = (int) ((paddRectWidth * 1000 / fopimage - .getIntrinsicWidth()) + 1.0f); - int vertCount = (int) ((paddRectHeight * 1000 / fopimage - .getIntrinsicHeight()) + 1.0f); - if (back.getRepeat() == EN_NOREPEAT) { - horzCount = 1; - vertCount = 1; - } else if (back.getRepeat() == EN_REPEATX) { - vertCount = 1; - } else if (back.getRepeat() == EN_REPEATY) { - horzCount = 1; - } - // change from points to millipoints - sx *= 1000; - sy *= 1000; - if (horzCount == 1) { - sx += back.getHoriz(); - } - if (vertCount == 1) { - sy += back.getVertical(); - } - for (int x = 0; x < horzCount; x++) { - for (int y = 0; y < vertCount; y++) { - // place once - Rectangle2D pos; - // Image positions are relative to the currentIP/BP - pos = new Rectangle2D.Float( - sx - currentIPPosition - + (x * fopimage.getIntrinsicWidth()), - sy - currentBPPosition - + (y * fopimage.getIntrinsicHeight()), - fopimage.getIntrinsicWidth(), - fopimage.getIntrinsicHeight()); - drawImage(back.getURL(), pos, null); - } + if (back.getImageInfo() != null) { + ImageSize imageSize = back.getImageInfo().getSize(); + saveGraphicsState(); + clipRect(sx, sy, paddRectWidth, paddRectHeight); + int horzCount = (int) ((paddRectWidth * 1000 / imageSize.getWidthMpt()) + 1.0f); + int vertCount = (int) ((paddRectHeight * 1000 / imageSize.getHeightMpt()) + 1.0f); + if (back.getRepeat() == EN_NOREPEAT) { + horzCount = 1; + vertCount = 1; + } else if (back.getRepeat() == EN_REPEATX) { + vertCount = 1; + } else if (back.getRepeat() == EN_REPEATY) { + horzCount = 1; + } + // change from points to millipoints + sx *= 1000; + sy *= 1000; + if (horzCount == 1) { + sx += back.getHoriz(); + } + if (vertCount == 1) { + sy += back.getVertical(); + } + for (int x = 0; x < horzCount; x++) { + for (int y = 0; y < vertCount; y++) { + // place once + Rectangle2D pos; + // Image positions are relative to the currentIP/BP + pos = new Rectangle2D.Float( + sx - currentIPPosition + + (x * imageSize.getWidthMpt()), + sy - currentBPPosition + + (y * imageSize.getHeightMpt()), + imageSize.getWidthMpt(), + imageSize.getHeightMpt()); + drawImage(back.getURL(), pos, null); } - restoreGraphicsState(); - } else { - log.warn( - "Can't find background image: " + back.getURL()); } + restoreGraphicsState(); } } @@ -1508,6 +1510,11 @@ public class PCLRenderer extends PrintRenderer { } } + /** + * Controls whether all text should be generated as bitmaps or only text for which there's + * no native font. + * @param allTextAsBitmaps true if all text should be painted as bitmaps + */ public void setAllTextAsBitmaps(boolean allTextAsBitmaps) { this.allTextAsBitmaps = allTextAsBitmaps; } diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererContext.java b/src/java/org/apache/fop/render/pcl/PCLRendererContext.java index 32510137b..62d4bcaa4 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererContext.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererContext.java @@ -62,11 +62,28 @@ public class PCLRendererContext extends RendererContext.RendererContextWrapper { && "true".equalsIgnoreCase((String)getForeignAttributes().get(qName)); } + /** + * Indicates whether the background should not be erased prior to painting. + * @return true if the background shouldn't be erased + */ public boolean isSourceTransparency() { QName qName = new QName(ExtensionElementMapping.URI, null, "source-transparency"); return getForeignAttributes() != null && "true".equalsIgnoreCase((String)getForeignAttributes().get(qName)); } + /** + * Indicates whether an RGB canvas should be used rather than one with grayscales. + * This can be used to work around limitations of Apache Batik if you get error while + * processing SVG graphics. Note, however, that RGB mode will use more memory. + * @return true if an EGB canvas should be used + */ + public boolean isColorCanvas() { + QName qName = new QName(ExtensionElementMapping.URI, null, "color-canvas"); + Boolean prop = (Boolean)context.getProperty(PCLRendererContextConstants.PCL_COLOR_CANVAS); + return Boolean.TRUE.equals(prop) + || (getForeignAttributes() != null + && "true".equalsIgnoreCase((String)getForeignAttributes().get(qName))); + } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererContextConstants.java b/src/java/org/apache/fop/render/pcl/PCLRendererContextConstants.java new file mode 100644 index 000000000..66ce40f5e --- /dev/null +++ b/src/java/org/apache/fop/render/pcl/PCLRendererContextConstants.java @@ -0,0 +1,32 @@ +/* + * 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.render.pcl; + +import org.apache.fop.render.RendererContextConstants; + +/** + * Defines a number of standard constants (keys) for use by the RendererContext class. + */ +public interface PCLRendererContextConstants extends RendererContextConstants { + + /** The PDF document that this image is being drawn into. */ + String PCL_COLOR_CANVAS = "color-canvas"; + +} diff --git a/src/java/org/apache/fop/render/pcl/PCLSVGHandler.java b/src/java/org/apache/fop/render/pcl/PCLSVGHandler.java index 8c9179063..a016c692f 100644 --- a/src/java/org/apache/fop/render/pcl/PCLSVGHandler.java +++ b/src/java/org/apache/fop/render/pcl/PCLSVGHandler.java @@ -22,6 +22,7 @@ package org.apache.fop.render.pcl; // FOP import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererContext; /** * PCL XML handler for SVG. Uses Apache Batik for SVG processing. @@ -36,5 +37,12 @@ public class PCLSVGHandler extends AbstractGenericSVGHandler { return (renderer instanceof PCLRenderer); } + /** {@inheritDoc} */ + protected void updateRendererContext(RendererContext context) { + //Work around a problem in Batik: Gradients cannot be done in ColorSpace.CS_GRAY + context.setProperty(PCLRendererContextConstants.PCL_COLOR_CANVAS, + Boolean.TRUE); + } + } diff --git a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java new file mode 100644 index 000000000..cd80a6797 --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java @@ -0,0 +1,200 @@ +/* + * 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.render.pdf; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.Image; + +import org.apache.fop.pdf.PDFColor; +import org.apache.fop.pdf.PDFConformanceException; +import org.apache.fop.pdf.PDFDeviceColorSpace; +import org.apache.fop.pdf.PDFDictionary; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFICCBasedColorSpace; +import org.apache.fop.pdf.PDFICCStream; +import org.apache.fop.pdf.PDFImage; +import org.apache.fop.pdf.PDFReference; +import org.apache.fop.util.ColorProfileUtil; + +/** + * Abstract PDFImage implementation for the PDF renderer. + */ +public abstract class AbstractImageAdapter implements PDFImage { + + /** logging instance */ + private static Log log = LogFactory.getLog(AbstractImageAdapter.class); + + private String key; + /** the image */ + protected Image image; + + private PDFICCStream pdfICCStream = null; + + /** + * Creates a new PDFImage from an Image instance. + * @param image the image + * @param key XObject key + */ + public AbstractImageAdapter(Image image, String key) { + this.image = image; + this.key = key; + } + + /** {@inheritDoc} */ + public String getKey() { + // key to look up XObject + return this.key; + } + + /** + * Returns the image's color space. + * @return the color space + */ + protected ColorSpace getImageColorSpace() { + return image.getColorSpace(); + } + + /** {@inheritDoc} */ + public void setup(PDFDocument doc) { + + ICC_Profile prof = image.getICCProfile(); + PDFDeviceColorSpace pdfCS = toPDFColorSpace(getImageColorSpace()); + if (prof != null) { + boolean defaultsRGB = ColorProfileUtil.isDefaultsRGB(prof); + String desc = ColorProfileUtil.getICCProfileDescription(prof); + if (log.isDebugEnabled()) { + log.debug("Image returns ICC profile: " + desc + ", default sRGB=" + defaultsRGB); + } + PDFICCBasedColorSpace cs = doc.getResources().getICCColorSpaceByProfileName(desc); + if (!defaultsRGB) { + if (cs == null) { + pdfICCStream = doc.getFactory().makePDFICCStream(); + pdfICCStream.setColorSpace(prof, pdfCS); + cs = doc.getFactory().makeICCBasedColorSpace(null, null, pdfICCStream); + } else { + pdfICCStream = cs.getICCStream(); + } + } else { + if (cs == null && "sRGB".equals(desc)) { + //It's the default sRGB profile which we mapped to DefaultRGB in PDFRenderer + cs = doc.getResources().getColorSpace("DefaultRGB"); + } + pdfICCStream = cs.getICCStream(); + } + } + if (doc.getProfile().getPDFAMode().isPDFA1LevelB()) { + if (pdfCS != null + && pdfCS.getColorSpace() != PDFDeviceColorSpace.DEVICE_RGB + && pdfCS.getColorSpace() != PDFDeviceColorSpace.DEVICE_GRAY + && prof == null) { + //See PDF/A-1, ISO 19005:1:2005(E), 6.2.3.3 + //FOP is currently restricted to DeviceRGB if PDF/A-1 is active. + throw new PDFConformanceException( + "PDF/A-1 does not allow mixing DeviceRGB and DeviceCMYK: " + + image.getInfo()); + } + } + } + + /** {@inheritDoc} */ + public int getWidth() { + return image.getSize().getWidthPx(); + } + + /** {@inheritDoc} */ + public int getHeight() { + return image.getSize().getHeightPx(); + } + + /** {@inheritDoc} */ + public boolean isTransparent() { + return false; + } + + /** {@inheritDoc} */ + public PDFColor getTransparentColor() { + return null; + } + + /** {@inheritDoc} */ + public String getMask() { + return null; + } + + /** {@inheritDoc} */ + public String getSoftMask() { + return null; + } + + /** {@inheritDoc} */ + public PDFReference getSoftMaskReference() { + return null; + } + + /** {@inheritDoc} */ + public boolean isInverted() { + return false; + } + + /** {@inheritDoc} */ + public boolean isPS() { + return false; + } + + /** {@inheritDoc} */ + public PDFICCStream getICCStream() { + return pdfICCStream; + } + + /** {@inheritDoc} */ + public void populateXObjectDictionary(PDFDictionary dict) { + //nop + } + + /** + * Converts a ColorSpace object to a PDFColorSpace object. + * @param cs ColorSpace instance + * @return PDFColorSpace new converted object + */ + public static PDFDeviceColorSpace toPDFColorSpace(ColorSpace cs) { + if (cs == null) { + return null; + } + + PDFDeviceColorSpace pdfCS = new PDFDeviceColorSpace(0); + switch (cs.getType()) { + case ColorSpace.TYPE_CMYK: + pdfCS.setColorSpace(PDFDeviceColorSpace.DEVICE_CMYK); + break; + case ColorSpace.TYPE_GRAY: + pdfCS.setColorSpace(PDFDeviceColorSpace.DEVICE_GRAY); + break; + default: + pdfCS.setColorSpace(PDFDeviceColorSpace.DEVICE_RGB); + } + return pdfCS; + } + +} + diff --git a/src/java/org/apache/fop/render/pdf/FopPDFImage.java b/src/java/org/apache/fop/render/pdf/FopPDFImage.java deleted file mode 100644 index e60c207d6..000000000 --- a/src/java/org/apache/fop/render/pdf/FopPDFImage.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.pdf; -import java.awt.color.ColorSpace; -import java.awt.color.ICC_Profile; -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.fop.image.EPSImage; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.TIFFImage; -import org.apache.fop.pdf.BitmapImage; -import org.apache.fop.pdf.CCFFilter; -import org.apache.fop.pdf.DCTFilter; -import org.apache.fop.pdf.PDFColor; -import org.apache.fop.pdf.PDFConformanceException; -import org.apache.fop.pdf.PDFDeviceColorSpace; -import org.apache.fop.pdf.PDFDictionary; -import org.apache.fop.pdf.PDFDocument; -import org.apache.fop.pdf.PDFFilter; -import org.apache.fop.pdf.PDFFilterList; -import org.apache.fop.pdf.PDFICCBasedColorSpace; -import org.apache.fop.pdf.PDFICCStream; -import org.apache.fop.pdf.PDFImage; -import org.apache.fop.pdf.PDFReference; -import org.apache.fop.util.ColorProfileUtil; - -/** - * PDFImage implementation for the PDF renderer. - */ -public class FopPDFImage implements PDFImage { - - /** logging instance */ - private static Log log = LogFactory.getLog(FopPDFImage.class); - - private FopImage fopImage; - private PDFICCStream pdfICCStream = null; - private PDFFilter pdfFilter = null; - private String maskRef; - private PDFReference softMask; - private boolean isPS = false; - private boolean isCCF = false; - private boolean isDCT = false; - private String key; - - /** - * Creates a new PDFImage from a FopImage - * @param image Image - * @param key XObject key - */ - public FopPDFImage(FopImage image, String key) { - fopImage = image; - this.key = key; - isPS = (fopImage instanceof EPSImage); - } - - /** - * {@inheritDoc} - */ - public String getKey() { - // key to look up XObject - return this.key; - } - - /** - * {@inheritDoc} - */ - public void setup(PDFDocument doc) { - if ("image/jpeg".equals(fopImage.getMimeType())) { - pdfFilter = new DCTFilter(); - pdfFilter.setApplied(true); - isDCT = true; - - } else if ("image/tiff".equals(fopImage.getMimeType()) - && fopImage instanceof TIFFImage) { - TIFFImage tiffImage = (TIFFImage) fopImage; - if (tiffImage.getStripCount() == 1) { - int comp = tiffImage.getCompression(); - if (comp == 1) { - // Nothing to do - } else if (comp == 3) { - pdfFilter = new CCFFilter(); - pdfFilter.setApplied(true); - isCCF = true; - } else if (comp == 4) { - pdfFilter = new CCFFilter(); - pdfFilter.setApplied(true); - PDFDictionary dict = new PDFDictionary(); - dict.put("K", -1); - dict.put("Columns", tiffImage.getWidth()); - ((CCFFilter)pdfFilter).setDecodeParms(dict); - isCCF = true; - } else if (comp == 6) { - pdfFilter = new DCTFilter(); - pdfFilter.setApplied(true); - isDCT = true; - } - } - } - if (isPS || isDCT || isCCF) { - fopImage.load(FopImage.ORIGINAL_DATA); - } else { - fopImage.load(FopImage.BITMAP); - } - ICC_Profile prof = fopImage.getICCProfile(); - PDFDeviceColorSpace pdfCS = toPDFColorSpace(fopImage.getColorSpace()); - if (prof != null) { - boolean defaultsRGB = ColorProfileUtil.isDefaultsRGB(prof); - String desc = ColorProfileUtil.getICCProfileDescription(prof); - if (log.isDebugEnabled()) { - log.debug("Image returns ICC profile: " + desc + ", default sRGB=" + defaultsRGB); - } - PDFICCBasedColorSpace cs = doc.getResources().getICCColorSpaceByProfileName(desc); - if (!defaultsRGB) { - if (cs == null) { - pdfICCStream = doc.getFactory().makePDFICCStream(); - pdfICCStream.setColorSpace(prof, pdfCS); - cs = doc.getFactory().makeICCBasedColorSpace(null, null, pdfICCStream); - } else { - pdfICCStream = cs.getICCStream(); - } - } else { - if (cs == null && "sRGB".equals(desc)) { - //It's the default sRGB profile which we mapped to DefaultRGB in PDFRenderer - cs = doc.getResources().getColorSpace("DefaultRGB"); - } - pdfICCStream = cs.getICCStream(); - } - } - //Handle transparency mask if applicable - if (fopImage.hasSoftMask()) { - doc.getProfile().verifyTransparencyAllowed(fopImage.getOriginalURI()); - //TODO Implement code to combine image with background color if transparency is not - //allowed (need BufferedImage support for that) - byte [] softMaskBitmap = fopImage.getSoftMask(); - if (softMaskBitmap == null) { - return; - } - BitmapImage fopimg = new BitmapImage - ("Mask:" + key, fopImage.getWidth(), fopImage.getHeight(), - softMaskBitmap, null); - fopimg.setColorSpace(new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_GRAY)); - softMask = doc.addImage(null, fopimg).makeReference(); - } - if (doc.getProfile().getPDFAMode().isPDFA1LevelB()) { - if (pdfCS != null - && pdfCS.getColorSpace() != PDFDeviceColorSpace.DEVICE_RGB - && pdfCS.getColorSpace() != PDFDeviceColorSpace.DEVICE_GRAY - && prof == null) { - //See PDF/A-1, ISO 19005:1:2005(E), 6.2.3.3 - //FOP is currently restricted to DeviceRGB if PDF/A-1 is active. - throw new PDFConformanceException( - "PDF/A-1 does not allow mixing DeviceRGB and DeviceCMYK: " - + fopImage.getOriginalURI()); - } - } - } - - /** - * {@inheritDoc} - */ - public int getWidth() { - return fopImage.getWidth(); - } - - /** - * {@inheritDoc} - */ - public int getHeight() { - return fopImage.getHeight(); - } - - /** - * {@inheritDoc} - */ - public PDFDeviceColorSpace getColorSpace() { - // DeviceGray, DeviceRGB, or DeviceCMYK - if (isCCF || isDCT || isPS) { - return toPDFColorSpace(fopImage.getColorSpace()); - } else { - return toPDFColorSpace(ColorSpace.getInstance(ColorSpace.CS_sRGB)); - } - } - - /** - * {@inheritDoc} - */ - public int getBitsPerPixel() { - if (isCCF) { - return fopImage.getBitsPerPixel(); - } else { - return 8; //TODO This is suboptimal, handling everything as RGB - //The image wrappers can mostly only return RGB bitmaps right now. This should - //be improved so the renderers can deal directly with RenderedImage instances. - } - } - - /** - * {@inheritDoc} - */ - public boolean isTransparent() { - return fopImage.isTransparent(); - } - - /** - * {@inheritDoc} - */ - public PDFColor getTransparentColor() { - return new PDFColor(fopImage.getTransparentColor().getRed(), - fopImage.getTransparentColor().getGreen(), - fopImage.getTransparentColor().getBlue()); - } - - /** - * {@inheritDoc} - */ - public String getMask() { - return maskRef; - } - - /** {@inheritDoc} */ - public PDFReference getSoftMaskReference() { - return softMask; - } - - /** @return true for CMYK images generated by Adobe Photoshop */ - public boolean isInverted() { - return fopImage.isInverted(); - } - - /** - * {@inheritDoc} - */ - public boolean isPS() { - return isPS; - } - - /** - * {@inheritDoc} - */ - public PDFFilter getPDFFilter() { - return pdfFilter; - } - - /** - * {@inheritDoc} - */ - public void outputContents(OutputStream out) throws IOException { - if (isPS) { - outputPostScriptContents(out); - } else { - if (fopImage.getBitmapsSize() > 0) { - out.write(fopImage.getBitmaps()); - } else { - out.write(fopImage.getRessourceBytes()); - } - } - } - - /** - * Serializes an EPS image to an OutputStream. - * @param out OutputStream to write to - * @throws IOException in case of an I/O problem - */ - protected void outputPostScriptContents(OutputStream out) throws IOException { - EPSImage epsImage = (EPSImage) fopImage; - int[] bbox = epsImage.getBBox(); - int bboxw = bbox[2] - bbox[0]; - int bboxh = bbox[3] - bbox[1]; - - // delegate the stream work to PDFStream - //PDFStream imgStream = new PDFStream(0); - - StringBuffer preamble = new StringBuffer(); - preamble.append("%%BeginDocument: " + epsImage.getDocName() + "\n"); - - preamble.append("userdict begin % Push userdict on dict stack\n"); - preamble.append("/PreEPS_state save def\n"); - preamble.append("/dict_stack countdictstack def\n"); - preamble.append("/ops_count count 1 sub def\n"); - preamble.append("/showpage {} def\n"); - - - preamble.append((double)(1f / (double) bboxw) + " " - + (double)(1f / (double) bboxh) + " scale\n"); - preamble.append(-bbox[0] + " " + (-bbox[1]) + " translate\n"); - preamble.append(bbox[0] + " " + bbox[1] + " " - + bboxw + " " + bboxh + " rectclip\n"); - preamble.append("newpath\n"); - - StringBuffer post = new StringBuffer(); - post.append("%%EndDocument\n"); - post.append("count ops_count sub {pop} repeat\n"); - post.append("countdictstack dict_stack sub {end} repeat\n"); - post.append("PreEPS_state restore\n"); - post.append("end % userdict\n"); - - //Write Preamble - out.write(PDFDocument.encode(preamble.toString())); - //Write EPS contents - out.write(((EPSImage)fopImage).getEPSImage()); - //Writing trailer - out.write(PDFDocument.encode(post.toString())); - } - - /** - * {@inheritDoc} - */ - public PDFICCStream getICCStream() { - return pdfICCStream; - } - - /** - * Converts a ColorSpace object to a PDFColorSpace object. - * @param cs ColorSpace instance - * @return PDFColorSpace new converted object - */ - public static PDFDeviceColorSpace toPDFColorSpace(ColorSpace cs) { - if (cs == null) { - return null; - } - - PDFDeviceColorSpace pdfCS = new PDFDeviceColorSpace(0); - switch(cs.getType()) { - case ColorSpace.TYPE_CMYK: - pdfCS.setColorSpace(PDFDeviceColorSpace.DEVICE_CMYK); - break; - case ColorSpace.TYPE_RGB: - pdfCS.setColorSpace(PDFDeviceColorSpace.DEVICE_RGB); - break; - case ColorSpace.TYPE_GRAY: - pdfCS.setColorSpace(PDFDeviceColorSpace.DEVICE_GRAY); - break; - } - return pdfCS; - } - - /** - * {@inheritDoc} - */ - public String getFilterHint() { - if (isPS) { - return PDFFilterList.CONTENT_FILTER; - } else if (isDCT) { - return PDFFilterList.JPEG_FILTER; - } else if (isCCF) { - return PDFFilterList.TIFF_FILTER; - } else { - return PDFFilterList.IMAGE_FILTER; - } - } - -} - diff --git a/src/java/org/apache/fop/render/pdf/ImageRawCCITTFaxAdapter.java b/src/java/org/apache/fop/render/pdf/ImageRawCCITTFaxAdapter.java new file mode 100644 index 000000000..b80e2c03e --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/ImageRawCCITTFaxAdapter.java @@ -0,0 +1,110 @@ +/* + * 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.render.pdf; +import java.awt.color.ColorSpace; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; + +import org.apache.fop.pdf.CCFFilter; +import org.apache.fop.pdf.PDFDeviceColorSpace; +import org.apache.fop.pdf.PDFDictionary; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFFilter; +import org.apache.fop.pdf.PDFFilterList; + +/** + * PDFImage implementation for the PDF renderer which handles raw CCITT fax images. + */ +public class ImageRawCCITTFaxAdapter extends AbstractImageAdapter { + + private PDFFilter pdfFilter = null; + + /** + * Creates a new PDFImage from an Image instance. + * @param image the CCITT encoded image + * @param key XObject key + */ + public ImageRawCCITTFaxAdapter(ImageRawCCITTFax image, String key) { + super(image, key); + } + + /** + * Returns the {@link ImageRawCCITTFax} instance for this adapter. + * @return the image instance + */ + public ImageRawCCITTFax getImage() { + return ((ImageRawCCITTFax)this.image); + } + + /** {@inheritDoc} */ + public void setup(PDFDocument doc) { + pdfFilter = new CCFFilter(); + pdfFilter.setApplied(true); + PDFDictionary dict = new PDFDictionary(); + dict.put("Columns", this.image.getSize().getWidthPx()); + int compression = getImage().getCompression(); + switch (compression) { + case TIFFImage.COMP_FAX_G3_1D : + dict.put("K", 0); + break; + case TIFFImage.COMP_FAX_G3_2D : + dict.put("K", 1); + break; + case TIFFImage.COMP_FAX_G4_2D : + dict.put("K", -1); + break; + default: + throw new IllegalStateException("Invalid compression scheme: " + compression); + } + ((CCFFilter)pdfFilter).setDecodeParms(dict); + + super.setup(doc); + } + + /** {@inheritDoc} */ + public PDFDeviceColorSpace getColorSpace() { + return toPDFColorSpace(ColorSpace.getInstance(ColorSpace.CS_GRAY)); + } + + /** {@inheritDoc} */ + public int getBitsPerComponent() { + return 1; + } + + /** {@inheritDoc} */ + public PDFFilter getPDFFilter() { + return pdfFilter; + } + + /** {@inheritDoc} */ + public void outputContents(OutputStream out) throws IOException { + getImage().writeTo(out); + } + + /** {@inheritDoc} */ + public String getFilterHint() { + return PDFFilterList.TIFF_FILTER; + } + +} + diff --git a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java new file mode 100644 index 000000000..4b0ce4a85 --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java @@ -0,0 +1,96 @@ +/* + * 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.render.pdf; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; + +import org.apache.fop.pdf.DCTFilter; +import org.apache.fop.pdf.PDFDeviceColorSpace; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFFilter; +import org.apache.fop.pdf.PDFFilterList; + +/** + * PDFImage implementation for the PDF renderer which handles raw JPEG images. + */ +public class ImageRawJPEGAdapter extends AbstractImageAdapter { + + private PDFFilter pdfFilter = null; + + /** + * Creates a new PDFImage from an Image instance. + * @param image the JPEG image + * @param key XObject key + */ + public ImageRawJPEGAdapter(ImageRawJPEG image, String key) { + super(image, key); + } + + /** + * Returns the {@link ImageRawJPEG} instance for this adapter. + * @return the image instance + */ + public ImageRawJPEG getImage() { + return ((ImageRawJPEG)this.image); + } + + /** {@inheritDoc} */ + public void setup(PDFDocument doc) { + pdfFilter = new DCTFilter(); + pdfFilter.setApplied(true); + + super.setup(doc); + } + + /** {@inheritDoc} */ + public PDFDeviceColorSpace getColorSpace() { + // DeviceGray, DeviceRGB, or DeviceCMYK + return toPDFColorSpace(getImageColorSpace()); + } + + /** {@inheritDoc} */ + public int getBitsPerComponent() { + return 8; + } + + /** @return true for CMYK images generated by Adobe Photoshop */ + public boolean isInverted() { + return getImage().isInverted(); + } + + /** {@inheritDoc} */ + public PDFFilter getPDFFilter() { + return pdfFilter; + } + + /** {@inheritDoc} */ + public void outputContents(OutputStream out) throws IOException { + getImage().writeTo(out); + } + + /** {@inheritDoc} */ + public String getFilterHint() { + return PDFFilterList.JPEG_FILTER; + } + +} + diff --git a/src/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java b/src/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java new file mode 100644 index 000000000..62e83da81 --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java @@ -0,0 +1,249 @@ +/* + * 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.render.pdf; +import java.awt.color.ColorSpace; +import java.awt.image.ColorModel; +import java.awt.image.IndexColorModel; +import java.awt.image.RenderedImage; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.ps.ImageEncodingHelper; + +import org.apache.fop.pdf.AlphaRasterImage; +import org.apache.fop.pdf.PDFArray; +import org.apache.fop.pdf.PDFColor; +import org.apache.fop.pdf.PDFDeviceColorSpace; +import org.apache.fop.pdf.PDFDictionary; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFFilter; +import org.apache.fop.pdf.PDFFilterList; +import org.apache.fop.pdf.PDFName; +import org.apache.fop.pdf.PDFReference; + +/** + * PDFImage implementation for the PDF renderer which handles RenderedImages. + */ +public class ImageRenderedAdapter extends AbstractImageAdapter { + + /** logging instance */ + private static Log log = LogFactory.getLog(ImageRenderedAdapter.class); + + private ImageEncodingHelper encodingHelper; + + private PDFFilter pdfFilter = null; + private String maskRef; + private PDFReference softMask; + + /** + * Creates a new PDFImage from an Image instance. + * @param image the image + * @param key XObject key + */ + public ImageRenderedAdapter(ImageRendered image, String key) { + super(image, key); + this.encodingHelper = new ImageEncodingHelper(image.getRenderedImage()); + } + + /** + * Returns the ImageRendered instance for this adapter. + * @return the ImageRendered instance + */ + public ImageRendered getImage() { + return ((ImageRendered)this.image); + } + + private ColorModel getEffectiveColorModel() { + return encodingHelper.getEncodedColorModel(); + } + + /** {@inheritDoc} */ + protected ColorSpace getImageColorSpace() { + return getEffectiveColorModel().getColorSpace(); + } + + /** {@inheritDoc} */ + public void setup(PDFDocument doc) { + RenderedImage ri = getImage().getRenderedImage(); + ColorModel cm = getEffectiveColorModel(); + + super.setup(doc); + + //Handle transparency mask if applicable + ColorModel orgcm = ri.getColorModel(); + if (orgcm.hasAlpha() && orgcm.getTransparency() == ColorModel.TRANSLUCENT) { + doc.getProfile().verifyTransparencyAllowed(image.getInfo().getOriginalURI()); + //TODO Implement code to combine image with background color if transparency is not + //allowed (need BufferedImage support for that) + + AlphaRasterImage alphaImage = new AlphaRasterImage("Mask:" + getKey(), ri); + this.softMask = doc.addImage(null, alphaImage).makeReference(); + } + } + + /** {@inheritDoc} */ + public PDFDeviceColorSpace getColorSpace() { + // DeviceGray, DeviceRGB, or DeviceCMYK + return toPDFColorSpace(getEffectiveColorModel().getColorSpace()); + } + + /** {@inheritDoc} */ + public int getBitsPerComponent() { + ColorModel cm = getEffectiveColorModel(); + if (cm instanceof IndexColorModel) { + IndexColorModel icm = (IndexColorModel)cm; + return icm.getComponentSize(0); + } else { + return cm.getComponentSize(0); + } + } + + /** {@inheritDoc} */ + public boolean isTransparent() { + ColorModel cm = getEffectiveColorModel(); + if (cm instanceof IndexColorModel) { + if (cm.getTransparency() == IndexColorModel.TRANSLUCENT) { + return true; + } + } + return (getImage().getTransparentColor() != null); + } + + private static Integer getIndexOfFirstTransparentColorInPalette(RenderedImage image) { + ColorModel cm = image.getColorModel(); + if (cm instanceof IndexColorModel) { + IndexColorModel icm = (IndexColorModel)cm; + //Identify the transparent color in the palette + byte[] alphas = new byte[icm.getMapSize()]; + byte[] reds = new byte[icm.getMapSize()]; + byte[] greens = new byte[icm.getMapSize()]; + byte[] blues = new byte[icm.getMapSize()]; + icm.getAlphas(alphas); + icm.getReds(reds); + icm.getGreens(greens); + icm.getBlues(blues); + for (int i = 0; + i < ((IndexColorModel) cm).getMapSize(); + i++) { + if ((alphas[i] & 0xFF) == 0) { + return new Integer(i); + } + } + } + return null; + } + + /** {@inheritDoc} */ + public PDFColor getTransparentColor() { + ColorModel cm = getEffectiveColorModel(); + if (cm instanceof IndexColorModel) { + IndexColorModel icm = (IndexColorModel)cm; + if (cm.getTransparency() == IndexColorModel.TRANSLUCENT) { + int transPixel = icm.getTransparentPixel(); + return new PDFColor( + icm.getRed(transPixel), + icm.getGreen(transPixel), + icm.getBlue(transPixel)); + } + } + return new PDFColor(getImage().getTransparentColor()); + } + + /** {@inheritDoc} */ + public String getMask() { + return maskRef; + } + + /** {@inheritDoc} */ + public PDFReference getSoftMaskReference() { + return softMask; + } + + /** {@inheritDoc} */ + public PDFFilter getPDFFilter() { + return pdfFilter; + } + + /** {@inheritDoc} */ + public void outputContents(OutputStream out) throws IOException { + encodingHelper.encode(out); + } + + private static final int MAX_HIVAL = 255; + + /** {@inheritDoc} */ + public void populateXObjectDictionary(PDFDictionary dict) { + ColorModel cm = getEffectiveColorModel(); + if (cm instanceof IndexColorModel) { + IndexColorModel icm = (IndexColorModel)cm; + PDFArray indexed = new PDFArray(dict); + indexed.add(new PDFName("Indexed")); + + if (icm.getColorSpace().getType() != ColorSpace.TYPE_RGB) { + log.warn("Indexed color space is not using RGB as base color space." + + " The image may not be handled correctly." + + " Base color space: " + icm.getColorSpace() + + " Image: " + image.getInfo()); + } + indexed.add(new PDFName(toPDFColorSpace(icm.getColorSpace()).getName())); + int c = icm.getMapSize(); + int hival = c - 1; + if (hival > MAX_HIVAL) { + throw new UnsupportedOperationException("hival must not go beyond " + MAX_HIVAL); + } + indexed.add(new Integer(hival)); + int[] palette = new int[c]; + icm.getRGBs(palette); + ByteArrayOutputStream baout = new ByteArrayOutputStream(); + for (int i = 0; i < c; i++) { + //TODO Probably doesn't work for non RGB based color spaces + //See log warning above + int entry = palette[i]; + baout.write((entry & 0xFF0000) >> 16); + baout.write((entry & 0xFF00) >> 8); + baout.write(entry & 0xFF); + } + indexed.add(baout.toByteArray()); + + dict.put("ColorSpace", indexed); + dict.put("BitsPerComponent", icm.getPixelSize()); + + Integer index = getIndexOfFirstTransparentColorInPalette(getImage().getRenderedImage()); + if (index != null) { + PDFArray mask = new PDFArray(dict); + mask.add(index); + mask.add(index); + dict.put("Mask", mask); + } + } + } + + /** {@inheritDoc} */ + public String getFilterHint() { + return PDFFilterList.IMAGE_FILTER; + } + +} + diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java index eb0e4b378..d1e0abd5c 100644 --- a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java @@ -28,8 +28,9 @@ import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + import org.apache.fop.render.AbstractGraphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContext.RendererContextWrapper; import org.apache.fop.svg.PDFGraphics2D; diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandler.java b/src/java/org/apache/fop/render/pdf/PDFImageHandler.java index 52043b38e..d62dcbc5b 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandler.java @@ -19,11 +19,15 @@ package org.apache.fop.render.pdf; +import java.awt.Point; +import java.awt.Rectangle; import java.io.IOException; -import org.apache.fop.image.FopImage; -import org.apache.fop.pdf.PDFDocument; +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; + import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.RendererContext; /** * This interface is used for handling all sorts of image type for PDF output. @@ -31,20 +35,38 @@ import org.apache.fop.pdf.PDFXObject; public interface PDFImageHandler { /** - * Returns the MIME type supported by this instance. - * @return the MIME type + * Returns the priority for this image handler. A lower value means higher priority. This + * information is used to build the ordered/prioritized list of supported ImageFlavors for + * the PDF renderer. The built-in handlers use priorities between 100 and 999. + * @return a positive integer (>0) indicating the priority + */ + int getPriority(); + + /** + * Returns the {@link ImageFlavor}s supported by this instance + * @return the supported image flavors + */ + ImageFlavor[] getSupportedImageFlavors(); + + /** + * Returns the {@link Image} subclass supported by this instance. + * @return the Image type */ - String getSupportedMimeType(); + Class getSupportedImageClass(); /** - * Generates the PDF objects for the given FopImage instance and returns - * the resulting XObject. + * Generates the PDF objects for the given {@link Image} instance. If the handler generates + * an XObject, it shall return it or otherwise return null. A generated XObject shall be + * placed in the current viewport according to the two parameters "origin" and "pos". + * @param context the PDF renderer context * @param image the image to be handled - * @param uri the URI of the image - * @param pdfDoc the target PDF document - * @return the generated XObject + * @param origin the current position in the current viewport (in millipoints) + * @param pos the position and scaling of the image relative to the origin point + * (in millipoints) + * @return the generated XObject or null if no XObject was generated * @throws IOException if an I/O error occurs */ - PDFXObject generateImage(FopImage image, String uri, PDFDocument pdfDoc) throws IOException; + PDFXObject generateImage(RendererContext context, Image image, + Point origin, Rectangle pos) throws IOException; } diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java new file mode 100644 index 000000000..f1825297e --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java @@ -0,0 +1,68 @@ +/* + * 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.render.pdf; + +import java.awt.Point; +import java.awt.Rectangle; +import java.io.IOException; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; + +import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.RendererContext; + +/** + * PDFImageHandler implementation which handles Graphics2D images. + */ +public class PDFImageHandlerGraphics2D implements PDFImageHandler { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.GRAPHICS2D, + }; + + /** {@inheritDoc} */ + public PDFXObject generateImage(RendererContext context, Image image, + Point origin, Rectangle pos) + throws IOException { + PDFRenderer renderer = (PDFRenderer)context.getRenderer(); + ImageGraphics2D imageG2D = (ImageGraphics2D)image; + renderer.getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(), + context, origin.x + pos.x, origin.y + pos.y, pos.width, pos.height); + return null; + } + + /** {@inheritDoc} */ + public int getPriority() { + return 200; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageGraphics2D.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + +} diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java new file mode 100644 index 000000000..65142878a --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java @@ -0,0 +1,83 @@ +/* + * 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.render.pdf; + +import java.awt.Point; +import java.awt.Rectangle; +import java.io.IOException; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; + +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFImage; +import org.apache.fop.pdf.PDFResourceContext; +import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.RendererContext; + +/** + * PDFImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4). + */ +public class PDFImageHandlerRawCCITTFax implements PDFImageHandler { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.RAW_CCITTFAX, + }; + + /** {@inheritDoc} */ + public PDFXObject generateImage(RendererContext context, Image image, + Point origin, Rectangle pos) + throws IOException { + PDFRenderer renderer = (PDFRenderer)context.getRenderer(); + ImageRawCCITTFax ccitt = (ImageRawCCITTFax)image; + PDFDocument pdfDoc = (PDFDocument)context.getProperty( + PDFRendererContextConstants.PDF_DOCUMENT); + PDFResourceContext resContext = (PDFResourceContext)context.getProperty( + PDFRendererContextConstants.PDF_CONTEXT); + + PDFImage pdfimage = new ImageRawCCITTFaxAdapter(ccitt, image.getInfo().getOriginalURI()); + PDFXObject xobj = pdfDoc.addImage(resContext, pdfimage); + + float x = (float)pos.getX() / 1000f; + float y = (float)pos.getY() / 1000f; + float w = (float)pos.getWidth() / 1000f; + float h = (float)pos.getHeight() / 1000f; + renderer.placeImage(x, y, w, h, xobj); + + return xobj; + } + + /** {@inheritDoc} */ + public int getPriority() { + return 100; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageRawCCITTFax.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + +} diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java new file mode 100644 index 000000000..58c9f1f53 --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java @@ -0,0 +1,83 @@ +/* + * 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.render.pdf; + +import java.awt.Point; +import java.awt.Rectangle; +import java.io.IOException; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; + +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFImage; +import org.apache.fop.pdf.PDFResourceContext; +import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.RendererContext; + +/** + * PDFImageHandler implementation which handles raw JPEG images. + */ +public class PDFImageHandlerRawJPEG implements PDFImageHandler { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.RAW_JPEG, + }; + + /** {@inheritDoc} */ + public PDFXObject generateImage(RendererContext context, Image image, + Point origin, Rectangle pos) + throws IOException { + PDFRenderer renderer = (PDFRenderer)context.getRenderer(); + ImageRawJPEG jpeg = (ImageRawJPEG)image; + PDFDocument pdfDoc = (PDFDocument)context.getProperty( + PDFRendererContextConstants.PDF_DOCUMENT); + PDFResourceContext resContext = (PDFResourceContext)context.getProperty( + PDFRendererContextConstants.PDF_CONTEXT); + + PDFImage pdfimage = new ImageRawJPEGAdapter(jpeg, image.getInfo().getOriginalURI()); + PDFXObject xobj = pdfDoc.addImage(resContext, pdfimage); + + float x = (float)pos.getX() / 1000f; + float y = (float)pos.getY() / 1000f; + float w = (float)pos.getWidth() / 1000f; + float h = (float)pos.getHeight() / 1000f; + renderer.placeImage(x, y, w, h, xobj); + + return xobj; + } + + /** {@inheritDoc} */ + public int getPriority() { + return 100; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageRawJPEG.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + +} diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java index 36e4ea7e1..536fc19b0 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java @@ -19,11 +19,17 @@ package org.apache.fop.render.pdf; +import java.util.Comparator; import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; import org.apache.xmlgraphics.util.Service; /** @@ -36,8 +42,23 @@ public class PDFImageHandlerRegistry { /** the logger */ private static Log log = LogFactory.getLog(PDFImageHandlerRegistry.class); + private static final Comparator HANDLER_COMPARATOR = new Comparator() { + public int compare(Object o1, Object o2) { + PDFImageHandler h1 = (PDFImageHandler)o1; + PDFImageHandler h2 = (PDFImageHandler)o2; + return h1.getPriority() - h2.getPriority(); + } + }; + /** Map containing PDF image handlers for various MIME types */ private Map handlers = new java.util.HashMap(); + /** List containing the same handlers as above but ordered by priority */ + private List handlerList = new java.util.LinkedList(); + + /** Sorted Set of registered handlers */ + private ImageFlavor[] supportedFlavors = new ImageFlavor[0]; + private int handlerRegistrations; + private int lastSync; /** * Default constructor. @@ -75,24 +96,73 @@ public class PDFImageHandlerRegistry { * Add an image handler. The handler itself is inspected to find out what it supports. * @param handler the PDFImageHandler instance */ - public void addHandler(PDFImageHandler handler) { - String mime = handler.getSupportedMimeType(); - handlers.put(mime, handler); + public synchronized void addHandler(PDFImageHandler handler) { + Class imageClass = handler.getSupportedImageClass(); + this.handlers.put(imageClass, handler); + + //Sorted insert + ListIterator iter = this.handlerList.listIterator(); + while (iter.hasNext()) { + PDFImageHandler h = (PDFImageHandler)iter.next(); + if (HANDLER_COMPARATOR.compare(handler, h) < 0) { + iter.previous(); + break; + } + } + iter.add(handler); + this.handlerRegistrations++; } /** * Returns an PDFImageHandler which handles an specific image type given the MIME type * of the image. - * @param mime the requested MIME type + * @param img the Image to be handled * @return the PDFImageHandler responsible for handling the image or null if none is available */ - public PDFImageHandler getHandler(String mime) { - PDFImageHandler handler; + public PDFImageHandler getHandler(Image img) { + return getHandler(img.getClass()); + } - handler = (PDFImageHandler)handlers.get(mime); + /** + * Returns an PDFImageHandler which handles an specific image type given the MIME type + * of the image. + * @param imageClass the Image subclass for which to get a handler + * @return the PDFImageHandler responsible for handling the image or null if none is available + */ + protected synchronized PDFImageHandler getHandler(Class imageClass) { + PDFImageHandler handler = null; + Class cl = imageClass; + while (cl != null) { + handler = (PDFImageHandler)handlers.get(cl); + if (handler != null) { + break; + } + cl = cl.getSuperclass(); + } return handler; } + /** + * Returns the ordered array of supported image flavors. + * @return the array of image flavors + */ + public synchronized ImageFlavor[] getSupportedFlavors() { + if (this.lastSync != this.handlerRegistrations) { + //Extract all ImageFlavors into a single array + List flavors = new java.util.ArrayList(); + Iterator iter = this.handlerList.iterator(); + while (iter.hasNext()) { + ImageFlavor[] f = ((PDFImageHandler)iter.next()).getSupportedImageFlavors(); + for (int i = 0; i < f.length; i++) { + flavors.add(f[i]); + } + } + this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]); + this.lastSync = this.handlerRegistrations; + } + return this.supportedFlavors; + } + /** * Discovers PDFImageHandler implementations through the classpath and dynamically * registers them. diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java new file mode 100644 index 000000000..628883b9f --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java @@ -0,0 +1,84 @@ +/* + * 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.render.pdf; + +import java.awt.Point; +import java.awt.Rectangle; +import java.io.IOException; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; + +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFImage; +import org.apache.fop.pdf.PDFResourceContext; +import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.RendererContext; + +/** + * PDFImageHandler implementation which handles RenderedImage instances. + */ +public class PDFImageHandlerRenderedImage implements PDFImageHandler { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE + }; + + /** {@inheritDoc} */ + public PDFXObject generateImage(RendererContext context, Image image, + Point origin, Rectangle pos) + throws IOException { + PDFRenderer renderer = (PDFRenderer)context.getRenderer(); + ImageRendered imageRend = (ImageRendered)image; + PDFDocument pdfDoc = (PDFDocument)context.getProperty( + PDFRendererContextConstants.PDF_DOCUMENT); + PDFResourceContext resContext = (PDFResourceContext)context.getProperty( + PDFRendererContextConstants.PDF_CONTEXT); + + PDFImage pdfimage = new ImageRenderedAdapter(imageRend, image.getInfo().getOriginalURI()); + PDFXObject xobj = pdfDoc.addImage(resContext, pdfimage); + + float x = (float)pos.getX() / 1000f; + float y = (float)pos.getY() / 1000f; + float w = (float)pos.getWidth() / 1000f; + float h = (float)pos.getHeight() / 1000f; + renderer.placeImage(x, y, w, h, xobj); + + return xobj; + } + + /** {@inheritDoc} */ + public int getPriority() { + return 300; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageRendered.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + +} diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java new file mode 100644 index 000000000..ba47cce69 --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java @@ -0,0 +1,74 @@ +/* + * 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.render.pdf; + +import java.awt.Point; +import java.awt.Rectangle; +import java.io.IOException; +import java.util.Map; + +import org.w3c.dom.Document; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; + +import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.RendererContext; + +/** + * PDFImageHandler implementation which handles XML-based images. + */ +public class PDFImageHandlerXML implements PDFImageHandler { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.XML_DOM, + }; + + /** {@inheritDoc} */ + public PDFXObject generateImage(RendererContext context, Image image, + Point origin, Rectangle pos) + throws IOException { + PDFRenderer renderer = (PDFRenderer)context.getRenderer(); + ImageXMLDOM imgXML = (ImageXMLDOM)image; + Document doc = imgXML.getDocument(); + String ns = imgXML.getRootNamespace(); + Map foreignAttributes = (Map)context.getProperty( + PDFRendererContextConstants.FOREIGN_ATTRIBUTES); + renderer.renderDocument(doc, ns, pos, foreignAttributes); + return null; + } + + /** {@inheritDoc} */ + public int getPriority() { + return 400; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageXMLDOM.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + +} diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index f4aa5ee90..3b28cc34c 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -21,6 +21,8 @@ package org.apache.fop.render.pdf; // Java import java.awt.Color; +import java.awt.Point; +import java.awt.Rectangle; import java.awt.color.ColorSpace; import java.awt.color.ICC_Profile; import java.awt.geom.AffineTransform; @@ -37,11 +39,13 @@ import java.util.Map; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; -import org.w3c.dom.Document; - import org.apache.commons.io.IOUtils; -import org.apache.commons.io.output.CountingOutputStream; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.xmp.Metadata; import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter; import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema; @@ -68,14 +72,12 @@ import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.extensions.xmp.XMPMetadata; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.Typeface; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.apache.fop.image.XMLImage; import org.apache.fop.pdf.PDFAMode; import org.apache.fop.pdf.PDFAction; import org.apache.fop.pdf.PDFAnnotList; @@ -1661,29 +1663,44 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { endTextObject(); String url = image.getURL(); - putImage(url, pos); + putImage(url, pos, image.getForeignAttributes()); } /** {@inheritDoc} */ protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) { endTextObject(); - putImage(url, pos); + putImage(url, pos, foreignAttributes); } /** * Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced. - * @param url URL of the bitmap + * @param uri URL of the bitmap * @param pos Position of the bitmap + * @deprecated Use {@link @putImage(String, Rectangle2D, Map)} instead. */ - protected void putImage(String url, Rectangle2D pos) { - url = ImageFactory.getURL(url); - PDFXObject xobject = pdfDoc.getXObject(url); + protected void putImage(String uri, Rectangle2D pos) { + putImage(uri, pos, null); + } + + /** + * Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced. + * @param uri URL of the bitmap + * @param pos Position of the bitmap + * @param foreignAttributes foreign attributes associated with the image + */ + protected void putImage(String uri, Rectangle2D pos, Map foreignAttributes) { + Rectangle posInt = new Rectangle( + (int)pos.getX(), + (int)pos.getY(), + (int)pos.getWidth(), + (int)pos.getHeight()); + + uri = URISpecification.getURL(uri); + PDFXObject xobject = pdfDoc.getXObject(uri); if (xobject != null) { float w = (float) pos.getWidth() / 1000f; float h = (float) pos.getHeight() / 1000f; @@ -1691,79 +1708,47 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { (float)pos.getY() / 1000f, w, h, xobject); return; } + Point origin = new Point(currentIPPosition, currentBPPosition); + int x = origin.x + posInt.x; + int y = origin.y + posInt.y; - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage fopimage = fact.getImage(url, userAgent); - if (fopimage == null) { - return; - } - if (!fopimage.load(FopImage.DIMENSIONS)) { - return; - } - String mime = fopimage.getMimeType(); - - //First check for a dynamically registered handler - PDFImageHandler handler = imageHandlerRegistry.getHandler(mime); - if (handler != null) { - PDFXObject xobj; - try { - xobj = handler.generateImage(fopimage, url, pdfDoc); - } catch (IOException ioe) { - log.error("I/O error while handling " + mime + " image", ioe); - return; - } - fact.releaseImage(url, userAgent); + ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageInfo info = null; + try { + ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + info = manager.getImageInfo(uri, sessionContext); - float w = (float)pos.getWidth() / 1000f; - float h = (float)pos.getHeight() / 1000f; - placeImage((float) pos.getX() / 1000, - (float) pos.getY() / 1000, w, h, xobj); - } else if ("text/xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, null); - } else if ("image/svg+xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, null); - } else if ("image/eps".equals(mime)) { - FopPDFImage pdfimage = new FopPDFImage(fopimage, url); - PDFXObject xobj = pdfDoc.addImage(currentContext, pdfimage); - fact.releaseImage(url, userAgent); - float w = (float)pos.getWidth() / 1000f; - float h = (float)pos.getHeight() / 1000f; - placeImage((float) pos.getX() / 1000, - (float) pos.getY() / 1000, w, h, xobj); - } else if ("image/jpeg".equals(mime) || "image/tiff".equals(mime)) { - FopPDFImage pdfimage = new FopPDFImage(fopimage, url); - PDFXObject xobj = pdfDoc.addImage(currentContext, pdfimage); - fact.releaseImage(url, userAgent); - - float w = (float)pos.getWidth() / 1000f; - float h = (float)pos.getHeight() / 1000f; - placeImage((float) pos.getX() / 1000, - (float) pos.getY() / 1000, w, h, xobj); - } else { - if (!fopimage.load(FopImage.BITMAP)) { - return; + + Map hints = ImageUtil.getDefaultHints(sessionContext); + org.apache.xmlgraphics.image.loader.Image img = manager.getImage( + info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext); + + //First check for a dynamically registered handler + PDFImageHandler handler = imageHandlerRegistry.getHandler(img.getClass()); + if (handler != null) { + if (log.isDebugEnabled()) { + log.debug("Using PDFImageHandler: " + handler.getClass().getName()); + } + try { + RendererContext context = createRendererContext( + x, y, posInt.width, posInt.height, foreignAttributes); + handler.generateImage(context, img, origin, posInt); + } catch (IOException ioe) { + log.error("I/O error while handling image: " + info, ioe); + return; + } + } else { + throw new UnsupportedOperationException( + "No PDFImageHandler available for image: " + + info + " (" + img.getClass().getName() + ")"); } - FopPDFImage pdfimage = new FopPDFImage(fopimage, url); - PDFXObject xobj = pdfDoc.addImage(currentContext, pdfimage); - fact.releaseImage(url, userAgent); - - float w = (float) pos.getWidth() / 1000f; - float h = (float) pos.getHeight() / 1000f; - placeImage((float) pos.getX() / 1000f, - (float) pos.getY() / 1000f, w, h, xobj); + } catch (ImageException ie) { + log.error("Error while processing image: " + + (info != null ? info.toString() : uri), ie); + } catch (IOException ioe) { + log.error("I/O error while processing image: " + + (info != null ? info.toString() : uri), ioe); } // output new data @@ -1782,7 +1767,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * @param h height for image * @param xobj the image XObject */ - protected void placeImage(float x, float y, float w, float h, PDFXObject xobj) { + public void placeImage(float x, float y, float w, float h, PDFXObject xobj) { saveGraphicsState(); currentStream.add(format(w) + " 0 0 " + format(-h) + " " @@ -1792,10 +1777,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { restoreGraphicsState(); } - /** - * {@inheritDoc} - * int, int, int, int, java.util.Map) - */ + /** {@inheritDoc} */ protected RendererContext createRendererContext(int x, int y, int width, int height, Map foreignAttributes) { RendererContext context = super.createRendererContext( diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java index 5c5894d3b..aec094e3b 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.pdf; diff --git a/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java b/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java index b0ae29067..cbc0a8ec9 100644 --- a/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java @@ -19,42 +19,40 @@ package org.apache.fop.render.pdf; +import java.awt.Color; +import java.awt.geom.AffineTransform; import java.io.IOException; import java.io.OutputStream; import java.util.Map; -import java.awt.Color; -import java.awt.geom.AffineTransform; import org.w3c.dom.Document; -import org.apache.fop.render.AbstractGenericSVGHandler; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererContext; -import org.apache.fop.render.RendererContextConstants; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.GVTBuilder; +import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.util.SVGConstants; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.fo.extensions.ExtensionElementMapping; +import org.apache.fop.fonts.FontInfo; import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFPage; +import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFStream; -import org.apache.fop.pdf.PDFResourceContext; +import org.apache.fop.render.AbstractGenericSVGHandler; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererContext; +import org.apache.fop.render.RendererContextConstants; import org.apache.fop.svg.PDFAElementBridge; import org.apache.fop.svg.PDFBridgeContext; import org.apache.fop.svg.PDFGraphics2D; import org.apache.fop.svg.SVGUserAgent; import org.apache.fop.util.QName; -import org.apache.fop.fo.extensions.ExtensionElementMapping; -import org.apache.fop.fonts.FontInfo; - -// Commons-Logging -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.avalon.framework.configuration.Configuration; - -import org.apache.batik.bridge.GVTBuilder; -import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.dom.svg.SVGDOMImplementation; -import org.apache.batik.gvt.GraphicsNode; -import org.apache.batik.util.SVGConstants; /** * PDF XML handler for SVG (uses Apache Batik). @@ -154,10 +152,15 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler int xOffset = pdfInfo.currentXPosition; int yOffset = pdfInfo.currentYPosition; - final float deviceResolution = context.getUserAgent().getTargetResolution(); + FOUserAgent userAgent = context.getUserAgent(); + log.debug("Generating SVG at " + + userAgent.getTargetResolution() + + "dpi."); + final float deviceResolution = userAgent.getTargetResolution(); + log.debug("Generating SVG at " + deviceResolution + "dpi."); log.debug("Generating SVG at " + deviceResolution + "dpi."); - final float uaResolution = context.getUserAgent().getSourceResolution(); + final float uaResolution = userAgent.getSourceResolution(); SVGUserAgent ua = new SVGUserAgent(25.4f / uaResolution, new AffineTransform()); //Scale for higher resolution on-the-fly images from Batik @@ -176,6 +179,8 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler BridgeContext ctx = new PDFBridgeContext(ua, (strokeText ? null : pdfInfo.fi), + userAgent.getFactory().getImageManager(), + userAgent.getImageSessionContext(), new AffineTransform()); GraphicsNode root; diff --git a/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java b/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java new file mode 100644 index 000000000..ab39966d4 --- /dev/null +++ b/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java @@ -0,0 +1,71 @@ +/* + * 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.render.ps; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; +import org.apache.xmlgraphics.ps.ImageEncoder; + +/** + * ImageEncoder implementation for CCITT encoded images. + */ +public class ImageEncoderCCITTFax implements ImageEncoder { + + private final ImageRawCCITTFax ccitt; + + /** + * Main constructor. + * @param ccitt the CCITT encoded image + */ + public ImageEncoderCCITTFax(ImageRawCCITTFax ccitt) { + this.ccitt = ccitt; + } + + /** {@inheritDoc} */ + public void writeTo(OutputStream out) throws IOException { + ccitt.writeTo(out); + } + + /** {@inheritDoc} */ + public String getImplicitFilter() { + PSDictionary dict = new PSDictionary(); + dict.put("/Columns", new Integer(ccitt.getSize().getWidthPx())); + int compression = ccitt.getCompression(); + switch (compression) { + case TIFFImage.COMP_FAX_G3_1D : + dict.put("/K", new Integer(0)); + break; + case TIFFImage.COMP_FAX_G3_2D : + dict.put("/K", new Integer(1)); + break; + case TIFFImage.COMP_FAX_G4_2D : + dict.put("/K", new Integer(-1)); + break; + default: + throw new IllegalStateException( + "Invalid compression scheme: " + compression); + } + + return dict.toString() + " /CCITTFaxDecode"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/ps/ImageEncoderJPEG.java b/src/java/org/apache/fop/render/ps/ImageEncoderJPEG.java new file mode 100644 index 000000000..ef4b9f16c --- /dev/null +++ b/src/java/org/apache/fop/render/ps/ImageEncoderJPEG.java @@ -0,0 +1,51 @@ +/* + * 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.render.ps; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.ps.ImageEncoder; + +/** + * ImageEncoder implementation for JPEG images. + */ +public class ImageEncoderJPEG implements ImageEncoder { + private final ImageRawJPEG jpeg; + + /** + * Main constructor + * @param jpeg the JPEG image + */ + public ImageEncoderJPEG(ImageRawJPEG jpeg) { + this.jpeg = jpeg; + } + + /** {@inheritDoc} */ + public void writeTo(OutputStream out) throws IOException { + jpeg.writeTo(out); + } + + /** {@inheritDoc} */ + public String getImplicitFilter() { + return "<< >> /DCTDecode"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java index 286bbca80..787af69a1 100644 --- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java @@ -24,33 +24,43 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.IOException; -import org.apache.fop.render.Graphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; -import org.apache.fop.render.RendererContext; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; import org.apache.xmlgraphics.ps.PSGenerator; +import org.apache.fop.render.Graphics2DAdapter; +import org.apache.fop.render.RendererContext; + /** * Graphics2DAdapter implementation for PostScript. */ public class PSGraphics2DAdapter implements Graphics2DAdapter { - private PSRenderer renderer; + private PSGenerator gen; + private boolean clip = true; /** * Main constructor * @param renderer the Renderer instance to which this instance belongs */ public PSGraphics2DAdapter(PSRenderer renderer) { - this.renderer = renderer; + this(renderer.gen, true); + } + + /** + * Constructor for use without a PSRenderer instance. + * @param gen the PostScript generator + * @param clip true if the image should be clipped + */ + public PSGraphics2DAdapter(PSGenerator gen, boolean clip) { + this.gen = gen; + this.clip = clip; } /** {@inheritDoc} */ public void paintImage(Graphics2DImagePainter painter, RendererContext context, int x, int y, int width, int height) throws IOException { - PSGenerator gen = renderer.gen; - float fwidth = width / 1000f; float fheight = height / 1000f; float fx = x / 1000f; @@ -66,10 +76,12 @@ public class PSGraphics2DAdapter implements Graphics2DAdapter { gen.commentln("%FOPBeginGraphics2D"); gen.saveGraphicsState(); - // Clip to the image area. - gen.writeln("newpath"); - gen.defineRect(fx, fy, fwidth, fheight); - gen.writeln("clip"); + if (clip) { + // Clip to the image area. + gen.writeln("newpath"); + gen.defineRect(fx, fy, fwidth, fheight); + gen.writeln("clip"); + } // transform so that the coordinates (0,0) is from the top left // and positive is down and to the right. (0,0) is where the diff --git a/src/java/org/apache/fop/render/ps/PSImageUtils.java b/src/java/org/apache/fop/render/ps/PSImageUtils.java index 0ab329077..004d5a22a 100644 --- a/src/java/org/apache/fop/render/ps/PSImageUtils.java +++ b/src/java/org/apache/fop/render/ps/PSImageUtils.java @@ -19,113 +19,21 @@ package org.apache.fop.render.ps; -import java.awt.Dimension; -import java.awt.geom.Rectangle2D; -import java.io.IOException; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.ps.PSGenerator; + import org.apache.fop.image.EPSImage; import org.apache.fop.image.FopImage; -import org.apache.fop.image.JpegImage; -import org.apache.xmlgraphics.ps.PSGenerator; -import org.apache.xmlgraphics.ps.PSResource; /** - * Utility code for rendering images in PostScript. + * Utility code for rendering images in PostScript. */ public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils { /** logging instance */ protected static Log log = LogFactory.getLog(PSImageUtils.class); - /** - * Renders a bitmap image to PostScript. - * @param img image to render - * @param x x position - * @param y y position - * @param w width - * @param h height - * @param gen PS generator - * @throws IOException In case of an I/O problem while rendering the image - */ - public static void renderBitmapImage(FopImage img, - float x, float y, float w, float h, PSGenerator gen) - throws IOException { - boolean isJPEG = (img instanceof JpegImage && (gen.getPSLevel() >= 3)); - byte[] imgmap = convertImageToRawBitmapArray(img, isJPEG); - if (imgmap == null) { - gen.commentln("%Image data is not available: " + img); - return; //Image cannot be converted - } - - String imgDescription = img.getMimeType() + " " + img.getOriginalURI(); - Dimension imgDim = new Dimension(img.getWidth(), img.getHeight()); - Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h); - writeImage(imgmap, imgDim, imgDescription, targetRect, isJPEG, - img.getColorSpace(), gen); - } - - /** - * Renders a bitmap image (as form) to PostScript. - * @param img image to render - * @param form the form resource - * @param x x position - * @param y y position - * @param w width - * @param h height - * @param gen PS generator - * @throws IOException In case of an I/O problem while rendering the image - */ - public static void renderForm(FopImage img, PSResource form, - float x, float y, float w, float h, PSGenerator gen) - throws IOException { - Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h); - paintForm(form, targetRect, gen); - } - - /** - * Generates a form resource for a FopImage in PostScript. - * @param img image to render - * @param form the form resource - * @param gen PS generator - * @throws IOException In case of an I/O problem while rendering the image - */ - public static void generateFormResourceForImage(FopImage img, PSResource form, - PSGenerator gen) throws IOException { - boolean isJPEG = (img instanceof JpegImage && (gen.getPSLevel() >= 3)); - byte[] imgmap = convertImageToRawBitmapArray(img, isJPEG); - if (imgmap == null) { - gen.commentln("%Image data is not available: " + img); - return; //Image cannot be converted - } - - String imgDescription = img.getMimeType() + " " + img.getOriginalURI(); - Dimension imgDim = new Dimension(img.getWidth(), img.getHeight()); - writeReusableImage(imgmap, imgDim, form.getName(), imgDescription, isJPEG, - img.getColorSpace(), gen); - } - - private static byte[] convertImageToRawBitmapArray(FopImage img, boolean allowUndecodedJPEG) - throws IOException { - if (img instanceof JpegImage && allowUndecodedJPEG) { - if (!img.load(FopImage.ORIGINAL_DATA)) { - return null; - } - } else { - if (!img.load(FopImage.BITMAP)) { - return null; - } - } - byte[] imgmap; - if (img.getBitmapsSize() > 0) { - imgmap = img.getBitmaps(); - } else { - imgmap = img.getRessourceBytes(); - } - return imgmap; - } - /** * Renders an EPS image to PostScript. * @param img EPS image to render @@ -134,6 +42,8 @@ public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils { * @param w width * @param h height * @param gen PS generator + * @deprecated Use {@link #renderEPS(java.io.InputStream, String, java.awt.geom.Rectangle2D, + * java.awt.geom.Rectangle2D, PSGenerator)} instead */ public static void renderEPS(EPSImage img, float x, float y, float w, float h, diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index 7580bd0d5..21ae85259 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -24,6 +24,7 @@ import java.awt.Color; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.LineNumberReader; @@ -35,14 +36,28 @@ import java.util.Map; import javax.xml.transform.Source; -import org.w3c.dom.Document; - import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; +import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS; +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.pipeline.ImageProviderPipeline; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.ps.DSCConstants; +import org.apache.xmlgraphics.ps.ImageEncoder; import org.apache.xmlgraphics.ps.PSGenerator; +import org.apache.xmlgraphics.ps.PSImageUtils; import org.apache.xmlgraphics.ps.PSProcSets; import org.apache.xmlgraphics.ps.PSResource; import org.apache.xmlgraphics.ps.PSState; @@ -69,15 +84,12 @@ import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.Typeface; -import org.apache.fop.image.EPSImage; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.apache.fop.image.XMLImage; import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.ImageAdapter; @@ -108,7 +120,8 @@ import org.apache.fop.util.CharUtilities; * @author Apache FOP Development Team * @version $Id$ */ -public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAdapter { +public class PSRenderer extends AbstractPathOrientedRenderer + implements ImageAdapter, PSSupportedFlavors { /** logging instance */ private static Log log = LogFactory.getLog(PSRenderer.class); @@ -377,58 +390,183 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda } } + /** + * Indicates whether an image should be inlined or added as a PostScript form. + * @param uri the URI of the image + * @return true if the image should be inlined rather than added as a form + */ + protected boolean isImageInlined(String uri) { + return !isOptimizeResources() || uri == null || "".equals(uri); + } + + /** + * Indicates whether an image should be inlined or added as a PostScript form. + * @param info the ImageInfo object of the image + * @return true if the image should be inlined rather than added as a form + */ + protected boolean isImageInlined(ImageInfo info) { + if (isImageInlined(info.getOriginalURI())) { + return true; + } + + if (!isOptimizeResources()) { + throw new IllegalStateException("Must not get here if form support is enabled"); + } + + //Investigate choice for inline mode + ImageFlavor[] inlineFlavors = getInlineFlavors(); + ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageProviderPipeline[] inlineCandidates + = manager.getPipelineFactory().determineCandidatePipelines( + info, inlineFlavors); + ImageProviderPipeline inlineChoice = manager.choosePipeline(inlineCandidates); + ImageFlavor inlineFlavor = (inlineChoice != null ? inlineChoice.getTargetFlavor() : null); + + //Investigate choice for form mode + ImageFlavor[] formFlavors = getFormFlavors(); + ImageProviderPipeline[] formCandidates + = manager.getPipelineFactory().determineCandidatePipelines( + info, formFlavors); + ImageProviderPipeline formChoice = manager.choosePipeline(formCandidates); + ImageFlavor formFlavor = (formChoice != null ? formChoice.getTargetFlavor() : null); + + //Inline if form is not supported or if a better choice is available with inline mode + return formFlavor == null || !formFlavor.equals(inlineFlavor); + } + /** {@inheritDoc} */ protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { endTextObject(); - uri = ImageFactory.getURL(uri); - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage fopimage = fact.getImage(uri, userAgent); - if (fopimage == null) { - return; - } - if (!fopimage.load(FopImage.DIMENSIONS)) { - return; + int x = currentIPPosition + (int)Math.round(pos.getX()); + int y = currentBPPosition + (int)Math.round(pos.getY()); + uri = URISpecification.getURL(uri); + if (log.isDebugEnabled()) { + log.debug("Handling image: " + uri); } - float x = (float)pos.getX() / 1000f; - x += currentIPPosition / 1000f; - float y = (float)pos.getY() / 1000f; - y += currentBPPosition / 1000f; - float w = (float)pos.getWidth() / 1000f; - float h = (float)pos.getHeight() / 1000f; + + ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageInfo info = null; try { - String mime = fopimage.getMimeType(); - if ("text/xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; + ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + info = manager.getImageInfo(uri, sessionContext); + int width = (int)pos.getWidth(); + int height = (int)pos.getHeight(); + + //millipoints --> points for PostScript + float ptx = x / 1000f; + float pty = y / 1000f; + float ptw = width / 1000f; + float pth = height / 1000f; + + if (isImageInlined(info)) { + if (log.isDebugEnabled()) { + log.debug("Image " + info + " is inlined"); } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, foreignAttributes); - } else if ("image/svg+xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; + //Only now fully load/prepare the image + Map hints = ImageUtil.getDefaultHints(sessionContext); + org.apache.xmlgraphics.image.loader.Image img = manager.getImage( + info, getInlineFlavors(), hints, sessionContext); + + //...and embed as inline image + if (img instanceof ImageGraphics2D) { + ImageGraphics2D imageG2D = (ImageGraphics2D)img; + RendererContext context = createRendererContext( + x, y, width, height, foreignAttributes); + getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(), + context, x, y, width, height); + } else if (img instanceof ImageRendered) { + ImageRendered imgRend = (ImageRendered)img; + RenderedImage ri = imgRend.getRenderedImage(); + PSImageUtils.renderBitmapImage(ri, ptx, pty, ptw, pth, gen); + } else if (img instanceof ImageXMLDOM) { + ImageXMLDOM imgXML = (ImageXMLDOM)img; + renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(), + pos, foreignAttributes); + } else if (img instanceof ImageRawStream) { + final ImageRawStream raw = (ImageRawStream)img; + if (raw instanceof ImageRawEPS) { + ImageRawEPS eps = (ImageRawEPS)raw; + Rectangle2D bbox = eps.getBoundingBox(); + InputStream in = raw.createInputStream(); + try { + PSImageUtils.renderEPS(in, uri, + new Rectangle2D.Float(ptx, pty, ptw, pth), + bbox, + gen); + } finally { + IOUtils.closeQuietly(in); + } + } else if (raw instanceof ImageRawCCITTFax) { + final ImageRawCCITTFax ccitt = (ImageRawCCITTFax)raw; + ImageEncoder encoder = new ImageEncoderCCITTFax(ccitt); + Rectangle2D targetRect = new Rectangle2D.Float( + ptx, pty, ptw, pth); + PSImageUtils.writeImage(encoder, info.getSize().getDimensionPx(), + uri, targetRect, + ccitt.getColorSpace(), 1, false, gen); + } else if (raw instanceof ImageRawJPEG) { + ImageRawJPEG jpeg = (ImageRawJPEG)raw; + ImageEncoder encoder = new ImageEncoderJPEG(jpeg); + Rectangle2D targetRect = new Rectangle2D.Float( + ptx, pty, ptw, pth); + PSImageUtils.writeImage(encoder, info.getSize().getDimensionPx(), + uri, targetRect, + jpeg.getColorSpace(), 8, jpeg.isInverted(), gen); + } else { + throw new UnsupportedOperationException("Unsupported raw image: " + info); + } + } else { + throw new UnsupportedOperationException("Unsupported image type: " + img); } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, foreignAttributes); - } else if (fopimage instanceof EPSImage) { - PSImageUtils.renderEPS((EPSImage)fopimage, x, y, w, h, gen); } else { - if (isImageInlined(uri, fopimage)) { - PSImageUtils.renderBitmapImage(fopimage, x, y, w, h, gen); - } else { - PSResource form = getFormForImage(uri, fopimage); - PSImageUtils.renderForm(fopimage, form, x, y, w, h, gen); + if (log.isDebugEnabled()) { + log.debug("Image " + info + " is embedded as a form later"); } + //Don't load image at this time, just put a form placeholder in the stream + PSResource form = getFormForImage(uri); + Rectangle2D targetRect = new Rectangle2D.Double(ptx, pty, ptw, pth); + PSImageUtils.paintForm(form, info.getSize().getDimensionPt(), targetRect, gen); } + + } catch (ImageException ie) { + log.error("Error while processing image: " + + (info != null ? info.toString() : uri), ie); + } catch (FileNotFoundException fe) { + log.error(fe.getMessage()); } catch (IOException ioe) { handleIOTrouble(ioe); } } - protected PSResource getFormForImage(String uri, FopImage fopimage) { + private ImageFlavor[] getInlineFlavors() { + ImageFlavor[] flavors; + if (gen.getPSLevel() >= 3) { + flavors = LEVEL_3_FLAVORS_INLINE; + } else { + flavors = LEVEL_2_FLAVORS_INLINE; + } + return flavors; + } + + private ImageFlavor[] getFormFlavors() { + ImageFlavor[] flavors; + if (gen.getPSLevel() >= 3) { + flavors = LEVEL_3_FLAVORS_FORM; + } else { + flavors = LEVEL_2_FLAVORS_FORM; + } + return flavors; + } + + /** + * Returns a PSResource instance representing a image as a PostScript form. + * @param uri the image URI + * @return a PSResource instance + */ + protected PSResource getFormForImage(String uri) { + if (uri == null || "".equals(uri)) { + throw new IllegalArgumentException("uri must not be empty or null"); + } if (this.formResources == null) { this.formResources = new java.util.HashMap(); } @@ -439,11 +577,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda } return form; } - - protected boolean isImageInlined(String uri, FopImage image) { - return !isOptimizeResources(); - } - + /** {@inheritDoc} */ public void paintImage(RenderedImage image, RendererContext context, int x, int y, int width, int height) throws IOException { diff --git a/src/java/org/apache/fop/render/ps/PSSupportedFlavors.java b/src/java/org/apache/fop/render/ps/PSSupportedFlavors.java new file mode 100644 index 000000000..8ccfa8e26 --- /dev/null +++ b/src/java/org/apache/fop/render/ps/PSSupportedFlavors.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.render.ps; + +import org.apache.xmlgraphics.image.loader.ImageFlavor; + +/** + * Defines the set of supported ImageFlavors for the PostScript renderer. + */ +public interface PSSupportedFlavors { + + /** The flavors supported inline with PostScript level 2. */ + ImageFlavor[] LEVEL_2_FLAVORS_INLINE = new ImageFlavor[] + {ImageFlavor.RAW_EPS, + ImageFlavor.RAW_CCITTFAX, + ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE, + ImageFlavor.XML_DOM}; + + /** The flavors supported inline with PostScript level 3 and higher. */ + ImageFlavor[] LEVEL_3_FLAVORS_INLINE = new ImageFlavor[] + {ImageFlavor.RAW_EPS, + ImageFlavor.RAW_JPEG, + ImageFlavor.RAW_CCITTFAX, + ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE, + ImageFlavor.XML_DOM}; + + /** The flavors supported as forms with PostScript level 2. */ + ImageFlavor[] LEVEL_2_FLAVORS_FORM = new ImageFlavor[] + {//ImageFlavor.RAW_EPS, + ImageFlavor.RAW_CCITTFAX, + ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE/*, + ImageFlavor.XML_DOM*/}; + + /** The flavors supported as forms with PostScript level 3 or higher. */ + ImageFlavor[] LEVEL_3_FLAVORS_FORM = new ImageFlavor[] + {//ImageFlavor.RAW_EPS, + ImageFlavor.RAW_JPEG, + ImageFlavor.RAW_CCITTFAX, + ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE/*, + ImageFlavor.XML_DOM*/}; + +} diff --git a/src/java/org/apache/fop/render/ps/ResourceHandler.java b/src/java/org/apache/fop/render/ps/ResourceHandler.java index a0762e6e0..0dfb8029f 100644 --- a/src/java/org/apache/fop/render/ps/ResourceHandler.java +++ b/src/java/org/apache/fop/render/ps/ResourceHandler.java @@ -19,6 +19,8 @@ package org.apache.fop.render.ps; +import java.awt.geom.Dimension2D; +import java.awt.image.RenderedImage; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.InputStream; @@ -27,8 +29,25 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; +import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS; +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.ps.DSCConstants; +import org.apache.xmlgraphics.ps.FormGenerator; +import org.apache.xmlgraphics.ps.ImageEncoder; +import org.apache.xmlgraphics.ps.ImageFormGenerator; import org.apache.xmlgraphics.ps.PSGenerator; +import org.apache.xmlgraphics.ps.PSProcSets; import org.apache.xmlgraphics.ps.dsc.DSCException; import org.apache.xmlgraphics.ps.dsc.DSCFilter; import org.apache.xmlgraphics.ps.dsc.DSCParser; @@ -50,8 +69,6 @@ import org.apache.xmlgraphics.ps.dsc.tools.DSCTools; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fonts.FontInfo; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; /** * This class is used when two-pass production is used to generate the PostScript file (setting @@ -59,7 +76,7 @@ import org.apache.fop.image.ImageFactory; * temporary file generated by the PSRenderer and adds all used fonts and images as resources * to the PostScript file. */ -public class ResourceHandler implements DSCParserConstants { +public class ResourceHandler implements DSCParserConstants, PSSupportedFlavors { /** * Rewrites the temporary PostScript file generated by PSRenderer adding all needed resources @@ -208,13 +225,129 @@ public class ResourceHandler implements DSCParserConstants { Iterator iter = formResources.values().iterator(); while (iter.hasNext()) { PSImageFormResource form = (PSImageFormResource)iter.next(); - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage image = fact.getImage(form.getImageURI(), userAgent); - if (image == null) { - throw new NullPointerException("Image not found: " + form.getImageURI()); + final String uri = form.getImageURI(); + + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageInfo info = null; + try { + ImageSessionContext sessionContext = userAgent.getImageSessionContext(); + info = manager.getImageInfo(uri, sessionContext); + + ImageFlavor[] flavors; + if (gen.getPSLevel() >= 3) { + flavors = LEVEL_3_FLAVORS_FORM; + } else { + flavors = LEVEL_2_FLAVORS_FORM; + } + Map hints = ImageUtil.getDefaultHints(sessionContext); + org.apache.xmlgraphics.image.loader.Image img = manager.getImage( + info, flavors, hints, sessionContext); + + String imageDescription = info.getMimeType() + " " + info.getOriginalURI(); + final Dimension2D dimensionsPt = info.getSize().getDimensionPt(); + final Dimension2D dimensionsMpt = info.getSize().getDimensionMpt(); + + if (img instanceof ImageGraphics2D) { + final ImageGraphics2D imageG2D = (ImageGraphics2D)img; + FormGenerator formGen = new FormGenerator( + form.getName(), imageDescription, dimensionsPt) { + + protected void generatePaintProc(PSGenerator gen) + throws IOException { + gen.getResourceTracker().notifyResourceUsageOnPage( + PSProcSets.EPS_PROCSET); + gen.writeln("BeginEPSF"); + PSGraphics2DAdapter adapter = new PSGraphics2DAdapter(gen, false); + adapter.paintImage(imageG2D.getGraphics2DImagePainter(), + null, + 0, 0, + (int)Math.round(dimensionsMpt.getWidth()), + (int)Math.round(dimensionsMpt.getHeight())); + gen.writeln("EndEPSF"); + } + + }; + formGen.generate(gen); + } else if (img instanceof ImageRendered) { + ImageRendered imgRend = (ImageRendered)img; + RenderedImage ri = imgRend.getRenderedImage(); + FormGenerator formGen = new ImageFormGenerator( + form.getName(), imageDescription, + info.getSize().getDimensionPt(), + ri, false); + formGen.generate(gen); + } else if (img instanceof ImageXMLDOM) { + throw new UnsupportedOperationException( + "Embedding an ImageXMLDOM as a form isn't supported, yet"); + } else if (img instanceof ImageRawStream) { + final ImageRawStream raw = (ImageRawStream)img; + if (raw instanceof ImageRawEPS) { + final ImageRawEPS eps = (ImageRawEPS)raw; + throw new UnsupportedOperationException( + "Embedding EPS as forms isn't supported, yet"); + /* + InputStream in = eps.createInputStream(); + try { + FormGenerator formGen = new EPSFormGenerator(form.getName(), + imageDescription, dimensions, in); + formGen.generate(gen); + } finally { + IOUtils.closeQuietly(in); + }*/ + } else if (raw instanceof ImageRawCCITTFax) { + ImageRawCCITTFax jpeg = (ImageRawCCITTFax)raw; + ImageEncoder encoder = new ImageEncoderCCITTFax(jpeg); + FormGenerator formGen = new ImageFormGenerator( + form.getName(), imageDescription, + info.getSize().getDimensionPt(), + info.getSize().getDimensionPx(), + encoder, + jpeg.getColorSpace(), 1, false); + formGen.generate(gen); + } else if (raw instanceof ImageRawJPEG) { + ImageRawJPEG jpeg = (ImageRawJPEG)raw; + ImageEncoder encoder = new ImageEncoderJPEG(jpeg); + FormGenerator formGen = new ImageFormGenerator( + form.getName(), imageDescription, + info.getSize().getDimensionPt(), + info.getSize().getDimensionPx(), + encoder, + jpeg.getColorSpace(), jpeg.isInverted()); + formGen.generate(gen); + } else { + throw new UnsupportedOperationException("Unsupported raw image: " + info); + } + } else { + throw new UnsupportedOperationException("Unsupported image type: " + img); + } + } catch (ImageException ie) { + throw new IOException("Error while generating form for image: " + ie.getMessage()); } - PSImageUtils.generateFormResourceForImage(image, form, gen); } } + private static FormGenerator createMissingForm(String formName, final Dimension2D dimensions) { + FormGenerator formGen = new FormGenerator(formName, null, dimensions) { + + protected void generatePaintProc(PSGenerator gen) throws IOException { + gen.writeln("0 setgray"); + gen.writeln("0 setlinewidth"); + String w = gen.formatDouble(dimensions.getWidth()); + String h = gen.formatDouble(dimensions.getHeight()); + gen.writeln(w + " " + h + " scale"); + gen.writeln("0 0 1 1 rectstroke"); + gen.writeln("newpath"); + gen.writeln("0 0 moveto"); + gen.writeln("1 1 lineto"); + gen.writeln("stroke"); + gen.writeln("newpath"); + gen.writeln("0 1 moveto"); + gen.writeln("1 0 lineto"); + gen.writeln("stroke"); + } + + }; + return formGen; + } + } diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index eb50a3ea7..333e4ab95 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -20,26 +20,33 @@ package org.apache.fop.render.rtf; // Java -import java.awt.color.ColorSpace; import java.awt.geom.Point2D; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.ComponentColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.PixelInterleavedSampleModel; -import java.awt.image.Raster; -import java.awt.image.SampleModel; -import java.awt.image.WritableRaster; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.Iterator; +import java.util.Map; -import org.apache.batik.dom.svg.SVGDOMImplementation; -import org.apache.commons.io.output.ByteArrayOutputStream; +import org.w3c.dom.Document; + +import org.xml.sax.SAXException; + +import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.LengthBase; @@ -79,9 +86,6 @@ import org.apache.fop.fo.pagination.SimplePageMaster; import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fonts.FontSetup; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.apache.fop.image.XMLImage; import org.apache.fop.render.DefaultFontResolver; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfBeforeContainer; @@ -108,10 +112,6 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel; import org.apache.fop.render.rtf.rtflib.tools.BuilderContext; import org.apache.fop.render.rtf.rtflib.tools.TableContext; -import org.apache.xmlgraphics.image.writer.ImageWriter; -import org.apache.xmlgraphics.image.writer.ImageWriterRegistry; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; /** * RTF Handler: generates RTF output using the structure events from @@ -1104,24 +1104,18 @@ public class RTFHandler extends FOEventHandler { } try { - String url = eg.getURL(); + String uri = eg.getURL(); //set image data FOUserAgent userAgent = eg.getUserAgent(); - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage fopimage = fact.getImage(url, userAgent); - if (fopimage == null) { - log.error("Image could not be found: " + url); + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageInfo info = manager.getImageInfo(uri, userAgent.getImageSessionContext()); + if (info == null) { + log.error("Image could not be found: " + uri); return; } - if ("image/gif".equals(fopimage.getMimeType())) { - //GIF is not directly supported by RTF, so it must be converted to PNG - fopimage.load(FopImage.BITMAP); - } else { - fopimage.load(FopImage.ORIGINAL_DATA); - } - putGraphic(eg, fopimage); + putGraphic(eg, info); } catch (Exception e) { log.error("Error while handling an external-graphic: " + e.getMessage(), e); } @@ -1140,85 +1134,83 @@ public class RTFHandler extends FOEventHandler { Document doc = child.getDOMDocument(); String ns = child.getNamespaceURI(); - if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) { - // Build the image info. - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.mimeType = "image/svg+xml"; - info.str = SVGDOMImplementation.SVG_NAMESPACE_URI; - info.originalURI = ""; - info.data = doc; - - // Set the resolution to that of the FOUserAgent - FOUserAgent ua = ifo.getUserAgent(); - info.dpiHorizontal = 25.4f / ua.getSourcePixelUnitToMillimeter(); - info.dpiVertical = info.dpiHorizontal; - - // Set the image size to the size of the svg. - Point2D csize = new Point2D.Float(-1, -1); - Point2D intrinsicDimensions = child.getDimension(csize); - info.width = (int) intrinsicDimensions.getX(); - info.height = (int) intrinsicDimensions.getY(); - - FopImage fopImage = new XMLImage(info); - fopImage.load(FopImage.ORIGINAL_DATA); - - putGraphic(ifo, fopImage); - } else { - log.warn("The namespace " + ns - + " for instream-foreign-objects is not supported."); - } + ImageInfo info = new ImageInfo(null, null); + // Set the resolution to that of the FOUserAgent + FOUserAgent ua = ifo.getUserAgent(); + ImageSize size = new ImageSize(); + size.setResolution(ua.getSourceResolution()); + + // Set the image size to the size of the svg. + Point2D csize = new Point2D.Float(-1, -1); + Point2D intrinsicDimensions = child.getDimension(csize); + size.setSizeInMillipoints( + (int)Math.round(intrinsicDimensions.getX() * 1000), + (int)Math.round(intrinsicDimensions.getY() * 1000)); + size.calcPixelsFromSize(); + info.setSize(size); + + ImageXMLDOM image = new ImageXMLDOM(info, doc, ns); + FOUserAgent userAgent = ifo.getUserAgent(); + ImageManager manager = userAgent.getFactory().getImageManager(); + Image converted = manager.convertImage(image, FLAVORS); + putGraphic(ifo, converted); } catch (Exception e) { log.error("Error while handling an instream-foreign-object: " + e.getMessage(), e); } } - private BufferedImage createBufferedImageFromBitmaps(FopImage image) { - // TODO Hardcoded color and sample models, FIX ME! - ColorModel cm = new ComponentColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), - new int[] {8, 8, 8}, - false, false, - ColorModel.OPAQUE, DataBuffer.TYPE_BYTE); - SampleModel sampleModel = new PixelInterleavedSampleModel( - DataBuffer.TYPE_BYTE, image.getWidth(), image.getHeight(), 3, image.getWidth() * 3, - new int[] {0, 1, 2}); - DataBuffer dbuf = new DataBufferByte(image.getBitmaps(), - image.getWidth() * image.getHeight() * 3); - - WritableRaster raster = Raster.createWritableRaster(sampleModel, - dbuf, null); - - // Combine the color model and raster into a buffered image - return new BufferedImage(cm, raster, false, null); + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.RAW_EMF, ImageFlavor.RAW_PNG, ImageFlavor.RAW_JPEG + }; + + /** + * Puts a graphic/image into the generated RTF file. + * @param abstractGraphic the graphic (external-graphic or instream-foreign-object) + * @param info the image info object + * @throws IOException In case of an I/O error + */ + private void putGraphic(AbstractGraphics abstractGraphic, ImageInfo info) + throws IOException { + try { + FOUserAgent userAgent = abstractGraphic.getUserAgent(); + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageSessionContext sessionContext = userAgent.getImageSessionContext(); + Map hints = ImageUtil.getDefaultHints(sessionContext); + Image image = manager.getImage(info, FLAVORS, hints, sessionContext); + + putGraphic(abstractGraphic, image); + } catch (ImageException ie) { + log.error("Error while loading/processing image: " + info.getOriginalURI(), ie); + } } /** * Puts a graphic/image into the generated RTF file. * @param abstractGraphic the graphic (external-graphic or instream-foreign-object) - * @param fopImage the image + * @param image the image * @throws IOException In case of an I/O error */ - private void putGraphic(AbstractGraphics abstractGraphic, FopImage fopImage) + private void putGraphic(AbstractGraphics abstractGraphic, Image image) throws IOException { - byte[] rawData; - if ("image/svg+xml".equals(fopImage.getMimeType())) { - rawData = SVGConverter.convertToJPEG((XMLImage) fopImage); - } else if (fopImage.getRessourceBytes() != null) { - rawData = fopImage.getRessourceBytes(); - } else { - //TODO Revisit after the image library redesign!!! - //Convert the decoded bitmaps to a BufferedImage - BufferedImage bufImage = createBufferedImageFromBitmaps(fopImage); - ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor("image/png"); - ByteArrayOutputStream baout = new ByteArrayOutputStream(); - writer.writeImage(bufImage, baout); - rawData = baout.toByteArray(); + byte[] rawData = null; + + ImageInfo info = image.getInfo(); + + if (image instanceof ImageRawStream) { + ImageRawStream rawImage = (ImageRawStream)image; + InputStream in = rawImage.createInputStream(); + try { + rawData = IOUtils.toByteArray(in); + } finally { + IOUtils.closeQuietly(in); + } } + if (rawData == null) { log.warn(FONode.decorateWithContextInfo("Image could not be embedded: " - + fopImage.getOriginalURI(), abstractGraphic)); + + image, abstractGraphic)); return; } @@ -1229,7 +1221,9 @@ public class RTFHandler extends FOEventHandler { final RtfExternalGraphic rtfGraphic = c.getTextrun().newImage(); //set URL - rtfGraphic.setURL(fopImage.getOriginalURI()); + if (info.getOriginalURI() != null) { + rtfGraphic.setURL(info.getOriginalURI()); + } rtfGraphic.setImageData(rawData); //set scaling @@ -1240,7 +1234,7 @@ public class RTFHandler extends FOEventHandler { //get width int width = 0; if (abstractGraphic.getWidth().getEnum() == Constants.EN_AUTO) { - width = fopImage.getIntrinsicWidth(); + width = info.getSize().getWidthMpt(); } else { width = abstractGraphic.getWidth().getValue(); } @@ -1248,7 +1242,7 @@ public class RTFHandler extends FOEventHandler { //get height int height = 0; if (abstractGraphic.getWidth().getEnum() == Constants.EN_AUTO) { - height = fopImage.getIntrinsicHeight(); + height = info.getSize().getHeightMpt(); } else { height = abstractGraphic.getHeight().getValue(); } @@ -1257,7 +1251,7 @@ public class RTFHandler extends FOEventHandler { int contentwidth = 0; if (abstractGraphic.getContentWidth().getEnum() == Constants.EN_AUTO) { - contentwidth = fopImage.getIntrinsicWidth(); + contentwidth = info.getSize().getWidthMpt(); } else if (abstractGraphic.getContentWidth().getEnum() == Constants.EN_SCALE_TO_FIT) { contentwidth = width; @@ -1271,7 +1265,7 @@ public class RTFHandler extends FOEventHandler { if (abstractGraphic.getContentHeight().getEnum() == Constants.EN_AUTO) { - contentheight = fopImage.getIntrinsicHeight(); + contentheight = info.getSize().getHeightMpt(); } else if (abstractGraphic.getContentHeight().getEnum() == Constants.EN_SCALE_TO_FIT) { diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java index a79679450..932198676 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java @@ -26,19 +26,17 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import org.apache.commons.io.IOUtils; -import org.apache.fop.render.rtf.rtflib.tools.ImageConstants; -import org.apache.fop.render.rtf.rtflib.tools.ImageUtil; -//import org.apache.fop.render.rtf.rtflib.tools.jpeg.Encoder; -//import org.apache.fop.render.rtf.rtflib.tools.jpeg.JPEGException; - +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Writer; - -import java.io.File; -import java.net.URL; import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.commons.io.IOUtils; + +import org.apache.fop.render.rtf.rtflib.tools.ImageConstants; +import org.apache.fop.render.rtf.rtflib.tools.ImageUtil; /** * Creates an RTF image from an external graphic file. @@ -342,13 +340,13 @@ public class RtfExternalGraphic extends RtfElement { } - if (url == null) { - throw new ExternalGraphicException("The attribute 'url' of " - + " is null."); + if (url == null && imagedata == null) { + throw new ExternalGraphicException( + "No image data is available (neither URL, nor in-memory)"); } String linkToRoot = System.getProperty("jfor_link_to_root"); - if (linkToRoot != null) { + if (url != null && linkToRoot != null) { writer.write("{\\field {\\* \\fldinst { INCLUDEPICTURE \""); writer.write(linkToRoot); File urlFile = new File(url.getFile()); @@ -380,7 +378,7 @@ public class RtfExternalGraphic extends RtfElement { } // Determine image file format - String file = url.getFile (); + String file = (url != null ? url.getFile() : ""); imageformat = FormatBase.determineFormat(imagedata); if (imageformat != null) { imageformat = imageformat.convert(imageformat, imagedata); diff --git a/src/java/org/apache/fop/svg/PDFBridgeContext.java b/src/java/org/apache/fop/svg/PDFBridgeContext.java index 3ffad3335..9f235b6a9 100644 --- a/src/java/org/apache/fop/svg/PDFBridgeContext.java +++ b/src/java/org/apache/fop/svg/PDFBridgeContext.java @@ -26,6 +26,10 @@ import org.apache.batik.bridge.Bridge; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.DocumentLoader; import org.apache.batik.bridge.UserAgent; + +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; + import org.apache.fop.fonts.FontInfo; /** @@ -36,6 +40,9 @@ public class PDFBridgeContext extends BridgeContext { /** The font list. */ private final FontInfo fontInfo; + private final ImageManager imageManager; + private final ImageSessionContext imageSessionContext; + private AffineTransform linkTransform; /** @@ -50,9 +57,13 @@ public class PDFBridgeContext extends BridgeContext { public PDFBridgeContext(UserAgent userAgent, DocumentLoader loader, FontInfo fontInfo, + ImageManager imageManager, + ImageSessionContext imageSessionContext, AffineTransform linkTransform) { super(userAgent, loader); this.fontInfo = fontInfo; + this.imageManager = imageManager; + this.imageSessionContext = imageSessionContext; this.linkTransform = linkTransform; } @@ -66,9 +77,13 @@ public class PDFBridgeContext extends BridgeContext { */ public PDFBridgeContext(UserAgent userAgent, FontInfo fontInfo, + ImageManager imageManager, + ImageSessionContext imageSessionContext, AffineTransform linkTransform) { super(userAgent); this.fontInfo = fontInfo; + this.imageManager = imageManager; + this.imageSessionContext = imageSessionContext; this.linkTransform = linkTransform; } @@ -78,10 +93,29 @@ public class PDFBridgeContext extends BridgeContext { * @param fontInfo the font list for the text painter, may be null * in which case text is painted as shapes */ - public PDFBridgeContext(UserAgent userAgent, FontInfo fontInfo) { - this(userAgent, fontInfo, null); + public PDFBridgeContext(UserAgent userAgent, + FontInfo fontInfo, + ImageManager imageManager, + ImageSessionContext imageSessionContext) { + this(userAgent, fontInfo, imageManager, imageSessionContext, null); } + /** + * Returns the ImageManager to be used by the ImageElementBridge. + * @return the image manager + */ + public ImageManager getImageManager() { + return this.imageManager; + } + + /** + * Returns the ImageSessionContext to be used by the ImageElementBridge. + * @return the image session context + */ + public ImageSessionContext getImageSessionContext() { + return this.imageSessionContext; + } + private void putPDFElementBridgeConditional(String className, String testFor) { try { Class.forName(testFor); @@ -136,7 +170,10 @@ public class PDFBridgeContext extends BridgeContext { //TODO There's no matching method in the super-class here public BridgeContext createBridgeContext() { return new PDFBridgeContext(getUserAgent(), getDocumentLoader(), - fontInfo, linkTransform); + fontInfo, + getImageManager(), + getImageSessionContext(), + linkTransform); } - + } diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 2436e1a10..c3c336000 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -62,13 +62,17 @@ import org.apache.batik.ext.awt.RadialGradientPaint; import org.apache.batik.ext.awt.RenderingHintsKeyExt; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.PatternPaint; + +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.java2d.AbstractGraphics2D; +import org.apache.xmlgraphics.java2d.GraphicContext; + import org.apache.fop.fonts.CIDFont; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.LazyFont; -import org.apache.fop.image.JpegImage; import org.apache.fop.pdf.BitmapImage; import org.apache.fop.pdf.PDFAnnotList; import org.apache.fop.pdf.PDFColor; @@ -76,6 +80,7 @@ import org.apache.fop.pdf.PDFConformanceException; import org.apache.fop.pdf.PDFDeviceColorSpace; import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFGState; +import org.apache.fop.pdf.PDFImage; import org.apache.fop.pdf.PDFImageXObject; import org.apache.fop.pdf.PDFLink; import org.apache.fop.pdf.PDFName; @@ -86,10 +91,8 @@ import org.apache.fop.pdf.PDFResources; import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFText; import org.apache.fop.pdf.PDFXObject; -import org.apache.fop.render.pdf.FopPDFImage; +import org.apache.fop.render.pdf.ImageRawJPEGAdapter; import org.apache.fop.util.ColorExt; -import org.apache.xmlgraphics.java2d.AbstractGraphics2D; -import org.apache.xmlgraphics.java2d.GraphicContext; /** * PDF Graphics 2D. @@ -397,7 +400,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { * @param width the width to draw the image * @param height the height to draw the image */ - public void addJpegImage(JpegImage jpeg, float x, float y, + public void addJpegImage(ImageRawJPEG jpeg, float x, float y, float width, float height) { preparePainting(); // Need to include hash code as when invoked from FO you @@ -405,9 +408,9 @@ public class PDFGraphics2D extends AbstractGraphics2D { // count is not enough. String key = "__AddJPEG_" + hashCode() + "_" + jpegCount[0]; jpegCount[0]++; - FopPDFImage fopimage = new FopPDFImage(jpeg, key); + PDFImage pdfimage = new ImageRawJPEGAdapter(jpeg, key); PDFName imageName = this.pdfDoc.addImage(resourceContext, - fopimage).getName(); + pdfimage).getName(); AffineTransform at = getTransform(); double[] matrix = new double[6]; at.getMatrix(matrix); diff --git a/src/java/org/apache/fop/svg/PDFImageElementBridge.java b/src/java/org/apache/fop/svg/PDFImageElementBridge.java index 1545fc475..a2542e86f 100644 --- a/src/java/org/apache/fop/svg/PDFImageElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFImageElementBridge.java @@ -19,24 +19,28 @@ package org.apache.fop.svg; -import org.apache.batik.bridge.SVGImageElementBridge; - -import java.awt.Shape; import java.awt.Graphics2D; +import java.awt.Shape; import java.awt.geom.Rectangle2D; -import java.io.BufferedInputStream; -import java.io.InputStream; import org.w3c.dom.Element; +import org.w3c.dom.svg.SVGDocument; import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.SVGImageElementBridge; import org.apache.batik.gvt.AbstractGraphicsNode; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.util.ParsedURL; -import org.apache.fop.image.JpegImage; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.analyser.ImageReaderFactory; +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; /** * Bridge class for the <image> element when jpeg images. @@ -50,6 +54,10 @@ public class PDFImageElementBridge extends SVGImageElementBridge { */ public PDFImageElementBridge() { } + private final ImageFlavor[] supportedFlavors = new ImageFlavor[] + {ImageFlavor.RAW_JPEG, + ImageFlavor.GRAPHICS2D, + ImageFlavor.XML_DOM}; /** * Create the raster image node. * THis checks if it is a jpeg file and creates a jpeg node @@ -60,51 +68,68 @@ public class PDFImageElementBridge extends SVGImageElementBridge { * @return a new graphics node */ protected GraphicsNode createImageGraphicsNode - (BridgeContext ctx, Element imageElement, ParsedURL purl) { + (BridgeContext ctx, Element imageElement, ParsedURL purl) { + PDFBridgeContext pdfCtx = (PDFBridgeContext)ctx; + + ImageManager manager = pdfCtx.getImageManager(); + ImageSessionContext sessionContext = pdfCtx.getImageSessionContext(); try { - InputStream is = purl.openStream(); - if (!is.markSupported()) { - is = new BufferedInputStream(is, 1024); - } + ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext); + Image image = manager.getImage(info, supportedFlavors, sessionContext); - is.mark(3); - byte [] data = new byte[3]; - is.read(data); - is.reset(); - if ((data[0] == (byte)0xFF) - && (data[1] == (byte)0xD8) - && (data[2] == (byte)0xFF)) { - FopImage.ImageInfo ii = ImageReaderFactory.make - (purl.toString(), is, null); - JpegImage jpeg = new JpegImage(ii); - jpeg.load(FopImage.ORIGINAL_DATA); - PDFJpegNode node = new PDFJpegNode(jpeg, ctx, imageElement, purl); - - Rectangle2D imgBounds = getImageBounds(ctx, imageElement); - Rectangle2D bounds = node.getPrimitiveBounds(); - float [] vb = new float[4]; - vb[0] = 0; // x - vb[1] = 0; // y - vb[2] = (float) bounds.getWidth(); // width - vb[3] = (float) bounds.getHeight(); // height - - // handles the 'preserveAspectRatio', 'overflow' and 'clip' - // and sets the appropriate AffineTransform to the image node - initializeViewport(ctx, imageElement, node, vb, imgBounds); - return node; + AbstractGraphicsNode specializedNode = null; + if (image instanceof ImageXMLDOM) { + ImageXMLDOM xmlImage = (ImageXMLDOM)image; + if (xmlImage.getDocument() instanceof SVGDocument) { + return createSVGImageNode(ctx, imageElement, + (SVGDocument)xmlImage.getDocument()); + } else { + //Convert image to Graphics2D + image = manager.convertImage(xmlImage, + new ImageFlavor[] {ImageFlavor.GRAPHICS2D}); + } } - } catch (Exception ex) { - //TODO Handle this exception - } + if (image instanceof ImageRawJPEG) { + ImageRawJPEG jpegImage = (ImageRawJPEG)image; + specializedNode = new PDFJpegNode(jpegImage, ctx, imageElement, purl); + + } else if (image instanceof ImageGraphics2D) { + ImageGraphics2D g2dImage = (ImageGraphics2D)image; + specializedNode = new Graphics2DNode(g2dImage); + } else { + ctx.getUserAgent().displayError( + new ImageException("Cannot convert an image to a usable format: " + purl)); + } + + Rectangle2D imgBounds = getImageBounds(ctx, imageElement); + Rectangle2D bounds = specializedNode.getPrimitiveBounds(); + float [] vb = new float[4]; + vb[0] = 0; // x + vb[1] = 0; // y + vb[2] = (float) bounds.getWidth(); // width + vb[3] = (float) bounds.getHeight(); // height + // handles the 'preserveAspectRatio', 'overflow' and 'clip' + // and sets the appropriate AffineTransform to the image node + initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds); + return specializedNode; + } catch (Exception e) { + ctx.getUserAgent().displayError(e); + } + return superCreateGraphicsNode(ctx, imageElement, purl); } /** + * Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode. + * @param ctx the bridge context + * @param imageElement the image element + * @param purl the parsed URL + * @return the newly created graphics node * @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element) */ protected GraphicsNode superCreateGraphicsNode - (BridgeContext ctx, Element imageElement, ParsedURL purl) { + (BridgeContext ctx, Element imageElement, ParsedURL purl) { return super.createImageGraphicsNode(ctx, imageElement, purl); } @@ -116,21 +141,21 @@ public class PDFImageElementBridge extends SVGImageElementBridge { */ public class PDFJpegNode extends AbstractGraphicsNode { - private JpegImage jpeg; + private ImageRawJPEG jpeg; private BridgeContext ctx; private Element imageElement; private ParsedURL purl; private GraphicsNode origGraphicsNode = null; /** - * Create a new pdf jpeg node for drawing jpeg images + * Create a new PDF JPEG node for drawing JPEG images * into pdf graphics. - * @param j the jpeg image + * @param j the JPEG image * @param ctx the bridge context * @param imageElement the SVG image element * @param purl the URL to the image */ - public PDFJpegNode(JpegImage j, BridgeContext ctx, + public PDFJpegNode(ImageRawJPEG j, BridgeContext ctx, Element imageElement, ParsedURL purl) { this.jpeg = j; this.ctx = ctx; @@ -138,32 +163,23 @@ public class PDFImageElementBridge extends SVGImageElementBridge { this.purl = purl; } - /** - * Get the outline of this image. - * @return the outline shape which is the primitive bounds - */ + /** {@inheritDoc} */ public Shape getOutline() { return getPrimitiveBounds(); } - /** - * Paint this jpeg image. - * As this is used for inserting jpeg into pdf - * it adds the jpeg image to the PDFGraphics2D. - * @param g2d the graphics to draw the image on - */ + /** {@inheritDoc} */ public void primitivePaint(Graphics2D g2d) { if (g2d instanceof PDFGraphics2D) { PDFGraphics2D pdfg = (PDFGraphics2D) g2d; float x = 0; float y = 0; try { - float width = jpeg.getWidth(); - float height = jpeg.getHeight(); + float width = jpeg.getSize().getWidthPx(); + float height = jpeg.getSize().getHeightPx(); pdfg.addJpegImage(jpeg, x, y, width, height); } catch (Exception e) { - //TODO Handle this exception properly - e.printStackTrace(); + ctx.getUserAgent().displayError(e); } } else { // Not going directly into PDF so use @@ -179,40 +195,71 @@ public class PDFImageElementBridge extends SVGImageElementBridge { } } - /** - * Get the geometrix bounds of the image. - * @return the primitive bounds - */ + /** {@inheritDoc} */ public Rectangle2D getGeometryBounds() { return getPrimitiveBounds(); } - /** - * Get the primitive bounds of this bridge element. - * @return the bounds of the jpeg image - */ + /** {@inheritDoc} */ public Rectangle2D getPrimitiveBounds() { - try { - return new Rectangle2D.Double(0, 0, jpeg.getWidth(), - jpeg.getHeight()); - } catch (Exception e) { - //TODO Handle this exception properly - e.printStackTrace(); - } - return null; + return new Rectangle2D.Double(0, 0, + jpeg.getSize().getWidthPx(), + jpeg.getSize().getHeightPx()); + } + + /** {@inheritDoc} */ + public Rectangle2D getSensitiveBounds() { + //No interactive features, just return primitive bounds + return getPrimitiveBounds(); } + } + + /** + * A node that holds a Graphics2D image. + */ + public class Graphics2DNode extends AbstractGraphicsNode { + + private ImageGraphics2D image; + /** - * Returns the bounds of the sensitive area covered by this node, - * This includes the stroked area but does not include the effects - * of clipping, masking or filtering. - * @return the bounds of the sensitive area + * Create a new Graphics2D node. + * @param g2d the Graphics2D image */ + public Graphics2DNode(ImageGraphics2D g2d) { + this.image = g2d; + } + + /** {@inheritDoc} */ + public Shape getOutline() { + return getPrimitiveBounds(); + } + + /** {@inheritDoc} */ + public void primitivePaint(Graphics2D g2d) { + int width = image.getSize().getWidthPx(); + int height = image.getSize().getHeightPx(); + Rectangle2D area = new Rectangle2D.Double(0, 0, width, height); + image.getGraphics2DImagePainter().paint(g2d, area); + } + + /** {@inheritDoc} */ + public Rectangle2D getGeometryBounds() { + return getPrimitiveBounds(); + } + + /** {@inheritDoc} */ + public Rectangle2D getPrimitiveBounds() { + return new Rectangle2D.Double(0, 0, + image.getSize().getWidthPx(), + image.getSize().getHeightPx()); + } + + /** {@inheritDoc} */ public Rectangle2D getSensitiveBounds() { //No interactive features, just return primitive bounds return getPrimitiveBounds(); } } - } diff --git a/src/java/org/apache/fop/svg/PDFTranscoder.java b/src/java/org/apache/fop/svg/PDFTranscoder.java index 417b82097..281df1b1d 100644 --- a/src/java/org/apache/fop/svg/PDFTranscoder.java +++ b/src/java/org/apache/fop/svg/PDFTranscoder.java @@ -23,6 +23,10 @@ import java.awt.Color; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.InputStream; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Document; import org.w3c.dom.svg.SVGLength; @@ -41,6 +45,12 @@ import org.apache.batik.transcoder.TranscodingHints; import org.apache.batik.transcoder.image.ImageTranscoder; import org.apache.batik.transcoder.keys.BooleanKey; import org.apache.batik.transcoder.keys.FloatKey; +import org.apache.batik.util.ParsedURL; + +import org.apache.xmlgraphics.image.loader.ImageContext; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext; import org.apache.fop.Version; import org.apache.fop.fonts.FontInfo; @@ -99,6 +109,9 @@ public class PDFTranscoder extends AbstractFOPTranscoder /** Graphics2D instance that is used to paint to */ protected PDFDocumentGraphics2D graphics = null; + private ImageManager imageManager; + private ImageSessionContext imageSessionContext; + /** * Constructs a new PDFTranscoder. */ @@ -141,6 +154,11 @@ public class PDFTranscoder extends AbstractFOPTranscoder graphics.getPDFDocument().getInfo().setProducer("Apache FOP Version " + Version.getVersion() + ": PDF Transcoder for Batik"); + if (hints.containsKey(KEY_DEVICE_RESOLUTION)) { + graphics.setDeviceDPI(((Float)hints.get(KEY_DEVICE_RESOLUTION)).floatValue()); + } + + setupImageInfrastructure(uri); try { Configuration effCfg = this.cfg; @@ -196,9 +214,6 @@ public class PDFTranscoder extends AbstractFOPTranscoder //int h = (int)(height + 0.5); try { - if (hints.containsKey(KEY_DEVICE_RESOLUTION)) { - graphics.setDeviceDPI(((Float)hints.get(KEY_DEVICE_RESOLUTION)).floatValue()); - } OutputStream out = output.getOutputStream(); if (!(out instanceof BufferedOutputStream)) { out = new BufferedOutputStream(out); @@ -227,6 +242,39 @@ public class PDFTranscoder extends AbstractFOPTranscoder } } + private void setupImageInfrastructure(final String baseURI) { + final ImageContext imageContext = new ImageContext() { + public float getSourceResolution() { + return 25.4f / userAgent.getPixelUnitToMillimeter(); + } + }; + this.imageManager = new ImageManager(imageContext); + this.imageSessionContext = new AbstractImageSessionContext() { + + public ImageContext getParentContext() { + return imageContext; + } + + public float getTargetResolution() { + return graphics.getDeviceDPI(); + } + + public Source resolveURI(String uri) { + System.out.println("resolve " + uri); + try { + ParsedURL url = new ParsedURL(baseURI, uri); + InputStream in = url.openStream(); + StreamSource source = new StreamSource(in, url.toString()); + return source; + } catch (IOException ioe) { + userAgent.displayError(ioe); + return null; + } + } + + }; + } + /** {@inheritDoc} */ protected BridgeContext createBridgeContext() { //For compatibility with Batik 1.6 @@ -239,7 +287,8 @@ public class PDFTranscoder extends AbstractFOPTranscoder if (isTextStroked()) { fontInfo = null; } - BridgeContext ctx = new PDFBridgeContext(userAgent, fontInfo); + BridgeContext ctx = new PDFBridgeContext(userAgent, fontInfo, + this.imageManager, this.imageSessionContext); return ctx; } diff --git a/src/java/org/apache/fop/util/dijkstra/DefaultEdgeDirectory.java b/src/java/org/apache/fop/util/dijkstra/DefaultEdgeDirectory.java new file mode 100644 index 000000000..381b356a2 --- /dev/null +++ b/src/java/org/apache/fop/util/dijkstra/DefaultEdgeDirectory.java @@ -0,0 +1,109 @@ +/* + * 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.dijkstra; + +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; + +/** + * Default implementation of an edge directory for the {@link DijkstraAlgorithm}. + */ +public class DefaultEdgeDirectory implements EdgeDirectory { + + /** The directory of edges */ + private Map edges = new java.util.HashMap(); + //Map> + + /** + * Adds a new edge between two vertices. + * @param edge the new edge + */ + public void addEdge(Edge edge) { + Map directEdges = (Map)edges.get(edge.getStart()); + if (directEdges == null) { + directEdges = new java.util.HashMap(); + edges.put(edge.getStart(), directEdges); + } + directEdges.put(edge.getEnd(), edge); + } + + /** {@inheritDoc} */ + public int getPenalty(Vertex start, Vertex end) { + Map edgeMap = (Map)edges.get(start); + if (edgeMap != null) { + Edge route = (Edge)edgeMap.get(end); + if (route != null) { + int penalty = route.getPenalty(); + if (penalty < 0) { + throw new IllegalStateException("Penalty must not be negative"); + } + return penalty; + } + } + return 0; + } + + /** {@inheritDoc} */ + public Iterator getDestinations(Vertex origin) { + Map directRoutes = (Map)edges.get(origin); + if (directRoutes != null) { + Iterator iter = directRoutes.keySet().iterator(); + return iter; + } + return Collections.EMPTY_LIST.iterator(); + } + + /** + * Returns an iterator over all edges with the given origin. + * @param origin the origin + * @return an iterator over Edge instances + */ + public Iterator getEdges(Vertex origin) { + Map directRoutes = (Map)edges.get(origin); + if (directRoutes != null) { + Iterator iter = directRoutes.values().iterator(); + return iter; + } + return Collections.EMPTY_LIST.iterator(); + } + + /** + * Returns the best edge (the edge with the lowest penalty) between two given vertices. + * @param start the start vertex + * @param end the end vertex + * @return the best vertex or null if none is found + */ + public Edge getBestEdge(Vertex start, Vertex end) { + Edge best = null; + Iterator iter = getEdges(start); + while (iter.hasNext()) { + Edge edge = (Edge)iter.next(); + if (edge.getEnd().equals(end)) { + if (best == null || edge.getPenalty() < best.getPenalty()) { + best = edge; + } + } + } + return best; + } + + +} diff --git a/src/java/org/apache/fop/util/dijkstra/DijkstraAlgorithm.java b/src/java/org/apache/fop/util/dijkstra/DijkstraAlgorithm.java new file mode 100644 index 000000000..a5b2fe202 --- /dev/null +++ b/src/java/org/apache/fop/util/dijkstra/DijkstraAlgorithm.java @@ -0,0 +1,215 @@ +/* + * 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.dijkstra; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +/** + * This is an implementation of Dijkstra's algorithm to find the shortest path for a directed + * graph with non-negative edge weights. + * @see WikiPedia on Dijkstra's + * Algorithm + */ +public class DijkstraAlgorithm { + + /** Infinity value for distances. */ + public static final int INFINITE = Integer.MAX_VALUE; + + /** Compares penalties between two possible destinations. */ + private final Comparator penaltyComparator = new Comparator() { + public int compare(Object left, Object right) { + int leftPenalty = getLowestPenalty((Vertex)left); + int rightPenalty = getLowestPenalty((Vertex)right); + if (leftPenalty < rightPenalty) { + return -1; + } else if (leftPenalty == rightPenalty) { + return ((Comparable)left).compareTo(right); + } else { + return 1; + } + } + }; + + /** The directory of edges */ + private EdgeDirectory edgeDirectory; + + /** The priority queue for all vertices under inspection, ordered by penalties/distances. */ + private TreeSet priorityQueue = new TreeSet(penaltyComparator); + //Set + + /** The set of vertices for which the lowest penalty has been found. */ + private Set finishedVertices = new java.util.HashSet(); + //Set + + /** The currently known lowest penalties for all vertices. */ + private Map lowestPenalties = new java.util.HashMap(); + //Map + + /** Map of all predecessors in the spanning tree of best routes. */ + private Map predecessors = new java.util.HashMap(); + //Map + + /** + * Main Constructor. + * @param edgeDirectory the edge directory this instance should work on + */ + public DijkstraAlgorithm(EdgeDirectory edgeDirectory) { + this.edgeDirectory = edgeDirectory; + } + + /** + * Returns the penalty between two vertices. + * @param start the start vertex + * @param end the end vertex + * @return the penalty between two vertices, or 0 if no single edge between the two vertices + * exists. + */ + protected int getPenalty(Vertex start, Vertex end) { + return this.edgeDirectory.getPenalty(start, end); + } + + /** + * Returns an iterator over all valid destinations for a given vertex. + * @param origin the origin from which to search for destinations + * @return the iterator over all valid destinations for a given vertex + */ + protected Iterator getDestinations(Vertex origin) { + return this.edgeDirectory.getDestinations(origin); + } + + private void reset() { + finishedVertices.clear(); + priorityQueue.clear(); + + lowestPenalties.clear(); + predecessors.clear(); + } + + /** + * Run Dijkstra's shortest path algorithm. After this method is finished you can use + * {@link #getPredecessor(Vertex)} to reconstruct the best/shortest path starting from the + * destination backwards. + * @param start the starting vertex + * @param destination the destination vertex. + */ + public void execute(Vertex start, Vertex destination) { + if (start == null || destination == null) { + throw new NullPointerException("start and destination may not be null"); + } + + reset(); + setShortestDistance(start, 0); + priorityQueue.add(start); + + // the current node + Vertex u; + + // extract the vertex with the shortest distance + while (priorityQueue.size() > 0) { + u = (Vertex)priorityQueue.first(); + priorityQueue.remove(u); + + if (destination.equals(u)) { + //Destination reached + break; + } + + finishedVertices.add(u); + relax(u); + } + } + + /** + * Compute new lowest penalties for neighboring vertices. Update the lowest penalties and the + * predecessor map if a better solution is found. + * @param u the vertex to process + */ + private void relax(Vertex u) { + Iterator iter = getDestinations(u); + while (iter.hasNext()) { + Vertex v = (Vertex)iter.next(); + // skip node already settled + if (isFinished(v)) { + continue; + } + + int shortDist = getLowestPenalty(u) + getPenalty(u, v); + + if (shortDist < getLowestPenalty(v)) { + // assign new shortest distance and mark unsettled + setShortestDistance(v, shortDist); + + // assign predecessor in shortest path + setPredecessor(v, u); + } + } + } + + private void setPredecessor(Vertex a, Vertex b) { + predecessors.put(a, b); + } + + /** + * Indicates whether a shortest route to a vertex has been found. + * @param v the vertex + * @return true if the shortest route to this vertex has been found. + */ + private boolean isFinished(Vertex v) { + return finishedVertices.contains(v); + } + + private void setShortestDistance(Vertex vertex, int distance) { + //Remove so it is inserted at the right position after the lowest penalty changes for this + //vertex. + priorityQueue.remove(vertex); + + //Update the lowest penalty. + lowestPenalties.put(vertex, new Integer(distance)); + + //Insert the vertex again at the new position based on the lowest penalty + priorityQueue.add(vertex); + } + + /** + * Returns the lowest penalty from the start point to a given vertex. + * @param vertex the vertex + * @return the lowest penalty or {@link DijkstraAlgorithm#INFINITE} if there is no route to + * the destination. + */ + public int getLowestPenalty(Vertex vertex) { + Integer d = ((Integer)lowestPenalties.get(vertex)); + return (d == null) ? INFINITE : d.intValue(); + } + + /** + * Returns the vertex's predecessor on the shortest path. + * @param vertex the vertex for which to find the predecessor + * @return the vertex's predecessor on the shortest path, or + * null if there is no route to the destination. + */ + public Vertex getPredecessor(Vertex vertex) { + return (Vertex)predecessors.get(vertex); + } + +} diff --git a/src/java/org/apache/fop/util/dijkstra/Edge.java b/src/java/org/apache/fop/util/dijkstra/Edge.java new file mode 100644 index 000000000..f709b9e26 --- /dev/null +++ b/src/java/org/apache/fop/util/dijkstra/Edge.java @@ -0,0 +1,47 @@ +/* + * 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.dijkstra; + +/** + * Represents an edge (or direct route between two points) for the {@link DijkstraAlgorithm}. + * Implement this class to hold the start and end vertex for an edge and implement the + * getPenalty() method. + */ +public interface Edge { + + /** + * Returns the start vertex of the edge. + * @return the start vertex + */ + Vertex getStart(); + + /** + * Returns the end vertex of the edge. + * @return the end vertex + */ + Vertex getEnd(); + + /** + * Returns the penalty (or distance) for this edge. + * @return the penalty value (must be non-negative) + */ + int getPenalty(); + +} diff --git a/src/java/org/apache/fop/util/dijkstra/EdgeDirectory.java b/src/java/org/apache/fop/util/dijkstra/EdgeDirectory.java new file mode 100644 index 000000000..6a2dc848b --- /dev/null +++ b/src/java/org/apache/fop/util/dijkstra/EdgeDirectory.java @@ -0,0 +1,45 @@ +/* + * 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.dijkstra; + +import java.util.Iterator; + +/** + * Represents a directory of edges for use by the {@link DijkstraAlgorithm}. + */ +public interface EdgeDirectory { + + /** + * Returns the penalty between two vertices. + * @param start the start vertex + * @param end the end vertex + * @return the penalty between two vertices, or 0 if no single edge between the two vertices + * exists. + */ + int getPenalty(Vertex start, Vertex end); + + /** + * Returns an iterator over all valid destinations for a given vertex. + * @param origin the origin from which to search for destinations + * @return the iterator over all valid destinations for a given vertex + */ + Iterator getDestinations(Vertex origin); + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/util/dijkstra/Vertex.java b/src/java/org/apache/fop/util/dijkstra/Vertex.java new file mode 100644 index 000000000..40c41b0b7 --- /dev/null +++ b/src/java/org/apache/fop/util/dijkstra/Vertex.java @@ -0,0 +1,32 @@ +/* + * 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.dijkstra; + +/** + * Represents a vertex to be used by {@link DijkstraAlgorithm}. If you want to represent a city, + * you can do "public class City implements Vertex". The purpose of this interface is to make + * sure the Vertex implementation implements the Comparable interface so the sorting order is + * well-defined even when two vertices have the same penalty/distance from an origin point. + * Therefore, make sure you implement the compareTo(Object) and + * equals(Object) methods. + */ +public interface Vertex extends Comparable { + +} diff --git a/status.xml b/status.xml index e66635844..5cf11f580 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + A new image loading framework has been introduced to fix various problems with external + graphics and improve performance. + Fixed generation of named destinations so it works when the PDF document is encrypted. @@ -45,6 +49,10 @@ such as multi-page TIFF images to be inserted as peers to a page-sequence. Each image will make up an entire page. See the documentation for details.
+ + Added minimal support for the .minimum/.maximum components of block/inline-progression-dimension + on fo:external-graphic and fo:instream-foreign-object. + Added support for scale-down-to-fit and scale-up-to-fit (introduced in XSL 1.1). @@ -52,7 +60,7 @@ Bugfix: content of a row with zero height overriding the previous row - Added SVG support for AFP (GOCA). + Added SVG support for AFP (GOCA). Bugfix: allow multiple bookmarks to point at the same destination. diff --git a/test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java b/test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java new file mode 100644 index 000000000..9261e6d84 --- /dev/null +++ b/test/java/org/apache/fop/image/loader/batik/ImageLoaderTestCase.java @@ -0,0 +1,118 @@ +/* + * 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.image.loader.batik; + +import java.io.File; + +import junit.framework.TestCase; + +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.writer.ImageWriterUtil; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.FopFactory; + +/** + * Tests for bundled ImageLoader implementations. + */ +public class ImageLoaderTestCase extends TestCase { + + private static final File DEBUG_TARGET_DIR = null; //new File("D:/"); + + private FopFactory fopFactory; + + public ImageLoaderTestCase(String name) { + super(name); + fopFactory = FopFactory.newInstance(); + fopFactory.setSourceResolution(72); + fopFactory.setTargetResolution(300); + } + + public void testSVG() throws Exception { + String uri = "test/resources/images/img-w-size.svg"; + + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + ImageManager manager = fopFactory.getImageManager(); + ImageInfo info = manager.preloadImage(uri, userAgent.getImageSessionContext()); + assertNotNull("ImageInfo must not be null", info); + + Image img = manager.getImage(info, ImageFlavor.XML_DOM, + userAgent.getImageSessionContext()); + assertNotNull("Image must not be null", img); + assertEquals(ImageFlavor.XML_DOM, img.getFlavor()); + ImageXMLDOM imgDom = (ImageXMLDOM)img; + assertNotNull(imgDom.getDocument()); + assertEquals("http://www.w3.org/2000/svg", imgDom.getRootNamespace()); + info = imgDom.getInfo(); //Switch to the ImageInfo returned by the image + assertEquals(16000, info.getSize().getWidthMpt()); + assertEquals(16000, info.getSize().getHeightMpt()); + + img = manager.getImage(info, ImageFlavor.RENDERED_IMAGE, + userAgent.getImageSessionContext()); + assertNotNull("Image must not be null", img); + assertEquals(ImageFlavor.RENDERED_IMAGE, img.getFlavor()); + ImageRendered imgRed = (ImageRendered)img; + assertNotNull(imgRed.getRenderedImage()); + if (DEBUG_TARGET_DIR != null) { + ImageWriterUtil.saveAsPNG(imgRed.getRenderedImage(), + (int)userAgent.getTargetResolution(), + new File(DEBUG_TARGET_DIR, "out.svg.png")); + } + assertEquals(67, imgRed.getRenderedImage().getWidth()); + assertEquals(67, imgRed.getRenderedImage().getHeight()); + info = imgRed.getInfo(); //Switch to the ImageInfo returned by the image + assertEquals(16000, info.getSize().getWidthMpt()); + assertEquals(16000, info.getSize().getHeightMpt()); + } + + public void testWMF() throws Exception { + String uri = "test/resources/images/testChart.wmf"; + + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + ImageManager manager = fopFactory.getImageManager(); + ImageInfo info = manager.preloadImage(uri, userAgent.getImageSessionContext()); + assertNotNull("ImageInfo must not be null", info); + + Image img = manager.getImage(info, ImageFlavor.RENDERED_IMAGE, + userAgent.getImageSessionContext()); + assertNotNull("Image must not be null", img); + assertEquals(ImageFlavor.RENDERED_IMAGE, img.getFlavor()); + ImageRendered imgRed = (ImageRendered)img; + assertNotNull(imgRed.getRenderedImage()); + if (DEBUG_TARGET_DIR != null) { + ImageWriterUtil.saveAsPNG(imgRed.getRenderedImage(), + (int)userAgent.getTargetResolution(), + new File(DEBUG_TARGET_DIR, "out.wmf.png")); + } + assertEquals(3300, imgRed.getRenderedImage().getWidth()); + assertEquals(2550, imgRed.getRenderedImage().getHeight()); + info = imgRed.getInfo(); //Switch to the ImageInfo returned by the image + assertEquals(792000, info.getSize().getWidthMpt()); + assertEquals(612000, info.getSize().getHeightMpt()); + } + +} diff --git a/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java b/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java new file mode 100644 index 000000000..b14dd1fb8 --- /dev/null +++ b/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java @@ -0,0 +1,109 @@ +/* + * 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.image.loader.batik; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.image.loader.batik.ImageWMF; + +/** + * Tests for bundled image preloader implementations. + */ +public class ImagePreloaderTestCase extends TestCase { + + private FopFactory fopFactory; + + public ImagePreloaderTestCase(String name) { + super(name); + fopFactory = FopFactory.newInstance(); + fopFactory.setSourceResolution(72); + fopFactory.setTargetResolution(300); + } + + public void testSVG() throws Exception { + String uri = "test/resources/images/img-w-size.svg"; + + checkSVGFile(uri); + } + + public void testSVGZ() throws Exception { + String uri = "test/resources/images/img-w-size.svgz"; + + checkSVGFile(uri); + } + + private void checkSVGFile(String uri) throws ImageException, IOException { + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + ImageManager manager = fopFactory.getImageManager(); + ImageInfo info = manager.preloadImage(uri, userAgent.getImageSessionContext()); + assertNotNull("ImageInfo must not be null", info); + assertEquals(MimeConstants.MIME_SVG, info.getMimeType()); + assertEquals(uri, info.getOriginalURI()); + assertEquals(16, info.getSize().getWidthPx()); + assertEquals(16, info.getSize().getHeightPx()); + assertEquals(userAgent.getSourceResolution(), info.getSize().getDpiHorizontal(), 0.1); + assertEquals(16000, info.getSize().getWidthMpt()); + assertEquals(16000, info.getSize().getHeightMpt()); + } + + public void testSVGNoSize() throws Exception { + String uri = "test/resources/images/img.svg"; + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + ImageManager manager = fopFactory.getImageManager(); + ImageInfo info = manager.preloadImage(uri, userAgent.getImageSessionContext()); + assertNotNull("ImageInfo must not be null", info); + assertEquals(MimeConstants.MIME_SVG, info.getMimeType()); + assertEquals(uri, info.getOriginalURI()); + assertEquals(100, info.getSize().getWidthPx()); //100 = default viewport size + assertEquals(100, info.getSize().getHeightPx()); + assertEquals(userAgent.getSourceResolution(), info.getSize().getDpiHorizontal(), 0.1); + assertEquals(100000, info.getSize().getWidthMpt()); + assertEquals(100000, info.getSize().getHeightMpt()); + } + + public void testWMF() throws Exception { + String uri = "test/resources/images/testChart.wmf"; + + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + ImageManager manager = fopFactory.getImageManager(); + ImageInfo info = manager.preloadImage(uri, userAgent.getImageSessionContext()); + assertNotNull("ImageInfo must not be null", info); + assertEquals(ImageWMF.MIME_WMF, info.getMimeType()); + assertEquals(uri, info.getOriginalURI()); + assertEquals(27940, info.getSize().getWidthPx()); + assertEquals(21590, info.getSize().getHeightPx()); + assertEquals(2540, info.getSize().getDpiHorizontal(), 0.1); + assertEquals(792000, info.getSize().getWidthMpt()); + assertEquals(612000, info.getSize().getHeightMpt()); + } + +} diff --git a/test/java/org/apache/fop/memory/MemoryEater.java b/test/java/org/apache/fop/memory/MemoryEater.java index 555ddf19c..1bea0f123 100644 --- a/test/java/org/apache/fop/memory/MemoryEater.java +++ b/test/java/org/apache/fop/memory/MemoryEater.java @@ -36,6 +36,7 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.io.output.NullOutputStream; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; @@ -63,7 +64,9 @@ public class MemoryEater { transformer.setParameter("repeats", new Integer(replicatorRepeats)); OutputStream out = new NullOutputStream(); //write to /dev/nul - Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out); + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + userAgent.setBaseURL(foFile.getParentFile().toURL().toExternalForm()); + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out); Result res = new SAXResult(fop.getDefaultHandler()); transformer.transform(src, res); diff --git a/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java b/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java index 54ea5b571..881a8abd2 100644 --- a/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java +++ b/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java @@ -88,20 +88,6 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { } } - /** - * Test exception when PDF/A-1 is enabled and an EPS is used. - * @throws Exception if the test fails - */ - public void testEPSUsage() throws Exception { - File foFile = new File(foBaseDir, "with-eps.fo"); - try { - convertFO(foFile, getUserAgent(), dumpPDF); - fail("Expected PDFConformanceException. PDF/A-1 does not allow PostScript XObjects."); - } catch (PDFConformanceException e) { - //Good! - } - } - /** * Test exception when PDF/A-1 is enabled and images. * @throws Exception if the test fails diff --git a/test/java/org/apache/fop/threading/FOPTestbed.java b/test/java/org/apache/fop/threading/FOPTestbed.java index e5cdaaf74..875c04617 100644 --- a/test/java/org/apache/fop/threading/FOPTestbed.java +++ b/test/java/org/apache/fop/threading/FOPTestbed.java @@ -19,12 +19,12 @@ package org.apache.fop.threading; -import java.util.List; -import java.util.Iterator; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.text.DecimalFormat; +import java.util.Iterator; +import java.util.List; import javax.xml.transform.Source; import javax.xml.transform.Templates; @@ -40,35 +40,45 @@ import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.container.ContainerUtil; import org.apache.avalon.framework.logger.AbstractLogEnabled; -import org.apache.avalon.framework.logger.Logger; import org.apache.commons.io.IOUtils; +/** + * Testbed for multi-threading tests. The class can run a configurable set of task a number of + * times in a configurable number of threads to easily reproduce multi-threading issues. + */ public class FOPTestbed extends AbstractLogEnabled implements Configurable, Initializable { private int repeat; - private List tasks = new java.util.ArrayList(); + private List taskList = new java.util.ArrayList(); private int threads; private File outputDir; private Configuration fopCfg; + private FOProcessor foprocessor; private int counter = 0; + /** {@inheritDoc} */ public void configure(Configuration configuration) throws ConfigurationException { this.threads = configuration.getChild("threads").getValueAsInteger(10); this.outputDir = new File(configuration.getChild("output-dir").getValue()); Configuration tasks = configuration.getChild("tasks"); this.repeat = tasks.getAttributeAsInteger("repeat", 1); Configuration[] entries = tasks.getChildren("task"); - for (int i=0; i - + 2 C:/Dev/FOP/temp/out - - + --> + application/pdf + .pdf diff --git a/test/java/org/apache/fop/util/dijkstra/City.java b/test/java/org/apache/fop/util/dijkstra/City.java new file mode 100644 index 000000000..4562c36c7 --- /dev/null +++ b/test/java/org/apache/fop/util/dijkstra/City.java @@ -0,0 +1,57 @@ +/* + * 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.dijkstra; + +/** + * Represents a city. + */ +public class City implements Vertex { + + private String name; + + /** + * Main constructor + * @param name the city's name + */ + public City(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + return this.name.equals(((City)obj).name); + } + + /** {@inheritDoc} */ + public int hashCode() { + return this.name.hashCode(); + } + + /** {@inheritDoc} */ + public int compareTo(Object obj) { + return this.name.compareTo(((City)obj).name); + } + + /** {@inheritDoc} */ + public String toString() { + return this.name; + } + +} \ No newline at end of file diff --git a/test/java/org/apache/fop/util/dijkstra/DijkstraTestCase.java b/test/java/org/apache/fop/util/dijkstra/DijkstraTestCase.java new file mode 100644 index 000000000..fb56f1f53 --- /dev/null +++ b/test/java/org/apache/fop/util/dijkstra/DijkstraTestCase.java @@ -0,0 +1,139 @@ +/* + * 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.dijkstra; + +import java.util.Iterator; +import java.util.LinkedList; + +import junit.framework.TestCase; + +/** + * Tests the Dijkstra algorithm implementation. We're comparing best solutions with focus on + * time or distance getting from St. Gallen to Lucerne on Switzerland's railroads. + */ +public class DijkstraTestCase extends TestCase { + + private static final boolean DEBUG = false; + + private static final City ROMANSHORN = new City("Romanshorn"); + private static final City ST_GALLEN = new City("St. Gallen"); + private static final City WINTERTHUR = new City("Winterthur"); + private static final City ZURICH = new City("Zurich"); + private static final City ZUG = new City("Zug"); + private static final City RAPPERSWIL = new City("Rapperswil"); + private static final City ARTH_GOLDAU = new City("Arth-Goldau"); + private static final City LUCERNE = new City("Lucerne"); + + private static final City NOWHERE = new City("nowhere"); + + private DijkstraAlgorithm algo; + private DefaultEdgeDirectory edges; + private Mode mode; + + /** {@inheritDoc} */ + protected void setUp() throws Exception { + super.setUp(); + + edges = new DefaultEdgeDirectory(); + algo = new DijkstraAlgorithm(edges); + mode = new Mode(); + + //St.Gallen - Winterthur - Zurich - Zug - Lucerne: 161 km, 2h 01min + edges.addEdge(new TrainRoute(mode, ST_GALLEN, WINTERTHUR, 61, 39)); + edges.addEdge(new TrainRoute(mode, WINTERTHUR, ZURICH, 31, 31)); + edges.addEdge(new TrainRoute(mode, ZURICH, ZUG, 39, 31)); + edges.addEdge(new TrainRoute(mode, ZUG, LUCERNE, 30, 20)); + + //St.Gallen - Rapperswil - Arth-Goldau - Lucerne: 158km, 2h 18min + edges.addEdge(new TrainRoute(mode, ST_GALLEN, RAPPERSWIL, 72, 57)); + edges.addEdge(new TrainRoute(mode, RAPPERSWIL, ARTH_GOLDAU, 55, 48)); + edges.addEdge(new TrainRoute(mode, ARTH_GOLDAU, LUCERNE, 31, 33)); + + //A detour to make it interesting (St.Gallen - Romanshorn - Winterthur): 89km, 1h 23min + edges.addEdge(new TrainRoute(mode, ST_GALLEN, ROMANSHORN, 30, 32)); + edges.addEdge(new TrainRoute(mode, ROMANSHORN, WINTERTHUR, 59, 51)); + } + + public void testAlgorithmWithDistance() throws Exception { + mode.useDistance(); + City origin = ST_GALLEN; + City destination = LUCERNE; + String route = executeAlgorithm(origin, destination); + + int distance = algo.getLowestPenalty(destination); + + if (DEBUG) { + System.out.println(route + " " + distance + " km"); + } + + assertEquals(158, distance); + assertEquals("St. Gallen - Rapperswil - Arth-Goldau - Lucerne", route); + } + + public void testAlgorithmWithDuration() throws Exception { + mode.useDuration(); + City origin = ST_GALLEN; + City destination = LUCERNE; + String route = executeAlgorithm(origin, destination); + + int duration = algo.getLowestPenalty(destination); + + if (DEBUG) { + System.out.println(route + " " + duration + " minutes"); + } + + assertEquals(121, duration); + assertEquals("St. Gallen - Winterthur - Zurich - Zug - Lucerne", route); + } + + public void testAlgorithmWithNonExistentRoute() throws Exception { + City origin = ST_GALLEN; + City destination = NOWHERE; + algo.execute(origin, destination); + Vertex pred = algo.getPredecessor(destination); + assertNull(pred); + } + + private String executeAlgorithm(City origin, City destination) { + algo.execute(origin, destination); + Vertex prev = destination; + Vertex pred = algo.getPredecessor(destination); + if (pred == null) { + fail("No route found!"); + } + LinkedList stops = new LinkedList(); + stops.addLast(destination); + while ((pred = algo.getPredecessor(prev)) != null) { + stops.addFirst(pred); + prev = pred; + } + StringBuffer sb = new StringBuffer(); + Iterator iter = stops.iterator(); + while (iter.hasNext()) { + if (sb.length() > 0) { + sb.append(" - "); + } + sb.append(iter.next()); + } + String route = sb.toString(); + return route; + } + +} diff --git a/test/java/org/apache/fop/util/dijkstra/Mode.java b/test/java/org/apache/fop/util/dijkstra/Mode.java new file mode 100644 index 000000000..4e75e57af --- /dev/null +++ b/test/java/org/apache/fop/util/dijkstra/Mode.java @@ -0,0 +1,51 @@ +/* + * 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.dijkstra; + +/** + * Class to allow easy switching between duration and distance mode. + */ +public class Mode { + + private boolean duration = true; + + /** + * Switch to duration mode. + */ + public void useDuration() { + this.duration = true; + } + + /** + * Switch to distance mode. + */ + public void useDistance() { + this.duration = false; + } + + /** + * Indicates whether to use duration mode or distance mode. + * @return true if duration mode is active, otherwise it's the distance mode. + */ + public boolean isDuration() { + return this.duration; + } + +} diff --git a/test/java/org/apache/fop/util/dijkstra/TrainRoute.java b/test/java/org/apache/fop/util/dijkstra/TrainRoute.java new file mode 100644 index 000000000..16ad0dc3a --- /dev/null +++ b/test/java/org/apache/fop/util/dijkstra/TrainRoute.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.util.dijkstra; + +/** + * Represents a train route with both distance and duration. + */ +public class TrainRoute implements Edge { + + private Mode mode; + private Vertex start; + private Vertex end; + private int distance; + private int minutes; + + /** + * Main constructor. + * @param origin the start city + * @param dest the destination city + * @param distance the distance between the two cities + * @param minutes the duration for the route + */ + public TrainRoute(Mode mode, City origin, City dest, int distance, int minutes) { + this.mode = mode; + this.start = origin; + this.end = dest; + this.distance = distance; + this.minutes = minutes; + } + + /** {@inheritDoc} */ + public int getPenalty() { + if (mode.isDuration()) { + return this.minutes; + } else { + return this.distance; + } + } + + /** {@inheritDoc} */ + public Vertex getEnd() { + return this.end; + } + + /** {@inheritDoc} */ + public Vertex getStart() { + return this.start; + } + +} diff --git a/test/java/org/apache/fop/visual/BatchDiffer.java b/test/java/org/apache/fop/visual/BatchDiffer.java index aa3f5504f..9d354e7ce 100644 --- a/test/java/org/apache/fop/visual/BatchDiffer.java +++ b/test/java/org/apache/fop/visual/BatchDiffer.java @@ -20,31 +20,28 @@ package org.apache.fop.visual; import java.awt.image.BufferedImage; -import java.awt.image.RenderedImage; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.util.Collection; import java.util.Iterator; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.stream.StreamSource; +import org.xml.sax.SAXException; + import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.avalon.framework.container.ContainerUtil; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.SuffixFileFilter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.image.writer.ImageWriterUtil; + import org.apache.fop.layoutengine.LayoutEngineTestSuite; -import org.apache.xmlgraphics.image.writer.ImageWriter; -import org.apache.xmlgraphics.image.writer.ImageWriterRegistry; -import org.xml.sax.SAXException; /** * This class is used to visually diff bitmap images created through various sources. @@ -109,22 +106,6 @@ public class BatchDiffer { + " for the batch run."); } - /** - * Saves a BufferedImage as a PNG file. - * @param bitmap the bitmap to encode - * @param outputFile the target file - * @throws IOException in case of an I/O problem - */ - public static void saveAsPNG(RenderedImage bitmap, File outputFile) throws IOException { - OutputStream out = new FileOutputStream(outputFile); - try { - ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor("image/png"); - writer.writeImage(bitmap, out); - } finally { - IOUtils.closeQuietly(out); - } - } - /** * Runs the batch. * @param cfgFile configuration file to use @@ -216,14 +197,14 @@ public class BatchDiffer { //Save combined bitmap as PNG file File outputFile = new File(targetDir, f.getName() + "._combined.png"); - saveAsPNG(combined, outputFile); + ImageWriterUtil.saveAsPNG(combined, outputFile); if (createDiffs) { for (int k = 1; k < bitmaps.length; k++) { BufferedImage diff = BitmapComparator.buildDiffImage( bitmaps[0], bitmaps[k]); outputFile = new File(targetDir, f.getName() + "._diff" + k + ".png"); - saveAsPNG(diff, outputFile); + ImageWriterUtil.saveAsPNG(diff, outputFile); } } //Release memory as soon as possible. These images are huge! diff --git a/test/layoutengine/standard-testcases/external-graphic_bmp.xml b/test/layoutengine/standard-testcases/external-graphic_bmp.xml index 34e76dbd3..2482b1dbd 100644 --- a/test/layoutengine/standard-testcases/external-graphic_bmp.xml +++ b/test/layoutengine/standard-testcases/external-graphic_bmp.xml @@ -45,13 +45,13 @@ - - - - - - - - + + + + + + + + diff --git a/test/layoutengine/standard-testcases/external-graphic_emf.xml b/test/layoutengine/standard-testcases/external-graphic_emf.xml index 4dc21d98c..9c3f03302 100644 --- a/test/layoutengine/standard-testcases/external-graphic_emf.xml +++ b/test/layoutengine/standard-testcases/external-graphic_emf.xml @@ -41,9 +41,9 @@ - - - - + + + + diff --git a/test/layoutengine/standard-testcases/external-graphic_eps.xml b/test/layoutengine/standard-testcases/external-graphic_eps.xml index 1171f9f56..5ffb4b410 100644 --- a/test/layoutengine/standard-testcases/external-graphic_eps.xml +++ b/test/layoutengine/standard-testcases/external-graphic_eps.xml @@ -41,9 +41,9 @@ - - - - + + + + diff --git a/test/layoutengine/standard-testcases/external-graphic_png.xml b/test/layoutengine/standard-testcases/external-graphic_png.xml index 0e00d4b1a..aae0daef9 100644 --- a/test/layoutengine/standard-testcases/external-graphic_png.xml +++ b/test/layoutengine/standard-testcases/external-graphic_png.xml @@ -45,14 +45,14 @@ - - - - + + + + - - - - + + + + diff --git a/test/layoutengine/standard-testcases/external-graphic_size_1.xml b/test/layoutengine/standard-testcases/external-graphic_size_1.xml new file mode 100644 index 000000000..e0dfcaa56 --- /dev/null +++ b/test/layoutengine/standard-testcases/external-graphic_size_1.xml @@ -0,0 +1,121 @@ + + + + + +

+ This test checks external-graphics with size properties. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/standard-testcases/external-graphic_tiff.xml b/test/layoutengine/standard-testcases/external-graphic_tiff.xml index ae6f1a2a8..719e64bf4 100644 --- a/test/layoutengine/standard-testcases/external-graphic_tiff.xml +++ b/test/layoutengine/standard-testcases/external-graphic_tiff.xml @@ -53,21 +53,21 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/fox_external-document_1.xml b/test/layoutengine/standard-testcases/fox_external-document_1.xml index ca73806e8..4b31809ab 100644 --- a/test/layoutengine/standard-testcases/fox_external-document_1.xml +++ b/test/layoutengine/standard-testcases/fox_external-document_1.xml @@ -38,15 +38,15 @@ - + - - - - - - - + + + + + + + diff --git a/test/layoutengine/standard-testcases/fox_external-document_2.xml b/test/layoutengine/standard-testcases/fox_external-document_2.xml index 5bce78f35..abd5fd2bf 100644 --- a/test/layoutengine/standard-testcases/fox_external-document_2.xml +++ b/test/layoutengine/standard-testcases/fox_external-document_2.xml @@ -63,19 +63,19 @@ - + - + - - + + - + - - + + - + diff --git a/test/layoutengine/standard-testcases/fox_external-document_3.xml b/test/layoutengine/standard-testcases/fox_external-document_3.xml new file mode 100644 index 000000000..ece892346 --- /dev/null +++ b/test/layoutengine/standard-testcases/fox_external-document_3.xml @@ -0,0 +1,53 @@ + + + + + +

+ This test checks fox:external-document with multi-page images. +

+
+ + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/standard-testcases/inline_vertical-align_2.xml b/test/layoutengine/standard-testcases/inline_vertical-align_2.xml index 509275a01..7019ba603 100644 --- a/test/layoutengine/standard-testcases/inline_vertical-align_2.xml +++ b/test/layoutengine/standard-testcases/inline_vertical-align_2.xml @@ -71,52 +71,52 @@ - + - - - - - - + + + + + + - + - + - - - - + + + + - + - - + + - + - + - - + + - + - + diff --git a/test/resources/images/fop-logo-color-24bit.png b/test/resources/images/fop-logo-color-24bit.png new file mode 100644 index 000000000..ba7513fe1 Binary files /dev/null and b/test/resources/images/fop-logo-color-24bit.png differ diff --git a/test/resources/images/fop-logo-color-palette-2bit.png b/test/resources/images/fop-logo-color-palette-2bit.png new file mode 100644 index 000000000..048925640 Binary files /dev/null and b/test/resources/images/fop-logo-color-palette-2bit.png differ diff --git a/test/resources/images/fop-logo-color-palette-4bit.png b/test/resources/images/fop-logo-color-palette-4bit.png new file mode 100644 index 000000000..492792ec0 Binary files /dev/null and b/test/resources/images/fop-logo-color-palette-4bit.png differ diff --git a/test/resources/images/fop-logo-color-palette-8bit.png b/test/resources/images/fop-logo-color-palette-8bit.png new file mode 100644 index 000000000..ce159f01b Binary files /dev/null and b/test/resources/images/fop-logo-color-palette-8bit.png differ diff --git a/test/resources/images/fop-logo-gray-8bit.png b/test/resources/images/fop-logo-gray-8bit.png new file mode 100644 index 000000000..9c5e79d5c Binary files /dev/null and b/test/resources/images/fop-logo-gray-8bit.png differ diff --git a/test/resources/images/fop-logo-mono-1bit.png b/test/resources/images/fop-logo-mono-1bit.png new file mode 100644 index 000000000..efc3811d2 Binary files /dev/null and b/test/resources/images/fop-logo-mono-1bit.png differ diff --git a/test/resources/images/img-with-tiff-preview.eps b/test/resources/images/img-with-tiff-preview.eps new file mode 100644 index 000000000..20f494b01 Binary files /dev/null and b/test/resources/images/img-with-tiff-preview.eps differ diff --git a/test/resources/images/multi-page.tiff b/test/resources/images/multi-page.tiff new file mode 100644 index 000000000..0ab4aabc3 Binary files /dev/null and b/test/resources/images/multi-page.tiff differ diff --git a/test/resources/images/no-resolution.bmp b/test/resources/images/no-resolution.bmp new file mode 100644 index 000000000..a94701fd2 Binary files /dev/null and b/test/resources/images/no-resolution.bmp differ diff --git a/test/resources/images/no-resolution.tif b/test/resources/images/no-resolution.tif new file mode 100644 index 000000000..18e778b45 Binary files /dev/null and b/test/resources/images/no-resolution.tif differ diff --git a/test/resources/images/testChart.wmf b/test/resources/images/testChart.wmf new file mode 100644 index 000000000..42c825a4b Binary files /dev/null and b/test/resources/images/testChart.wmf differ diff --git a/test/resources/images/tiff_group3-1d.tif b/test/resources/images/tiff_group3-1d.tif new file mode 100644 index 000000000..c6ca273b0 Binary files /dev/null and b/test/resources/images/tiff_group3-1d.tif differ diff --git a/test/resources/images/tiff_group3-2d.tif b/test/resources/images/tiff_group3-2d.tif new file mode 100644 index 000000000..f5438070c Binary files /dev/null and b/test/resources/images/tiff_group3-2d.tif differ diff --git a/test/resources/images/tiff_group3-multi-strip.tif b/test/resources/images/tiff_group3-multi-strip.tif new file mode 100644 index 000000000..182db2790 Binary files /dev/null and b/test/resources/images/tiff_group3-multi-strip.tif differ diff --git a/test/xml/pdf-a/with-eps.fo b/test/xml/pdf-a/with-eps.fo deleted file mode 100644 index 0f8913f01..000000000 --- a/test/xml/pdf-a/with-eps.fo +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - Hello World! - - - - -- cgit v1.2.3 From 6101c1c37f5f2f5be2cfccc91f55112084ce6882 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 11 Jan 2008 20:03:36 +0000 Subject: Removed stray reference to ImageFactory. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@611285 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/properties/CommonBorderPaddingBackground.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index 68d4bcab1..96c1e80e2 100755 --- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java +++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java @@ -28,10 +28,10 @@ import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; -import org.apache.fop.image.ImageFactory; /** * Stores all common border and padding properties. @@ -235,7 +235,7 @@ public class CommonBorderPaddingBackground { Constants.PR_BACKGROUND_POSITION_VERTICAL).getLength(); //Additional processing: preload image - String uri = ImageFactory.getURL(backgroundImage); + String uri = URISpecification.getURL(backgroundImage); FOUserAgent userAgent = pList.getFObj().getUserAgent(); ImageManager manager = userAgent.getFactory().getImageManager(); ImageSessionContext sessionContext = userAgent.getImageSessionContext(); -- cgit v1.2.3 From e77d6863bbe2671af4a34d250417867264631238 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 14 Jan 2008 11:01:11 +0000 Subject: java.net.URI doesn't eat non-escaped URIs so I added an escaping method to URISpecification that should cover most cases. Usually, it's just about a space in a filename. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@611766 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/datatypes/URISpecification.java | 85 ++++++++++++++++++++++ .../layoutmgr/ExternalDocumentLayoutManager.java | 3 +- .../fop/datatypes/URISpecificationTestCase.java | 61 ++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 test/java/org/apache/fop/datatypes/URISpecificationTestCase.java (limited to 'src') diff --git a/src/java/org/apache/fop/datatypes/URISpecification.java b/src/java/org/apache/fop/datatypes/URISpecification.java index 2a3a3cba9..99d445b4d 100644 --- a/src/java/org/apache/fop/datatypes/URISpecification.java +++ b/src/java/org/apache/fop/datatypes/URISpecification.java @@ -19,6 +19,9 @@ package org.apache.fop.datatypes; +import java.io.UnsupportedEncodingException; + + /** * This class contains method to deal with the datatype from XSL-FO. */ @@ -52,5 +55,87 @@ public class URISpecification { return href; } + private static final String PUNCT = ",;:$&+="; + private static final String RESERVED = PUNCT + "?/[]@"; + + private static boolean isValidURIChar(char ch) { + return true; + } + + private static boolean isDigit(char ch) { + return (ch >= '0' && ch <= '9'); + } + + private static boolean isAlpha(char ch) { + return (ch >= 'A' && ch <= 'Z') || (ch >= 'A' && ch <= 'z'); + } + + private static boolean isHexDigit(char ch) { + return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'); + } + + private static boolean isReserved(char ch) { + if (RESERVED.indexOf(ch) >= 0) { + return true; + } else if ('#' == ch) { + //# is not a reserved character but is used for the fragment + return true; + } + return false; + } + + private static boolean isUnreserved(char ch) { + if (isDigit(ch) || isAlpha(ch)) { + return true; + } else if ("_-!.~\'()*".indexOf(ch) >= 0) { + //remaining unreserved characters + return true; + } + return false; + } + + private final static char[] HEX_DIGITS = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + private static void appendEscape(StringBuffer sb, byte b) { + sb.append('%').append(HEX_DIGITS[(b >> 4) & 0x0f]).append(HEX_DIGITS[(b >> 0) & 0x0f]); + } + + /** + * Escapes any illegal URI character in a given URI, for example, it escapes a space to "%20". + * Note: This method does not "parse" the URI and therefore does not treat the individual + * components (user-info, path, query etc.) individually. + * @param uri the URI to inspect + * @return the escaped URI + */ + public static String escapeURI(String uri) { + uri = getURL(uri); + StringBuffer sb = new StringBuffer(); + for (int i = 0, c = uri.length(); i < c; i++) { + char ch = uri.charAt(i); + if (ch == '%') { + if (i < c - 3 && isHexDigit(uri.charAt(i + 1)) && isHexDigit(uri.charAt(i + 2))) { + sb.append(ch); + continue; + } + } + if (isReserved(ch) || isUnreserved(ch)) { + //Note: this may not be accurate for some very special cases. + sb.append(ch); + } else { + try { + byte[] utf8 = Character.toString(ch).getBytes("UTF-8"); + for (int j = 0, cj = utf8.length; j < cj; j++) { + appendEscape(sb, utf8[j]); + } + } catch (UnsupportedEncodingException e) { + throw new Error("Incompatible JVM. UTF-8 not supported."); + } + } + } + return sb.toString(); + } } diff --git a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java index 0e51517f2..89065185b 100644 --- a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java @@ -44,6 +44,7 @@ import org.apache.fop.area.RegionViewport; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.Viewport; import org.apache.fop.datatypes.FODimension; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExternalDocument; import org.apache.fop.layoutmgr.inline.ImageLayout; @@ -114,7 +115,7 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan } URI originalURI; try { - originalURI = new URI(uri); + originalURI = new URI(URISpecification.escapeURI(uri)); int pageIndex = 1; while (hasMoreImages) { URI tempURI = new URI(originalURI.getScheme(), diff --git a/test/java/org/apache/fop/datatypes/URISpecificationTestCase.java b/test/java/org/apache/fop/datatypes/URISpecificationTestCase.java new file mode 100644 index 000000000..4f6f24f95 --- /dev/null +++ b/test/java/org/apache/fop/datatypes/URISpecificationTestCase.java @@ -0,0 +1,61 @@ +/* + * 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.datatypes; + +import junit.framework.TestCase; + +/** + * Tests for URISpecification. + */ +public class URISpecificationTestCase extends TestCase { + + public void testGetURL() throws Exception { + String actual; + + actual = URISpecification.getURL("http://localhost/test"); + assertEquals("http://localhost/test", actual); + + actual = URISpecification.getURL("url(http://localhost/test)"); + assertEquals("http://localhost/test", actual); + + actual = URISpecification.getURL("url('http://localhost/test')"); + assertEquals("http://localhost/test", actual); + + actual = URISpecification.getURL("url(\"http://localhost/test\")"); + assertEquals("http://localhost/test", actual); + } + + public void testEscapeURI() throws Exception { + String actual; + + actual = URISpecification.escapeURI("http://localhost/test"); + assertEquals("http://localhost/test", actual); + + actual = URISpecification.escapeURI("http://localhost/test%20test"); + assertEquals("http://localhost/test%20test", actual); + + actual = URISpecification.escapeURI("http://localhost/test test"); + assertEquals("http://localhost/test%20test", actual); + + actual = URISpecification.escapeURI("http://localhost/test test.pdf#page=6"); + assertEquals("http://localhost/test%20test.pdf#page=6", actual); + } + +} -- cgit v1.2.3 From 9ef58f47298a2fb14d866e296f1c8b47607e236e Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 14 Jan 2008 11:02:34 +0000 Subject: Restore default constructor for PDFArray. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@611767 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFArray.java | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFArray.java b/src/java/org/apache/fop/pdf/PDFArray.java index 2cb2adb1d..ec713b313 100644 --- a/src/java/org/apache/fop/pdf/PDFArray.java +++ b/src/java/org/apache/fop/pdf/PDFArray.java @@ -45,6 +45,13 @@ public class PDFArray extends PDFObject { super(parent); } + /** + * Create a new, empty array object with no parent. + */ + public PDFArray() { + this(null); + } + /** * Create an array object. * @param parent the array's parent if any @@ -120,22 +127,14 @@ public class PDFArray extends PDFObject { return this.values.get(index); } - /** - * Adds a new value to the array. - * @param obj the value - */ - public void add(PDFObject obj) { - if (obj != null) { - obj.setParent(this); - } - this.values.add(obj); - } - /** * Adds a new value to the array. * @param obj the value */ public void add(Object obj) { + if (obj instanceof PDFObject) { + ((PDFObject)obj).setParent(this); + } this.values.add(obj); } -- cgit v1.2.3 From 42cd3311c35480cb78129029b19eadf37ab362c6 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 14 Jan 2008 11:02:54 +0000 Subject: Clear parent if later on an object number is assigned to a PDFObject which means it is a top-level object. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@611768 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFObject.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java index 4bfd805f4..f791791b7 100644 --- a/src/java/org/apache/fop/pdf/PDFObject.java +++ b/src/java/org/apache/fop/pdf/PDFObject.java @@ -102,6 +102,7 @@ public abstract class PDFObject implements PDFWritable { */ public void setObjectNumber(int objnum) { this.objnum = objnum; + setParent(null); if (log.isTraceEnabled()) { log.trace("Assigning " + this + " object number " + objnum); } -- cgit v1.2.3 From 74b1c2e7f16021b7fce5413ae8308c10ea2cbdb9 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 16 Jan 2008 20:14:56 +0000 Subject: Fixed dead link. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@612560 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/team.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index 584a66e04..63d943702 100644 --- a/src/documentation/content/xdocs/team.xml +++ b/src/documentation/content/xdocs/team.xml @@ -70,7 +70,7 @@
  • Jeremias Märki (JM) is an independent software engineer and consultant from Lucerne, Switzerland. He's also - the creator of Barcode4J. + the creator of Barcode4J. See his home page for more information about him.
  • -- cgit v1.2.3 From 5b110dff04202cb6e9fd4181e231715b96372cc6 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 17 Jan 2008 10:36:36 +0000 Subject: added serial version id git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@612785 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/inline/ForeignObject.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/area/inline/ForeignObject.java b/src/java/org/apache/fop/area/inline/ForeignObject.java index 4daa41957..953d969f6 100644 --- a/src/java/org/apache/fop/area/inline/ForeignObject.java +++ b/src/java/org/apache/fop/area/inline/ForeignObject.java @@ -31,6 +31,8 @@ import org.w3c.dom.Document; */ public class ForeignObject extends Area { + private static final long serialVersionUID = -214947698798577885L; + private Document doc; private String namespace; -- cgit v1.2.3 From 341da37f0397ee32757588ffe5d72b63ef51db5b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Jan 2008 13:37:04 +0000 Subject: Fixed logic error setting the transformation matrix for block-container viewports (applies to absolute and fixed block-containers only). The CTM now only rotates and shifts the content as necessary for reference-orientation and writing-mode. All the rest of the transformation is done by the renderer which allows to add additional transformations as made possible by fox:transform (see below). Important: External renderer implementations need to adjust for the change and implement the new method concatenateTransformationMatrix(AffineTransform) if the renderer is derived from AbstractPathOrientedRenderer. New extension attribute fox:transform on fo:block-container allows free-form transformation (rotation, scaling etc.) of absolute and fixed block-containers. Supported only for PDF, PS and Java2D-based renderers. Added missing region background painting for PCL renderer. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@612815 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/extensions.xml | 21 +++++ src/java/org/apache/fop/area/CTM.java | 25 ++++++ .../fop/layoutmgr/BlockContainerLayoutManager.java | 27 +++---- .../fop/render/AbstractPathOrientedRenderer.java | 81 +++++++++++-------- .../org/apache/fop/render/AbstractRenderer.java | 29 +++++++ .../org/apache/fop/render/afp/AFPRenderer.java | 7 ++ .../apache/fop/render/java2d/Java2DRenderer.java | 9 ++- .../org/apache/fop/render/pcl/PCLRenderer.java | 90 +++++++++++++++------- .../org/apache/fop/render/pdf/PDFRenderer.java | 60 +++++++-------- src/java/org/apache/fop/render/ps/PSRenderer.java | 24 +++--- .../org/apache/fop/render/txt/TXTRenderer.java | 9 +++ status.xml | 16 ++++ ...k-container_absolute-position_display-align.xml | 10 +-- .../block-container_absolute-position_fixed.xml | 4 +- ...k-container_absolute-position_fox-transform.xml | 54 +++++++++++++ 15 files changed, 339 insertions(+), 127 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block-container_absolute-position_fox-transform.xml (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/extensions.xml b/src/documentation/content/xdocs/trunk/extensions.xml index f54afea00..4f6911f9b 100644 --- a/src/documentation/content/xdocs/trunk/extensions.xml +++ b/src/documentation/content/xdocs/trunk/extensions.xml @@ -187,6 +187,27 @@ to following pages. Here is an example of FO code creating such a table-header:<
    +
    + Free-form Transformation for fo:block-container +

    + For fo:block-container elements whose absolute-position set to + "absolute" or "fixed" you can use the extension attribute fox:transform + to apply a free-form transformation to the whole block-container. The content of the + fox:transform attribute is the same as for + SVG's transform attribute. + The transformation specified here is performed in addition to other implicit + transformations of the block-container (resulting from top, left and other properties) + and after them. +

    +

    + An example: fox:transform="rotate(45)" would rotate the block-container + by 45 degrees clock-wise around its upper-left corner. +

    + + This extension attribute doesn't work for all output formats! It's currently only + supported for PDF, PS and Java2D-based renderers. + +
    diff --git a/src/java/org/apache/fop/area/CTM.java b/src/java/org/apache/fop/area/CTM.java index d27e4ca20..c9fb52311 100644 --- a/src/java/org/apache/fop/area/CTM.java +++ b/src/java/org/apache/fop/area/CTM.java @@ -20,6 +20,7 @@ package org.apache.fop.area; import java.awt.Rectangle; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.Serializable; @@ -100,6 +101,22 @@ public class CTM implements Serializable { this.f = ctm.f; } + /** + * Initialize a CTM with the values of an AffineTransform. + * + * @param at the transformation matrix + */ + public CTM(AffineTransform at) { + double[] matrix = new double[6]; + at.getMatrix(matrix); + this.a = matrix[0]; + this.b = matrix[1]; + this.c = matrix[2]; + this.d = matrix[3]; + this.e = matrix[4]; + this.f = matrix[5]; + } + /** * Return a CTM which will transform coordinates for a particular writing-mode * into normalized first quandrant coordinates. @@ -245,6 +262,14 @@ public class CTM implements Serializable { return new double[]{a, b, c, d, e, f}; } + /** + * Returns this CTM as an AffineTransform object. + * @return the AffineTransform representation + */ + public AffineTransform toAffineTransform() { + return new AffineTransform(toArray()); + } + /** * Construct a coordinate transformation matrix (CTM). * @param absRefOrient absolute reference orientation diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 03aa380d2..ab153090b 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -19,25 +19,26 @@ package org.apache.fop.layoutmgr; +import java.awt.Point; +import java.awt.geom.Rectangle2D; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; -import java.awt.Point; -import java.awt.geom.Rectangle2D; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; -import org.apache.fop.area.BlockViewport; import org.apache.fop.area.Block; +import org.apache.fop.area.BlockViewport; +import org.apache.fop.area.CTM; import org.apache.fop.area.Trait; +import org.apache.fop.datatypes.FODimension; +import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.BlockContainer; import org.apache.fop.fo.properties.CommonAbsolutePosition; import org.apache.fop.layoutmgr.inline.InlineLayoutManager; -import org.apache.fop.area.CTM; -import org.apache.fop.datatypes.FODimension; -import org.apache.fop.datatypes.Length; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; @@ -485,15 +486,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager vpContentBPD = allocBPD - getBPIndents(); setContentAreaIPD(allocIPD - getIPIndents()); - double contentRectOffsetX = offset.getX(); - contentRectOffsetX += getBlockContainerFO() - .getCommonMarginBlock().startIndent.getValue(this); - double contentRectOffsetY = offset.getY(); - contentRectOffsetY += getSpaceBefore(); //TODO Uhm, is that necessary? - contentRectOffsetY += getBlockContainerFO() - .getCommonBorderPaddingBackground().getBorderBeforeWidth(false); - contentRectOffsetY += getBlockContainerFO() - .getCommonBorderPaddingBackground().getPaddingBefore(false, this); + double contentRectOffsetX = 0; + double contentRectOffsetY = 0; Rectangle2D rect = new Rectangle2D.Double( contentRectOffsetX, contentRectOffsetY, @@ -871,7 +865,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } else { viewportBlockArea.setBPD(getContentAreaBPD()); } - + transferForeignAttributes(viewportBlockArea); + TraitSetter.setProducerID(viewportBlockArea, getBlockContainerFO().getId()); TraitSetter.addBorders(viewportBlockArea, getBlockContainerFO().getCommonBorderPaddingBackground(), diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index ac11d56d5..285cc5ded 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -21,12 +21,15 @@ package org.apache.fop.render; import java.awt.Color; import java.awt.Rectangle; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.util.List; import java.util.Map; import org.w3c.dom.Document; +import org.apache.batik.parser.AWTTransformProducer; + import org.apache.xmlgraphics.image.loader.ImageSize; import org.apache.fop.area.Area; @@ -39,8 +42,10 @@ import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.Viewport; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.FontMetrics; import org.apache.fop.traits.BorderProps; +import org.apache.fop.util.QName; /** * Abstract base class for renderers like PDF and PostScript where many painting operations @@ -401,6 +406,8 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { } + private final QName FOX_TRANSFORM = new QName(ExtensionElementMapping.URI, "fox:transform"); + /** {@inheritDoc} */ protected void renderBlockViewport(BlockViewport bv, List children) { // clip and position viewport if necessary @@ -408,25 +415,17 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { // save positions int saveIP = currentIPPosition; int saveBP = currentBPPosition; - //String saveFontName = currentFontName; CTM ctm = bv.getCTM(); int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore(); - float x, y; - x = (float)(bv.getXOffset() + containingIPPosition) / 1000f; - y = (float)(bv.getYOffset() + containingBPPosition) / 1000f; //This is the content-rect float width = (float)bv.getIPD() / 1000f; float height = (float)bv.getBPD() / 1000f; - if (bv.getPositioning() == Block.ABSOLUTE || bv.getPositioning() == Block.FIXED) { - currentIPPosition = bv.getXOffset(); - currentBPPosition = bv.getYOffset(); - //For FIXED, we need to break out of the current viewports to the //one established by the page. We save the state stack for restoration //after the block-container has been painted. See below. @@ -435,37 +434,51 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { breakOutList = breakOutOfStateStack(); } - CTM tempctm = new CTM(containingIPPosition, containingBPPosition); - ctm = tempctm.multiply(ctm); - - //Adjust for spaces (from margin or indirectly by start-indent etc. - x += bv.getSpaceStart() / 1000f; - currentIPPosition += bv.getSpaceStart(); + AffineTransform positionTransform = new AffineTransform(); + positionTransform.translate(bv.getXOffset(), bv.getYOffset()); - y += bv.getSpaceBefore() / 1000f; - currentBPPosition += bv.getSpaceBefore(); + //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle + positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); + + //Free transformation for the block-container viewport + String transf; + transf = bv.getForeignAttributeValue(FOX_TRANSFORM); + if (transf != null) { + AffineTransform freeTransform = AWTTransformProducer.createAffineTransform(transf); + positionTransform.concatenate(freeTransform); + } + saveGraphicsState(); + //Viewport position + concatenateTransformationMatrix(mptToPt(positionTransform)); + + //Background and borders float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; + drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight); - drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight); - - //Now adjust for border/padding - currentIPPosition += borderPaddingStart; - currentBPPosition += borderPaddingBefore; + //Shift to content rectangle after border painting + AffineTransform contentRectTransform = new AffineTransform(); + contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); + concatenateTransformationMatrix(mptToPt(contentRectTransform)); - Rectangle2D clippingRect = null; + //Clipping if (bv.getClip()) { - clippingRect = new Rectangle(currentIPPosition, currentBPPosition, - bv.getIPD(), bv.getBPD()); + clipRect(0f, 0f, width, height); } - startVParea(ctm, clippingRect); + saveGraphicsState(); + //Set up coordinate system for content rectangle + AffineTransform contentTransform = ctm.toAffineTransform(); + concatenateTransformationMatrix(mptToPt(contentTransform)); + currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); - endVParea(); + restoreGraphicsState(); + restoreGraphicsState(); + if (breakOutList != null) { restoreStateStackAfterBreakOut(breakOutList); } @@ -505,9 +518,15 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { currentBPPosition += (int)(bv.getAllocBPD()); } - //currentFontName = saveFontName; } + /** + * Concatenates the current transformation matrix with the given one, therefore establishing + * a new coordinate system. + * @param at the transformation matrix to process (coordinates in points) + */ + protected abstract void concatenateTransformationMatrix(AffineTransform at); + /** * Render an inline viewport. * This renders an inline viewport by clipping if necessary. @@ -613,10 +632,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { /** * Clip using a rectangular area. - * @param x the x coordinate - * @param y the y coordinate - * @param width the width of the rectangle - * @param height the height of the rectangle + * @param x the x coordinate (in points) + * @param y the y coordinate (in points) + * @param width the width of the rectangle (in points) + * @param height the height of the rectangle (in points) */ protected abstract void clipRect(float x, float y, float width, float height); diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 1fff79f77..c23f7ae8e 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -21,6 +21,7 @@ package org.apache.fop.render; // Java import java.awt.Rectangle; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.OutputStream; @@ -836,4 +837,32 @@ public abstract class AbstractRenderer public String getMimeType() { return null; } + + /** + * Converts a millipoint-based transformation matrix to points. + * @param at a millipoint-based transformation matrix + * @return a point-based transformation matrix + */ + protected AffineTransform mptToPt(AffineTransform at) { + double[] matrix = new double[6]; + at.getMatrix(matrix); + //Convert to points + matrix[4] = matrix[4] / 1000; + matrix[5] = matrix[5] / 1000; + return new AffineTransform(matrix); + } + + /** + * Converts a point-based transformation matrix to millipoints. + * @param at a point-based transformation matrix + * @return a millipoint-based transformation matrix + */ + protected AffineTransform ptToMpt(AffineTransform at) { + double[] matrix = new double[6]; + at.getMatrix(matrix); + //Convert to millipoints + matrix[4] = matrix[4] * 1000; + matrix[5] = matrix[5] * 1000; + return new AffineTransform(matrix); + } } diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index cdb2f2ec8..5cdd55d98 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -22,6 +22,7 @@ package org.apache.fop.render.afp; import java.awt.Color; import java.awt.Point; import java.awt.Rectangle; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; import java.io.FileNotFoundException; @@ -525,6 +526,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // currentFontName = saveFontName; } + /** {@inheritDoc} */ + protected void concatenateTransformationMatrix(AffineTransform at) { + //Not used here since AFPRenderer defines its own renderBlockViewport() method. + throw new UnsupportedOperationException("NYI"); + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 0f73c5761..63d5ad04c 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -399,9 +399,12 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem state = (Java2DGraphicsState)stateStack.pop(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ + protected void concatenateTransformationMatrix(AffineTransform at) { + state.transform(at); + } + + /** {@inheritDoc} */ protected void startVParea(CTM ctm, Rectangle2D clippingRect) { saveGraphicsState(); diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index b48c28089..1d606e919 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -66,6 +66,7 @@ import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.CTM; import org.apache.fop.area.PageViewport; +import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.AbstractTextArea; import org.apache.fop.area.inline.ForeignObject; @@ -92,6 +93,12 @@ import org.apache.fop.traits.BorderProps; import org.apache.fop.util.QName; import org.apache.fop.util.UnitConv; +/* Note: + * There are some commonalities with AbstractPathOrientedRenderer but it's not possible + * to derive from it due to PCL's restrictions. We may need an additional common subclass to + * avoid methods copied from AbstractPathOrientedRenderer. Or we wait until after the IF redesign. + */ + /** * Renderer for the PCL 5 printer language. It also uses HP GL/2 for certain graphic elements. */ @@ -580,6 +587,24 @@ public class PCLRenderer extends PrintRenderer { drawBackAndBorders(block, startx, starty, width, height); } + /** + * {@inheritDoc} + * @todo Copied from AbstractPathOrientedRenderer + */ + protected void handleRegionTraits(RegionViewport region) { + Rectangle2D viewArea = region.getViewArea(); + float startx = (float)(viewArea.getX() / 1000f); + float starty = (float)(viewArea.getY() / 1000f); + float width = (float)(viewArea.getWidth() / 1000f); + float height = (float)(viewArea.getHeight() / 1000f); + + if (region.getRegionReference().getRegionClass() == FO_REGION_BODY) { + currentBPPosition = region.getBorderAndPaddingWidthBefore(); + currentIPPosition = region.getBorderAndPaddingWidthStart(); + } + drawBackAndBorders(region, startx, starty, width, height); + } + /** * {@inheritDoc} */ @@ -881,14 +906,10 @@ public class PCLRenderer extends PrintRenderer { // save positions int saveIP = currentIPPosition; int saveBP = currentBPPosition; - //String saveFontName = currentFontName; CTM ctm = bv.getCTM(); int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore(); - float x, y; - x = (float)(bv.getXOffset() + containingIPPosition) / 1000f; - y = (float)(bv.getYOffset() + containingBPPosition) / 1000f; //This is the content-rect float width = (float)bv.getIPD() / 1000f; float height = (float)bv.getBPD() / 1000f; @@ -897,9 +918,6 @@ public class PCLRenderer extends PrintRenderer { if (bv.getPositioning() == Block.ABSOLUTE || bv.getPositioning() == Block.FIXED) { - currentIPPosition = bv.getXOffset(); - currentBPPosition = bv.getYOffset(); - //For FIXED, we need to break out of the current viewports to the //one established by the page. We save the state stack for restoration //after the block-container has been painted. See below. @@ -908,36 +926,42 @@ public class PCLRenderer extends PrintRenderer { breakOutList = breakOutOfStateStack(); } - CTM tempctm = new CTM(containingIPPosition, containingBPPosition); - ctm = tempctm.multiply(ctm); - - //Adjust for spaces (from margin or indirectly by start-indent etc. - x += bv.getSpaceStart() / 1000f; - currentIPPosition += bv.getSpaceStart(); + AffineTransform positionTransform = new AffineTransform(); + positionTransform.translate(bv.getXOffset(), bv.getYOffset()); - y += bv.getSpaceBefore() / 1000f; - currentBPPosition += bv.getSpaceBefore(); + //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle + positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); + saveGraphicsState(); + //Viewport position + concatenateTransformationMatrix(mptToPt(positionTransform)); + + //Background and borders float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; + drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight); - drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight); - - //Now adjust for border/padding - currentIPPosition += borderPaddingStart; - currentBPPosition += borderPaddingBefore; + //Shift to content rectangle after border painting + AffineTransform contentRectTransform = new AffineTransform(); + contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); + concatenateTransformationMatrix(mptToPt(contentRectTransform)); - Rectangle2D clippingRect = null; + //Clipping if (bv.getClip()) { - clippingRect = new Rectangle(currentIPPosition, currentBPPosition, - bv.getIPD(), bv.getBPD()); + clipRect(0f, 0f, width, height); } - startVParea(ctm, clippingRect); + saveGraphicsState(); + //Set up coordinate system for content rectangle + AffineTransform contentTransform = ctm.toAffineTransform(); + concatenateTransformationMatrix(mptToPt(contentTransform)); + currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); - endVParea(); + + restoreGraphicsState(); + restoreGraphicsState(); if (breakOutList != null) { restoreStateStackAfterBreakOut(breakOutList); @@ -981,6 +1005,18 @@ public class PCLRenderer extends PrintRenderer { //currentFontName = saveFontName; } + /** + * Concatenates the current transformation matrix with the given one, therefore establishing + * a new coordinate system. + * @param at the transformation matrix to process (coordinates in points) + */ + protected void concatenateTransformationMatrix(AffineTransform at) { + if (!at.isIdentity()) { + graphicContext.transform(ptToMpt(at)); + changePrintDirection(); + } + } + private List breakOutOfStateStack() { log.debug("Block.FIXED --> break out"); List breakOutList = new java.util.ArrayList(); @@ -1280,8 +1316,8 @@ public class PCLRenderer extends PrintRenderer { final BorderProps bpsStart, final BorderProps bpsEnd) { Graphics2DAdapter g2a = getGraphics2DAdapter(); final Rectangle.Float effBorderRect = new Rectangle2D.Float( - borderRect.x - (currentIPPosition / 1000f), - borderRect.y - (currentBPPosition / 1000f), + 0, + 0, borderRect.width, borderRect.height); final Rectangle paintRect = new Rectangle( diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 3b28cc34c..f32a25725 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -639,16 +639,24 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } } - /** Saves the graphics state of the rendering engine. */ + /** {@inheritDoc} */ protected void saveGraphicsState() { endTextObject(); + currentState.push(); currentStream.add("q\n"); } - /** Restores the last graphics state of the rendering engine. */ - protected void restoreGraphicsState() { + private void restoreGraphicsState(boolean popState) { endTextObject(); currentStream.add("Q\n"); + if (popState) { + currentState.pop(); + } + } + + /** {@inheritDoc} */ + protected void restoreGraphicsState() { + restoreGraphicsState(true); } /** Indicates the beginning of a text object. */ @@ -786,16 +794,14 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { this.pdfDoc.output(ostream); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startVParea(CTM ctm, Rectangle2D clippingRect) { + saveGraphicsState(); + //currentState.push(); // Set the given CTM in the graphics state - currentState.push(); currentState.concatenate( new AffineTransform(CTMHelper.toPDFArray(ctm))); - saveGraphicsState(); if (clippingRect != null) { clipRect((float)clippingRect.getX() / 1000f, (float)clippingRect.getY() / 1000f, @@ -806,14 +812,21 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { currentStream.add(CTMHelper.toPDFString(ctm) + " cm\n"); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endVParea() { restoreGraphicsState(); - currentState.pop(); + //currentState.pop(); } + /** {@inheritDoc} */ + protected void concatenateTransformationMatrix(AffineTransform at) { + System.out.println(at); + if (!at.isIdentity()) { + currentState.concatenate(at); + currentStream.add(CTMHelper.toPDFString(at, false) + " cm\n"); + } + } + /** * Handle the traits for a region * This is used to draw the traits for the given page region. @@ -1015,15 +1028,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } } - /** - * Clip a rectangular area. - * write a clipping operation given coordinates in the current - * transform. - * @param x the x coordinate - * @param y the y coordinate - * @param width the width of the area - * @param height the height of the area - */ + /** {@inheritDoc} */ protected void clipRect(float x, float y, float width, float height) { currentStream.add(format(x) + " " + format(y) + " " + format(width) + " " + format(height) + " re "); @@ -1104,7 +1109,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { comment("------ break out!"); } breakOutList.add(0, data); //Insert because of stack-popping - restoreGraphicsState(); + restoreGraphicsState(false); } return breakOutList; } @@ -1114,23 +1119,14 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * @param breakOutList the state stack to restore. */ protected void restoreStateStackAfterBreakOut(List breakOutList) { - CTM tempctm; comment("------ restoring context after break-out..."); PDFState.Data data; Iterator i = breakOutList.iterator(); - double[] matrix = new double[6]; while (i.hasNext()) { data = (PDFState.Data)i.next(); - currentState.push(); saveGraphicsState(); AffineTransform at = data.getTransform(); - if (!at.isIdentity()) { - currentState.concatenate(at); - at.getMatrix(matrix); - tempctm = new CTM(matrix[0], matrix[1], matrix[2], matrix[3], - matrix[4] * 1000, matrix[5] * 1000); - currentStream.add(CTMHelper.toPDFString(tempctm) + " cm\n"); - } + concatenateTransformationMatrix(at); //TODO Break-out: Also restore items such as line width and color //Left out for now because all this painting stuff is very //inconsistent. Some values go over PDFState, some don't. diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index 21ae85259..7e3ce87a2 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -21,6 +21,7 @@ package org.apache.fop.render.ps; // Java import java.awt.Color; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; import java.io.File; @@ -326,15 +327,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer writeln("clip newpath"); } - /** - * Clip an area. - * Write a clipping operation given coordinates in the current - * transform. - * @param x the x coordinate - * @param y the y coordinate - * @param width the width of the area - * @param height the height of the area - */ + /** {@inheritDoc} */ protected void clipRect(float x, float y, float width, float height) { try { gen.defineRect(x, y, width, height); @@ -619,6 +612,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer /** Restores the last graphics state of the rendering engine. */ public void restoreGraphicsState() { try { + endTextObject(); //delegate gen.restoreGraphicsState(); } catch (IOException ioe) { @@ -657,6 +651,15 @@ public class PSRenderer extends AbstractPathOrientedRenderer } } + /** {@inheritDoc} */ + protected void concatenateTransformationMatrix(AffineTransform at) { + try { + gen.concatMatrix(at); + } catch (IOException ioe) { + handleIOTrouble(ioe); + } + } + private String getPostScriptNameForFontKey(String key) { Map fonts = fontInfo.getFonts(); Typeface tf = (Typeface)fonts.get(key); @@ -1284,9 +1287,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer /** Indicates the end of a text object. */ protected void endTextObject() { if (inTextMode) { + inTextMode = false; //set before restoreGraphicsState() to avoid recursion writeln("ET"); restoreGraphicsState(); - inTextMode = false; } } @@ -1466,7 +1469,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer * {@inheritDoc} */ protected void endVParea() { - endTextObject(); restoreGraphicsState(); } diff --git a/src/java/org/apache/fop/render/txt/TXTRenderer.java b/src/java/org/apache/fop/render/txt/TXTRenderer.java index f1d959553..b6d09d769 100644 --- a/src/java/org/apache/fop/render/txt/TXTRenderer.java +++ b/src/java/org/apache/fop/render/txt/TXTRenderer.java @@ -21,6 +21,7 @@ package org.apache.fop.render.txt; import java.awt.Color; import java.awt.Point; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.OutputStream; @@ -322,6 +323,7 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ protected void saveGraphicsState() { + currentState.push(new CTM()); } /** @@ -329,6 +331,7 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ protected void restoreGraphicsState() { + currentState.pop(); } /** @@ -564,4 +567,10 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { protected void endVParea() { currentState.pop(); } + + /** {@inheritDoc} */ + protected void concatenateTransformationMatrix(AffineTransform at) { + currentState.push(new CTM(ptToMpt(at))); + } + } diff --git a/status.xml b/status.xml index 5cf11f580..917598bbe 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,22 @@ + + Compliance fix: for absolutely positioned block-containers, "top" wasn't + interpreted correctly. + + + New extension attribute fox:transform on fo:block-container allows free-form transformation + (rotation, scaling etc.) of absolute and fixed block-containers. Supported only + for PDF, PS and Java2D-based renderers. + + + Fixed logic error setting the transformation matrix for block-container viewports + (applies to absolute and fixed block-containers only). + Important: External renderer implementations need to adjust for the change and implement + the new method concatenateTransformationMatrix(AffineTransform) if the renderer is + derived from AbstractPathOrientedRenderer. + A new image loading framework has been introduced to fix various problems with external graphics and improve performance. diff --git a/test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml b/test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml index 6fb1916c6..667d2a37c 100644 --- a/test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml +++ b/test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml @@ -58,7 +58,7 @@ - + @@ -74,7 +74,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + diff --git a/test/layoutengine/standard-testcases/block-container_absolute-position_fixed.xml b/test/layoutengine/standard-testcases/block-container_absolute-position_fixed.xml index 54db8dea7..b35fbadfe 100644 --- a/test/layoutengine/standard-testcases/block-container_absolute-position_fixed.xml +++ b/test/layoutengine/standard-testcases/block-container_absolute-position_fixed.xml @@ -56,8 +56,8 @@ - - + + diff --git a/test/layoutengine/standard-testcases/block-container_absolute-position_fox-transform.xml b/test/layoutengine/standard-testcases/block-container_absolute-position_fox-transform.xml new file mode 100644 index 000000000..2061ccf77 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_absolute-position_fox-transform.xml @@ -0,0 +1,54 @@ + + + + + +

    + This test checks absolutely positioned block-containers with fox:transform. +

    +
    + + + + + + + + + + + ro = 0 + + + ro = 90 + + + ro = 180 + + + ro = 270 + + + + + + + + + +
    -- cgit v1.2.3 From 43a55cf8498e0f8400e3eeadcadce52d5765c2c2 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 18 Jan 2008 15:25:26 +0000 Subject: Copy/Paste problem with TTF has long been fixed. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@613185 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/0.93/fonts.xml | 13 +------------ src/documentation/content/xdocs/0.94/fonts.xml | 13 +------------ src/documentation/content/xdocs/trunk/fonts.xml | 13 +------------ 3 files changed, 3 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/0.93/fonts.xml b/src/documentation/content/xdocs/0.93/fonts.xml index ca6209c6d..53d4bd97f 100644 --- a/src/documentation/content/xdocs/0.93/fonts.xml +++ b/src/documentation/content/xdocs/0.93/fonts.xml @@ -200,17 +200,6 @@ Please note that this information only applies to TrueType fonts and TrueType co Limited to WinAnsi character set, which is roughly equivalent to iso-8889-1. Limited only by the characters in the font itself. - - Character Encoding in the Output Document. - Correct. - Never correct. Search, index, and cut-and-paste operations in the output document -will produce incorrect results. - - - Character Display - Correct. - Correct, but copy/paste won't work in Acrobat Reader. (FOP currently doesn't emit the /ToUnicode table which is necessary for copy/paste to work.) - Embedding the Font Optional. @@ -219,7 +208,7 @@ will produce incorrect results. You may experience failures with certain TrueType fonts, especially if they don't contain - the so-called "cmap" table. TTFReader can currently not deal with font like this. + the so-called Unicode "cmap" table. TTFReader can currently not deal with font like this.
    diff --git a/src/documentation/content/xdocs/0.94/fonts.xml b/src/documentation/content/xdocs/0.94/fonts.xml index 2eeaf095a..1f1c66b31 100644 --- a/src/documentation/content/xdocs/0.94/fonts.xml +++ b/src/documentation/content/xdocs/0.94/fonts.xml @@ -200,17 +200,6 @@ Please note that this information only applies to TrueType fonts and TrueType co Limited to WinAnsi character set, which is roughly equivalent to iso-8889-1. Limited only by the characters in the font itself. - - Character Encoding in the Output Document. - Correct. - Never correct. Search, index, and cut-and-paste operations in the output document -will produce incorrect results. - - - Character Display - Correct. - Correct, but copy/paste won't work in Acrobat Reader. (FOP currently doesn't emit the /ToUnicode table which is necessary for copy/paste to work.) - Embedding the Font Optional. @@ -219,7 +208,7 @@ will produce incorrect results. You may experience failures with certain TrueType fonts, especially if they don't contain - the so-called "cmap" table. TTFReader can currently not deal with font like this. + the so-called Unicode "cmap" table. TTFReader can currently not deal with font like this.
    diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml index 7d90f757e..e12527fe3 100644 --- a/src/documentation/content/xdocs/trunk/fonts.xml +++ b/src/documentation/content/xdocs/trunk/fonts.xml @@ -226,17 +226,6 @@ Please note that this information only applies to TrueType fonts and TrueType co Limited to WinAnsi character set, which is roughly equivalent to iso-8889-1. Limited only by the characters in the font itself. - - Character Encoding in the Output Document. - Correct. - Never correct. Search, index, and cut-and-paste operations in the output document -will produce incorrect results. - - - Character Display - Correct. - Correct, but copy/paste won't work in Acrobat Reader. (FOP currently doesn't emit the /ToUnicode table which is necessary for copy/paste to work.) - Embedding the Font Optional. @@ -245,7 +234,7 @@ will produce incorrect results. You may experience failures with certain TrueType fonts, especially if they don't contain - the so-called "cmap" table. TTFReader can currently not deal with font like this. + the so-called Unicode "cmap" table. TTFReader can currently not deal with font like this.
    -- cgit v1.2.3 From 40f39c202ed281809d2c151144c5e36dd131fcb3 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 21 Jan 2008 10:21:25 +0000 Subject: Removed stray System.out git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@613828 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/pdf/PDFRenderer.java | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index f32a25725..899bc1240 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -797,7 +797,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** {@inheritDoc} */ protected void startVParea(CTM ctm, Rectangle2D clippingRect) { saveGraphicsState(); - //currentState.push(); // Set the given CTM in the graphics state currentState.concatenate( new AffineTransform(CTMHelper.toPDFArray(ctm))); @@ -815,12 +814,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** {@inheritDoc} */ protected void endVParea() { restoreGraphicsState(); - //currentState.pop(); } /** {@inheritDoc} */ protected void concatenateTransformationMatrix(AffineTransform at) { - System.out.println(at); if (!at.isIdentity()) { currentState.concatenate(at); currentStream.add(CTMHelper.toPDFString(at, false) + " cm\n"); -- cgit v1.2.3 From ec59ecf8a78788e07c53c0791cb54e6f5c0e7084 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 21 Jan 2008 10:33:10 +0000 Subject: A name object can be encoded as a stand-along PDF object with object number and all, so extend from PDFObject. Fixes a possible ClassCastException with the PDF-in-PDF extension. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@613831 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFName.java | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFName.java b/src/java/org/apache/fop/pdf/PDFName.java index 8c626d53f..6ad6ff9eb 100644 --- a/src/java/org/apache/fop/pdf/PDFName.java +++ b/src/java/org/apache/fop/pdf/PDFName.java @@ -23,10 +23,12 @@ import java.io.IOException; import java.io.OutputStream; import java.io.Writer; +import org.apache.commons.io.output.CountingOutputStream; + /** * Class representing a PDF name object. */ -public class PDFName implements PDFWritable { +public class PDFName extends PDFObject { private String name; @@ -35,6 +37,7 @@ public class PDFName implements PDFWritable { * @param name the name value */ public PDFName(String name) { + super(); this.name = escapeName(name); } @@ -74,6 +77,24 @@ public class PDFName implements PDFWritable { return this.name; } + /** {@inheritDoc} */ + protected int output(OutputStream stream) throws IOException { + CountingOutputStream cout = new CountingOutputStream(stream); + Writer writer = PDFDocument.getWriterFor(cout); + if (hasObjectNumber()) { + writer.write(getObjectID()); + } + + outputInline(stream, writer); + + if (hasObjectNumber()) { + writer.write("\nendobj\n"); + } + + writer.flush(); + return cout.getCount(); + } + /** {@inheritDoc} */ public void outputInline(OutputStream out, Writer writer) throws IOException { writer.write(toString()); -- cgit v1.2.3 From daa5c136fe06ba0da6fc8b8b079b4d7ba6a813a6 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 21 Jan 2008 10:40:38 +0000 Subject: Correct inline writing when object has an object number. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@613835 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFName.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFName.java b/src/java/org/apache/fop/pdf/PDFName.java index 6ad6ff9eb..26d449591 100644 --- a/src/java/org/apache/fop/pdf/PDFName.java +++ b/src/java/org/apache/fop/pdf/PDFName.java @@ -85,7 +85,7 @@ public class PDFName extends PDFObject { writer.write(getObjectID()); } - outputInline(stream, writer); + writer.write(toString()); if (hasObjectNumber()) { writer.write("\nendobj\n"); @@ -97,7 +97,11 @@ public class PDFName extends PDFObject { /** {@inheritDoc} */ public void outputInline(OutputStream out, Writer writer) throws IOException { - writer.write(toString()); + if (hasObjectNumber()) { + writer.write(referencePDF()); + } else { + writer.write(toString()); + } } } -- cgit v1.2.3 From f549f74c84d9937efb21b8216056965ec16f2383 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 21 Jan 2008 14:13:29 +0000 Subject: A note about the internal coordinate system when using fox:transform. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@613896 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/extensions.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/extensions.xml b/src/documentation/content/xdocs/trunk/extensions.xml index 4f6911f9b..fb3db86fe 100644 --- a/src/documentation/content/xdocs/trunk/extensions.xml +++ b/src/documentation/content/xdocs/trunk/extensions.xml @@ -200,8 +200,10 @@ to following pages. Here is an example of FO code creating such a table-header:< and after them.

    - An example: fox:transform="rotate(45)" would rotate the block-container + Examples: fox:transform="rotate(45)" would rotate the block-container by 45 degrees clock-wise around its upper-left corner. + fox:transform="translate(10000,0)" would move the block-container to the + right by 10 points (=10000 millipoints, FOP uses millipoints internally!).

    This extension attribute doesn't work for all output formats! It's currently only -- cgit v1.2.3 From 95287ea8d8dc32e0d492284b0003ccbc0c6a027b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 22 Jan 2008 09:26:05 +0000 Subject: Complete overhaul of the "Graphics" page after the new image loading framework has been introduced. Some updates on external links and about Java 1.4. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614156 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/site.xml | 25 +- .../content/xdocs/trunk/embedding.xml | 6 +- src/documentation/content/xdocs/trunk/graphics.xml | 623 +++++++++++++-------- src/documentation/content/xdocs/trunk/running.xml | 24 +- src/documentation/content/xdocs/trunk/servlets.xml | 2 +- 5 files changed, 406 insertions(+), 274 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/site.xml b/src/documentation/content/xdocs/site.xml index cb9ce9d78..7914d5ef2 100644 --- a/src/documentation/content/xdocs/site.xml +++ b/src/documentation/content/xdocs/site.xml @@ -231,37 +231,20 @@ END Development tab --> - - - + - + + - - - @@ -270,6 +253,8 @@ + + diff --git a/src/documentation/content/xdocs/trunk/embedding.xml b/src/documentation/content/xdocs/trunk/embedding.xml index 3e3c964f8..b2c802db7 100644 --- a/src/documentation/content/xdocs/trunk/embedding.xml +++ b/src/documentation/content/xdocs/trunk/embedding.xml @@ -166,7 +166,7 @@ try { Logging

    Logging is now a little different than it was in FOP 0.20.5. We've switched from - Avalon Logging to Jakarta Commons Logging. + Avalon Logging to Jakarta Commons Logging. While with Avalon Logging the loggers were directly given to FOP, FOP now retrieves its logger(s) through a statically available LogFactory. This is similar to the general pattern that you use when you work with Apache Log4J directly, for example. @@ -187,10 +187,10 @@ try { which documents what we're going to build.

    - By default, Jakarta Commons Logging uses + By default, Jakarta Commons Logging uses JDK logging (available in JDKs 1.4 or higher) as its backend. You can configure Commons Logging to use an alternative backend, for example Log4J. Please consult the - documentation for Jakarta Commons Logging on + documentation for Jakarta Commons Logging on how to configure alternative backends.

    diff --git a/src/documentation/content/xdocs/trunk/graphics.xml b/src/documentation/content/xdocs/trunk/graphics.xml index 164069733..b0ca327dd 100644 --- a/src/documentation/content/xdocs/trunk/graphics.xml +++ b/src/documentation/content/xdocs/trunk/graphics.xml @@ -23,61 +23,91 @@ $Revision$ +
    + Introduction +

    + After the Apache FOP 0.94 release, the image handling subsystem has been rewritten in + order to improve the range of supported images and image subtypes, to lower the + overall memory consumption when handling images, to produce smaller output files and to + increase the performance in certain areas. Of course, this causes a few changes most of + which the user will probably not notice. The most important changes are: +

    +
      +
    • + The image libraries Jimi and JAI are no longer supported. Instead, Apache FOP uses the + Image I/O API that was introduced with Java 1.4 for all bitmap codecs. +
    • +
    • + Some bitmap images are no longer converted to a standardized 24 bit RGB image but are + instead handled in their native format. +
    • +
    • + A plug-in mechanism offers a possibility to add support for new formats without changing + the FOP's source code. +
    • +
    +

    + The actual image loading framework + no longer resides in Apache FOP, but was instead placed in + XML Graphics Commons. +

    +
    Overview of Graphics Support

    - The table below summarizes the theoretical support for graphical formats within FOP. In other words, within the constraints of the limitations listed here, these formats should work. However, many of them have not been tested, and there may be limitations that have not yet been discovered or documented. The packages needed to support some formats are not included in the FOP distribution and must be installed separately. Follow the links in the "Support Thru" column for more details. + The table below summarizes the theoretical support for graphical formats + within FOP. In other words, within the constraints of the limitations listed here, + these formats should work. However, many of them have not been tested, + and there may be limitations that have not yet been discovered or documented. + The packages needed to support some formats are not included in the FOP distribution + and must be installed separately. Follow the links in the "Support Through" columns + for more details.

    - - - - - + + + + + + + - - - - + + + + + + - + - - - - - - - - - @@ -85,9 +115,6 @@ - - - @@ -95,271 +122,379 @@ - - - - - - - - + - + - - - - +
    FormatTypeFOP native supportBatik SVGBatik codecsFormatTypeSupport Through
    Apache FOP (native)Apache Batik Image I/OJAIJIMI
    BMP (Microsoft Windows Bitmap) bitmapX X [1]
    EMF (Windows Enhanced Metafile)vector (with embedded bitmaps)(X)
    EPS (Encapsulated PostScript)metafile (both bitmap and vector), probably most frequently used for vector drawingsmetafile (both bitmap and vector), most frequently used for vector drawings (X)
    GIF (Graphics Interchange Format) bitmapX XXX
    JPEG (Joint Photographic Experts Group) bitmap (X) X
    PNG (Portable Network Graphic) XX
    SVG (Scalable Vector Graphics) X
    TIFF (Tag Image Format File) bitmap (X) XXXX [1]
    EMF (Windows Enhanced Metafile)WMF (Windows Metafile) vector (with embedded bitmaps)(X) (X)
    - "(X)" means restricted support. Please see the details below. +

    + Legend: +

    +
      +
    • "(X)" means restricted support. Please see the details below.
    • +
    • + [1]: Requires the presence of JAI Image I/O Tools + (or an equivalent Image I/O compatible codec) in the classpath. JAI Image I/O Tools also + adds support for JPEG 2000, WBMP, RAW and PNM. Other Image I/O codecs may provide + support for additional formats. +
    • +
    +
    + Map of supported image formats by output format +

    + Not all image formats are supported for all output formats! For example, while you can + use EPS (Encapsulated PostScript) files when you generate PostScript output, this format + will not be supported by any other output format. Here's an overview which image formats + are supported by which output format: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Image FormatPDFPostScriptJava2D, PNG, TIFF, AWTPCLAFPRTF
    BMP (Microsoft Windows Bitmap)XXXXXX
    EMF (Windows Enhanced Metafile)X [1]
    EPS (Encapsulated PostScript)X [1]
    GIF (Graphics Interchange Format)XXXXXX
    JPEG (Joint Photographic Experts Group)X [1]X [1]XXX [1]X
    PNG (Portable Network Graphic)XXXXXX
    SVG (Scalable Vector Graphics)XXXXXX
    TIFF (Tag Image Format File)X [2]X [2]XXX [2]X
    WMF (Windows Metafile)XXXXXX
    +

    + Legend: +

    +
      +
    • + [1]: Supported without the need to decode the image. +
    • +
    • + [2]: Supported without the need to decode the image, but only for certain subtypes. +
    • +
    +
    Graphics Packages
    - FOP Native + XML Graphics Commons Native

    - FOP has native ability to handle some graphic file formats. + XML Graphics Commons supports a number + graphic file formats natively as basic functionality: all bitmap formats for which there + are Image I/O codecs available (JPEG, PNG, GIF, TIFF, etc.), EPS and EMF.

    -
    - "Internal" codecs +
    + FOP Native

    - Apache XML Graphics Commons contains codecs for PNG and TIFF access. FOP can use these. + FOP has no native image plug-ins for the image loading framework of its own but currently + hosts the Batik-dependent SVG and WMF plug-ins until they can be moved to + Apache Batik.

    -
    - Image I/O (JDK 1.4 or higher) +
    + Apache Batik

    - For JDKs 1.4 or higher, FOP provides a wrapper to load images through the - JDK's Image I/O API (JSR 015). - Image I/O allows to dynamically add additional image codecs. An example of such an add-on library are the - JAI Image I/O Tools available from Sun. + Apache Batik will later receive the + SVG and WMF plug-ins for the image loading framework that are currently hosted inside + FOP.

    -
    -
    - JIMI

    - Because of licensing issues, the JIMI image library is not included in the FOP distribution. First, download and install it. -Then, copy the file "JimiProClasses.zip" from the archive to {fop-install-dir}/lib/jimi-1.0.jar. Please note that FOP binary distributions are compiled with JIMI support, so there is no need for you to build FOP to add the support. If jimi-1.0.jar is installed in the right place, it will automatically be used by FOP, otherwise it will not. + Current FOP distributions include a distribution of the + Apache Batik. + Because Batik's API changes frequently, it is highly recommended that you use the + version that ships with FOP, at least when running FOP.

    -
    -
    - JAI (Java Advanced Imaging API) + Batik must be run in a graphical environment.

    - FOP has been compiled with JAI support, but JAI is not included in the FOP distribution. -To use it, install JAI, then copy the jai_core.jar and the jai_codec.jar files to {fop-install-dir}/lib. -JAI is much faster than JIMI, but is not available for all platforms. See What platforms are supported? on the JAI FAQ page for more details. + Batik must be run in a graphical environment. + It uses AWT classes for rendering SVG, which in turn require an X server on Unixish + systems. If you run a server without X, or if you can't connect to the X server due to + security restrictions or policies (a so-called "headless" environment), SVG rendering + will fail.

    -
    -
    - Apache Batik -

    Current FOP distributions include a distribution of the Apache Batik version 1.6. -It is automatically installed with FOP. -Because Batik's API changes frequently, it is highly recommended that you use the version that ships with FOP, at least when running FOP.

    - Batik must be run in a graphical environment. -

    Batik must be run in a graphical environment. -It uses AWT classes for rendering SVG, which in turn require an X server on Unixish systems. -If you run a server without X, or if you can't connect to the X server due to security restrictions or policies (a so-called "headless" environment), SVG rendering will fail.

    Here are some workarounds:

      -
    • If you are using JDK 1.4, start it with the -Djava.awt.headless=true command line option.
    • -
    • Install an X server which provides an in-memory framebuffer without actually using a screen device or any display hardware. One example is Xvfb.
    • -
    • Install a toolkit which emulates AWT without the need for an underlying X server. One example is the PJA toolkit, which is free and comes with detailed installation instructions.
    • +
    • + If you are using JDK 1.4, start it with the -Djava.awt.headless=true + command line option. +
    • +
    • + Install an X server which provides an in-memory framebuffer without actually using a + screen device or any display hardware. One example is Xvfb. +
    • +
    • + Install a toolkit which emulates AWT without the need for an underlying X server. One + example is the PJA toolkit, which is free + and comes with detailed installation instructions. +
    -
    - BMP -

    FOP native support for BMP images is limited to the RGB color-space.

    -
    -
    - EPS -

    FOP provides support for two output targets:

    -
      -
    • PostScript (full support).
    • -
    • - PDF (partial support). Due to the lack of a built-in PostScript interpreter, FOP - can only embed the EPS file into the PDF. Acrobat Reader will not currently display - the EPS (it doesn't have a PostScript interpreter, either) but it will be shown - correctly when you print the PDF on a PostScript-capable printer. PostScript devices - (including GhostScript) will render the EPS correctly. -
    • -
    - - Please note that the EPS embedding feature has been deprecated in the - PDF specification version 1.4. You should not use this feature anymore, especially - since newer PDF tools don't support embedded EPS files anymore. - -

    - Other output targets can't be supported at the moment because - FOP lacks a PostScript interpreter. Furthermore, FOP is not able - to parse the preview bitmaps sometimes contained in EPS files. -

    -
    -
    - JPEG -

    - FOP native support of JPEG does not include all variants, especially those containing - unusual color lookup tables and color profiles. - If you have trouble with a JPEG image in FOP, try opening it with an image processing - program (such as Photoshop or Gimp) and then saving it. Specifying 24-bit color output - may also help. For the PDF and PostScript renderers most JPEG images can be passed - through without decompression. User reports indicate that grayscale, RGB, and - CMYK color-spaces are all rendered properly. -

    -
    -
    - PNG -

    - If using JAI for PNG support, only RGB and RGBA color-spaces are supported for - FOP rendering. -

    -

    - Transparency is supported but not guaranteed to work with every output format. -

    -
    -
    - SVG -
    - Introduction -

    FOP uses Apache Batik for SVG support. -This format can be handled as an fo:instream-foreign-object or in a separate -file referenced with fo:external-graphic.

    - -Batik's SVG Rasterizer utility may also be used to convert standalone SVG -documents into PDF. For more information please see the -SVG Rasterizer documentation -on the Batik site. - +
    + Details on image formats +
    + BMP +

    + BMP images are supported through an Image I/O codec. There may be limitations of the + codec which are outside the control of Apache FOP. +

    -
    - Placing SVG Graphics into PDF +
    + EMF

    -The SVG is rendered into PDF by using PDF commands to draw and fill -lines and curves. This means that the graphical objects created with -this remain as vector graphics. The same applies to PostScript output. -For other output formats the SVG graphic will be converted to a bitmap -image. + Windows Enhanced Metafiles (EMF) are only supported in RTF output where they are + embedded without decoding.

    +
    +
    + EPS +

    Apache FOP allows to use EPS files when generating PostScript output only.

    -There are a number of SVG things that cannot be converted directly into -PDF. Parts of the graphic such as effects, patterns and images are inserted -into the PDF as a raster graphic. The resolution of these raster images can - be controlled through the "target resolution" setting in the - configuration.

    + Other output targets can't be supported at the moment because + FOP lacks a PostScript interpreter. Furthermore, FOP is currently not able + to parse the preview bitmaps sometimes contained in EPS files. +

    +
    +
    + GIF

    -Currently transparency is limited in PDF so many svg images that -contain effects or graphics with transparent areas may not be displayed -correctly. + GIF images are supported through an Image I/O codec. Transparency is supported but + not guaranteed to work with every output format.

    -
    - Placing SVG Text into PDF and PostScript -

    If possible, Batik will use normal PDF or PostScript text when inserting text. It does -this by checking if the text can be drawn normally and the font is -supported. This example svg text.svg / -text.pdf -shows how various types and effects with text are handled. -Note that tspan and outlined text are not yet implemented.

    +
    + JPEG

    -Otherwise, text is converted and drawn as a set of shapes by Batik, using the stroking text painter. -This means that a typical character will -have about 10 curves (each curve consists of at least 20 characters). -This can make the output files large and when it is viewed the -viewer may not normally draw those fine curves very well (In Adobe Acrobat, turning on -"Smooth Line Art" in the preferences will fix this). -If the text is inserted into the output file using the inbuilt text commands -it will use a single character. + FOP native support (i.e. the handling of undecoded images) of JPEG does not include all + variants, especially those containing unusual color lookup tables and color profiles. + If you have trouble with a JPEG image in FOP, try opening it with an image processing + program (such as Photoshop or Gimp) and then saving it. Specifying 24-bit color output + may also help. For the PDF and PostScript renderers most JPEG images can be passed + through without decompression. User reports indicate that grayscale, RGB, and + CMYK color spaces are all rendered properly. However, for other output formats, the + JPEG images have to be decompressed. Tests have shown that there are some limitation + in some Image I/O codecs concerning images in the CMYK color space. Work-arounds are + in place but may not always work as expected.

    +
    +
    + PNG

    - Note that because SVG text can be rendered as either text or a vector graphic, you - may need to consider settings in your viewer for both. The Acrobat viewer has both - "smooth line art" and "smooth text" settings that may need to be set for SVG images - to be displayed nicely on your screen (see Edit / Preferences / Display). - This setting will not affect the printing of your document, which should be OK in - any case, but will only affect the quality of the screen display.

    + PNG images are supported through an Image I/O codec. Transparency is supported but + not guaranteed to work with every output format. +

    -
    - Scaling +
    + SVG +
    + Introduction +

    FOP uses Apache Batik for SVG support. + This format can be handled as an fo:instream-foreign-object or in a separate + file referenced with fo:external-graphic.

    + + Batik's SVG Rasterizer utility may also be used to convert standalone SVG + documents into PDF. For more information please see the + SVG Rasterizer documentation + on the Batik site. + +
    +
    + Placing SVG Graphics into PDF +

    + The SVG is rendered into PDF by using PDF commands to draw and fill + lines and curves. This means that the graphical objects created with + this remain as vector graphics. The same applies to PostScript output. + For other output formats the SVG graphic may be converted to a bitmap + image. +

    +

    + There are a number of SVG things that cannot be converted directly into + PDF. Parts of the graphic such as effects, patterns and images are inserted + into the PDF as a raster graphic. The resolution of these raster images can + be controlled through the "target resolution" setting in the + configuration.

    +

    + Currently transparency is limited in PDF so many SVG images that + contain effects or graphics with transparent areas may not be displayed + correctly. +

    +
    +
    + Placing SVG Text into PDF and PostScript +

    If possible, Batik will use normal PDF or PostScript text when inserting text. It does + this by checking if the text can be drawn normally and the font is + supported. This example svg text.svg / + text.pdf + shows how various types and effects with text are handled. + Note that tspan and outlined text are not yet implemented.

    +

    + Otherwise, text is converted and drawn as a set of shapes by Batik, using the + stroking text painter. This means that a typical character will + have about 10 curves (each curve consists of at least 20 characters). + This can make the output files large and when it is viewed the + viewer may not normally draw those fine curves very well (In Adobe Acrobat, turning on + "Smooth Line Art" in the preferences will fix this). Copy/paste functionality + will not be supported in this case. + If the text is inserted into the output file using the inbuilt text commands + it will use a single character. +

    +

    + Note that because SVG text can be rendered as either text or a vector graphic, you + may need to consider settings in your viewer for both. The Acrobat viewer has both + "smooth line art" and "smooth text" settings that may need to be set for SVG images + to be displayed nicely on your screen (see Edit / Preferences / Display). + This setting will not affect the printing of your document, which should be OK in + any case, but will only affect the quality of the screen display.

    +
    +
    + Scaling +

    + Currently, SVG images are rendered with the dimensions specified in the SVG + file, within the viewport specified in the fo:external-graphic element. + For everything to work properly, the two should be equal. The SVG standard leaves + this issue as an implementation detail. Additional scaling options are available + through XSL-FO means. +

    +

    + If you use pixels to specify the size of an SVG graphic the "source resolution" setting + in the configuration will be used to determine the + size of a pixel. The use of pixels to specify sizes is discouraged as they may + be interpreted differently in different environments. +

    +
    +
    + Known Problems +
      +
    • + Soft mask transparency is combined with white so that it looks better + on PDF 1.3 viewers but this causes the soft mask to be slightly lighter + or darker on PDF 1.4 viewers. +
    • +
    • + There is some problem with a gradient inside a pattern which may cause a PDF + error when viewed in Acrobat 5. +
    • +
    • + Text is not always handled correctly, it may select the wrong font + especially if characters have multiple fonts in the font list. +
    • +
    • + Uniform transparency for images and other SVG elements that are converted + into a raster graphic are not drawn properly in PDF. The image is opaque. +
    • +
    +
    +
    +
    + TIFF

    - Currently, SVG images are rendered with the dimensions specified in the SVG - file, within the viewport specified in the fo:external-graphic element. - For everything to work properly, the two should be equal. The SVG standard leaves - this issue as an implementation detail. FOP will probably implement a scaling - mechanism in the future. + FOP can embed TIFF images without decompression into PDF, PostScript and AFP if they + have either CCITT T.4, CCITT T.6, or JPEG compression. Otherwise, a TIFF-capable + Image I/O codec is necessary for decoding the image.

    - If you use pixels to specify the size of an SVG graphic the "source resolution" setting - in the configuration will be used to determine the - size of a pixel. The use of pixels to specify sizes is discouraged as they may - be interpreted differently in different environments. + There may be some limitation concerning images in the CMYK color space.

    -
    - Known Problems -
      -
    • -Soft mask transparency is combined with white so that it looks better -on pdf 1.3 viewers but this causes the soft mask to be slightly lighter -or darker on pdf 1.4 viewers. -
    • -
    • -There is some problem with a gradient inside a pattern causing a PDF -error when viewed in acrobat 5. -
    • -
    • -Text is not always handled correctly, it may select the wrong font -especially if characters have multiple fonts in the font list. -
    • -
    • -More PDF text handling could be implemented. -It could draw the string using the attributed character iterator -to handle tspans and other simple changes of text. -
    • -
    • -JPEG images are not inserted directly into the pdf document. -This area has not been implemented yet since the appropriate -method in batik is static. -
    • -
    • -Uniform transparency for images and other svg elements that are converted -into a raster graphic are not drawn properly in PDF. The image is opaque. -
    • -
    +
    + WMF +

    + Windows Metafiles (WMF) are supported through classes in + Apache Batik. At the moment, support + for this format is experimental and may not always work as expected. +

    -
    - TIFF -

    - FOP-native TIFF support is limited to PDF and PostScript output only. Also, - according to user reports, FOP's native support for TIFF is limited to images with the - following characteristics (all must be true for successful rendering): -

    -
      -
    • single channel images (i.e., bi-level and grayscale only)
    • -
    • uncompressed images, or images using CCITT T.4, CCITT T.6, or JPEG compression
    • -
    • images using white-is-zero encoding in the TIFF PhotometricInterpretation tag
    • -
    - - Native support in this case means that the images can be embedded into the output format - without decoding it. - -

    JAI: Supports RGB and RGBA only for FOP rendering.

    -
    -
    - EMF -

    Windows Enhanced Metafiles (EMF) are only supported in RTF output.

    -
    Graphics Resolution

    @@ -371,7 +506,8 @@ into a raster graphic are not drawn properly in PDF. The image is opaque.

    Please note that not all images contain resolution information. If it's not available - 72 dpi is assumed (the default resolution of PDF and PostScript). + the source resolution set on the FopFactory (or through the user configuration XML) is used. + The default here is 72 dpi.

    Bitmap images are generally embedded into the output format at their original resolution @@ -382,14 +518,23 @@ into a raster graphic are not drawn properly in PDF. The image is opaque. used as a work-around to resample images in FO documents.

    +
    + Page selection for multi-page formats +

    + Some image formats such as TIFF support multiple pages/sub-images per file. You can + select a particular page using a special URI fragment in the form: + <uri>#page=<nr> + (for example: http://localhost/images/myimage.tiff#page=3) +

    +
    Image caching

    FOP caches images between runs. There is one cache per FopFactory instance. The URI is used as a key to identify images which means that when a particular URI appears again, the image is taken from the cache. If you have a servlet that generates a different - image each time it is called with the same URL you need to use a constantly - changing dummy parameter on the URL to avoid caching. + image each time it is called with the same URI you need to use a constantly + changing dummy parameter on the URI to avoid caching.

    The image cache has been improved considerably in the redesigned code. Therefore, a diff --git a/src/documentation/content/xdocs/trunk/running.xml b/src/documentation/content/xdocs/trunk/running.xml index a3d2dd0d2..38df4be82 100644 --- a/src/documentation/content/xdocs/trunk/running.xml +++ b/src/documentation/content/xdocs/trunk/running.xml @@ -28,21 +28,24 @@ System Requirements

    The following software must be installed:

      -
    • Java 1.3.x or later Runtime Environment.
    • +
    • + Java 1.4.x or later Runtime Environment. +
        +
      • + Many JREs >=1.4 contain older JAXP implementations (which often contain bugs). It's + usually a good idea to replace them with a current implementation. +
      • +
      +
    • Apache FOP. The FOP distribution includes all libraries that you will need to run a basic FOP installation. These can be found in the [fop-root]/lib directory. These libraries include the following:
    • @@ -51,8 +54,7 @@
      • Graphics libraries. Generally, FOP contains direct support for the most important - bitmap image formats (including PNG, TIFF, JPEG and GIF). If you're using JDK 1.3, - you may need additional packages to get GIF images to work. See + bitmap image formats (including PNG, JPEG and GIF). See FOP: Graphics Formats for details.
      • diff --git a/src/documentation/content/xdocs/trunk/servlets.xml b/src/documentation/content/xdocs/trunk/servlets.xml index 119ac701e..07c22312d 100644 --- a/src/documentation/content/xdocs/trunk/servlets.xml +++ b/src/documentation/content/xdocs/trunk/servlets.xml @@ -161,7 +161,7 @@ public void init() throws ServletException {
        • Instead of java.io.ByteArrayOutputStream consider using the ByteArrayOutputStream - implementation from the Jakarta Commons IO project which allocates less memory. + implementation from the Jakarta Commons IO project which allocates less memory. The full class name is: org.apache.commons.io.output.ByteArrayOutputStream
        • -- cgit v1.2.3 From 450450ded82131c048c19e48f445d550c5965639 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 22 Jan 2008 10:48:43 +0000 Subject: Fixed minor typos git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614169 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/graphics.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/graphics.xml b/src/documentation/content/xdocs/trunk/graphics.xml index b0ca327dd..7fc5c31e2 100644 --- a/src/documentation/content/xdocs/trunk/graphics.xml +++ b/src/documentation/content/xdocs/trunk/graphics.xml @@ -155,8 +155,8 @@

          Not all image formats are supported for all output formats! For example, while you can use EPS (Encapsulated PostScript) files when you generate PostScript output, this format - will not be supported by any other output format. Here's an overview which image formats - are supported by which output format: + will not be supported by any other output format. Here's an overview of which image + formats are supported by which output format:

          @@ -269,8 +269,8 @@ XML Graphics Commons Native

          XML Graphics Commons supports a number - graphic file formats natively as basic functionality: all bitmap formats for which there - are Image I/O codecs available (JPEG, PNG, GIF, TIFF, etc.), EPS and EMF. + of graphic file formats natively as basic functionality: all bitmap formats for which + there are Image I/O codecs available (JPEG, PNG, GIF, TIFF, etc.), EPS and EMF.

          @@ -501,7 +501,7 @@ Some bitmapped image file formats store a dots-per-inch (dpi) or other resolution values. FOP tries to use this resolution information whenever possible to determine the image's intrinsic size. This size is used during the layout process when it is not - superceeded by an explicit size on fo:external-graphic (content-width and content-height + superseded by an explicit size on fo:external-graphic (content-width and content-height properties).

          -- cgit v1.2.3 From 1ebf696d404dc426c1ce1d99a560a07cb1c1d027 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 22 Jan 2008 10:50:24 +0000 Subject: Updated text to reflect the upgrading of the minimum Java requirement to 1.4 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614170 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/graphics.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/graphics.xml b/src/documentation/content/xdocs/trunk/graphics.xml index 7fc5c31e2..6fa0671aa 100644 --- a/src/documentation/content/xdocs/trunk/graphics.xml +++ b/src/documentation/content/xdocs/trunk/graphics.xml @@ -305,8 +305,7 @@

          Here are some workarounds:

          • - If you are using JDK 1.4, start it with the -Djava.awt.headless=true - command line option. + Start Java with the -Djava.awt.headless=true command line option.
          • Install an X server which provides an in-memory framebuffer without actually using a -- cgit v1.2.3 From f92cc1b2d3e144dd33efe2f4925d543c9ccaa3f6 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 22 Jan 2008 12:31:11 +0000 Subject: A note on the difference between JAI Image I/O Tools, the codec package, and JAI, the image library. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614191 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/graphics.xml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/graphics.xml b/src/documentation/content/xdocs/trunk/graphics.xml index 6fa0671aa..31e54d8fd 100644 --- a/src/documentation/content/xdocs/trunk/graphics.xml +++ b/src/documentation/content/xdocs/trunk/graphics.xml @@ -150,6 +150,12 @@ support for additional formats.
          + + JAI Image I/O Tools is not the same as the + JAI library! The + former simply exposes JAI's codecs using the Image I/O API but does not include all + the image manipulation functionality. +
          Map of supported image formats by output format

          -- cgit v1.2.3 From 449a0d0764f7269b5924f7b7822b67409386cdda Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 22 Jan 2008 14:02:27 +0000 Subject: Bugzilla #44160: Fixed a possible IndexOutOfBoundsException that could happen with certain constellations when footnotes are used. Note: I haven't been able to come up with a scaled-down testcase for regression testing. Maybe someone more intimate with the footnote handling can. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614201 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/PageBreakingAlgorithm.java | 14 +++++++++----- status.xml | 4 ++++ 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index a9ef9fd13..32c2b8d3b 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -25,11 +25,11 @@ import java.util.ListIterator; 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.FObj; import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition; - import org.apache.fop.traits.MinOptMax; class PageBreakingAlgorithm extends BreakingAlgorithm { @@ -641,10 +641,14 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { demerits += (footnotesList.size() - 1 - footnoteListIndex) * deferredFootnoteDemerits; } - if (footnoteElementIndex - < ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1) { - // add demerits for the footnote split between pages - demerits += splitFootnoteDemerits; + if (footnoteListIndex < footnotesList.size()) { + if (footnoteElementIndex + < ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1) { + // add demerits for the footnote split between pages + demerits += splitFootnoteDemerits; + } + } else { + //TODO Why can this happen in the first place? Does anybody know? See #44160 } } demerits += activeNode.totalDemerits; diff --git a/status.xml b/status.xml index e866f3972..21c98c9ab 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Fixed a possible IndexOutOfBoundsException that could happen with certain constellations + when footnotes are used. + Compliance fix: for absolutely positioned block-containers, "top" wasn't interpreted correctly. -- cgit v1.2.3 From 58868131c9b55c3bf8f91cad92304e118ab1de41 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 23 Jan 2008 15:22:05 +0000 Subject: Added support for conditional borders (and paddings) in tables. The proper borders are not selected yet between the header/footer and the body. There might still be a few glitches in some cases git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614566 13f79535-47bb-0310-9956-ffa450edef68 --- .../fo/flow/table/CollapsingBorderResolver.java | 59 +++- .../fop/fo/flow/table/ConditionalBorder.java | 6 + .../fop/fo/flow/table/FixedColRowGroupBuilder.java | 23 -- .../org/apache/fop/fo/flow/table/GridUnit.java | 158 ++++----- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 151 +++++--- src/java/org/apache/fop/fo/flow/table/Table.java | 4 +- src/java/org/apache/fop/layoutmgr/TraitSetter.java | 38 +- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 227 ++++++++---- .../org/apache/fop/layoutmgr/table/CellPart.java | 73 +++- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 12 +- .../org/apache/fop/layoutmgr/table/RowPainter.java | 301 ++++++++-------- .../layoutmgr/table/TableCellLayoutManager.java | 257 ++++++++------ .../layoutmgr/table/TableContentLayoutManager.java | 32 +- .../apache/fop/layoutmgr/table/TableStepper.java | 16 +- status.xml | 4 + ...collapsed-conditional-borders_test-generator.py | 22 +- .../table/CollapsedConditionalBorderTestCase.java | 88 ++--- .../org/apache/fop/fotreetest/FOTreeTestSuite.java | 2 + .../table-cell_block_break-after.xml | 12 +- .../table-cell_span-combinations.xml | 7 +- .../table-row_break-before_break-after_2.xml | 30 +- ...table_border-collapse_collapse_conditionals.xml | 177 ++++++++++ .../table_border-collapse_collapse_spans_1.xml | 8 + ...e_border-collapse_separate_border-spacing_2.xml | 36 +- ...table_border-collapse_separate_conditionals.xml | 386 +++++++++++++++++++++ .../table_break-before_break-after.xml | 33 +- .../standard-testcases/table_bug36403.xml | 19 +- .../standard-testcases/table_empty-cells.xml | 10 +- 28 files changed, 1521 insertions(+), 670 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table_border-collapse_collapse_conditionals.xml create mode 100644 test/layoutengine/standard-testcases/table_border-collapse_separate_conditionals.xml (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index 16fc55cfc..235f05042 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -47,12 +47,21 @@ class CollapsingBorderResolver implements BorderResolver { private Resolver delegate; + // Re-use the same ResolverInBody for every table-body + // Important to properly handle firstInBody!! + private Resolver resolverInBody = new ResolverInBody(); + private Resolver resolverInFooter; private List/**/ leadingBorders; private List/**/ trailingBorders; + /* TODO Temporary hack for resolved borders in header */ + /* Currently the normal border is always used. */ + private List/**/ headerLastRow = null; + /* End of temporary hack */ + /** * Base class for delegate resolvers. Implementation of the State design pattern: the * treatment differs slightly whether we are in the table's header, footer or body. To @@ -184,14 +193,12 @@ class CollapsingBorderResolver implements BorderResolver { TableRow tableRow = (TableRow) container; for (Iterator iter = row.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); - if (gu.getRowSpanIndex() == 0) { - gu.integrateBorderSegment(CommonBorderPaddingBackground.BEFORE, tableRow, - true, true, true); - } - if (gu.isLastGridUnitRowSpan()) { - gu.integrateBorderSegment(CommonBorderPaddingBackground.AFTER, tableRow, - true, true, true); - } + boolean first = (gu.getRowSpanIndex() == 0); + boolean last = gu.isLastGridUnitRowSpan(); + gu.integrateBorderSegment(CommonBorderPaddingBackground.BEFORE, tableRow, + first, first, true); + gu.integrateBorderSegment(CommonBorderPaddingBackground.AFTER, tableRow, + last, last, true); } } if (firstInPart) { @@ -249,7 +256,7 @@ class CollapsingBorderResolver implements BorderResolver { */ for (Iterator guIter = row.iterator(); guIter.hasNext();) { ConditionalBorder borderBefore = ((GridUnit) guIter.next()).borderBefore; - borderBefore.leadingTrailing = null; + borderBefore.leadingTrailing = borderBefore.nonLeadingTrailing; borderBefore.rest = borderBefore.nonLeadingTrailing; } resolveBordersFirstRowInTable(row, false, true, true); @@ -275,6 +282,9 @@ class CollapsingBorderResolver implements BorderResolver { borderAfter.rest = borderAfter.nonLeadingTrailing; leadingBorders.add(borderAfter); } + /* TODO Temporary hack for resolved borders in header */ + headerLastRow = previousRow; + /* End of temporary hack */ } void endTable() { @@ -314,7 +324,7 @@ class CollapsingBorderResolver implements BorderResolver { // See endRow method in ResolverInHeader for an explanation of the hack for (Iterator guIter = footerLastRow.iterator(); guIter.hasNext();) { ConditionalBorder borderAfter = ((GridUnit) guIter.next()).borderAfter; - borderAfter.leadingTrailing = null; + borderAfter.leadingTrailing = borderAfter.nonLeadingTrailing; borderAfter.rest = borderAfter.nonLeadingTrailing; } resolveBordersLastRowInTable(footerLastRow, false, true, true); @@ -323,6 +333,8 @@ class CollapsingBorderResolver implements BorderResolver { private class ResolverInBody extends Resolver { + private boolean firstInBody = true; + void endRow(List/**/ row, TableCellContainer container) { super.endRow(row, container); if (firstInTable) { @@ -335,6 +347,13 @@ class CollapsingBorderResolver implements BorderResolver { } integrateTrailingBorders(row); previousRow = row; + if (firstInBody) { + firstInBody = false; + for (Iterator iter = row.iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + gu.borderBefore.leadingTrailing = gu.borderBefore.nonLeadingTrailing; + } + } } void endTable() { @@ -343,6 +362,10 @@ class CollapsingBorderResolver implements BorderResolver { } else { // Trailing and rest borders already resolved with integrateTrailingBorders resolveBordersLastRowInTable(previousRow, false, true, false); + for (Iterator iter = previousRow.iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + gu.borderAfter.leadingTrailing = gu.borderAfter.nonLeadingTrailing; + } } } } @@ -386,7 +409,7 @@ class CollapsingBorderResolver implements BorderResolver { trailingBorders.add(border); } } - delegate = new ResolverInBody(); + delegate = resolverInBody; } } delegate.startPart(part); @@ -401,5 +424,19 @@ class CollapsingBorderResolver implements BorderResolver { public void endTable() { delegate.endTable(); delegate = null; + /* TODO Temporary hack for resolved borders in header */ + if (headerLastRow != null) { + for (Iterator iter = headerLastRow.iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + gu.borderAfter.leadingTrailing = gu.borderAfter.nonLeadingTrailing; + } + } + if (footerLastRow != null) { + for (Iterator iter = footerLastRow.iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + gu.borderAfter.leadingTrailing = gu.borderAfter.nonLeadingTrailing; + } + } + /* End of temporary hack */ } } diff --git a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java index 4f3cca046..4313b82a6 100644 --- a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java +++ b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java @@ -36,6 +36,12 @@ import org.apache.fop.layoutmgr.table.CollapsingBorderModel; */ public class ConditionalBorder { + public static final int NORMAL = 0; + + public static final int LEADING_TRAILING = 1; + + public static final int REST = 2; + /** Special case: the cell is at the top or the bottom of the page. */ BorderSpecification leadingTrailing; diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index 7df071191..2f8b0bbb8 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -43,8 +43,6 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { /** The rows belonging to this row group. List of List of {@link GridUnit}s. */ private List/*>*/ rows; - private boolean firstInTable = true; - private boolean firstInPart = true; /** The last encountered row. This is the last row of the table if it has no footer. */ @@ -52,10 +50,6 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { private BorderResolver borderResolver; - private boolean inFooter; - - private List lastFooterRow; - FixedColRowGroupBuilder(Table t) { super(t); numberOfColumns = t.getNumberOfColumns(); @@ -134,14 +128,6 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { } } borderResolver.endRow(currentRow, container); - ((GridUnit) currentRow.get(0)).setFlag(GridUnit.IN_FIRST_COLUMN); - ((GridUnit) currentRow.get(numberOfColumns - 1)).setFlag(GridUnit.IN_LAST_COLUMN); - if (inFooter) { - lastFooterRow = currentRow; - } else if (firstInTable) { - setFlagForCols(GridUnit.FIRST_IN_TABLE, currentRow); - firstInTable = false; - } if (firstInPart) { setFlagForCols(GridUnit.FIRST_IN_PART, currentRow); firstInPart = false; @@ -159,7 +145,6 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { /** {@inheritDoc} */ void startTablePart(TableBody part) { firstInPart = true; - inFooter = part.isTableFooter(); borderResolver.startPart(part); } @@ -171,18 +156,10 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { } setFlagForCols(GridUnit.LAST_IN_PART, lastRow); borderResolver.endPart(); - inFooter = false; } /** {@inheritDoc} */ void endTable(TableBody lastTablePart) { - List lastTableRow; - if (lastFooterRow != null) { - lastTableRow = lastFooterRow; - } else { - lastTableRow = lastRow; - } - setFlagForCols(GridUnit.LAST_IN_TABLE, lastTableRow); borderResolver.endTable(); } } diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java index d6d622d57..a583697f6 100644 --- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java @@ -19,8 +19,6 @@ package org.apache.fop.fo.flow.table; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.FONode; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; @@ -31,37 +29,23 @@ import org.apache.fop.layoutmgr.table.CollapsingBorderModel; */ public class GridUnit { - private static Log log = LogFactory.getLog(GridUnit.class); - - /** Indicates that the grid unit is in the first column. */ - public static final int IN_FIRST_COLUMN = 0; - - /** Indicates that the grid unit is in the last column. */ - public static final int IN_LAST_COLUMN = 1; - - /** Indicates that the grid unit is in the first row of the table. */ - public static final int FIRST_IN_TABLE = 2; - /** * Indicates that the grid unit is in the first row of the table part (header, footer, * body). */ - public static final int FIRST_IN_PART = 3; + public static final int FIRST_IN_PART = 0; /** * Indicates that the grid unit is in the last row of the table part (header, footer, * body). */ - public static final int LAST_IN_PART = 4; - - /** Indicates that the grid unit is in the last row of the table. */ - public static final int LAST_IN_TABLE = 5; + public static final int LAST_IN_PART = 1; /** Indicates that the primary grid unit has a pending keep-with-next. */ - public static final int KEEP_WITH_NEXT_PENDING = 6; + public static final int KEEP_WITH_NEXT_PENDING = 2; /** Indicates that the primary grid unit has a pending keep-with-previous. */ - public static final int KEEP_WITH_PREVIOUS_PENDING = 7; + public static final int KEEP_WITH_PREVIOUS_PENDING = 3; /** Primary grid unit */ private PrimaryGridUnit primary; @@ -84,9 +68,6 @@ public class GridUnit { /** index of grid unit within cell in row direction */ private int rowSpanIndex; - /** effective borders for a cell slot */ - private CommonBorderPaddingBackground effectiveBorders; - /** flags for the grid unit */ private byte flags = 0; @@ -156,29 +137,35 @@ public class GridUnit { } private void setBorders(Table table/*TODO*/) { - if (table.isSeparateBorderModel()) { - assignBorderForSeparateBorderModel(); - } else { + if (!table.isSeparateBorderModel()) { collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table .getBorderCollapse()); setBordersFromCell(); } } + /** + * Prepares the borders of this grid unit for upcoming resolution, in the collapsing + * model. + */ protected void setBordersFromCell() { borderBefore = cell.borderBefore.copy(); if (rowSpanIndex > 0) { - borderBefore.nonLeadingTrailing = null; + borderBefore.nonLeadingTrailing = BorderSpecification.getDefaultBorder(); } borderAfter = cell.borderAfter.copy(); if (!isLastGridUnitRowSpan()) { - borderAfter.nonLeadingTrailing = null; + borderAfter.nonLeadingTrailing = BorderSpecification.getDefaultBorder(); } if (colSpanIndex == 0) { borderStart = cell.borderStart; + } else { + borderStart = BorderSpecification.getDefaultBorder(); } if (isLastGridUnitColSpan()) { borderEnd = cell.borderEnd; + } else { + borderEnd = BorderSpecification.getDefaultBorder(); } } @@ -235,6 +222,11 @@ public class GridUnit { return cell == null; } + /** + * Returns the index of the column this grid unit belongs to. + * + * @return the column index, 0-based + */ public int getStartCol() { return startCol; } @@ -264,89 +256,67 @@ public class GridUnit { } /** - * Returns a BorderInfo instance for a side of the currently applicable cell before - * border resolution (i.e. the value from the FO). A return value of null indicates an - * empty cell. See CollapsingBorderModel(EyeCatching) where this method is used. + * Returns the resolved border-before of this grid unit, in the collapsing-border + * model. * - * @param side for which side to return the BorderInfo - * @return the requested BorderInfo instance or null if the grid unit is an empty cell + * @param which one of {@link ConditionalBorder#NORMAL}, + * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST} + * @return the corresponding border */ - public BorderInfo getOriginalBorderInfoForCell(int side) { - if (cell != null) { - return cell.getCommonBorderPaddingBackground().getBorderInfo(side); - } else { + public BorderInfo getBorderBefore(int which) { + switch (which) { + case ConditionalBorder.NORMAL: + return borderBefore.nonLeadingTrailing.getBorderInfo(); + case ConditionalBorder.LEADING_TRAILING: + return borderBefore.leadingTrailing.getBorderInfo(); + case ConditionalBorder.REST: + return borderBefore.rest.getBorderInfo(); + default: + assert false; return null; } } /** - * @return the resolved normal borders for this grid unit + * Returns the resolved border-after of this grid unit, in the collapsing-border + * model. + * + * @param which one of {@link ConditionalBorder#NORMAL}, + * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST} + * @return the corresponding border */ - public CommonBorderPaddingBackground getBorders() { - // TODO - if (effectiveBorders == null) { - effectiveBorders = new CommonBorderPaddingBackground(); - setBorderInfo(CommonBorderPaddingBackground.BEFORE); - setBorderInfo(CommonBorderPaddingBackground.AFTER); - setBorderInfo(CommonBorderPaddingBackground.START); - setBorderInfo(CommonBorderPaddingBackground.END); - if (cell != null) { - effectiveBorders.setPadding(cell.getCommonBorderPaddingBackground()); - } - if (log.isDebugEnabled()) { - log.debug(this + " resolved borders: " + "before=" - + effectiveBorders.getBorderBeforeWidth(false) + ", " + "after=" - + effectiveBorders.getBorderAfterWidth(false) + ", " + "start=" - + effectiveBorders.getBorderStartWidth(false) + ", " + "end=" - + effectiveBorders.getBorderEndWidth(false)); - } - } - return effectiveBorders; - } - - private void setBorderInfo(int side) { - switch (side) { - case CommonBorderPaddingBackground.BEFORE: - if (borderBefore.nonLeadingTrailing/*TODO*/ != null) { - effectiveBorders.setBorderInfo(borderBefore.nonLeadingTrailing.getBorderInfo(), - side); - } - break; - case CommonBorderPaddingBackground.AFTER: - if (borderAfter.nonLeadingTrailing/*TODO*/ != null) { - effectiveBorders.setBorderInfo(borderAfter.nonLeadingTrailing.getBorderInfo(), - side); - } - break; - case CommonBorderPaddingBackground.START: - if (borderStart != null) { - effectiveBorders.setBorderInfo(borderStart.getBorderInfo(), side); - } - break; - case CommonBorderPaddingBackground.END: - if (borderEnd != null) { - effectiveBorders.setBorderInfo(borderEnd.getBorderInfo(), side); - } - break; - default: assert false; + public BorderInfo getBorderAfter(int which) { + switch (which) { + case ConditionalBorder.NORMAL: + return borderAfter.nonLeadingTrailing.getBorderInfo(); + case ConditionalBorder.LEADING_TRAILING: + return borderAfter.leadingTrailing.getBorderInfo(); + case ConditionalBorder.REST: + return borderAfter.rest.getBorderInfo(); + default: + assert false; + return null; } } /** - * @return true if the grid unit has any borders. + * Returns the resolved border-start of this grid unit, in the collapsing-border + * model. + * + * @return the corresponding border */ - public boolean hasBorders() { - return (getBorders() != null) && getBorders().hasBorder(); + public BorderInfo getBorderStart() { + return borderStart.getBorderInfo(); } /** - * Assigns the borders from the given cell to this cell info. Used in case of separate - * border model. + * Returns the resolved border-end of this grid unit, in the collapsing-border + * model. + * + * @return the corresponding border */ - void assignBorderForSeparateBorderModel() { - if (cell != null) { - effectiveBorders = cell.getCommonBorderPaddingBackground(); - } + public BorderInfo getBorderEnd() { + return borderEnd.getBorderInfo(); } /** diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index ae8db7ba7..684fa58d1 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.table.TableCellLayoutManager; @@ -46,6 +47,9 @@ public class PrimaryGridUnit extends GridUnit { /** The calculated size of the cell's content. (cached value) */ private int contentLength = -1; + private boolean isSeparateBorderModel; + private int halfBorderSeparationBPD; + /** * Creates a new primary grid unit. * @@ -57,6 +61,9 @@ public class PrimaryGridUnit extends GridUnit { */ PrimaryGridUnit(TableCell cell, TableRow row, TableColumn column, int startCol) { super(cell, row, column, startCol, 0, 0); + this.isSeparateBorderModel = column.getTable().isSeparateBorderModel(); // TODO + this.halfBorderSeparationBPD = column.getTable().getBorderSeparation().getBPD().getLength() + .getValue() / 2; // TODO log.trace("PrimaryGridUnit created, row " + startRow + " col " + startCol); } @@ -89,58 +96,120 @@ public class PrimaryGridUnit extends GridUnit { } /** - * @return half the maximum before border width of this cell. + * Returns the widths of the border-before and -after for this cell. In the separate + * border model the border-separation is included. In the collapsing model only half + * of them is counted, since the other halves belong to the neighbouring cells; also, + * the returned value is the maximum of the segments of each applicable grid unit. + * + * @return the sum of the before and after border widths */ - public int getHalfMaxBeforeBorderWidth() { - int value = 0; - if (getRows() != null) { - int before = 0; - //first row for before borders - GridUnit[] row = (GridUnit[])getRows().get(0); - for (int i = 0; i < row.length; i++) { - if (row[i].hasBorders()) { - before = Math.max(before, - row[i].getBorders().getBorderBeforeWidth(false)); + public int getBeforeAfterBorderWidth() { + return getBeforeBorderWidth(0, ConditionalBorder.NORMAL) + + getAfterBorderWidth(ConditionalBorder.NORMAL); + } + + /** + * Returns the width of the before-border for the given row-span of this cell. In the + * separate border model half of the border-separation is included. In the collapsing + * model only half of the border is counted, since the other half belongs to the + * preceding cell; also, the returned value is the maximum of the segments of each + * applicable grid unit. + * + * @param rowIndex index of the span for which the border must be computed, 0-based + * @param which one of {@link ConditionalBorder#NORMAL}, + * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST} + * @return the before border width + */ + public int getBeforeBorderWidth(int rowIndex, int which) { + if (isSeparateBorderModel) { + if (getCell() == null) { + return 0; + } else { + CommonBorderPaddingBackground cellBorders = getCell() + .getCommonBorderPaddingBackground(); + switch (which) { + case ConditionalBorder.NORMAL: + case ConditionalBorder.LEADING_TRAILING: + return cellBorders.getBorderBeforeWidth(false) + halfBorderSeparationBPD; + case ConditionalBorder.REST: + if (cellBorders.getBorderInfo(CommonBorderPaddingBackground.BEFORE).getWidth() + .isDiscard()) { + return 0; + } else { + return cellBorders.getBorderBeforeWidth(true) + halfBorderSeparationBPD; + } + default: + assert false; + return 0; } } - value += before / 2; } else { - if (hasBorders()) { - value += getBorders().getBorderBeforeWidth(false) / 2; + int width = 0; + GridUnit[] row = (GridUnit[]) rows.get(rowIndex); + for (int i = 0; i < row.length; i++) { + width = Math.max(width, + row[i].getBorderBefore(which).getRetainedWidth()); } + return width / 2; } - return value; } /** - * @return half the maximum after border width of this cell. + * Returns the width of the before-after for the given row-span of this cell. In the + * separate border model half of the border-separation is included. In the collapsing + * model only half of the border is counted, since the other half belongs to the + * following cell; also, the returned value is the maximum of the segments of each + * applicable grid unit. + * + * @param rowIndex index of the span for which the border must be computed, 0-based + * @param which one of {@link ConditionalBorder#NORMAL}, + * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST} + * @return the after border width */ - public int getHalfMaxAfterBorderWidth() { - int value = 0; - if (getRows() != null) { - //Last row for after borders - int after = 0; - GridUnit[] row = (GridUnit[])getRows().get(getRows().size() - 1); - for (int i = 0; i < row.length; i++) { - if (row[i].hasBorders()) { - after = Math.max(after, row[i].getBorders().getBorderAfterWidth(false)); + public int getAfterBorderWidth(int rowIndex, int which) { + if (isSeparateBorderModel) { + if (getCell() == null) { + return 0; + } else { + CommonBorderPaddingBackground cellBorders = getCell() + .getCommonBorderPaddingBackground(); + switch (which) { + case ConditionalBorder.NORMAL: + case ConditionalBorder.LEADING_TRAILING: + return cellBorders.getBorderAfterWidth(false) + halfBorderSeparationBPD; + case ConditionalBorder.REST: + if (cellBorders.getBorderInfo(CommonBorderPaddingBackground.AFTER).getWidth() + .isDiscard()) { + return 0; + } else { + return cellBorders.getBorderAfterWidth(true) + halfBorderSeparationBPD; + } + default: + assert false; + return 0; } } - value += after / 2; } else { - if (hasBorders()) { - value += getBorders().getBorderAfterWidth(false) / 2; + int width = 0; + GridUnit[] row = (GridUnit[]) rows.get(rowIndex); + for (int i = 0; i < row.length; i++) { + width = Math.max(width, + row[i].getBorderAfter(which).getRetainedWidth()); } + return width / 2; } - return value; } /** - * @return the sum of half the maximum before and after border - * widths of this cell. + * Returns the width of the before-after for the last row-span of this cell. See + * {@link #getAfterBorderWidth(int, int)}. + * + * @param which one of {@link ConditionalBorder#NORMAL}, + * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST} + * @return the after border width */ - public int getHalfMaxBorderWidth() { - return getHalfMaxBeforeBorderWidth() + getHalfMaxAfterBorderWidth(); + public int getAfterBorderWidth(int which) { + return getAfterBorderWidth(getCell().getNumberRowsSpanned() - 1, which); } /** @return the length of the cell content. */ @@ -201,18 +270,18 @@ public class PrimaryGridUnit extends GridUnit { */ public int[] getStartEndBorderWidths() { int[] widths = new int[2]; - if (rows == null) { - widths[0] = getBorders().getBorderStartWidth(false); - widths[1] = getBorders().getBorderEndWidth(false); + if (getCell() == null) { + return widths; + } else if (getCell().getTable().isSeparateBorderModel()) { + widths[0] = getCell().getCommonBorderPaddingBackground().getBorderStartWidth(false); + widths[1] = getCell().getCommonBorderPaddingBackground().getBorderEndWidth(false); } else { for (int i = 0; i < rows.size(); i++) { GridUnit[] gridUnits = (GridUnit[])rows.get(i); widths[0] = Math.max(widths[0], - (gridUnits[0]). - getBorders().getBorderStartWidth(false)); - widths[1] = Math.max(widths[1], - (gridUnits[gridUnits.length - 1]). - getBorders().getBorderEndWidth(false)); + gridUnits[0].borderStart.getBorderInfo().getRetainedWidth()); + widths[1] = Math.max(widths[1], gridUnits[gridUnits.length - 1].borderEnd + .getBorderInfo().getRetainedWidth()); } } return widths; diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index a915edf87..2b6570dcc 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -395,7 +395,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { * @param index index of the column to be retrieved, 0-based * @return the corresponding column (may be an implicitly created column) */ - TableColumn getColumn(int index) { + public TableColumn getColumn(int index) { return (TableColumn) columns.get(index); } @@ -404,7 +404,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { * * @return the number of columns, implicit or explicit, in this table */ - int getNumberOfColumns() { + public int getNumberOfColumns() { return columns.size(); } diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java index f1e5ffdc6..841a94705 100644 --- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java +++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java @@ -21,7 +21,6 @@ package org.apache.fop.layoutmgr; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.area.Area; import org.apache.fop.area.Trait; import org.apache.fop.datatypes.LengthBase; @@ -31,6 +30,7 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.CommonTextDecoration; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.fonts.Font; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.MinOptMax; @@ -178,32 +178,30 @@ public class TraitSetter { * Layout managers that create areas with borders can use this to * add the borders to the area. * @param area the area to set the traits on. - * @param bordProps border properties + * @param borderBefore the resolved before border + * @param borderAfter the resolved after border + * @param borderStart the resolved start border + * @param borderEnd the resolved end border * @param outer 4 boolean values indicating if the side represents the * table's outer border. Order: before, after, start, end - * @param context Property evaluation context */ - public static void addCollapsingBorders(Area area, - CommonBorderPaddingBackground bordProps, - boolean[] outer, - PercentBaseContext context) { - BorderProps bps = getCollapsingBorderProps(bordProps, - CommonBorderPaddingBackground.BEFORE, outer[0]); + public static void addCollapsingBorders(Area area, + BorderInfo borderBefore, BorderInfo borderAfter, + BorderInfo borderStart, BorderInfo borderEnd, + boolean[] outer) { + BorderProps bps = getCollapsingBorderProps(borderBefore, outer[0]); if (bps != null) { area.addTrait(Trait.BORDER_BEFORE, bps); } - bps = getCollapsingBorderProps(bordProps, - CommonBorderPaddingBackground.AFTER, outer[1]); + bps = getCollapsingBorderProps(borderAfter, outer[1]); if (bps != null) { area.addTrait(Trait.BORDER_AFTER, bps); } - bps = getCollapsingBorderProps(bordProps, - CommonBorderPaddingBackground.START, outer[2]); + bps = getCollapsingBorderProps(borderStart, outer[2]); if (bps != null) { area.addTrait(Trait.BORDER_START, bps); } - bps = getCollapsingBorderProps(bordProps, - CommonBorderPaddingBackground.END, outer[3]); + bps = getCollapsingBorderProps(borderEnd, outer[3]); if (bps != null) { area.addTrait(Trait.BORDER_END, bps); } @@ -270,13 +268,11 @@ public class TraitSetter { } } - private static BorderProps getCollapsingBorderProps( - CommonBorderPaddingBackground bordProps, int side, boolean outer) { - int width = bordProps.getBorderWidth(side, false); + private static BorderProps getCollapsingBorderProps(BorderInfo borderInfo, boolean outer) { + assert borderInfo != null; + int width = borderInfo.getRetainedWidth(); if (width != 0) { - BorderProps bps; - bps = new BorderProps(bordProps.getBorderStyle(side), - width, bordProps.getBorderColor(side), + BorderProps bps = new BorderProps(borderInfo.getStyle(), width, borderInfo.getColor(), (outer ? BorderProps.COLLAPSE_OUTER : BorderProps.COLLAPSE_INNER)); return bps; } else { diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index a1957eb27..4321c32b8 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -22,9 +22,11 @@ package org.apache.fop.layoutmgr.table; import java.util.List; import java.util.ListIterator; +import org.apache.fop.fo.flow.table.ConditionalBorder; 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.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -39,15 +41,8 @@ class ActiveCell { private List elementList; /** Iterator over the Knuth element list. */ private ListIterator knuthIter; - private boolean prevIsBox = false; /** Number of the row where the row-span ends, zero-based. */ private int endRowIndex; - /** Index, in the list of Knuth elements, of the element starting the current step. */ - private int start; - /** Index, in the list of Knuth elements, of the element ending the current step. */ - private int end; - /** Length of the Knuth elements up to the next feasible break. */ - private int nextStepLength; /** Length of the Knuth elements not yet included in the steps. */ private int remainingLength; /** Heights of the rows (in the row-group) preceding the one where this cell starts. */ @@ -56,17 +51,81 @@ class ActiveCell { private int totalLength; /** Length of the Knuth elements already included in the steps. */ private int includedLength; - private int borderBefore; - private int borderAfter; - private int paddingBefore; - private int paddingAfter; + + private int borderBeforeNormal; + private int borderBeforeLeading; + private int borderAfterNormal; + private int borderAfterTrailing; + private int paddingBeforeNormal; + private int paddingBeforeLeading; + private int paddingAfterNormal; + private int paddingAfterTrailing; + private boolean keepWithNextSignal; - /** Length of the penalty ending the last step, if any. */ - private int lastPenaltyLength; + + private int spanIndex = 0; + private CellPart lastCellPart; + + private Step previousStep; + private Step nextStep; + + /** + * Auxiliary class to store all the informations related to a breaking step. + */ + private static class Step { + /** Index, in the list of Knuth elements, of the element starting this step. */ + private int start; + /** Index, in the list of Knuth elements, of the element ending this step. */ + private int end; + /** Length of the Knuth elements up to this step. */ + private int contentLength; + /** Total length up to this step, including paddings and borders. */ + private int totalLength; + /** Length of the penalty ending this step, if any. */ + private int penaltyLength; + /** + * Length of the optional content for the next step. That is, content that will + * not appear if the next step starts a new page. + */ + private int nextCondBeforeContentLength; + + Step(int contentLength) { + this.contentLength = contentLength; + // TODO necessary if a cell part must be created while this cell hasn't + // contributed any content yet. To be removed along with the 900-penalty + // mechanism + this.end = -1; + } + + Step(Step other) { + set(other); + } + + void set(Step other) { + this.start = other.start; + this.end = other.end; + this.contentLength = other.contentLength; + this.totalLength = other.totalLength; + this.penaltyLength = other.penaltyLength; + this.nextCondBeforeContentLength = other.nextCondBeforeContentLength; + } + } ActiveCell(PrimaryGridUnit pgu, EffRow row, int rowIndex, int previousRowsLength, TableLayoutManager tableLM) { this.pgu = pgu; + CommonBorderPaddingBackground bordersPaddings = pgu.getCell() + .getCommonBorderPaddingBackground(); + borderBeforeNormal = pgu.getBeforeBorderWidth(0, ConditionalBorder.NORMAL); + borderBeforeLeading = pgu.getBeforeBorderWidth(0, ConditionalBorder.REST); + borderAfterNormal = pgu.getAfterBorderWidth(ConditionalBorder.NORMAL); + borderAfterTrailing = pgu.getAfterBorderWidth(0, ConditionalBorder.REST); + TableCellLayoutManager cellLM = pgu.getCellLM(); + paddingBeforeNormal = bordersPaddings.getPaddingBefore(false, cellLM); + paddingBeforeLeading = bordersPaddings.getPaddingBefore(true, cellLM); + paddingAfterNormal = bordersPaddings.getPaddingAfter(false, cellLM); + paddingAfterTrailing = bordersPaddings.getPaddingAfter(true, cellLM); + boolean makeBoxForWholeRow = false; if (row.getExplicitHeight().min > 0) { boolean contentsSmaller = ElementListUtils.removeLegalBreaks( @@ -81,38 +140,24 @@ class ActiveCell { } if (makeBoxForWholeRow) { elementList = new java.util.ArrayList(1); - int height = row.getExplicitHeight().opt; - if (height == 0) { - height = row.getHeight().opt; - } + int height = row.getHeight().opt; + height -= 2 * tableLM.getHalfBorderSeparationBPD(); + height -= borderBeforeNormal + borderAfterNormal; // TODO conditionals + height -= paddingBeforeNormal + paddingAfterNormal; elementList.add(new KnuthBoxCellWithBPD(height)); } else { elementList = pgu.getElements(); -// if (log.isTraceEnabled()) { -// log.trace("column " + (column+1) + ": recording " + elementLists.size() + " element(s)"); -// } } knuthIter = elementList.listIterator(); includedLength = -1; // Avoid troubles with cells having content of zero length this.previousRowsLength = previousRowsLength; - nextStepLength = previousRowsLength; totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); - if (tableLM.getTable().isSeparateBorderModel()) { - borderBefore = pgu.getBorders().getBorderBeforeWidth(false) - + tableLM.getHalfBorderSeparationBPD(); - borderAfter = pgu.getBorders().getBorderAfterWidth(false) - + tableLM.getHalfBorderSeparationBPD(); - } else { - borderBefore = pgu.getHalfMaxBeforeBorderWidth(); - borderAfter = pgu.getHalfMaxAfterBorderWidth(); - } - paddingBefore = pgu.getBorders().getPaddingBefore(false, pgu.getCellLM()); - paddingAfter = pgu.getBorders().getPaddingAfter(false, pgu.getCellLM()); - start = 0; - end = -1; endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1; keepWithNextSignal = false; remainingLength = totalLength - previousRowsLength; + + nextStep = new Step(previousRowsLength); + previousStep = new Step(nextStep); goToNextLegalBreak(); } @@ -139,36 +184,48 @@ class ActiveCell { } else if (includedLength == totalLength) { return 0; } else { - return remainingLength + borderBefore + borderAfter + paddingBefore + paddingAfter; + return borderBeforeLeading + paddingBeforeLeading + remainingLength + + paddingAfterNormal + borderAfterNormal; } } private void goToNextLegalBreak() { - lastPenaltyLength = 0; + nextStep.penaltyLength = 0; boolean breakFound = false; + boolean prevIsBox = false; while (!breakFound && knuthIter.hasNext()) { KnuthElement el = (KnuthElement) knuthIter.next(); if (el.isPenalty()) { prevIsBox = false; if (el.getP() < KnuthElement.INFINITE) { - //First legal break point - lastPenaltyLength = el.getW(); + // First legal break point + nextStep.penaltyLength = el.getW(); breakFound = true; } } else if (el.isGlue()) { if (prevIsBox) { - //Second legal break point + // Second legal break point breakFound = true; } else { - nextStepLength += el.getW(); + nextStep.contentLength += el.getW(); } prevIsBox = false; } else { prevIsBox = true; - nextStepLength += el.getW(); + nextStep.contentLength += el.getW(); } } - end = knuthIter.nextIndex() - 1; + nextStep.end = knuthIter.nextIndex() - 1; + if (nextStep.end == elementList.size() - 1) { + // TODO wait that every cell on the row has finished before including border-after!! + nextStep.totalLength = borderBeforeNormal + paddingBeforeNormal + + nextStep.contentLength + nextStep.penaltyLength + + paddingAfterNormal + borderAfterNormal; + } else { + nextStep.totalLength = borderBeforeNormal + paddingBeforeNormal + + nextStep.contentLength + nextStep.penaltyLength + + paddingAfterTrailing + borderAfterTrailing; + } } /** @@ -177,23 +234,20 @@ class ActiveCell { * @return the total length up to the next legal break (-1 signals no further step) */ int getNextStep() { - if (!includedInLastStep()) { - return nextStepLength + lastPenaltyLength - + borderBefore + borderAfter + paddingBefore + paddingAfter; - } else { - start = end + 1; - if (knuthIter.hasNext()) { - goToNextLegalBreak(); - return nextStepLength + lastPenaltyLength - + borderBefore + borderAfter + paddingBefore + paddingAfter; - } else { + if (includedInLastStep()) { + previousStep.set(nextStep); + nextStep.start = nextStep.end + 1; + if (!knuthIter.hasNext()) { return -1; + } else { + goToNextLegalBreak(); } } + return nextStep.totalLength; } private boolean includedInLastStep() { - return includedLength == nextStepLength; + return includedLength == nextStep.contentLength; } /** @@ -204,14 +258,26 @@ class ActiveCell { * @return */ boolean signalMinStep(int minStep) { - if (nextStepLength + lastPenaltyLength - + borderBefore + borderAfter + paddingBefore + paddingAfter <= minStep) { - includedLength = nextStepLength; + if (nextStep.totalLength <= minStep) { + includedLength = nextStep.contentLength; computeRemainingLength(); return false; } else { - return previousRowsLength + borderBefore - + borderAfter + paddingBefore + paddingAfter > minStep; + return borderBeforeNormal + paddingBeforeNormal + previousRowsLength + + paddingAfterTrailing + borderAfterTrailing > minStep; + } + } + + void endRow(int rowIndex) { + if (endsOnRow(rowIndex)) { + int bpAfterNormal = paddingAfterNormal + borderAfterNormal; + int bpAfterLast = paddingAfterNormal + + pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING); + lastCellPart.setLast(bpAfterNormal, bpAfterLast); + } else { + spanIndex++; + borderBeforeLeading = pgu.getBeforeBorderWidth(spanIndex, ConditionalBorder.REST); + borderAfterTrailing = pgu.getAfterBorderWidth(spanIndex, ConditionalBorder.REST); } } @@ -221,13 +287,15 @@ class ActiveCell { * paddings are not considered here. */ private void computeRemainingLength() { - remainingLength = totalLength - nextStepLength; + remainingLength = totalLength - nextStep.contentLength; + nextStep.nextCondBeforeContentLength = 0; // Save the current location in the element list int oldIndex = knuthIter.nextIndex(); KnuthElement el; while (knuthIter.hasNext() && !(el = (KnuthElement) knuthIter.next()).isBox()) { if (el.isGlue()) { remainingLength -= el.getW(); + nextStep.nextCondBeforeContentLength += el.getW(); } } // Reset the iterator to the current location @@ -244,7 +312,7 @@ class ActiveCell { boolean contributesContent() { // return includedInLastStep() && the cell hasn't finished yet, otherwise there's // nothing more to contribute - return includedInLastStep() && end >= start; + return includedInLastStep() && nextStep.end >= nextStep.start; } /** @@ -262,7 +330,7 @@ class ActiveCell { * @return true if the end of this cell is reached */ boolean isFinished() { - return includedInLastStep() && (end == elementList.size() - 1); + return includedInLastStep() && (nextStep.end == elementList.size() - 1); } /** @@ -272,7 +340,7 @@ class ActiveCell { * @return a CellPart instance */ CellPart createCellPart() { - if (end + 1 == elementList.size()) { + if (nextStep.end + 1 == elementList.size()) { if (pgu.getFlag(GridUnit.KEEP_WITH_NEXT_PENDING)) { keepWithNextSignal = true; } @@ -280,22 +348,47 @@ class ActiveCell { keepWithNextSignal = true; } } - if (start == 0 && end == 0 + int bpBeforeNormal; + int bpBeforeFirst; + int bpAfterNormal; + int bpAfterLast; + if (nextStep.start == 0) { + bpBeforeNormal = borderBeforeNormal + paddingBeforeNormal; + bpBeforeFirst = pgu.getBeforeBorderWidth(0, ConditionalBorder.LEADING_TRAILING) + + paddingBeforeNormal; + } else { + bpBeforeNormal = 0; + bpBeforeFirst = borderBeforeLeading + paddingBeforeLeading; + } + bpAfterNormal = 0; + bpAfterLast = paddingAfterTrailing + borderAfterTrailing; + int length = nextStep.contentLength - previousStep.contentLength + - previousStep.nextCondBeforeContentLength; + if (!includedInLastStep() || nextStep.start == elementList.size()) { + lastCellPart = new CellPart(pgu, nextStep.start, previousStep.end, + 0, 0, previousStep.penaltyLength, + bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterLast); + } else if (nextStep.start == 0 && nextStep.end == 0 && elementList.size() == 1 && elementList.get(0) instanceof KnuthBoxCellWithBPD) { //Special case: Cell with fixed BPD - return new CellPart(pgu, 0, pgu.getElements().size() - 1); + lastCellPart = new CellPart(pgu, 0, pgu.getElements().size() - 1, + previousStep.nextCondBeforeContentLength, length, nextStep.penaltyLength, + bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterLast); } else { - return new CellPart(pgu, start, end); + lastCellPart = new CellPart(pgu, nextStep.start, nextStep.end, + previousStep.nextCondBeforeContentLength, length, nextStep.penaltyLength, + bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterLast); } + return lastCellPart; } boolean isLastForcedBreak() { - return ((KnuthElement)elementList.get(end)).isForcedBreak(); + return ((KnuthElement)elementList.get(nextStep.end)).isForcedBreak(); } int getLastBreakClass() { - return ((KnuthPenalty)elementList.get(end)).getBreakClass(); + return ((KnuthPenalty)elementList.get(nextStep.end)).getBreakClass(); } boolean keepWithNextSignal() { diff --git a/src/java/org/apache/fop/layoutmgr/table/CellPart.java b/src/java/org/apache/fop/layoutmgr/table/CellPart.java index bf5ad64cf..f6c292f97 100644 --- a/src/java/org/apache/fop/layoutmgr/table/CellPart.java +++ b/src/java/org/apache/fop/layoutmgr/table/CellPart.java @@ -23,7 +23,7 @@ import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; /** - * Represents a non-dividable part of a grid unit. Used by the table stepper. + * Represents a non-divisible part of a grid unit. Used by the table stepper. */ class CellPart { @@ -34,16 +34,47 @@ class CellPart { /** Index of the ending element of this part */ protected int end; + private int condBeforeContentLength; + private int length; + private int condAfterContentLength; + private int bpBeforeNormal; + private int bpBeforeFirst; + private int bpAfterNormal; + private int bpAfterLast; + private boolean isLast; + /** * Creates a new CellPart. + * * @param pgu Primary grid unit * @param start starting element * @param end ending element + * @param condBeforeContentLength length of the additional content that will have to + * be displayed if this part will be the first one on the page + * @param length length of the content represented by this cell part + * @param condAfterContentLength length of the additional content that will have to be + * displayed if this part will be the last one on the page + * @param bpBeforeNormal width of border- and padding-before in the normal case + * @param bpBeforeFirst width of (possibly optional) border- and padding-before if + * this part will be the first one on the page + * @param bpAfterNormal width of border- and padding-after in the normal case + * @param bpAfterFirst width of (possibly optional) border- and padding-after if this + * part will be the last one on the page */ - protected CellPart(PrimaryGridUnit pgu, int start, int end) { + protected CellPart(PrimaryGridUnit pgu, int start, int end, + int condBeforeContentLength, int length, int condAfterContentLength, + int bpBeforeNormal, int bpBeforeFirst, + int bpAfterNormal, int bpAfterLast) { this.pgu = pgu; this.start = start; this.end = end; + this.condBeforeContentLength = condBeforeContentLength; + this.length = length; + this.condAfterContentLength = condAfterContentLength; + this.bpBeforeNormal = bpBeforeNormal; + this.bpBeforeFirst = bpBeforeFirst; + this.bpAfterNormal = bpAfterNormal; + this.bpAfterLast = bpAfterLast; } /** @return true if this part is the first part of a cell */ @@ -52,8 +83,42 @@ class CellPart { } /** @return true if this part is the last part of a cell */ - public boolean isLastPart() { - return (end >= 0 && end == pgu.getElements().size() - 1); + boolean isLastPart() { + return isLast; + } + + void setLast(int bpNormal, int bpLast) { + isLast = true; + bpAfterNormal = bpNormal; + bpAfterLast = bpLast; + } + + int getBorderPaddingBefore(boolean firstOnPage) { + if (firstOnPage) { + return bpBeforeFirst; + } else { + return bpBeforeNormal; + } + } + + int getBorderPaddingAfter(boolean lastOnPage) { + if (lastOnPage) { + return bpAfterLast; + } else { + return bpAfterNormal; + } + } + + int getConditionalBeforeContentLength() { + return condBeforeContentLength; + } + + int getLength() { + return length; + } + + int getConditionalAfterContentLength() { + return condAfterContentLength; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 3fa40a8fd..199af0fc1 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -34,7 +34,6 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListObserver; -import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.LayoutContext; @@ -239,13 +238,7 @@ class RowGroupLayoutManager { effectiveCellBPD = Math.max(effectiveCellBPD, primary.getContentLength()); - int borderWidths; - if (tableLM.getTable().isSeparateBorderModel()) { - borderWidths = primary.getBorders().getBorderBeforeWidth(false) - + primary.getBorders().getBorderAfterWidth(false); - } else { - borderWidths = primary.getHalfMaxBorderWidth(); - } + int borderWidths = primary.getBeforeAfterBorderWidth(); int padding = 0; maxCellBPD = Math.max(maxCellBPD, effectiveCellBPD); CommonBorderPaddingBackground cbpb @@ -253,8 +246,7 @@ class RowGroupLayoutManager { padding += cbpb.getPaddingBefore(false, primary.getCellLM()); padding += cbpb.getPaddingAfter(false, primary.getCellLM()); int effRowHeight = effectiveCellBPD - + padding + borderWidths - + 2 * tableLM.getHalfBorderSeparationBPD(); + + padding + borderWidths; for (int previous = 0; previous < gu.getRowSpanIndex(); previous++) { effRowHeight -= rowHeights[rgi - previous - 1].opt; } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 9a79d7744..f46b503bb 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -26,16 +26,17 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.fo.flow.table.ConditionalBorder; 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.fo.properties.LengthRangeProperty; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.SpaceResolver; +import org.apache.fop.traits.BorderProps; class RowPainter { private static Log log = LogFactory.getLog(RowPainter.class); @@ -50,6 +51,14 @@ class RowPainter { * Index of the first row of the current part present on the current page. */ private int firstRowIndex; + + /** + * Index of the very first row on the current page. Needed to properly handle + * {@link BorderProps#COLLAPSE_OUTER}. This is not the same as {@link #firstRowIndex} + * when the table has headers! + */ + private int firstRowOnPageIndex; + /** * Keeps track of the y-offsets of each row on a page. * This is particularly needed for spanned cells where you need to know the y-offset @@ -57,36 +66,23 @@ class RowPainter { */ private List rowOffsets = new ArrayList(); - //These three variables are our buffer to recombine the individual steps into cells - /** Primary grid units corresponding to the currently handled grid units, per row. */ - private PrimaryGridUnit[] primaryGridUnits; - /** - * Index, in the corresponding table cell's list of Knuth elements, of the first - * element present on the current page, per column. - */ - private int[] start; - /** - * Index, in the corresponding table cell's list of Knuth elements, of the last - * element present on the current page, per column. - */ - private int[] end; - /** - * Length, for each column, of the elements from the current cell put on the - * current page. This is the corresponding area's bpd. - */ - private int[] partBPD; + private int[] cellHeights; + private boolean[] firstCellOnPage; + private CellPart[] firstCellParts; + private CellPart[] lastCellParts; + private TableContentLayoutManager tclm; RowPainter(TableContentLayoutManager tclm, LayoutContext layoutContext) { this.tclm = tclm; this.layoutContext = layoutContext; this.colCount = tclm.getColumns().getColumnCount(); - this.primaryGridUnits = new PrimaryGridUnit[colCount]; - this.start = new int[colCount]; - this.end = new int[colCount]; - this.partBPD = new int[colCount]; + this.cellHeights = new int[colCount]; + this.firstCellOnPage = new boolean[colCount]; + this.firstCellParts = new CellPart[colCount]; + this.lastCellParts = new CellPart[colCount]; this.firstRowIndex = -1; - Arrays.fill(end, -1); + this.firstRowOnPageIndex = -1; } int getAccumulatedBPD() { @@ -101,7 +97,7 @@ class RowPainter { */ void handleTableContentPosition(TableContentPosition tcpos) { if (tcpos.row != currentRow && currentRow != null) { - addAreasAndFlushRow(false); + addAreasAndFlushRow(false, false); } if (log.isDebugEnabled()) { log.debug("===handleTableContentPosition(" + tcpos); @@ -110,6 +106,9 @@ class RowPainter { currentRow = tcpos.row; if (firstRowIndex < 0) { firstRowIndex = currentRow.getIndex(); + if (firstRowOnPageIndex < 0) { + firstRowOnPageIndex = firstRowIndex; + } } Iterator partIter = tcpos.cellParts.iterator(); //Iterate over all grid units in the current step @@ -119,173 +118,153 @@ class RowPainter { log.debug(">" + cellPart); } int colIndex = cellPart.pgu.getStartCol(); - if (primaryGridUnits[colIndex] != cellPart.pgu) { - if (primaryGridUnits[colIndex] != null) { - log.warn("Replacing GU in slot " + colIndex - + ". Some content may not be painted."); - } - primaryGridUnits[colIndex] = cellPart.pgu; - start[colIndex] = cellPart.start; - end[colIndex] = cellPart.end; + if (firstCellParts[colIndex] == null) { + firstCellParts[colIndex] = cellPart; + cellHeights[colIndex] = cellPart.getBorderPaddingBefore(firstCellOnPage[colIndex]); } else { - if (cellPart.end < end[colIndex]) { - throw new IllegalStateException("Internal Error: stepper problem"); - } - end[colIndex] = cellPart.end; + assert firstCellParts[colIndex].pgu == cellPart.pgu; + cellHeights[colIndex] += cellPart.getConditionalBeforeContentLength(); } + cellHeights[colIndex] += cellPart.getLength(); + lastCellParts[colIndex] = cellPart; } } /** - * Create the areas corresponding to the last row. This method is called either - * because the row is finished (all of the elements present on this row have been - * added), or because this is the last row on the current page, and the part of it - * lying on the current page must be drawn. + * Creates the areas corresponding to the last row. That is, an area with background + * for the row, plus areas for all the cells that finish on the row (not spanning over + * further rows). * - * @param forcedFlush true if the elements must be drawn even if the row isn't - * finished yet (last row on the page), or if the row is the last of the current table - * part + * @param lastInPart true if the row is the last from its table part to be displayed + * on the current page. In which case all the cells must be flushed even if they + * aren't finished, plus the proper collapsed borders must be selected (trailing + * instead of normal, or rest if the cell is unfinished) + * @param lastOnPage true if the row is the very last row of the table that will be + * displayed on the current page. In which case collapsed after borders must be drawn + * in the outer mode */ - void addAreasAndFlushRow(boolean forcedFlush) { - int actualRowHeight = 0; - + void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) { if (log.isDebugEnabled()) { log.debug("Remembering yoffset for row " + currentRow.getIndex() + ": " + currentRowOffset); } recordRowOffset(currentRow.getIndex(), currentRowOffset); - for (int i = 0; i < primaryGridUnits.length; i++) { - if ((primaryGridUnits[i] != null) - && (forcedFlush || (end[i] == primaryGridUnits[i].getElements().size() - 1))) { - actualRowHeight = Math.max(actualRowHeight, computeSpanHeight( - primaryGridUnits[i], start[i], end[i], i)); + // Need to compute the actual row height first + int actualRowHeight = 0; + for (int i = 0; i < colCount; i++) { + GridUnit currentGU = currentRow.getGridUnit(i); + if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 + && (lastInPart || currentGU.isLastGridUnitRowSpan())) { + int cellHeight = cellHeights[i]; + cellHeight += lastCellParts[i].getConditionalAfterContentLength(); + cellHeight += lastCellParts[i].getBorderPaddingAfter(lastInPart); + int cellOffset = getRowOffset(Math.max(firstCellParts[i].pgu.getStartRow(), + firstRowIndex)); + actualRowHeight = Math.max(actualRowHeight, cellOffset + cellHeight + - currentRowOffset); } } - actualRowHeight += 2 * tclm.getTableLM().getHalfBorderSeparationBPD(); - //Add areas for row + // Then add areas for cells finishing on the current row tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), currentRowOffset); - for (int i = 0; i < primaryGridUnits.length; i++) { + for (int i = 0; i < colCount; i++) { GridUnit currentGU = currentRow.getGridUnit(i); if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 - && (forcedFlush || currentGU.isLastGridUnitRowSpan())) { - addAreasForCell(currentGU.getPrimary(), start[i], end[i], currentRow, partBPD[i], - actualRowHeight); - primaryGridUnits[i] = null; - start[i] = 0; - end[i] = -1; - partBPD[i] = 0; + && (lastInPart || currentGU.isLastGridUnitRowSpan())) { + assert firstCellParts[i].pgu == currentGU.getPrimary(); + int borderBeforeWhich; + if (firstCellParts[i].start == 0) { + if (firstCellOnPage[i]) { + borderBeforeWhich = ConditionalBorder.LEADING_TRAILING; + } else { + borderBeforeWhich = ConditionalBorder.NORMAL; + } + } else { + assert firstCellOnPage[i]; + borderBeforeWhich = ConditionalBorder.REST; + } + int borderAfterWhich; + if (lastCellParts[i].isLastPart()) { + if (lastInPart) { + borderAfterWhich = ConditionalBorder.LEADING_TRAILING; + } else { + borderAfterWhich = ConditionalBorder.NORMAL; + } + } else { + borderAfterWhich = ConditionalBorder.REST; + } + addAreasForCell(firstCellParts[i].pgu, + firstCellParts[i].start, lastCellParts[i].end, + actualRowHeight, borderBeforeWhich, borderAfterWhich, + lastOnPage); + firstCellParts[i] = null; + firstCellOnPage[i] = false; } } currentRowOffset += actualRowHeight; - if (forcedFlush) { - // Either the end of the page is reached, then this was the last call of this - // method and we no longer care about currentRow; or the end of a table-part - // (header, footer, body) has been reached, and the next row will anyway be - // different from the current one, and this is unnecessary to recall this - // method in the first lines of handleTableContentPosition, so we may reset - // the following variables + if (lastInPart) { + /* + * Either the end of the page is reached, then this was the last call of this + * method and we no longer care about currentRow; or the end of a table-part + * (header, footer, body) has been reached, and the next row will anyway be + * different from the current one, and this is unnecessary to call this method + * again in the first lines of handleTableContentPosition, so we may reset the + * following variables. + */ currentRow = null; firstRowIndex = -1; rowOffsets.clear(); + /* + * The current table part has just been handled. Be it the first one or not, + * the header or the body, in any case the borders-before of the next row + * (i.e., the first row of the next part if any) must be painted in + * COLLAPSE_INNER mode. So the firstRowOnPageIndex indicator must be kept + * disabled. The following way is not the most elegant one but will be good + * enough. + */ + firstRowOnPageIndex = Integer.MAX_VALUE; } } - /** - * Computes the total height of the part of the given cell spanning on the current - * active row, including borders and paddings. The bpd is also stored in partBPD, and - * it is ensured that the cell's or row's explicit height is respected. - * - * @param pgu primary grid unit corresponding to the cell - * @param start index of the first element of the cell occuring on the current page - * @param end index of the last element of the cell occuring on the current page - * @param columnIndex column index of the cell - * @param bodyType {@link TableRowIterator#HEADER}, {@link TableRowIterator#FOOTER}, or - * {@link TableRowIterator#BODY} - * @return the cell's height - */ - private int computeSpanHeight(PrimaryGridUnit pgu, int start, int end, int columnIndex) { - if (log.isTraceEnabled()) { - log.trace("getting len for " + columnIndex + " " - + start + "-" + end); - } - int actualStart = start; - // Skip from the content length calculation glues and penalties occuring at the + // TODO this is not very efficient and should probably be done another way + // this method is only necessary when display-align = center or after, in which case + // the exact content length is needed to compute the size of the empty block that will + // be used as padding. + // This should be handled automatically by a proper use of Knuth elements + private int computeContentLength(PrimaryGridUnit pgu, int startIndex, int endIndex) { + int actualStart = startIndex; + // Skip from the content length calculation glues and penalties occurring at the // beginning of the page - while (actualStart <= end && !((KnuthElement)pgu.getElements().get(actualStart)).isBox()) { + while (actualStart <= endIndex + && !((KnuthElement) pgu.getElements().get(actualStart)).isBox()) { actualStart++; } int len = ElementListUtils.calcContentLength( - pgu.getElements(), actualStart, end); - KnuthElement el = (KnuthElement)pgu.getElements().get(end); + pgu.getElements(), actualStart, endIndex); + KnuthElement el = (KnuthElement)pgu.getElements().get(endIndex); if (el.isPenalty()) { len += el.getW(); } - partBPD[columnIndex] = len; - if (log.isTraceEnabled()) { - log.trace("len of part: " + len); - } - - if (start == 0) { - LengthRangeProperty bpd = pgu.getCell() - .getBlockProgressionDimension(); - if (!bpd.getMinimum(tclm.getTableLM()).isAuto()) { - int min = bpd.getMinimum(tclm.getTableLM()) - .getLength().getValue(tclm.getTableLM()); - if (min > 0) { - len = Math.max(len, min); - } - } - if (!bpd.getOptimum(tclm.getTableLM()).isAuto()) { - int opt = bpd.getOptimum(tclm.getTableLM()) - .getLength().getValue(tclm.getTableLM()); - if (opt > 0) { - len = Math.max(len, opt); - } - } - if (pgu.getRow() != null) { - bpd = pgu.getRow().getBlockProgressionDimension(); - if (!bpd.getMinimum(tclm.getTableLM()).isAuto()) { - int min = bpd.getMinimum(tclm.getTableLM()).getLength() - .getValue(tclm.getTableLM()); - if (min > 0) { - len = Math.max(len, min); - } - } - } - } - - // Add the padding if any - len += pgu.getBorders() - .getPaddingBefore(false, pgu.getCellLM()); - len += pgu.getBorders() - .getPaddingAfter(false, pgu.getCellLM()); - - //Now add the borders to the contentLength - if (tclm.isSeparateBorderModel()) { - len += pgu.getBorders().getBorderBeforeWidth(false); - len += pgu.getBorders().getBorderAfterWidth(false); - } else { - len += pgu.getHalfMaxBeforeBorderWidth(); - len += pgu.getHalfMaxAfterBorderWidth(); - } - int cellOffset = getRowOffset(Math.max(pgu.getStartRow(), firstRowIndex)); - len -= currentRowOffset - cellOffset; return len; } private void addAreasForCell(PrimaryGridUnit pgu, int startPos, int endPos, - EffRow row, int contentHeight, int rowHeight) { - //Determine the first row in this sequence + int rowHeight, int borderBeforeWhich, int borderAfterWhich, boolean lastOnPage) { + /* + * Determine the index of the first row of this cell that will be displayed on the + * current page. + */ int startRowIndex = Math.max(pgu.getStartRow(), firstRowIndex); int currentRowIndex = currentRow.getIndex(); - // In collapsing-border model, if the cell spans over several columns/rows then - // dedicated areas will be created for each grid unit to hold the corresponding - // borders. For that we need to know the height of each grid unit, that is of each - // grid row spanned over by the cell + /* + * In collapsing-border model, if the cell spans over several columns/rows then + * dedicated areas will be created for each grid unit to hold the corresponding + * borders. For that we need to know the height of each grid unit, that is of each + * grid row spanned over by the cell + */ int[] spannedGridRowHeights = null; if (!tclm.getTableLM().getTable().isSeparateBorderModel() && pgu.hasSpanning()) { spannedGridRowHeights = new int[currentRowIndex - startRowIndex + 1]; @@ -297,24 +276,19 @@ class RowPainter { } spannedGridRowHeights[currentRowIndex - startRowIndex] = rowHeight; } - int cellOffset = getRowOffset(startRowIndex); - int effCellHeight = rowHeight; - effCellHeight += currentRowOffset - cellOffset; + int cellTotalHeight = rowHeight + currentRowOffset - cellOffset; if (log.isDebugEnabled()) { log.debug("Creating area for cell:"); - log.debug(" current row: " + row.getIndex()); log.debug(" start row: " + pgu.getStartRow() + " " + currentRowOffset + " " + cellOffset); - log.debug(" contentHeight: " + contentHeight + " rowHeight=" + rowHeight - + " effCellHeight=" + effCellHeight); + log.debug(" rowHeight=" + rowHeight + " cellTotalHeight=" + cellTotalHeight); } TableCellLayoutManager cellLM = pgu.getCellLM(); cellLM.setXOffset(tclm.getXOffsetOfGridUnit(pgu)); cellLM.setYOffset(cellOffset); - cellLM.setContentHeight(contentHeight); - cellLM.setRowHeight(effCellHeight); - //cellLM.setRowHeight(row.getHeight().opt); + cellLM.setContentHeight(computeContentLength(pgu, startPos, endPos)); + cellLM.setTotalHeight(cellTotalHeight); int prevBreak = ElementListUtils.determinePreviousBreak(pgu.getElements(), startPos); if (endPos >= 0) { SpaceResolver.performConditionalsNotification(pgu.getElements(), @@ -322,7 +296,8 @@ class RowPainter { } cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(), startPos, endPos + 1), layoutContext, spannedGridRowHeights, startRowIndex - pgu.getStartRow(), - currentRowIndex - pgu.getStartRow() + 1); + currentRowIndex - pgu.getStartRow(), borderBeforeWhich, borderAfterWhich, + startRowIndex == firstRowOnPageIndex, lastOnPage); } /** @@ -358,4 +333,14 @@ class RowPainter { private int getRowOffset(int rowIndex) { return ((Integer) rowOffsets.get(rowIndex - firstRowIndex)).intValue(); } + + // TODO get rid of that + void startBody() { + Arrays.fill(firstCellOnPage, true); + } + + // TODO get rid of that + void endBody() { + Arrays.fill(firstCellOnPage, false); + } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 63810e057..421d3d580 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -28,11 +28,13 @@ import org.apache.fop.area.Block; import org.apache.fop.area.Trait; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.layoutmgr.AreaAdditionUtil; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; @@ -47,6 +49,7 @@ import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; +import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.MinOptMax; /** @@ -65,8 +68,6 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager private Block curBlockArea; - private int inRowIPDOffset; - private int xoffset; private int yoffset; private int cellIPD; @@ -137,7 +138,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager startIndent /= 2; endIndent /= 2; } - startIndent += getTableCell().getCommonBorderPaddingBackground().getPaddingStart(false, this); + startIndent += getTableCell().getCommonBorderPaddingBackground().getPaddingStart(false, + this); endIndent += getTableCell().getCommonBorderPaddingBackground().getPaddingEnd(false, this); return startIndent + endIndent; } @@ -271,15 +273,6 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager xoffset = off; } - /** - * Set the IPD offset of this cell inside the table-row. - * This offset is used to determine the absolute position of the cell. - * @param off the IPD offset - */ - public void setInRowIPDOffset(int off) { - this.inRowIPDOffset = off; - } - /** * Set the content height for this cell. This method is used during * addAreas() stage. @@ -291,36 +284,15 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } /** - * Set the row height that contains this cell. This method is used during - * addAreas() stage. - * - * @param h the height of the row + * Sets the total height of this cell on the current page. That is, the cell's bpd + * plus before and after borders and paddings, plus the table's border-separation. + * + * @param h the height of cell */ - public void setRowHeight(int h) { + public void setTotalHeight(int h) { rowHeight = h; } - /** - * Returns the bpd of the given grid unit. - * @param gu a grid unit belonging to this cell - * @return the content height of the grid unit - */ - private int getContentHeight(GridUnit gu) { - int bpd = rowHeight; - if (isSeparateBorderModel()) { - bpd -= gu.getPrimary().getBorders().getBorderBeforeWidth(false); - bpd -= gu.getPrimary().getBorders().getBorderAfterWidth(false); - } else { - bpd -= gu.getPrimary().getHalfMaxBorderWidth(); - } - CommonBorderPaddingBackground cbpb - = gu.getCell().getCommonBorderPaddingBackground(); - bpd -= cbpb.getPaddingBefore(false, this); - bpd -= cbpb.getPaddingAfter(false, this); - bpd -= 2 * ((TableLayoutManager)getParent()).getHalfBorderSeparationBPD(); - return bpd; - } - /** * Add the areas for the break points. The cell contains block stacking layout * managers that add block areas. @@ -336,99 +308,151 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * of each spanned grid row * @param startRow first grid row on the current page spanned over by the cell, * inclusive - * @param endRow last grid row on the current page spanned over by the cell, exclusive + * @param endRow last grid row on the current page spanned over by the cell, inclusive + * @param borderBeforeWhich one of {@link ConditionalBorder#NORMAL}, + * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST} + * @param borderAfterWhich one of {@link ConditionalBorder#NORMAL}, + * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST} + * @param firstOnPage true if the cell will be the very first one on the page, in + * which case collapsed before borders must be drawn in the outer mode + * @param lastOnPage true if the cell will be the very last one on the page, in which + * case collapsed after borders must be drawn in the outer mode */ public void addAreas(PositionIterator parentIter, LayoutContext layoutContext, int[] spannedGridRowHeights, int startRow, - int endRow) { + int endRow, + int borderBeforeWhich, + int borderAfterWhich, + boolean firstOnPage, + boolean lastOnPage) { getParentArea(null); getPSLM().addIDToPage(getTableCell().getId()); + int borderBeforeWidth = primaryGridUnit.getBeforeBorderWidth(startRow, borderBeforeWhich); + int borderAfterWidth = primaryGridUnit.getAfterBorderWidth(endRow, borderAfterWhich); if (isSeparateBorderModel()) { if (!emptyCell || getTableCell().showEmptyCells()) { - TraitSetter.addBorders(curBlockArea, getTableCell().getCommonBorderPaddingBackground(), - false, false, false, false, this); - TraitSetter.addPadding(curBlockArea, getTableCell().getCommonBorderPaddingBackground(), - false, false, false, false, this); + if (borderBeforeWidth > 0) { + int halfBorderSepBPD = getTableCell().getTable().getBorderSeparation().getBPD() + .getLength().getValue() / 2; + adjustYOffset(curBlockArea, halfBorderSepBPD); + } + TraitSetter.addBorders(curBlockArea, + getTableCell().getCommonBorderPaddingBackground(), + borderBeforeWidth == 0, borderAfterWidth == 0, + false, false, this); } } else { + boolean inFirstColumn = (primaryGridUnit.getStartCol() == 0); + boolean inLastColumn = (primaryGridUnit.getStartCol() + + getTableCell().getNumberColumnsSpanned() == getTable() + .getNumberOfColumns()); if (!primaryGridUnit.hasSpanning()) { + adjustYOffset(curBlockArea, -borderBeforeWidth); //Can set the borders directly if there's no span - boolean[] outer = new boolean[] { - primaryGridUnit.getFlag(GridUnit.FIRST_IN_TABLE), - primaryGridUnit.getFlag(GridUnit.LAST_IN_TABLE), - primaryGridUnit.getFlag(GridUnit.IN_FIRST_COLUMN), - primaryGridUnit.getFlag(GridUnit.IN_LAST_COLUMN)}; + boolean[] outer = new boolean[] {firstOnPage, lastOnPage, inFirstColumn, + inLastColumn}; TraitSetter.addCollapsingBorders(curBlockArea, - primaryGridUnit.getBorders(), outer, this); + primaryGridUnit.getBorderBefore(borderBeforeWhich), + primaryGridUnit.getBorderAfter(borderAfterWhich), + primaryGridUnit.getBorderStart(), + primaryGridUnit.getBorderEnd(), outer); } else { - boolean[] outer = new boolean[4]; + adjustYOffset(curBlockArea, borderBeforeWidth); + Block[][] blocks = new Block[getTableCell().getNumberRowsSpanned()][getTableCell() + .getNumberColumnsSpanned()]; + GridUnit[] gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(startRow); + for (int x = 0; x < getTableCell().getNumberColumnsSpanned(); x++) { + GridUnit gu = gridUnits[x]; + BorderInfo border = gu.getBorderBefore(borderBeforeWhich); + int borderWidth = border.getRetainedWidth() / 2; + if (borderWidth > 0) { + addBorder(blocks, startRow, x, Trait.BORDER_BEFORE, border, firstOnPage); + adjustYOffset(blocks[startRow][x], -borderWidth); + adjustBPD(blocks[startRow][x], -borderWidth); + } + } + gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(endRow); + for (int x = 0; x < getTableCell().getNumberColumnsSpanned(); x++) { + GridUnit gu = gridUnits[x]; + BorderInfo border = gu.getBorderAfter(borderAfterWhich); + int borderWidth = border.getRetainedWidth() / 2; + if (borderWidth > 0) { + addBorder(blocks, endRow, x, Trait.BORDER_AFTER, border, lastOnPage); + adjustBPD(blocks[endRow][x], -borderWidth); + } + } + for (int y = startRow; y <= endRow; y++) { + gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(y); + BorderInfo border = gridUnits[0].getBorderStart(); + int borderWidth = border.getRetainedWidth() / 2; + if (borderWidth > 0) { + addBorder(blocks, y, 0, Trait.BORDER_START, border, inFirstColumn); + adjustXOffset(blocks[y][0], borderWidth); + adjustIPD(blocks[y][0], -borderWidth); + } + border = gridUnits[gridUnits.length - 1].getBorderEnd(); + borderWidth = border.getRetainedWidth() / 2; + if (borderWidth > 0) { + addBorder(blocks, y, gridUnits.length - 1, Trait.BORDER_END, border, + inLastColumn); + adjustIPD(blocks[y][gridUnits.length - 1], -borderWidth); + } + } int dy = yoffset; - for (int y = startRow; y < endRow; y++) { - GridUnit[] gridUnits = (GridUnit[])primaryGridUnit.getRows().get(y); + for (int y = startRow; y <= endRow; y++) { + int bpd = spannedGridRowHeights[y - startRow]; int dx = xoffset; for (int x = 0; x < gridUnits.length; x++) { - GridUnit gu = gridUnits[x]; - if (gu.hasBorders()) { - //Blocks for painting grid unit borders - Block block = new Block(); - block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); - block.setPositioning(Block.ABSOLUTE); - - int bpd = spannedGridRowHeights[y - startRow]; - bpd -= gu.getBorders().getBorderBeforeWidth(false) / 2; - bpd -= gu.getBorders().getBorderAfterWidth(false) / 2; - block.setBPD(bpd); - if (log.isTraceEnabled()) { - log.trace("pgu: " + primaryGridUnit + "; gu: " + gu + "; yoffset: " - + (dy - gu.getBorders().getBorderBeforeWidth(false) / 2) - + "; bpd: " + bpd); - } - int ipd = gu.getColumn().getColumnWidth().getValue( - (PercentBaseContext) getParent()); - int borderStartWidth = gu.getBorders().getBorderStartWidth(false) / 2; - ipd -= borderStartWidth; - ipd -= gu.getBorders().getBorderEndWidth(false) / 2; - block.setIPD(ipd); - block.setXOffset(dx + borderStartWidth); - block.setYOffset(dy - gu.getBorders().getBorderBeforeWidth(false) / 2); - outer[0] = gu.getFlag(GridUnit.FIRST_IN_TABLE); - outer[1] = gu.getFlag(GridUnit.LAST_IN_TABLE); - outer[2] = gu.getFlag(GridUnit.IN_FIRST_COLUMN); - outer[3] = gu.getFlag(GridUnit.IN_LAST_COLUMN); - TraitSetter.addCollapsingBorders(block, gu.getBorders(), outer, this); + int ipd = getTable().getColumn(primaryGridUnit.getStartCol() + x) + .getColumnWidth().getValue((PercentBaseContext) getParent()); + if (blocks[y][x] != null) { + Block block = blocks[y][x]; + adjustYOffset(block, dy); + adjustXOffset(block, dx); + adjustIPD(block, ipd); + adjustBPD(block, bpd); parentLM.addChildArea(block); } - dx += gu.getColumn().getColumnWidth().getValue( - (PercentBaseContext) getParent()); + dx += ipd; } - dy += spannedGridRowHeights[y - startRow]; + dy += bpd; } } } - TraitSetter.addPadding(curBlockArea, primaryGridUnit.getBorders(), - false, false, false, false, this); + + CommonBorderPaddingBackground padding = primaryGridUnit.getCell() + .getCommonBorderPaddingBackground(); + TraitSetter.addPadding(curBlockArea, + padding, + borderBeforeWhich == ConditionalBorder.REST, + borderAfterWhich == ConditionalBorder.REST, + false, false, this); + + int cellBPD = rowHeight - borderBeforeWidth - borderAfterWidth; + cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this); + cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this); //Handle display-align - int contentBPD = getContentHeight(primaryGridUnit); - if (usedBPD < contentBPD) { + if (usedBPD < cellBPD) { if (getTableCell().getDisplayAlign() == EN_CENTER) { Block space = new Block(); - space.setBPD((contentBPD - usedBPD) / 2); + space.setBPD((cellBPD - usedBPD) / 2); curBlockArea.addBlock(space); } else if (getTableCell().getDisplayAlign() == EN_AFTER) { Block space = new Block(); - space.setBPD((contentBPD - usedBPD)); + space.setBPD(cellBPD - usedBPD); curBlockArea.addBlock(space); } } AreaAdditionUtil.addAreas(this, parentIter, layoutContext); - - curBlockArea.setBPD(contentBPD); + // Re-adjust the cell's bpd as it may have been modified by the previous call + // for some reason (?) + curBlockArea.setBPD(cellBPD); // Add background after we know the BPD if (isSeparateBorderModel()) { @@ -448,6 +472,34 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager curBlockArea = null; } + private void addBorder(Block[][] blocks, int i, int j, Integer side, BorderInfo border, + boolean outer) { + if (blocks[i][j] == null) { + blocks[i][j] = new Block(); + blocks[i][j].addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); + blocks[i][j].setPositioning(Block.ABSOLUTE); + } + blocks[i][j].addTrait(side, new BorderProps(border.getStyle(), + border.getRetainedWidth(), border.getColor(), + outer ? BorderProps.COLLAPSE_OUTER : BorderProps.COLLAPSE_INNER)); + } + + private static void adjustXOffset(Block block, int amount) { + block.setXOffset(block.getXOffset() + amount); + } + + private static void adjustYOffset(Block block, int amount) { + block.setYOffset(block.getYOffset() + amount); + } + + private static void adjustIPD(Block block, int amount) { + block.setIPD(block.getIPD() + amount); + } + + private static void adjustBPD(Block block, int amount) { + block.setBPD(block.getBPD() + amount); + } + /** * Return an Area which can contain the passed childArea. The childArea * may not yet have any content, but it has essential traits set. @@ -467,25 +519,10 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager curBlockArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); TraitSetter.setProducerID(curBlockArea, getTableCell().getId()); curBlockArea.setPositioning(Block.ABSOLUTE); - // set position - int borderAdjust = 0; - if (!isSeparateBorderModel()) { - if (primaryGridUnit.hasSpanning()) { - borderAdjust -= primaryGridUnit.getHalfMaxBeforeBorderWidth(); - } else { - borderAdjust += primaryGridUnit.getHalfMaxBeforeBorderWidth(); - } - } else { - //borderAdjust += primaryGridUnit.getBorders().getBorderBeforeWidth(false); - } - TableLayoutManager tableLM = (TableLayoutManager)getParent(); - curBlockArea.setXOffset(xoffset + inRowIPDOffset + startIndent); - curBlockArea.setYOffset(yoffset - borderAdjust - + tableLM.getHalfBorderSeparationBPD()); + curBlockArea.setXOffset(xoffset + startIndent); + curBlockArea.setYOffset(yoffset); curBlockArea.setIPD(cellIPD); - //curBlockArea.setHeight(); - // Set up dimensions /*Area parentArea =*/ parentLM.getParentArea(curBlockArea); // Get reference IPD from parentArea setCurrentArea(curBlockArea); // ??? for generic operations diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 57972078e..344c90e07 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -19,6 +19,7 @@ package org.apache.fop.layoutmgr.table; +import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -125,7 +126,7 @@ public class TableContentLayoutManager implements PercentBaseContext { return this.footerList; } - /** @see org.apache.fop.layoutmgr.LayoutManager#getNextKnuthElements(LayoutContext, int) */ + /** {@inheritDoc} */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { if (log.isDebugEnabled()) { log.debug("==> Columns: " + getTableLM().getColumns()); @@ -321,9 +322,12 @@ public class TableContentLayoutManager implements PercentBaseContext { } else if (pos instanceof TableHFPenaltyPosition) { //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 { - //leave order as is for the rest + } else if (pos instanceof TableContentPosition) { positions.add(pos); + } else { + if (log.isDebugEnabled()) { + log.debug("Ignoring position: " + pos); + } } } if (lastPos instanceof TableHFPenaltyPosition) { @@ -349,17 +353,20 @@ public class TableContentLayoutManager implements PercentBaseContext { //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); + iterateAndPaintPositions(nestedIter, painter, false); } //Iterate over all steps Iterator posIter = positions.iterator(); - iterateAndPaintPositions(posIter, painter); + painter.startBody(); + // Here we are sure that posIter iterates only over TableContentPosition instances + iterateAndPaintPositions(posIter, painter, footerElements == null); + painter.endBody(); if (footerElements != null) { //Positions for footers are simply added at the end PositionIterator nestedIter = new KnuthPossPosIter(footerElements); - iterateAndPaintPositions(nestedIter, painter); + iterateAndPaintPositions(nestedIter, painter, true); } this.usedBPD += painter.getAccumulatedBPD(); @@ -377,9 +384,12 @@ public class TableContentLayoutManager implements PercentBaseContext { * @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) { - List lst = new java.util.ArrayList(); + private void iterateAndPaintPositions(Iterator iterator, RowPainter painter, + boolean lastOnPage) { + List lst = new ArrayList(); boolean firstPos = false; TableBody body = null; while (iterator.hasNext()) { @@ -405,10 +415,6 @@ public class TableContentLayoutManager implements PercentBaseContext { body = null; lst.clear(); } - } else { - if (log.isDebugEnabled()) { - log.debug("Ignoring position: " + pos); - } } } if (body != null) { @@ -417,7 +423,7 @@ public class TableContentLayoutManager implements PercentBaseContext { // lastPos is necessarily false handleMarkersAndPositions(lst, body, firstPos, false, painter); } - painter.addAreasAndFlushRow(true); + painter.addAreasAndFlushRow(true, lastOnPage); } private void handleMarkersAndPositions(List positions, TableBody body, boolean firstPos, diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 35bf4c844..1d9f95ca1 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -133,7 +133,8 @@ public class TableStepper { 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, previousRowsLength, getTableLM())); + activeCells.add(new ActiveCell((PrimaryGridUnit) gu, row, activeRowIndex, + previousRowsLength, getTableLM())); } } } @@ -173,17 +174,17 @@ public class TableStepper { List cellParts = new java.util.ArrayList(maxColumnCount); for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); + CellPart part = activeCell.createCellPart(); + cellParts.add(part); if (activeCell.contributesContent()) { - CellPart part = activeCell.createCellPart(); - cellParts.add(part); forcedBreak = activeCell.isLastForcedBreak(); if (forcedBreak) { breakClass = activeCell.getLastBreakClass(); } - if (returnList.size() == 0 && part.isFirstPart() - && part.mustKeepWithPrevious()) { - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); - } + } + if (returnList.size() == 0 && part.isFirstPart() + && part.mustKeepWithPrevious()) { + context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); } } //log.debug(">>> guPARTS: " + cellParts); @@ -327,6 +328,7 @@ public class TableStepper { private void removeCellsEndingOnCurrentRow() { for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); + activeCell.endRow(activeRowIndex); if (activeCell.endsOnRow(activeRowIndex)) { iter.remove(); } diff --git a/status.xml b/status.xml index 21c98c9ab..c261f442b 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Added support for conditional borders in tables, for both the separate and the collapsing + border model. + Fixed a possible IndexOutOfBoundsException that could happen with certain constellations when footnotes are used. diff --git a/test/fotree/unittests/table/collapsed-conditional-borders_test-generator.py b/test/fotree/unittests/table/collapsed-conditional-borders_test-generator.py index b3b697235..1bd5d441d 100755 --- a/test/fotree/unittests/table/collapsed-conditional-borders_test-generator.py +++ b/test/fotree/unittests/table/collapsed-conditional-borders_test-generator.py @@ -74,7 +74,7 @@ class TableGenerator: ] bordersBefore = None - resBefore = None + resBefore = {} """The comma between each table; nothing before the first one.""" separator = '' @@ -85,8 +85,8 @@ class TableGenerator: Params: borderSet: a list of 5 border specifications for resp. table, table-column, table-body, table-row and table-cell - resolution: the resolved border for the leading and rest cases (for the normal - case the resolution is always the same) + resolution: the resolved border for the rest case (for the normal and leading + cases the resolution is always the same) """ if not self.bordersBefore: self.bordersBefore = borderSet @@ -110,16 +110,14 @@ class TableGenerator: sys.stderr.write(self.separator + '{') comma = '' for beforeAfter in [self.resBefore, resolution]: - for leadRest in range(2): - sys.stderr.write(comma + '{border' + beforeAfter[leadRest]['length'] - + ', Color.' + beforeAfter[leadRest]['color'] - + '}') - comma = ', ' + sys.stderr.write(comma + '{border' + beforeAfter['length'] + + ', Color.' + beforeAfter['color'] + '}') + comma = ', ' sys.stderr.write('}') self.separator = ',\n' # Reset self.bordersBefore = None - self.resBefore = None + self.resBefore = {} class TableHFGenerator: """Generates on stdout tables with headers and footers, and the border specifications @@ -254,7 +252,7 @@ def generateTestCases(): defaultBorders.append({'length': '4pt', 'cond': 'discard', 'color': color}) defaultBorders[fo_table]['length'] = '8pt' - resolution = [{'length': '4pt', 'color': 'yellow'}, {'length': '0pt', 'color': 'black'}] + resolution = {'length': '0pt', 'color': 'black'} tableGenerator.addBorderSet(defaultBorders, resolution) for combinations in createAllCombinations()[1:]: for combination in combinations: @@ -266,9 +264,9 @@ def generateTestCases(): if index != fo_table: finalBorders[index]['length'] = '6pt' if fo_table in combination: - resolution = [{'length': '8pt', 'color': 'black'}] * 2 + resolution = {'length': '8pt', 'color': 'black'} else: - resolution = [{'length': '6pt', 'color': finalBorders[index]['color']}] * 2 + resolution = {'length': '6pt', 'color': finalBorders[index]['color']} tableGenerator.addBorderSet(finalBorders, resolution) printFOEnd() diff --git a/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java b/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java index 8037df8ad..e42ee2935 100644 --- a/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java +++ b/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java @@ -47,46 +47,46 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase { * script. */ private Object[][][] resolvedBorders = { -{{border4pt, Color.yellow}, {border0pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border6pt, Color.red}, {border6pt, Color.red}, {border6pt, Color.magenta}, {border6pt, Color.magenta}}, -{{border6pt, Color.blue}, {border6pt, Color.blue}, {border6pt, Color.yellow}, {border6pt, Color.yellow}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border6pt, Color.red}, {border6pt, Color.red}, {border6pt, Color.magenta}, {border6pt, Color.magenta}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border6pt, Color.red}, {border6pt, Color.red}, {border6pt, Color.blue}, {border6pt, Color.blue}}, -{{border6pt, Color.magenta}, {border6pt, Color.magenta}, {border6pt, Color.blue}, {border6pt, Color.blue}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border6pt, Color.red}, {border6pt, Color.red}, {border6pt, Color.yellow}, {border6pt, Color.yellow}}, -{{border6pt, Color.magenta}, {border6pt, Color.magenta}, {border6pt, Color.yellow}, {border6pt, Color.yellow}}, -{{border6pt, Color.blue}, {border6pt, Color.blue}, {border6pt, Color.yellow}, {border6pt, Color.yellow}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border6pt, Color.red}, {border6pt, Color.red}}, -{{border6pt, Color.magenta}, {border6pt, Color.magenta}, {border6pt, Color.blue}, {border6pt, Color.blue}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border6pt, Color.red}, {border6pt, Color.red}, {border6pt, Color.magenta}, {border6pt, Color.magenta}}, -{{border6pt, Color.yellow}, {border6pt, Color.yellow}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border6pt, Color.red}, {border6pt, Color.red}, {border6pt, Color.blue}, {border6pt, Color.blue}}, -{{border6pt, Color.yellow}, {border6pt, Color.yellow}, {border6pt, Color.magenta}, {border6pt, Color.magenta}}, -{{border6pt, Color.blue}, {border6pt, Color.blue}, {border6pt, Color.yellow}, {border6pt, Color.yellow}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border6pt, Color.red}, {border6pt, Color.red}, {border6pt, Color.magenta}, {border6pt, Color.magenta}}, -{{border6pt, Color.blue}, {border6pt, Color.blue}, {border6pt, Color.yellow}, {border6pt, Color.yellow}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}}, -{{border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}} + {{border0pt, Color.black}, {border8pt, Color.black}}, + {{border6pt, Color.red}, {border6pt, Color.magenta}}, + {{border6pt, Color.blue}, {border6pt, Color.yellow}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border6pt, Color.red}, {border6pt, Color.magenta}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border6pt, Color.red}, {border6pt, Color.blue}}, + {{border6pt, Color.magenta}, {border6pt, Color.blue}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border6pt, Color.red}, {border6pt, Color.yellow}}, + {{border6pt, Color.magenta}, {border6pt, Color.yellow}}, + {{border6pt, Color.blue}, {border6pt, Color.yellow}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border6pt, Color.red}}, + {{border6pt, Color.magenta}, {border6pt, Color.blue}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border6pt, Color.red}, {border6pt, Color.magenta}}, + {{border6pt, Color.yellow}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border6pt, Color.red}, {border6pt, Color.blue}}, + {{border6pt, Color.yellow}, {border6pt, Color.magenta}}, + {{border6pt, Color.blue}, {border6pt, Color.yellow}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border6pt, Color.red}, {border6pt, Color.magenta}}, + {{border6pt, Color.blue}, {border6pt, Color.yellow}}, + {{border8pt, Color.black}, {border8pt, Color.black}}, + {{border8pt, Color.black}, {border8pt, Color.black}} }; /** @@ -142,13 +142,13 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase { String errorMsge = baseErrorMsge + "border-before"; checkBorder(errorMsge, gu.borderBefore.nonLeadingTrailing, 8000, Color.black); - checkBorder(errorMsge, gu.borderBefore.leadingTrailing, resolvedBorders[tableNum][0]); - checkBorder(errorMsge, gu.borderBefore.rest, resolvedBorders[tableNum][1]); + checkBorder(errorMsge, gu.borderBefore.leadingTrailing, 8000, Color.black); + checkBorder(errorMsge, gu.borderBefore.rest, resolvedBorders[tableNum][0]); errorMsge = baseErrorMsge + "border-after"; checkBorder(errorMsge, gu.borderAfter.nonLeadingTrailing, 8000, Color.black); - checkBorder(errorMsge, gu.borderAfter.leadingTrailing, resolvedBorders[tableNum][2]); - checkBorder(errorMsge, gu.borderAfter.rest, resolvedBorders[tableNum][3]); + checkBorder(errorMsge, gu.borderAfter.leadingTrailing, 8000, Color.black); + checkBorder(errorMsge, gu.borderAfter.rest, resolvedBorders[tableNum][1]); tableNum++; } while (tableIterator.hasNext()); diff --git a/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java b/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java index 5e492ec75..04752064f 100644 --- a/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java +++ b/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java @@ -36,6 +36,7 @@ import org.apache.commons.io.filefilter.PrefixFileFilter; import org.apache.commons.io.filefilter.SuffixFileFilter; import org.apache.commons.io.filefilter.TrueFileFilter; import org.apache.fop.DebugHelper; +import org.apache.fop.fo.flow.table.CollapsedConditionalBorderTestCase; import org.apache.fop.fo.flow.table.IllegalRowSpanTestCase; import org.apache.fop.fo.flow.table.RowGroupBuilderTestCase; import org.apache.fop.fo.flow.table.TableColumnColumnNumberTestCase; @@ -115,6 +116,7 @@ public final class FOTreeTestSuite { suite.addTestSuite(IllegalRowSpanTestCase.class); suite.addTestSuite(RowGroupBuilderTestCase.class); suite.addTestSuite(TableColumnColumnNumberTestCase.class); + suite.addTestSuite(CollapsedConditionalBorderTestCase.class); } private static class FOTreeTestCase extends TestCase { diff --git a/test/layoutengine/standard-testcases/table-cell_block_break-after.xml b/test/layoutengine/standard-testcases/table-cell_block_break-after.xml index 14c5f3b89..8b595ce3c 100644 --- a/test/layoutengine/standard-testcases/table-cell_block_break-after.xml +++ b/test/layoutengine/standard-testcases/table-cell_block_break-after.xml @@ -66,14 +66,14 @@ - - + + - + @@ -82,8 +82,8 @@ - - + + @@ -91,6 +91,6 @@ - + diff --git a/test/layoutengine/standard-testcases/table-cell_span-combinations.xml b/test/layoutengine/standard-testcases/table-cell_span-combinations.xml index fc2357e9f..22ccc303d 100644 --- a/test/layoutengine/standard-testcases/table-cell_span-combinations.xml +++ b/test/layoutengine/standard-testcases/table-cell_span-combinations.xml @@ -53,6 +53,9 @@ cell4 + +   + @@ -78,7 +81,7 @@ - - + + diff --git a/test/layoutengine/standard-testcases/table-row_break-before_break-after_2.xml b/test/layoutengine/standard-testcases/table-row_break-before_break-after_2.xml index 93b495d56..b7f2b7c6f 100644 --- a/test/layoutengine/standard-testcases/table-row_break-before_break-after_2.xml +++ b/test/layoutengine/standard-testcases/table-row_break-before_break-after_2.xml @@ -32,16 +32,15 @@ before the table - - - + + - - cell3 + + cell1 - - cell4 + + cell2 @@ -53,5 +52,22 @@ + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_conditionals.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_conditionals.xml new file mode 100644 index 000000000..a653be423 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_border-collapse_collapse_conditionals.xml @@ -0,0 +1,177 @@ + + + + + +

          + This test checks that conditional paddings and borders on table-cells are handled correctly. +

          + + + + + + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + + + + + Cell 1.2 + Cell 1.2 + Cell 1.2 + Cell 1.2 + + + + + + + Cell 2.1 + Cell 2.1 + + + + + + + + Before the table + + + + + + + Cell 1.1 + + + + + Cell 1.2 + + + + + + + Cell 2.1 + Cell 2.1 + + + + + + + Cell 3.1 + Cell 3.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_1.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_1.xml index 5bc7aed33..4a9464bf1 100644 --- a/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_1.xml +++ b/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_1.xml @@ -208,6 +208,7 @@ + @@ -216,6 +217,7 @@ + @@ -270,6 +272,7 @@ + @@ -278,6 +281,7 @@ + @@ -301,6 +305,7 @@ + @@ -309,6 +314,7 @@ + @@ -374,6 +380,7 @@ + @@ -382,6 +389,7 @@ + diff --git a/test/layoutengine/standard-testcases/table_border-collapse_separate_border-spacing_2.xml b/test/layoutengine/standard-testcases/table_border-collapse_separate_border-spacing_2.xml index bb4746cdd..52f0de812 100644 --- a/test/layoutengine/standard-testcases/table_border-collapse_separate_border-spacing_2.xml +++ b/test/layoutengine/standard-testcases/table_border-collapse_separate_border-spacing_2.xml @@ -134,17 +134,19 @@ - - - - - - - + + + + + - + + + + + @@ -154,17 +156,19 @@ - - - - - - - + + + + + - + + + + + diff --git a/test/layoutengine/standard-testcases/table_border-collapse_separate_conditionals.xml b/test/layoutengine/standard-testcases/table_border-collapse_separate_conditionals.xml new file mode 100644 index 000000000..227d5563f --- /dev/null +++ b/test/layoutengine/standard-testcases/table_border-collapse_separate_conditionals.xml @@ -0,0 +1,386 @@ + + + + + +

          + This test checks that conditional paddings and borders on table-cells are handled correctly. +

          +
          + + + + + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + Cell 1.1 + + + + + Cell 1.2 + Cell 1.2 + Cell 1.2 + Cell 1.2 + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + Cell 1.1 + + + + + Cell 1.2 + Cell 1.2 + Cell 1.2 + Cell 1.2 + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + Cell 1.1 + + + + + Cell 1.2 + Cell 1.2 + Cell 1.2 + Cell 1.2 + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + Cell 1.1 + + + + + Cell 1.2 + Cell 1.2 + Cell 1.2 + Cell 1.2 + + + + + + + + + Before the table + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          diff --git a/test/layoutengine/standard-testcases/table_break-before_break-after.xml b/test/layoutengine/standard-testcases/table_break-before_break-after.xml index b85e0ea62..31c1fd8cb 100644 --- a/test/layoutengine/standard-testcases/table_break-before_break-after.xml +++ b/test/layoutengine/standard-testcases/table_break-before_break-after.xml @@ -25,23 +25,23 @@ - + before the table - - - + + - - cell3 + + cell1 - - cell4 + + cell2 @@ -53,5 +53,22 @@ + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/table_bug36403.xml b/test/layoutengine/standard-testcases/table_bug36403.xml index 8d8e8950b..ee2116b50 100644 --- a/test/layoutengine/standard-testcases/table_bug36403.xml +++ b/test/layoutengine/standard-testcases/table_bug36403.xml @@ -79,21 +79,22 @@ - - - + + + + 3 - - - + + + - - - + + + 3 diff --git a/test/layoutengine/standard-testcases/table_empty-cells.xml b/test/layoutengine/standard-testcases/table_empty-cells.xml index 9d93aaab0..e9911fb4b 100644 --- a/test/layoutengine/standard-testcases/table_empty-cells.xml +++ b/test/layoutengine/standard-testcases/table_empty-cells.xml @@ -87,13 +87,13 @@ 6 - - + + - + - - + + 16 -- cgit v1.2.3 From 8f8d5b995c0d964311705ef7f3a6262f55340158 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 24 Jan 2008 11:32:07 +0000 Subject: Removed the no longer needed maxColumnCount parameter git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614845 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 7 ++----- .../fop/layoutmgr/table/TableContentLayoutManager.java | 3 ++- .../org/apache/fop/layoutmgr/table/TableStepper.java | 18 ++++++++---------- 3 files changed, 12 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 199af0fc1..9364d2fba 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -136,7 +136,6 @@ class RowGroupLayoutManager { MinOptMax[] rowHeights = new MinOptMax[rowGroup.length]; MinOptMax[] explicitRowHeights = new MinOptMax[rowGroup.length]; EffRow row; - int maxColumnCount = 0; List pgus = new java.util.ArrayList(); //holds a list of a row's primary grid units for (int rgi = 0; rgi < rowGroup.length; rgi++) { row = rowGroup[rgi]; @@ -151,8 +150,6 @@ class RowGroupLayoutManager { // The BPD of the biggest cell in the row int maxCellBPD = 0; for (int j = 0; j < row.getGridUnits().size(); j++) { - assert maxColumnCount == 0 || maxColumnCount == row.getGridUnits().size(); - maxColumnCount = Math.max(maxColumnCount, row.getGridUnits().size()); GridUnit gu = row.getGridUnit(j); if ((gu.isPrimary() || (gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan())) && !gu.isEmpty()) { @@ -281,8 +278,8 @@ class RowGroupLayoutManager { log.debug(" height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]); } } - LinkedList returnedList = tableStepper.getCombinedKnuthElementsForRowGroup( - context, rowGroup, maxColumnCount, bodyType); + LinkedList returnedList = tableStepper.getCombinedKnuthElementsForRowGroup(context, + rowGroup, bodyType); if (returnedList != null) { returnList.addAll(returnedList); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 344c90e07..3455e8a32 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -69,7 +69,7 @@ public class TableContentLayoutManager implements PercentBaseContext { private int startXOffset; private int usedBPD; - private TableStepper stepper = new TableStepper(this); + private TableStepper stepper; /** * Main constructor @@ -85,6 +85,7 @@ public class TableContentLayoutManager implements PercentBaseContext { if (table.getTableFooter() != null) { footerIter = new TableRowIterator(table, TableRowIterator.FOOTER); } + stepper = new TableStepper(this); } /** diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 1d9f95ca1..3e038604a 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -65,15 +65,16 @@ public class TableStepper { */ public TableStepper(TableContentLayoutManager tclm) { this.tclm = tclm; + this.columnCount = tclm.getTableLM().getTable().getNumberOfColumns(); } /** * Initializes the fields of this instance to handle a new row group. * - * @param columnCount number of columns the row group has + * @param rowGroup the new row group to handle */ - private void setup(int columnCount) { - this.columnCount = columnCount; + private void setup(EffRow[] rowGroup) { + this.rowGroup = rowGroup; this.activeRowIndex = 0; this.previousRowsLength = 0; } @@ -143,15 +144,12 @@ public class TableStepper { * Creates the combined element list for a row group. * @param context Active LayoutContext * @param rowGroup the row group - * @param maxColumnCount the maximum number of columns to expect * @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, int maxColumnCount, int bodyType) { - this.rowGroup = rowGroup; - setup(maxColumnCount); + public LinkedList getCombinedKnuthElementsForRowGroup(LayoutContext context, EffRow[] rowGroup, + int bodyType) { + setup(rowGroup); initializeElementLists(); calcTotalHeight(); @@ -171,7 +169,7 @@ public class TableStepper { boolean forcedBreak = false; int breakClass = -1; //Put all involved grid units into a list - List cellParts = new java.util.ArrayList(maxColumnCount); + List cellParts = new java.util.ArrayList(columnCount); for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); CellPart part = activeCell.createCellPart(); -- cgit v1.2.3 From c1492fcb2473e44a309be8fd5e432f1cc7744d4c Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 24 Jan 2008 16:40:46 +0000 Subject: Cleanup: - renamed startRow/startCol into rowIndex/colIndex - improved javadoc of PrimaryGridUnit.getRowIndex() - moved colIndex from GridUnit into PrimaryGridUnit since it's only needed there - simplified EmptyGridUnit constructor git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614920 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/EffRow.java | 2 +- .../apache/fop/fo/flow/table/EmptyGridUnit.java | 7 ++- .../fop/fo/flow/table/FixedColRowGroupBuilder.java | 7 ++- .../org/apache/fop/fo/flow/table/GridUnit.java | 42 ++++++------------ .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 50 ++++++++++++++-------- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 4 +- .../org/apache/fop/layoutmgr/table/RowPainter.java | 12 +++--- .../layoutmgr/table/TableCellLayoutManager.java | 6 +-- .../layoutmgr/table/TableContentLayoutManager.java | 6 +-- 9 files changed, 64 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java index 03012aa3c..fb2162e55 100644 --- a/src/java/org/apache/fop/fo/flow/table/EffRow.java +++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java @@ -57,7 +57,7 @@ public class EffRow { for (Iterator guIter = gridUnits.iterator(); guIter.hasNext();) { Object gu = guIter.next(); if (gu instanceof PrimaryGridUnit) { - ((PrimaryGridUnit) gu).setStartRow(index); + ((PrimaryGridUnit) gu).setRowIndex(index); } } } diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java index 7a8b0be62..1f0f7be04 100644 --- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java @@ -30,11 +30,10 @@ public class EmptyGridUnit extends GridUnit { /** * @param table the containing table * @param row the table-row element this grid unit belongs to (if any) - * @param startRow index of the row this grid unit belongs to, 0-based - * @param startCol column index, 0-based + * @param colIndex column index, 0-based */ - EmptyGridUnit(Table table, TableRow row, int startRow, int startCol) { - super(table, row, table.getColumn(startCol), startCol, 0, 0); + EmptyGridUnit(Table table, TableRow row, int colIndex) { + super(table, row, table.getColumn(colIndex), 0, 0); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index 2f8b0bbb8..51279c399 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -87,8 +87,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { GridUnit[] cellRow = new GridUnit[cell.getNumberColumnsSpanned()]; cellRow[0] = pgu; for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) { - GridUnit gu = new GridUnit(pgu, currentTableRow, table.getColumn(columnIndex + j), - columnIndex + j, j, 0); + GridUnit gu = new GridUnit(pgu, currentTableRow, table.getColumn(columnIndex + j), j, 0); row.set(columnIndex + j, gu); cellRow[j] = gu; } @@ -98,7 +97,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { cellRow = new GridUnit[cell.getNumberColumnsSpanned()]; for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) { GridUnit gu = new GridUnit(pgu, currentTableRow, table.getColumn(columnIndex + j), - columnIndex + j, j, i); + j, i); row.set(columnIndex + j, gu); cellRow[j] = gu; } @@ -124,7 +123,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { // Fill gaps with empty grid units for (int i = 0; i < numberOfColumns; i++) { if (currentRow.get(i) == null) { - currentRow.set(i, new EmptyGridUnit(table, currentTableRow, currentRowIndex, i)); + currentRow.set(i, new EmptyGridUnit(table, currentTableRow, i)); } } borderResolver.endRow(currentRow, container); diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java index a583697f6..75d0c5516 100644 --- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java @@ -59,9 +59,6 @@ public class GridUnit { /** Table column that this grid unit belongs to */ private TableColumn column; - /** start index of grid unit within row in column direction */ - private int startCol; - /** index of grid unit within cell in column direction */ private int colSpanIndex; @@ -84,13 +81,12 @@ public class GridUnit { * @param table the containing table * @param row the table-row element this grid unit belongs to (if any) * @param column table column this grid unit belongs to - * @param startCol index of the column this grid unit belongs to * @param colSpanIndex index of this grid unit in the span, in column direction * @param rowSpanIndex index of this grid unit in the span, in row direction */ - protected GridUnit(Table table, TableRow row, TableColumn column, int startCol, - int colSpanIndex, int rowSpanIndex) { - this(row, column, startCol, colSpanIndex, rowSpanIndex); + protected GridUnit(Table table, TableRow row, TableColumn column, int colSpanIndex, + int rowSpanIndex) { + this(row, column, colSpanIndex, rowSpanIndex); setBorders(table); } @@ -100,13 +96,12 @@ public class GridUnit { * @param cell table cell which occupies this grid unit * @param row the table-row element this grid unit belongs to (if any) * @param column table column this grid unit belongs to - * @param startCol index of the column this grid unit belongs to * @param colSpanIndex index of this grid unit in the span, in column direction * @param rowSpanIndex index of this grid unit in the span, in row direction */ - protected GridUnit(TableCell cell, TableRow row, TableColumn column, int startCol, - int colSpanIndex, int rowSpanIndex) { - this(row, column, startCol, colSpanIndex, rowSpanIndex); + protected GridUnit(TableCell cell, TableRow row, TableColumn column, int colSpanIndex, + int rowSpanIndex) { + this(row, column, colSpanIndex, rowSpanIndex); this.cell = cell; setBorders(cell.getTable()); } @@ -117,21 +112,18 @@ public class GridUnit { * @param primary the before-start grid unit of the cell containing this grid unit * @param row the table-row element this grid unit belongs to (if any) * @param column table column this grid unit belongs to - * @param startCol index of the column this grid unit belongs to * @param colSpanIndex index of this grid unit in the span, in column direction * @param rowSpanIndex index of this grid unit in the span, in row direction */ - GridUnit(PrimaryGridUnit primary, TableRow row, TableColumn column, int startCol, - int colSpanIndex, int rowSpanIndex) { - this(primary.getCell(), row, column, startCol, colSpanIndex, rowSpanIndex); + GridUnit(PrimaryGridUnit primary, TableRow row, TableColumn column, int colSpanIndex, + int rowSpanIndex) { + this(primary.getCell(), row, column, colSpanIndex, rowSpanIndex); this.primary = primary; } - private GridUnit(TableRow row, TableColumn column, int startCol, int colSpanIndex, - int rowSpanIndex) { + private GridUnit(TableRow row, TableColumn column, int colSpanIndex, int rowSpanIndex) { this.row = row; this.column = column; - this.startCol = startCol; this.colSpanIndex = colSpanIndex; this.rowSpanIndex = rowSpanIndex; } @@ -222,15 +214,6 @@ public class GridUnit { return cell == null; } - /** - * Returns the index of the column this grid unit belongs to. - * - * @return the column index, 0-based - */ - public int getStartCol() { - return startCol; - } - /** @return true if the grid unit is the last in column spanning direction */ public boolean isLastGridUnitColSpan() { return (colSpanIndex == cell.getNumberColumnsSpanned() - 1); @@ -474,10 +457,9 @@ public class GridUnit { buffer.append("(last)"); } } - buffer.append(" startCol=").append(startCol); if (!isPrimary() && getPrimary() != null) { - buffer.append(" primary=").append(getPrimary().getStartRow()); - buffer.append("/").append(getPrimary().getStartCol()); + buffer.append(" primary=").append(getPrimary().getRowIndex()); + buffer.append("/").append(getPrimary().getColIndex()); if (getPrimary().getCell() != null) { buffer.append(" id=" + getPrimary().getCell().getId()); } diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 684fa58d1..b73cd62d7 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -22,8 +22,6 @@ package org.apache.fop.fo.flow.table; import java.util.LinkedList; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.table.TableCellLayoutManager; @@ -34,14 +32,17 @@ import org.apache.fop.layoutmgr.table.TableCellLayoutManager; */ public class PrimaryGridUnit extends GridUnit { - private static Log log = LogFactory.getLog(PrimaryGridUnit.class); - /** Cell layout manager. */ private TableCellLayoutManager cellLM; /** List of Knuth elements representing the contents of the cell. */ private LinkedList elements; - /** Index of row where this cell starts */ - private int startRow; + + /** Index of the row where this cell starts. */ + private int rowIndex; + + /** Index of the column where this cell starts. */ + private int colIndex; + /** Links to the spanned grid units. (List of GridUnit arrays, one array represents a row) */ private List rows; /** The calculated size of the cell's content. (cached value) */ @@ -56,15 +57,14 @@ public class PrimaryGridUnit extends GridUnit { * @param cell table cell which occupies this grid unit * @param row the table-row element this grid unit belongs to (if any) * @param column table column this grid unit belongs to - * @param startCol index of the column this grid unit belongs to, zero-based - * @param startRow index of the row this grid unit belongs to, zero-based + * @param colIndex index of the column this grid unit belongs to, zero-based */ - PrimaryGridUnit(TableCell cell, TableRow row, TableColumn column, int startCol) { - super(cell, row, column, startCol, 0, 0); + PrimaryGridUnit(TableCell cell, TableRow row, TableColumn column, int colIndex) { + super(cell, row, column, 0, 0); + this.colIndex = colIndex; this.isSeparateBorderModel = column.getTable().isSeparateBorderModel(); // TODO this.halfBorderSeparationBPD = column.getTable().getBorderSeparation().getBPD().getLength() .getValue() / 2; // TODO - log.trace("PrimaryGridUnit created, row " + startRow + " col " + startCol); } public TableCellLayoutManager getCellLM() { @@ -248,17 +248,29 @@ public class PrimaryGridUnit extends GridUnit { rows.add(row); } - void setStartRow(int startRow) { - this.startRow = startRow; + void setRowIndex(int rowIndex) { + this.rowIndex = rowIndex; } /** - * Returns the index of the row this grid unit belongs to. - * - * @return the index of the row this grid unit belongs to. + * Returns the index of the row this grid unit belongs to. This is the index, in the + * enclosing table part, of the first row spanned by the cell. Note that if the table + * has several table-body children, then the index grows continuously across them; + * they are considered to form one single part, the "body of the table". + * + * @return the index of the row this grid unit belongs to, 0-based. + */ + public int getRowIndex() { + return rowIndex; + } + + /** + * Returns the index of the column this grid unit belongs to. + * + * @return the column index, 0-based */ - public int getStartRow() { - return this.startRow; + public int getColIndex() { + return colIndex; } /** @@ -290,7 +302,7 @@ public class PrimaryGridUnit extends GridUnit { /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer(super.toString()); - sb.append(" startRow=").append(startRow); + sb.append(" rowIndex=").append(rowIndex); return sb.toString(); } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 9364d2fba..6d66da097 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -175,8 +175,8 @@ class RowGroupLayoutManager { //Calculate width of cell int spanWidth = 0; - for (int i = primary.getStartCol(); - i < primary.getStartCol() + for (int i = primary.getColIndex(); + i < primary.getColIndex() + primary.getCell().getNumberColumnsSpanned(); i++) { if (tableLM.getColumns().getColumn(i + 1) != null) { diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index f46b503bb..e5b90aa5f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -117,7 +117,7 @@ class RowPainter { if (log.isDebugEnabled()) { log.debug(">" + cellPart); } - int colIndex = cellPart.pgu.getStartCol(); + int colIndex = cellPart.pgu.getColIndex(); if (firstCellParts[colIndex] == null) { firstCellParts[colIndex] = cellPart; cellHeights[colIndex] = cellPart.getBorderPaddingBefore(firstCellOnPage[colIndex]); @@ -159,7 +159,7 @@ class RowPainter { int cellHeight = cellHeights[i]; cellHeight += lastCellParts[i].getConditionalAfterContentLength(); cellHeight += lastCellParts[i].getBorderPaddingAfter(lastInPart); - int cellOffset = getRowOffset(Math.max(firstCellParts[i].pgu.getStartRow(), + int cellOffset = getRowOffset(Math.max(firstCellParts[i].pgu.getRowIndex(), firstRowIndex)); actualRowHeight = Math.max(actualRowHeight, cellOffset + cellHeight - currentRowOffset); @@ -256,7 +256,7 @@ class RowPainter { * Determine the index of the first row of this cell that will be displayed on the * current page. */ - int startRowIndex = Math.max(pgu.getStartRow(), firstRowIndex); + int startRowIndex = Math.max(pgu.getRowIndex(), firstRowIndex); int currentRowIndex = currentRow.getIndex(); /* @@ -280,7 +280,7 @@ class RowPainter { int cellTotalHeight = rowHeight + currentRowOffset - cellOffset; if (log.isDebugEnabled()) { log.debug("Creating area for cell:"); - log.debug(" start row: " + pgu.getStartRow() + " " + currentRowOffset + " " + log.debug(" start row: " + pgu.getRowIndex() + " " + currentRowOffset + " " + cellOffset); log.debug(" rowHeight=" + rowHeight + " cellTotalHeight=" + cellTotalHeight); } @@ -295,8 +295,8 @@ class RowPainter { startPos, endPos, prevBreak); } cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(), startPos, endPos + 1), - layoutContext, spannedGridRowHeights, startRowIndex - pgu.getStartRow(), - currentRowIndex - pgu.getStartRow(), borderBeforeWhich, borderAfterWhich, + layoutContext, spannedGridRowHeights, startRowIndex - pgu.getRowIndex(), + currentRowIndex - pgu.getRowIndex(), borderBeforeWhich, borderAfterWhich, startRowIndex == firstRowOnPageIndex, lastOnPage); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 421d3d580..9469a1121 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -346,8 +346,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager false, false, this); } } else { - boolean inFirstColumn = (primaryGridUnit.getStartCol() == 0); - boolean inLastColumn = (primaryGridUnit.getStartCol() + boolean inFirstColumn = (primaryGridUnit.getColIndex() == 0); + boolean inLastColumn = (primaryGridUnit.getColIndex() + getTableCell().getNumberColumnsSpanned() == getTable() .getNumberOfColumns()); if (!primaryGridUnit.hasSpanning()) { @@ -407,7 +407,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager int bpd = spannedGridRowHeights[y - startRow]; int dx = xoffset; for (int x = 0; x < gridUnits.length; x++) { - int ipd = getTable().getColumn(primaryGridUnit.getStartCol() + x) + int ipd = getTable().getColumn(primaryGridUnit.getColIndex() + x) .getColumnWidth().getValue((PercentBaseContext) getParent()); if (blocks[y][x] != null) { Block block = blocks[y][x]; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 3455e8a32..1c748a5cf 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -33,7 +33,7 @@ import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; 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.Table; import org.apache.fop.fo.flow.table.TableBody; import org.apache.fop.fo.flow.table.TableRow; @@ -273,8 +273,8 @@ public class TableContentLayoutManager implements PercentBaseContext { * @param gu the grid unit * @return the requested X offset */ - protected int getXOffsetOfGridUnit(GridUnit gu) { - int col = gu.getStartCol(); + protected int getXOffsetOfGridUnit(PrimaryGridUnit gu) { + int col = gu.getColIndex(); return startXOffset + getTableLM().getColumns().getXOffset(col + 1, getTableLM()); } -- cgit v1.2.3 From 6228167d445d4116243142819a9ce214b4cf4fa8 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 24 Jan 2008 16:51:53 +0000 Subject: Removed no longer needed reference to TableColumn in GridUnit git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614924 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fo/flow/table/EmptyGridUnit.java | 2 +- .../fop/fo/flow/table/FixedColRowGroupBuilder.java | 8 +++---- .../org/apache/fop/fo/flow/table/GridUnit.java | 28 ++++++---------------- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 9 ++++--- 4 files changed, 15 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java index 1f0f7be04..ac793f889 100644 --- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java @@ -33,7 +33,7 @@ public class EmptyGridUnit extends GridUnit { * @param colIndex column index, 0-based */ EmptyGridUnit(Table table, TableRow row, int colIndex) { - super(table, row, table.getColumn(colIndex), 0, 0); + super(table, row, 0, 0); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index 51279c399..b0126dff0 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -79,15 +79,14 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { rows.add(effRow); } int columnIndex = cell.getColumnNumber() - 1; - PrimaryGridUnit pgu = new PrimaryGridUnit(cell, currentTableRow, - table.getColumn(columnIndex), columnIndex); + PrimaryGridUnit pgu = new PrimaryGridUnit(cell, currentTableRow, columnIndex); List row = (List) rows.get(currentRowIndex); row.set(columnIndex, pgu); // TODO GridUnit[] cellRow = new GridUnit[cell.getNumberColumnsSpanned()]; cellRow[0] = pgu; for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) { - GridUnit gu = new GridUnit(pgu, currentTableRow, table.getColumn(columnIndex + j), j, 0); + GridUnit gu = new GridUnit(pgu, currentTableRow, j, 0); row.set(columnIndex + j, gu); cellRow[j] = gu; } @@ -96,8 +95,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { row = (List) rows.get(currentRowIndex + i); cellRow = new GridUnit[cell.getNumberColumnsSpanned()]; for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) { - GridUnit gu = new GridUnit(pgu, currentTableRow, table.getColumn(columnIndex + j), - j, i); + GridUnit gu = new GridUnit(pgu, currentTableRow, j, i); row.set(columnIndex + j, gu); cellRow[j] = gu; } diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java index 75d0c5516..edf0c99ea 100644 --- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java @@ -56,9 +56,6 @@ public class GridUnit { /** Table row occupied by this grid unit (may be null). */ private TableRow row; - /** Table column that this grid unit belongs to */ - private TableColumn column; - /** index of grid unit within cell in column direction */ private int colSpanIndex; @@ -80,13 +77,11 @@ public class GridUnit { * * @param table the containing table * @param row the table-row element this grid unit belongs to (if any) - * @param column table column this grid unit belongs to * @param colSpanIndex index of this grid unit in the span, in column direction * @param rowSpanIndex index of this grid unit in the span, in row direction */ - protected GridUnit(Table table, TableRow row, TableColumn column, int colSpanIndex, - int rowSpanIndex) { - this(row, column, colSpanIndex, rowSpanIndex); + protected GridUnit(Table table, TableRow row, int colSpanIndex, int rowSpanIndex) { + this(row, colSpanIndex, rowSpanIndex); setBorders(table); } @@ -95,13 +90,11 @@ public class GridUnit { * * @param cell table cell which occupies this grid unit * @param row the table-row element this grid unit belongs to (if any) - * @param column table column this grid unit belongs to * @param colSpanIndex index of this grid unit in the span, in column direction * @param rowSpanIndex index of this grid unit in the span, in row direction */ - protected GridUnit(TableCell cell, TableRow row, TableColumn column, int colSpanIndex, - int rowSpanIndex) { - this(row, column, colSpanIndex, rowSpanIndex); + protected GridUnit(TableCell cell, TableRow row, int colSpanIndex, int rowSpanIndex) { + this(row, colSpanIndex, rowSpanIndex); this.cell = cell; setBorders(cell.getTable()); } @@ -111,19 +104,16 @@ public class GridUnit { * * @param primary the before-start grid unit of the cell containing this grid unit * @param row the table-row element this grid unit belongs to (if any) - * @param column table column this grid unit belongs to * @param colSpanIndex index of this grid unit in the span, in column direction * @param rowSpanIndex index of this grid unit in the span, in row direction */ - GridUnit(PrimaryGridUnit primary, TableRow row, TableColumn column, int colSpanIndex, - int rowSpanIndex) { - this(primary.getCell(), row, column, colSpanIndex, rowSpanIndex); + GridUnit(PrimaryGridUnit primary, TableRow row, int colSpanIndex, int rowSpanIndex) { + this(primary.getCell(), row, colSpanIndex, rowSpanIndex); this.primary = primary; } - private GridUnit(TableRow row, TableColumn column, int colSpanIndex, int rowSpanIndex) { + private GridUnit(TableRow row, int colSpanIndex, int rowSpanIndex) { this.row = row; - this.column = column; this.colSpanIndex = colSpanIndex; this.rowSpanIndex = rowSpanIndex; } @@ -165,10 +155,6 @@ public class GridUnit { return cell; } - public TableColumn getColumn() { - return column; - } - /** * Returns the fo:table-row element (if any) this grid unit belongs to. * diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index b73cd62d7..4c4ffa9ce 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -56,14 +56,13 @@ public class PrimaryGridUnit extends GridUnit { * * @param cell table cell which occupies this grid unit * @param row the table-row element this grid unit belongs to (if any) - * @param column table column this grid unit belongs to * @param colIndex index of the column this grid unit belongs to, zero-based */ - PrimaryGridUnit(TableCell cell, TableRow row, TableColumn column, int colIndex) { - super(cell, row, column, 0, 0); + PrimaryGridUnit(TableCell cell, TableRow row, int colIndex) { + super(cell, row, 0, 0); this.colIndex = colIndex; - this.isSeparateBorderModel = column.getTable().isSeparateBorderModel(); // TODO - this.halfBorderSeparationBPD = column.getTable().getBorderSeparation().getBPD().getLength() + this.isSeparateBorderModel = cell.getTable().isSeparateBorderModel(); // TODO + this.halfBorderSeparationBPD = cell.getTable().getBorderSeparation().getBPD().getLength() .getValue() / 2; // TODO } -- cgit v1.2.3 From 4b75aa4cd571bb6d8bee5a6c6fe581e3b20618c4 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 24 Jan 2008 21:10:22 +0000 Subject: Bugzilla #44289: Wrong border resolution when header/footer omitted at break git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@614993 13f79535-47bb-0310-9956-ffa450edef68 --- .../fo/flow/table/CollapsingBorderResolver.java | 12 +- status.xml | 7 +- .../table_border-collapse_collapse_omitHF.xml | 147 +++++++++++++++++++++ 3 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table_border-collapse_collapse_omitHF.xml (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index 235f05042..23f797a3e 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -362,10 +362,10 @@ class CollapsingBorderResolver implements BorderResolver { } else { // Trailing and rest borders already resolved with integrateTrailingBorders resolveBordersLastRowInTable(previousRow, false, true, false); - for (Iterator iter = previousRow.iterator(); iter.hasNext();) { - GridUnit gu = (GridUnit) iter.next(); - gu.borderAfter.leadingTrailing = gu.borderAfter.nonLeadingTrailing; - } + } + for (Iterator iter = previousRow.iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + gu.borderAfter.leadingTrailing = gu.borderAfter.nonLeadingTrailing; } } } @@ -385,7 +385,7 @@ class CollapsingBorderResolver implements BorderResolver { if (part.isTableHeader()) { delegate = new ResolverInHeader(); } else { - if (leadingBorders == null) { + if (leadingBorders == null || table.omitHeaderAtBreak()) { // No header, leading borders determined by the table leadingBorders = new ArrayList(table.getNumberOfColumns()); for (Iterator colIter = table.getColumns().iterator(); colIter.hasNext();) { @@ -399,7 +399,7 @@ class CollapsingBorderResolver implements BorderResolver { resolverInFooter = new ResolverInFooter(); delegate = resolverInFooter; } else { - if (trailingBorders == null) { + if (trailingBorders == null || table.omitFooterAtBreak()) { // No footer, trailing borders determined by the table trailingBorders = new ArrayList(table.getNumberOfColumns()); for (Iterator colIter = table.getColumns().iterator(); colIter.hasNext();) { diff --git a/status.xml b/status.xml index c261f442b..a213a13be 100644 --- a/status.xml +++ b/status.xml @@ -28,9 +28,12 @@ + + Fixed the resolution of borders when header/footer is omitted at page breaks. + - Added support for conditional borders in tables, for both the separate and the collapsing - border model. + Added support for conditional borders in tables, for both the separate and the collapsing + border model. Fixed a possible IndexOutOfBoundsException that could happen with certain constellations diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_omitHF.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_omitHF.xml new file mode 100644 index 000000000..d13b257c9 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_border-collapse_collapse_omitHF.xml @@ -0,0 +1,147 @@ + + + + + +

          + This test checks that collapsed borders are correctly resolved when the table’s header or + footer is omitted at breaks. +

          +
          + + + + + + + + + + + Before the table + + + + + Header 1.1 + + + Header 1.2 + + + + + Footer 1.1 + + + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          -- cgit v1.2.3 From 8b281b7c15488402a4dd30d41c4d8e2359e92140 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Jan 2008 08:26:54 +0000 Subject: Added support for DOMSource to Preloader SVG so a URI Resolver can be written that provides the SVG as a W3C SVG DOM. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615144 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/image/loader/batik/PreloaderSVG.java | 125 ++++++++++++--------- .../image/loader/batik/ImagePreloaderTestCase.java | 56 ++++++++- 2 files changed, 129 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java index e83a302da..db03cbbf2 100644 --- a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -25,6 +25,7 @@ import java.io.InputStream; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Element; import org.w3c.dom.svg.SVGDocument; @@ -61,14 +62,13 @@ public class PreloaderSVG extends AbstractImagePreloader { /** {@inheritDoc} */ public ImageInfo preloadImage(String uri, Source src, ImageContext context) throws IOException { - if (!ImageUtil.hasInputStream(src)) { - //TODO Remove this and support DOMSource and possibly SAXSource - return null; - } ImageInfo info = null; if (batikAvailable) { try { Loader loader = new Loader(); + if (!loader.isSupportedSource(src)) { + return null; + } info = loader.getImage(uri, src, context); } catch (NoClassDefFoundError e) { batikAvailable = false; @@ -76,7 +76,7 @@ public class PreloaderSVG extends AbstractImagePreloader { return null; } } - if (info != null) { + if (info != null && ImageUtil.hasInputStream(src)) { ImageUtil.closeQuietly(src); //Image is fully read } return info; @@ -106,57 +106,30 @@ public class PreloaderSVG extends AbstractImagePreloader { ImageContext context) { // parse document and get the size attributes of the svg element - InputStream in = new UnclosableInputStream(ImageUtil.needInputStream(src)); + InputStream in = null; try { - int length = in.available(); - in.mark(length + 1); - SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( - getParserName()); - SVGDocument doc = (SVGDocument) factory.createSVGDocument(src.getSystemId(), in); - - Element e = doc.getRootElement(); - float pxUnitToMillimeter = 25.4f / context.getSourceResolution(); - SVGUserAgent userAg = new SVGUserAgent(pxUnitToMillimeter, - new AffineTransform()); - BridgeContext ctx = new BridgeContext(userAg); - UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); - - String s; - // 'width' attribute - default is 100% - s = e.getAttributeNS(null, SVGOMDocument.SVG_WIDTH_ATTRIBUTE); - if (s.length() == 0) { - s = SVGOMDocument.SVG_SVG_WIDTH_DEFAULT_VALUE; - } - float width = UnitProcessor.svgHorizontalLengthToUserSpace( - s, SVGOMDocument.SVG_WIDTH_ATTRIBUTE, uctx); - - // 'height' attribute - default is 100% - s = e.getAttributeNS(null, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE); - if (s.length() == 0) { - s = SVGOMDocument.SVG_SVG_HEIGHT_DEFAULT_VALUE; + SVGDocument doc; + if (src instanceof DOMSource) { + DOMSource domSrc = (DOMSource)src; + doc = (SVGDocument)domSrc.getNode(); + } else { + in = new UnclosableInputStream(ImageUtil.needInputStream(src)); + int length = in.available(); + in.mark(length + 1); + SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( + getParserName()); + doc = (SVGDocument) factory.createSVGDocument(src.getSystemId(), in); } - float height = UnitProcessor.svgVerticalLengthToUserSpace( - s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx); - - ImageInfo info = new ImageInfo(uri, MimeConstants.MIME_SVG); - ImageSize size = new ImageSize(); - size.setSizeInMillipoints(Math.round(width * 1000), Math.round(height * 1000)); - //Set the resolution to that of the FOUserAgent - size.setResolution(context.getSourceResolution()); - size.calcPixelsFromSize(); - info.setSize(size); - - //The whole image had to be loaded for this, so keep it - ImageXMLDOM xmlImage = new ImageXMLDOM(info, - doc, SVGDOMImplementation.SVG_NAMESPACE_URI); - info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, xmlImage); + ImageInfo info = createImageInfo(uri, context, doc); return info; } catch (NoClassDefFoundError ncdfe) { - try { - in.reset(); - } catch (IOException ioe) { - // we're more interested in the original exception + if (in != null) { + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } } batikAvailable = false; log.warn("Batik not in class path", ncdfe); @@ -177,6 +150,56 @@ public class PreloaderSVG extends AbstractImagePreloader { return null; } } + + private ImageInfo createImageInfo(String uri, ImageContext context, SVGDocument doc) { + Element e = doc.getRootElement(); + float pxUnitToMillimeter = 25.4f / context.getSourceResolution(); + SVGUserAgent userAg = new SVGUserAgent(pxUnitToMillimeter, + new AffineTransform()); + BridgeContext ctx = new BridgeContext(userAg); + UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); + + String s; + // 'width' attribute - default is 100% + s = e.getAttributeNS(null, SVGOMDocument.SVG_WIDTH_ATTRIBUTE); + if (s.length() == 0) { + s = SVGOMDocument.SVG_SVG_WIDTH_DEFAULT_VALUE; + } + float width = UnitProcessor.svgHorizontalLengthToUserSpace( + s, SVGOMDocument.SVG_WIDTH_ATTRIBUTE, uctx); + + // 'height' attribute - default is 100% + s = e.getAttributeNS(null, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE); + if (s.length() == 0) { + s = SVGOMDocument.SVG_SVG_HEIGHT_DEFAULT_VALUE; + } + float height = UnitProcessor.svgVerticalLengthToUserSpace( + s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx); + + ImageInfo info = new ImageInfo(uri, MimeConstants.MIME_SVG); + ImageSize size = new ImageSize(); + size.setSizeInMillipoints(Math.round(width * 1000), Math.round(height * 1000)); + //Set the resolution to that of the FOUserAgent + size.setResolution(context.getSourceResolution()); + size.calcPixelsFromSize(); + info.setSize(size); + + //The whole image had to be loaded for this, so keep it + ImageXMLDOM xmlImage = new ImageXMLDOM(info, + doc, SVGDOMImplementation.SVG_NAMESPACE_URI); + info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, xmlImage); + return info; + } + + private boolean isSupportedSource(Source src) { + if (src instanceof DOMSource) { + DOMSource domSrc = (DOMSource)src; + return (domSrc.getNode() instanceof SVGDocument); + } else { + return ImageUtil.hasInputStream(src); + } + } + } } diff --git a/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java b/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java index b14dd1fb8..9406ed65c 100644 --- a/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java +++ b/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java @@ -21,8 +21,19 @@ package org.apache.fop.image.loader.batik; import java.io.IOException; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.URIResolver; +import javax.xml.transform.dom.DOMSource; + import junit.framework.TestCase; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.batik.dom.svg.SVGDOMImplementation; + import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageManager; @@ -30,7 +41,6 @@ import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; -import org.apache.fop.image.loader.batik.ImageWMF; /** * Tests for bundled image preloader implementations. @@ -89,6 +99,50 @@ public class ImagePreloaderTestCase extends TestCase { assertEquals(100000, info.getSize().getHeightMpt()); } + public void testSVGWithDOM() throws Exception { + String uri = "my:SVGImage"; + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + userAgent.setURIResolver(new URIResolver() { + + public Source resolve(String href, String base) throws TransformerException { + if (href.startsWith("my:")) { + DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); + String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; + Document doc = impl.createDocument(svgNS, "svg", null); + Element element = doc.getDocumentElement(); + element.setAttribute("viewBox", "0 0 20 20"); + element.setAttribute("width", "20pt"); + element.setAttribute("height", "20pt"); + + Element rect = doc.createElementNS(svgNS, "rect"); + rect.setAttribute("x", "5"); + rect.setAttribute("y", "5"); + rect.setAttribute("width", "10"); + rect.setAttribute("height", "10"); + element.appendChild(rect); + + DOMSource src = new DOMSource(doc); + return src; + } else { + return null; + } + } + + }); + + ImageManager manager = fopFactory.getImageManager(); + ImageInfo info = manager.preloadImage(uri, userAgent.getImageSessionContext()); + assertNotNull("ImageInfo must not be null", info); + assertEquals(MimeConstants.MIME_SVG, info.getMimeType()); + assertEquals(uri, info.getOriginalURI()); + assertEquals(20, info.getSize().getWidthPx()); //100 = default viewport size + assertEquals(20, info.getSize().getHeightPx()); + assertEquals(userAgent.getSourceResolution(), info.getSize().getDpiHorizontal(), 0.1); + assertEquals(20000, info.getSize().getWidthMpt()); + assertEquals(20000, info.getSize().getHeightMpt()); + } + public void testWMF() throws Exception { String uri = "test/resources/images/testChart.wmf"; -- cgit v1.2.3 From efee9986bd606e232cd547f431d39467dfd8a5e6 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Jan 2008 09:59:29 +0000 Subject: Fix exception when closing Source that doesn't have any streams. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615164 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.3svn.jar | Bin 498867 -> 498800 bytes .../fop/image/loader/batik/PreloaderSVG.java | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/lib/xmlgraphics-commons-1.3svn.jar b/lib/xmlgraphics-commons-1.3svn.jar index cc3c3c6da..75b10615a 100644 Binary files a/lib/xmlgraphics-commons-1.3svn.jar and b/lib/xmlgraphics-commons-1.3svn.jar differ diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java index db03cbbf2..e59e06b6b 100644 --- a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -76,7 +76,7 @@ public class PreloaderSVG extends AbstractImagePreloader { return null; } } - if (info != null && ImageUtil.hasInputStream(src)) { + if (info != null) { ImageUtil.closeQuietly(src); //Image is fully read } return info; -- cgit v1.2.3 From ab66977cddab31240ab6f132996939bddd243245 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Jan 2008 12:14:52 +0000 Subject: Improved error tolerance: an enum property value with leading or trailing spaces is still recognized. Example: content-width="scale-to-fit " git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615197 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fo/properties/PropertyMaker.java | 4 +-- test/fotree/testcases/enum-trim.fo | 37 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 test/fotree/testcases/enum-trim.fo (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/PropertyMaker.java b/src/java/org/apache/fop/fo/properties/PropertyMaker.java index 3faf1971e..b1162563d 100644 --- a/src/java/org/apache/fop/fo/properties/PropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/PropertyMaker.java @@ -427,8 +427,8 @@ public class PropertyMaker implements Cloneable { } } } else { - // Check for keyword shorthand values to be substituted. - pvalue = checkValueKeywords(pvalue); + // Check for keyword shorthand values to be substituted. + pvalue = checkValueKeywords(pvalue.trim()); newProp = checkEnumValues(pvalue); } if (newProp == null) { diff --git a/test/fotree/testcases/enum-trim.fo b/test/fotree/testcases/enum-trim.fo new file mode 100644 index 000000000..001243d80 --- /dev/null +++ b/test/fotree/testcases/enum-trim.fo @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + Test font-family parsing + + + + -- cgit v1.2.3 From 1902be605c9712faa705c54180c8b2b079437720 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 25 Jan 2008 15:52:53 +0000 Subject: Fixed a bug in computeContentLength when there are empty cells git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615251 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/RowPainter.java | 32 +++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index e5b90aa5f..9004e9c17 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -234,20 +234,26 @@ class RowPainter { // be used as padding. // This should be handled automatically by a proper use of Knuth elements private int computeContentLength(PrimaryGridUnit pgu, int startIndex, int endIndex) { - int actualStart = startIndex; - // Skip from the content length calculation glues and penalties occurring at the - // beginning of the page - while (actualStart <= endIndex - && !((KnuthElement) pgu.getElements().get(actualStart)).isBox()) { - actualStart++; - } - int len = ElementListUtils.calcContentLength( - pgu.getElements(), actualStart, endIndex); - KnuthElement el = (KnuthElement)pgu.getElements().get(endIndex); - if (el.isPenalty()) { - len += el.getW(); + if (startIndex >= endIndex) { + // May happen if the cell contributes no content on the current page (empty + // cell, in most cases) + return 0; + } else { + int actualStart = startIndex; + // Skip from the content length calculation glues and penalties occurring at the + // beginning of the page + while (actualStart <= endIndex + && !((KnuthElement) pgu.getElements().get(actualStart)).isBox()) { + actualStart++; + } + int len = ElementListUtils.calcContentLength( + pgu.getElements(), actualStart, endIndex); + KnuthElement el = (KnuthElement)pgu.getElements().get(endIndex); + if (el.isPenalty()) { + len += el.getW(); + } + return len; } - return len; } private void addAreasForCell(PrimaryGridUnit pgu, int startPos, int endPos, -- cgit v1.2.3 From 72f5b1bbedd98607b474eb88a257aa47c2f22084 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 27 Jan 2008 13:35:39 +0000 Subject: Bugzilla #44286: Fixed a memory-leak in XMLWhiteSpaceHandler. Submitted by: Stefan Ziel git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615598 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/XMLWhiteSpaceHandler.java | 49 ++++++++++++---------- status.xml | 3 ++ 2 files changed, 29 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java index dc0cf3b48..8e5e4f297 100644 --- a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java +++ b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java @@ -68,12 +68,9 @@ public class XMLWhiteSpaceHandler { /** Counter, increased every time a non-white-space is encountered */ private int nonWhiteSpaceCount; - private Block currentBlock; - private FObj currentFO; private int linefeedTreatment; private int whiteSpaceTreatment; private int whiteSpaceCollapse; - private FONode nextChild; private boolean endOfBlock; private boolean nextChildIsBlockLevel; private RecursiveCharIterator charIter; @@ -87,19 +84,28 @@ public class XMLWhiteSpaceHandler { * firstTextNode * @param fo the FO for which to handle white-space * @param firstTextNode the node at which to start + * @param nextChild the node that will be added to the list + * after firstTextNode */ - public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode) { + public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode, FONode nextChild) { + Block currentBlock = null; int foId = fo.getNameId(); if (foId == Constants.FO_BLOCK) { - if (nextChild != null && currentBlock != null) { - /* if already in a block, push the current block - * onto the stack of nested blocks - */ - nestedBlockStack.push(currentBlock); - } currentBlock = (Block) fo; + if (nestedBlockStack.isEmpty() || fo != nestedBlockStack.peek()) { + if (nextChild != null) { + /* if already in a block, push the current block + * onto the stack of nested blocks + */ + nestedBlockStack.push(currentBlock); + } + } else { + if (nextChild == null) { + nestedBlockStack.pop(); + } + } } else if (foId == Constants.FO_RETRIEVE_MARKER) { /* look for the nearest block ancestor, if any */ FONode ancestor = fo; @@ -111,6 +117,8 @@ public class XMLWhiteSpaceHandler { if (ancestor.getNameId() == Constants.FO_BLOCK) { currentBlock = (Block) ancestor; } + } else if (!nestedBlockStack.isEmpty()) { + currentBlock = (Block) nestedBlockStack.peek(); } if (currentBlock != null) { @@ -123,8 +131,6 @@ public class XMLWhiteSpaceHandler { whiteSpaceTreatment = Constants.EN_IGNORE_IF_SURROUNDING_LINEFEED; } - currentFO = fo; - if (firstTextNode == null) { //nothing to do but initialize related properties return; @@ -133,20 +139,20 @@ public class XMLWhiteSpaceHandler { charIter = new RecursiveCharIterator(fo, firstTextNode); inWhiteSpace = false; - if (currentFO == currentBlock + if (fo == currentBlock || currentBlock == null || (foId == Constants.FO_RETRIEVE_MARKER - && currentFO.getParent() == currentBlock)) { + && fo.getParent() == currentBlock)) { afterLinefeed = ( (firstTextNode == fo.firstChild) || (firstTextNode.siblings[0].getNameId() == Constants.FO_BLOCK)); } - endOfBlock = (nextChild == null && currentFO == currentBlock); + endOfBlock = (nextChild == null && fo == currentBlock); if (nextChild != null) { - int nextChildId = this.nextChild.getNameId(); + int nextChildId = nextChild.getNameId(); nextChildIsBlockLevel = ( nextChildId == Constants.FO_BLOCK || nextChildId == Constants.FO_TABLE_AND_CAPTION @@ -159,7 +165,7 @@ public class XMLWhiteSpaceHandler { handleWhiteSpace(); - if (currentFO == currentBlock + if (fo == currentBlock && pendingInlines != null && !pendingInlines.isEmpty()) { /* current FO is a block, and has pending inlines */ @@ -183,7 +189,7 @@ public class XMLWhiteSpaceHandler { } if (nextChild == null) { - if (currentFO != currentBlock) { + if (fo != currentBlock) { /* current FO is not a block, and is about to end */ if (nonWhiteSpaceCount > 0 && pendingInlines != null) { /* there is non-white-space text between the pending @@ -204,7 +210,6 @@ public class XMLWhiteSpaceHandler { } else { currentBlock = null; } - currentFO = null; charIter = null; } } @@ -218,10 +223,8 @@ public class XMLWhiteSpaceHandler { * @param nextChild the child-node that will be added to the list after * the last text-node */ - public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode, FONode nextChild) { - this.nextChild = nextChild; - handleWhiteSpace(fo, firstTextNode); - this.nextChild = null; + public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode) { + handleWhiteSpace(fo, firstTextNode, null); } private void handleWhiteSpace() { diff --git a/status.xml b/status.xml index a213a13be..83442d251 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Fixed a memory-leak in XMLWhiteSpaceHandler. + Fixed the resolution of borders when header/footer is omitted at page breaks. -- cgit v1.2.3 From 4476c5bed846a37d7ffcc77349eb7256a420f7c5 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Sun, 27 Jan 2008 14:09:12 +0000 Subject: Of course startIndex == endIndex means there is one element whose length must be computed... Changed >= into > git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615604 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 9004e9c17..54ac4867a 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -234,7 +234,7 @@ class RowPainter { // be used as padding. // This should be handled automatically by a proper use of Knuth elements private int computeContentLength(PrimaryGridUnit pgu, int startIndex, int endIndex) { - if (startIndex >= endIndex) { + if (startIndex > endIndex) { // May happen if the cell contributes no content on the current page (empty // cell, in most cases) return 0; -- cgit v1.2.3 From 74b2adc7ebb1c898d17bc5778de412522512d4c8 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 28 Jan 2008 10:32:46 +0000 Subject: Improve breaking for block-container and static-content so there are no more "breaking artifacts" (like additional border lines) in the overflowing part of the content anymore. This is done by removing all breaks from the result list prior to constructing the area tree. The presence of breaks simply indicates that there is an overflow. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615845 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/BlockContainerLayoutManager.java | 9 ++-- .../fop/layoutmgr/PageBreakingAlgorithm.java | 14 +++++ .../fop/layoutmgr/StaticContentLayoutManager.java | 10 ++-- .../block-container_content_size_percentage.xml | 4 +- .../block-container_overflow_2.xml | 53 ++++++++++++++++++ .../static-content_overflow_1.xml | 62 ++++++++++++++++++++++ 6 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block-container_overflow_2.xml create mode 100644 test/layoutengine/standard-testcases/static-content_overflow_1.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index ab153090b..3d9076efd 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -355,10 +355,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager MinOptMax range = new MinOptMax(relDims.ipd); BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); breaker.doLayout(relDims.bpd, autoHeight); - boolean contentOverflows = false; - if (!breaker.isEmpty()) { - contentOverflows = (breaker.deferredAlg.getPageBreaks().size() > 1); - } + boolean contentOverflows = breaker.isOverflow(); Position bcPosition = new BlockContainerPosition(this, breaker); returnList.add(new KnuthBox(vpContentBPD, notifyPos(bcPosition), false)); @@ -648,9 +645,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } //Rendering all parts (not just the first) at once for the case where the parts that //overflow should be visible. - //TODO Check if this has any unwanted side-effects. Feels a bit like a hack. + this.deferredAlg.removeAllPageBreaks(); this.addAreas(this.deferredAlg, - /*1*/ this.deferredAlg.getPageBreaks().size(), + this.deferredAlg.getPageBreaks().size(), this.deferredOriginalList, this.deferredEffectiveList); } diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 32c2b8d3b..57fc4600e 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -734,6 +734,20 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { pageBreaks.addFirst(pageBreak); } + /** + * Removes all page breaks from the result list. This is used by block-containers and + * static-content when it is only desired to know where there is an overflow but later the + * whole content should be painted as one part. + */ + public void removeAllPageBreaks() { + if (pageBreaks == null) { + return; + } + while (pageBreaks.size() > 1) { + pageBreaks.removeFirst(); + } + } + private int getPartCount() { if (pageBreaks == null) { return 0; diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 92437a452..c8b89e6af 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -25,9 +25,10 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.area.RegionReference; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; +import org.apache.fop.area.RegionReference; import org.apache.fop.fo.FONode; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.SideRegion; @@ -339,11 +340,14 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { protected void doPhase3(PageBreakingAlgorithm alg, int partCount, BlockSequence originalList, BlockSequence effectiveList) { - //Directly add areas after finding the breaks - this.addAreas(alg, partCount, originalList, effectiveList); if (partCount > 1) { overflow = true; } + //Rendering all parts (not just the first) at once for the case where the parts that + //overflow should be visible. + alg.removeAllPageBreaks(); + //Directly add areas after finding the breaks + this.addAreas(alg, 1, originalList, effectiveList); } protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) { diff --git a/test/layoutengine/standard-testcases/block-container_content_size_percentage.xml b/test/layoutengine/standard-testcases/block-container_content_size_percentage.xml index 14d09a5d6..c3b11805c 100644 --- a/test/layoutengine/standard-testcases/block-container_content_size_percentage.xml +++ b/test/layoutengine/standard-testcases/block-container_content_size_percentage.xml @@ -78,9 +78,7 @@ - + - - diff --git a/test/layoutengine/standard-testcases/block-container_overflow_2.xml b/test/layoutengine/standard-testcases/block-container_overflow_2.xml new file mode 100644 index 000000000..5fe97e7c3 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_overflow_2.xml @@ -0,0 +1,53 @@ + + + + + +

          + This test checks behaviour with overflowing content on block-containers. +

          +

          + Visual check: If there's a red line between the second and third line, the + behaviour is wrong. +

          +
          + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl. + + + + + + + + + + + + + +
          diff --git a/test/layoutengine/standard-testcases/static-content_overflow_1.xml b/test/layoutengine/standard-testcases/static-content_overflow_1.xml new file mode 100644 index 000000000..b620f018c --- /dev/null +++ b/test/layoutengine/standard-testcases/static-content_overflow_1.xml @@ -0,0 +1,62 @@ + + + + + +

          + This test checks behaviour with overflowing content on static-content. +

          +

          + Visual check: If there's a red line between the second and third line, the + behaviour is wrong. +

          +
          + + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl. + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl. + + + xsl-region-body + + + + + + + + + + + + + + + +
          -- cgit v1.2.3 From 1ea8b13df56f773fc3d28a9a4b69ed1ed8b97cf4 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 28 Jan 2008 15:04:39 +0000 Subject: Added support for the natural language indentifier ("Lang" in the document catalog) for PDF documents based on the language/country values on fo:page-sequence. This required a few changes in the AreaTreeModel and the Renderer interface because it didn't support passing through the PageSequence object, only its title. Now, we can put other values on the PageSequence and transport them to the renderers. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615906 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.3svn.jar | Bin 498800 -> 499126 bytes src/java/org/apache/fop/area/AreaTreeModel.java | 19 ++++-- src/java/org/apache/fop/area/AreaTreeParser.java | 21 ++++--- src/java/org/apache/fop/area/PageSequence.java | 53 +++++++++++++++- src/java/org/apache/fop/area/RenderPagesModel.java | 17 ++---- .../layoutmgr/ExternalDocumentLayoutManager.java | 4 +- .../fop/layoutmgr/PageSequenceLayoutManager.java | 8 ++- src/java/org/apache/fop/pdf/PDFMetadata.java | 11 +++- src/java/org/apache/fop/pdf/PDFRoot.java | 20 ++++++ .../org/apache/fop/render/AbstractRenderer.java | 29 +++++---- src/java/org/apache/fop/render/Renderer.java | 16 +++-- .../org/apache/fop/render/pdf/PDFRenderer.java | 27 +++++--- src/java/org/apache/fop/render/ps/PSRenderer.java | 6 -- .../org/apache/fop/render/xml/XMLRenderer.java | 17 ++++-- status.xml | 4 ++ .../fop/render/pdf/PDFAMetadataTestCase.java | 2 +- .../block_hyphenation_kerning.xml | 2 + .../standard-testcases/page-sequence_language.xml | 68 +++++++++++++++++++++ 18 files changed, 258 insertions(+), 66 deletions(-) create mode 100644 test/layoutengine/standard-testcases/page-sequence_language.xml (limited to 'src') diff --git a/lib/xmlgraphics-commons-1.3svn.jar b/lib/xmlgraphics-commons-1.3svn.jar index 75b10615a..ea00555ef 100644 Binary files a/lib/xmlgraphics-commons-1.3svn.jar and b/lib/xmlgraphics-commons-1.3svn.jar differ diff --git a/src/java/org/apache/fop/area/AreaTreeModel.java b/src/java/org/apache/fop/area/AreaTreeModel.java index bdbb88f2a..c43db31bb 100644 --- a/src/java/org/apache/fop/area/AreaTreeModel.java +++ b/src/java/org/apache/fop/area/AreaTreeModel.java @@ -22,10 +22,8 @@ package org.apache.fop.area; // Java import java.util.List; -// XML import org.xml.sax.SAXException; -// Apache import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -55,10 +53,13 @@ public class AreaTreeModel { /** * Start a page sequence on this model. - * @param title the title of the new page sequence + * @param pageSequence the page sequence about to start */ - public void startPageSequence(LineArea title) { - currentPageSequence = new PageSequence(title); + public void startPageSequence(PageSequence pageSequence) { + if (pageSequence == null) { + throw new NullPointerException("pageSequence must not be null"); + } + this.currentPageSequence = pageSequence; pageSequenceList.add(currentPageSequence); currentPageSequenceIndex = pageSequenceList.size() - 1; } @@ -90,6 +91,14 @@ public class AreaTreeModel { */ public void endDocument() throws SAXException {}; + /** + * Returns the currently active page-sequence. + * @return the currently active page-sequence + */ + public PageSequence getCurrentPageSequence() { + return this.currentPageSequence; + } + /** * Get the page sequence count. * @return the number of page sequences in the document. diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index d4cdf5239..fafb99ed6 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -141,7 +141,6 @@ public class AreaTreeParser { private Stack areaStack = new Stack(); private boolean firstFlow; - private boolean pendingStartPageSequence; private Stack delegateStack = new Stack(); private ContentHandler delegate; @@ -349,8 +348,12 @@ public class AreaTreeParser { private class PageSequenceMaker extends AbstractMaker { public void startElement(Attributes attributes) { - pendingStartPageSequence = true; - //treeModel.startPageSequence(null); Done after title or on the first viewport + PageSequence pageSequence = new PageSequence(null); + String lang = attributes.getValue("language"); + pageSequence.setLanguage(lang); + String country = attributes.getValue("country"); + pageSequence.setCountry(country); + areaStack.push(pageSequence); } } @@ -364,19 +367,19 @@ public class AreaTreeParser { public void endElement() { LineArea line = (LineArea)areaStack.pop(); - treeModel.startPageSequence(line); - pendingStartPageSequence = false; + PageSequence pageSequence = (PageSequence)areaStack.peek(); + pageSequence.setTitle(line); } - } private class PageViewportMaker extends AbstractMaker { public void startElement(Attributes attributes) { - if (pendingStartPageSequence) { - treeModel.startPageSequence(null); - pendingStartPageSequence = false; + if (!areaStack.isEmpty()) { + PageSequence pageSequence = (PageSequence)areaStack.peek(); + treeModel.startPageSequence(pageSequence); + areaStack.pop(); } if (currentPageViewport != null) { throw new IllegalStateException("currentPageViewport must be null"); diff --git a/src/java/org/apache/fop/area/PageSequence.java b/src/java/org/apache/fop/area/PageSequence.java index d39ec7cf2..3b65f7701 100644 --- a/src/java/org/apache/fop/area/PageSequence.java +++ b/src/java/org/apache/fop/area/PageSequence.java @@ -28,13 +28,15 @@ public class PageSequence { private List pages = new java.util.ArrayList(); private LineArea title; + private String language; + private String country; /** * Main constructor * @param title the title for the page-sequence, may be null */ public PageSequence(LineArea title) { - this.title = title; + setTitle(title); } /** @@ -44,6 +46,14 @@ public class PageSequence { return this.title; } + /** + * Sets the page sequence's title. + * @param title the title + */ + public void setTitle(LineArea title) { + this.title = title; + } + /** * Adds a new page to the page sequence * @param page the page to be added @@ -76,4 +86,45 @@ public class PageSequence { public boolean isFirstPage(PageViewport page) { return page.equals(getPage(0)); } + + /** + * Returns the language of the page-sequence. + * @return the language (the value of the language property, "none" is mapped to null) + */ + public String getLanguage() { + return this.language; + } + + /** + * Sets the language that applies to this page-sequence. + * @param language the language to set ("none" is mapped to null) + */ + public void setLanguage(String language) { + if ("none".equals(language)) { + this.language = null; + } else { + this.language = language; + } + } + + /** + * Returns the country of the page-sequence. + * @return the country (the value of the country property, "none" is mapped to null) + */ + public String getCountry() { + return this.country; + } + + /** + * Sets the country that applies to this page-sequence. + * @param country the country to set ("none" is mapped to null) + */ + public void setCountry(String country) { + if ("none".equals(country)) { + this.country = null; + } else { + this.country = country; + } + } + } diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java index 1b3a22706..e080e9cbe 100644 --- a/src/java/org/apache/fop/area/RenderPagesModel.java +++ b/src/java/org/apache/fop/area/RenderPagesModel.java @@ -81,16 +81,11 @@ public class RenderPagesModel extends AreaTreeModel { } } - /** - * Start a new page sequence. - * This tells the renderer that a new page sequence has - * started with the given title. - * @param title the title of the new page sequence - */ - public void startPageSequence(LineArea title) { - super.startPageSequence(title); + /** {@inheritDoc} */ + public void startPageSequence(PageSequence pageSequence) { + super.startPageSequence(pageSequence); if (renderer.supportsOutOfOrder()) { - renderer.startPageSequence(title); + renderer.startPageSequence(getCurrentPageSequence()); } } @@ -112,7 +107,7 @@ public class RenderPagesModel extends AreaTreeModel { boolean ready = renderer.supportsOutOfOrder() && page.isResolved(); if (ready) { if (!renderer.supportsOutOfOrder() && page.getPageSequence().isFirstPage(page)) { - renderer.startPageSequence(this.currentPageSequence.getTitle()); + renderer.startPageSequence(getCurrentPageSequence()); } try { renderer.renderPage(page); @@ -159,7 +154,7 @@ public class RenderPagesModel extends AreaTreeModel { if (pageViewport.isResolved() || renderUnresolved) { if (!renderer.supportsOutOfOrder() && pageViewport.getPageSequence().isFirstPage(pageViewport)) { - renderer.startPageSequence(this.currentPageSequence.getTitle()); + renderer.startPageSequence(getCurrentPageSequence()); } try { renderer.renderPage(pageViewport); diff --git a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java index 89065185b..21856c781 100644 --- a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java @@ -39,6 +39,7 @@ import org.apache.fop.area.Block; import org.apache.fop.area.BodyRegion; import org.apache.fop.area.CTM; import org.apache.fop.area.LineArea; +import org.apache.fop.area.PageSequence; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.inline.Image; @@ -102,7 +103,7 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan Dimension intrinsicSize = info.getSize().getDimensionMpt(); ImageLayout layout = new ImageLayout(getExternalDocument(), this, intrinsicSize); - areaTreeHandler.getAreaTreeModel().startPageSequence(null); + areaTreeHandler.getAreaTreeModel().startPageSequence(new PageSequence(null)); if (log.isDebugEnabled()) { log.debug("Starting layout"); } @@ -200,6 +201,7 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan } } + /** {@inheritDoc} */ protected Page createPage(int pageNumber, boolean isBlank) { String pageNumberString = pageSeq.makeFormattedPageNumber(pageNumber); diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java index efe64d284..5816fe482 100644 --- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.area.AreaTreeHandler; +import org.apache.fop.area.AreaTreeModel; import org.apache.fop.area.LineArea; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.PageSequenceMaster; @@ -88,7 +89,12 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager } } - areaTreeHandler.getAreaTreeModel().startPageSequence(title); + AreaTreeModel areaTreeModel = areaTreeHandler.getAreaTreeModel(); + org.apache.fop.area.PageSequence pageSequenceAreaObject + = new org.apache.fop.area.PageSequence(title); + pageSequenceAreaObject.setLanguage(getPageSequence().getLanguage()); + pageSequenceAreaObject.setCountry(getPageSequence().getCountry()); + areaTreeModel.startPageSequence(pageSequenceAreaObject); if (log.isDebugEnabled()) { log.debug("Starting layout"); } diff --git a/src/java/org/apache/fop/pdf/PDFMetadata.java b/src/java/org/apache/fop/pdf/PDFMetadata.java index 067502986..e0833a30f 100644 --- a/src/java/org/apache/fop/pdf/PDFMetadata.java +++ b/src/java/org/apache/fop/pdf/PDFMetadata.java @@ -25,6 +25,8 @@ import java.util.Date; import javax.xml.transform.TransformerConfigurationException; +import org.xml.sax.SAXException; + import org.apache.xmlgraphics.xmp.Metadata; import org.apache.xmlgraphics.xmp.XMPSerializer; import org.apache.xmlgraphics.xmp.schemas.DublinCoreAdapter; @@ -36,8 +38,6 @@ import org.apache.xmlgraphics.xmp.schemas.pdf.AdobePDFSchema; import org.apache.xmlgraphics.xmp.schemas.pdf.PDFAAdapter; import org.apache.xmlgraphics.xmp.schemas.pdf.PDFAXMPSchema; -import org.xml.sax.SAXException; - /** * Special PDFStream for Metadata. * @since PDF 1.4 @@ -118,10 +118,11 @@ public class PDFMetadata extends PDFStream { * @param pdfDoc the PDF Document * @return the requested XMP metadata */ - public static Metadata createXMPFromUserAgent(PDFDocument pdfDoc) { + public static Metadata createXMPFromPDFDocument(PDFDocument pdfDoc) { Metadata meta = new Metadata(); PDFInfo info = pdfDoc.getInfo(); + PDFRoot root = pdfDoc.getRoot(); //Set creation date if not available, yet if (info.getCreationDate() == null) { @@ -145,6 +146,10 @@ public class PDFMetadata extends PDFStream { //Subject maps to dc:description["x-default"] as per ISO-19005-1:2005/Cor.1:2007 dc.setDescription(null, info.getSubject()); } + if (root.getLanguage() != null) { + //Note: No check is performed to make sure the value is valid RFC 3066! + dc.addLanguage(root.getLanguage()); + } dc.addDate(info.getCreationDate()); //PDF/A identification diff --git a/src/java/org/apache/fop/pdf/PDFRoot.java b/src/java/org/apache/fop/pdf/PDFRoot.java index 54cadf616..0dd9b890c 100644 --- a/src/java/org/apache/fop/pdf/PDFRoot.java +++ b/src/java/org/apache/fop/pdf/PDFRoot.java @@ -232,4 +232,24 @@ public class PDFRoot extends PDFDictionary { } } + /** + * Returns the language identifier of the document. + * @return the language identifier of the document (or null if not set or undefined) + * @since PDF 1.4 + */ + public String getLanguage() { + return (String)get("Lang"); + } + + /** + * Sets the language identifier of the document. + * @param lang the language identifier of the document. + */ + public void setLanguage(String lang) { + if (lang == null) { + throw new NullPointerException("lang must not be null"); + } + put("Lang", lang); + } + } diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index c23f7ae8e..86820066f 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -25,32 +25,35 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.OutputStream; -import java.util.List; import java.util.Iterator; +import java.util.List; import java.util.Set; -// XML import org.w3c.dom.Document; -// FOP +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.BeforeFloat; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; import org.apache.fop.area.CTM; -import org.apache.fop.area.NormalFlow; import org.apache.fop.area.Footnote; import org.apache.fop.area.LineArea; import org.apache.fop.area.MainReference; -import org.apache.fop.area.Span; +import org.apache.fop.area.NormalFlow; +import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.Page; +import org.apache.fop.area.PageSequence; import org.apache.fop.area.PageViewport; -import org.apache.fop.area.RegionViewport; import org.apache.fop.area.RegionReference; +import org.apache.fop.area.RegionViewport; +import org.apache.fop.area.Span; import org.apache.fop.area.Trait; -import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.inline.Character; import org.apache.fop.area.inline.Container; import org.apache.fop.area.inline.ForeignObject; @@ -60,15 +63,12 @@ import org.apache.fop.area.inline.InlineBlockParent; import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.Space; -import org.apache.fop.area.inline.Viewport; +import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; +import org.apache.fop.area.inline.Viewport; import org.apache.fop.area.inline.WordArea; -import org.apache.fop.area.inline.SpaceArea; -import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * Abstract base class for all renderers. The Abstract renderer does all the @@ -219,6 +219,11 @@ public abstract class AbstractRenderer public void startPageSequence(LineArea seqTitle) { //do nothing } + + /** {@inheritDoc} */ + public void startPageSequence(PageSequence pageSequence) { + startPageSequence(pageSequence.getTitle()); + } // normally this would be overriden to create a page in the // output diff --git a/src/java/org/apache/fop/render/Renderer.java b/src/java/org/apache/fop/render/Renderer.java index d54a61025..b40eec0cf 100644 --- a/src/java/org/apache/fop/render/Renderer.java +++ b/src/java/org/apache/fop/render/Renderer.java @@ -20,16 +20,16 @@ package org.apache.fop.render; // Java -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; -// FOP import org.apache.fop.apps.FOPException; -import org.apache.fop.area.PageViewport; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.LineArea; import org.apache.fop.area.OffDocumentItem; +import org.apache.fop.area.PageSequence; +import org.apache.fop.area.PageViewport; import org.apache.fop.fonts.FontInfo; -import org.apache.fop.apps.FOUserAgent; /** @@ -142,9 +142,17 @@ public interface Renderer { * Tells the renderer that a new page sequence starts. * * @param seqTitle The title of the page sequence + * @deprecated Use startPageSequence(PageSequence) instead */ void startPageSequence(LineArea seqTitle); + /** + * Tells the renderer that a new page sequence starts. + * + * @param pageSequence the page sequence + */ + void startPageSequence(PageSequence pageSequence); + /** * Tells the renderer to render a particular page. A renderer typically * reponds by packing up the current page and writing it immediately to the diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 899bc1240..4d641517a 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -61,6 +61,7 @@ import org.apache.fop.area.DestinationData; import org.apache.fop.area.LineArea; import org.apache.fop.area.OffDocumentExtensionAttachment; import org.apache.fop.area.OffDocumentItem; +import org.apache.fop.area.PageSequence; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; @@ -611,7 +612,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { private void renderXMPMetadata(XMPMetadata metadata) { Metadata docXMP = metadata.getMetadata(); - Metadata fopXMP = PDFMetadata.createXMPFromUserAgent(pdfDoc); + Metadata fopXMP = PDFMetadata.createXMPFromPDFDocument(pdfDoc); //Merge FOP's own metadata into the one from the XSL-FO document fopXMP.mergeInto(docXMP); XMPBasicAdapter xmpBasic = XMPBasicSchema.getAdapter(docXMP); @@ -679,13 +680,15 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** * Start the next page sequence. - * For the pdf renderer there is no concept of page sequences + * For the PDF renderer there is no concept of page sequences * but it uses the first available page sequence title to set - * as the title of the pdf document. - * - * @param seqTitle the title of the page sequence + * as the title of the PDF document, and the language of the + * document. + * @param pageSequence the page sequence */ - public void startPageSequence(LineArea seqTitle) { + public void startPageSequence(PageSequence pageSequence) { + super.startPageSequence(pageSequence); + LineArea seqTitle = pageSequence.getTitle(); if (seqTitle != null) { String str = convertTitleToString(seqTitle); PDFInfo info = this.pdfDoc.getInfo(); @@ -693,10 +696,20 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { info.setTitle(str); } } + if (pageSequence.getLanguage() != null) { + String lang = pageSequence.getLanguage(); + String country = pageSequence.getCountry(); + String langCode = lang + (country != null ? "-" + country : ""); + if (pdfDoc.getRoot().getLanguage() == null) { + //Only set if not set already (first non-null is used) + //Note: No checking is performed whether the values are valid! + pdfDoc.getRoot().setLanguage(langCode); + } + } if (pdfDoc.getRoot().getMetadata() == null) { //If at this time no XMP metadata for the overall document has been set, create it //from the PDFInfo object. - Metadata xmp = PDFMetadata.createXMPFromUserAgent(pdfDoc); + Metadata xmp = PDFMetadata.createXMPFromPDFDocument(pdfDoc); PDFMetadata pdfMetadata = pdfDoc.getFactory().makeMetadata( xmp, true); pdfDoc.getRoot().setMetadata(pdfMetadata); diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index 7e3ce87a2..ecd403749 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -72,7 +72,6 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.CTM; -import org.apache.fop.area.LineArea; import org.apache.fop.area.OffDocumentExtensionAttachment; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; @@ -1082,11 +1081,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer super.processOffDocumentItem(oDI); } - /** {@inheritDoc} */ - public void startPageSequence(LineArea seqTitle) { - super.startPageSequence(seqTitle); - } - /** * Formats and writes a List of PSSetupCode instances to the output stream. * @param setupCodeList a List of PSSetupCode instances diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 213cba58d..66cce0ae1 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -61,6 +61,7 @@ import org.apache.fop.area.MainReference; import org.apache.fop.area.NormalFlow; import org.apache.fop.area.OffDocumentExtensionAttachment; import org.apache.fop.area.OffDocumentItem; +import org.apache.fop.area.PageSequence; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; @@ -585,14 +586,20 @@ public class XMLRenderer extends PrintRenderer { handleExtensionAttachments(page.getExtensionAttachments()); } - /** - * {@inheritDoc} - */ - public void startPageSequence(LineArea seqTitle) { + /** {@inheritDoc} */ + public void startPageSequence(PageSequence pageSequence) { handleDocumentExtensionAttachments(); endPageSequence(); // move this before handleDocumentExtensionAttachments() ? startedSequence = true; - startElement("pageSequence"); + atts.clear(); + if (pageSequence.getLanguage() != null) { + addAttribute("language", pageSequence.getLanguage()); + } + if (pageSequence.getCountry() != null) { + addAttribute("country", pageSequence.getCountry()); + } + startElement("pageSequence", atts); + LineArea seqTitle = pageSequence.getTitle(); if (seqTitle != null) { startElement("title"); List children = seqTitle.getInlineAreas(); diff --git a/status.xml b/status.xml index 83442d251..2622f4063 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Added support for the natural language indentifier ("Lang" in the document catalog) + for PDF documents based on the language/country values on fo:page-sequence. + Fixed a memory-leak in XMLWhiteSpaceHandler. diff --git a/test/java/org/apache/fop/render/pdf/PDFAMetadataTestCase.java b/test/java/org/apache/fop/render/pdf/PDFAMetadataTestCase.java index 2821dcb24..b645022bb 100644 --- a/test/java/org/apache/fop/render/pdf/PDFAMetadataTestCase.java +++ b/test/java/org/apache/fop/render/pdf/PDFAMetadataTestCase.java @@ -94,7 +94,7 @@ public class PDFAMetadataTestCase extends TestCase { cal2.set(Calendar.MILLISECOND, 0); info.setModDate(cal2.getTime()); - Metadata meta = PDFMetadata.createXMPFromUserAgent(doc); + Metadata meta = PDFMetadata.createXMPFromPDFDocument(doc); DublinCoreAdapter dc = DublinCoreSchema.getAdapter(meta); assertEquals("MyTitle", dc.getTitle()); diff --git a/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml b/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml index f1f0cbd1e..084f1e685 100644 --- a/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml +++ b/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml @@ -45,6 +45,8 @@ + + diff --git a/test/layoutengine/standard-testcases/page-sequence_language.xml b/test/layoutengine/standard-testcases/page-sequence_language.xml new file mode 100644 index 000000000..93238e282 --- /dev/null +++ b/test/layoutengine/standard-testcases/page-sequence_language.xml @@ -0,0 +1,68 @@ + + + + + +

          + This test checks the language and country property on page-sequence. +

          +
          + + + + + + + + + + language checking only + + + + + language checking only + + + + + language checking only + + + + + language checking only + + + + + + + + + + + + + + + + + +
          -- cgit v1.2.3 From 2b3848ca79cd31efc510c58ecbd74bfc38ebf56d Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 28 Jan 2008 15:45:10 +0000 Subject: A note on country/language. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615917 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 2a2768457..4b6dc024f 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -2546,7 +2546,14 @@ yes
          - + - + - + - - + +
          yes   +
            +
          • + [0.94 and earlier] Only used for controlling hyphenation.
          • +
          • + [trunk] For PDF output: Only 2-letter codes from ISO 3166 are supported properly to identify the natural language!
          • +
          +
          @@ -2562,7 +2569,14 @@ yes yes   +
            +
          • + [0.94 and earlier] Only used for controlling hyphenation.
          • +
          • + [trunk] For PDF output: Only 2-letter codes from ISO 639 are supported properly to identify the natural language!
          • +
          +
          -- cgit v1.2.3 From 88b4aa8d1986c176be86985eabdebab9c7523743 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 28 Jan 2008 22:05:39 +0000 Subject: Bugfix for invalid numTables entry in subset TrueType fonts if there was no "fpgm" table (Example: FreeSerif). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@616080 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java | 7 +++++-- status.xml | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java index 170aec194..c12a7900f 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java @@ -21,8 +21,8 @@ package org.apache.fop.fonts.truetype; import java.io.IOException; import java.util.Iterator; -import java.util.Map; import java.util.List; +import java.util.Map; /** @@ -71,7 +71,10 @@ public class TTFSubSetFile extends TTFFile { * Create the directory table */ private void createDirectory() { - int numTables = 9; + int numTables = 8; + if (hasFpgm()) { + numTables++; + } // Create the TrueType header writeByte((byte)0); writeByte((byte)1); diff --git a/status.xml b/status.xml index 2622f4063..60f0819c2 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Bugfix for invalid numTables entry in subset TrueType fonts if there was no "fpgm" table. + Added support for the natural language indentifier ("Lang" in the document catalog) for PDF documents based on the language/country values on fo:page-sequence. -- cgit v1.2.3 From 544607bcfc3af3db3d20909cc0308a1816940d55 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 29 Jan 2008 07:30:08 +0000 Subject: A more detailed comment on RTF output explaining that RTF has limitations besides the incomplete implementation on the FOP side. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@616191 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/output.xml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index 7a2a79862..663168a3c 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -661,8 +661,14 @@ out = proc.getOutputStream();]]>

          JFOR, an open source XSL-FO to RTF converter has been integrated into Apache FOP. This will create an RTF (rich text format) document that will - attempt to contain as much information from the fo document as - possible. The RTF output follows Microsoft's RTF specifications + attempt to contain as much information from the XSL-FO document as + possible. It should be noted that is not possible (due to RTF's limitations) to map all + XSL-FO features to RTF. For complex documents, the RTF output will never reach the feature + level from PDF, for example. Thus, using RTF output is only recommended for simple documents + such as letters. +

          +

          + The RTF output follows Microsoft's RTF specifications and produces best results on Microsoft Word.

          RTF output is currently unmaintained and lacks many features compared to other output -- cgit v1.2.3 From b9c4bae4480968732c0a2b02556771031eacdf17 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 30 Jan 2008 08:53:48 +0000 Subject: "cvt ", "fpgm" and "prep" are all optional tables in TrueType. Some PDF viewers fail because FOP didn't handle those correctly. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@616691 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fonts/truetype/TTFSubSetFile.java | 113 ++++++++++++--------- status.xml | 4 + 2 files changed, 69 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java index c12a7900f..99fd10315 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java @@ -67,14 +67,31 @@ public class TTFSubSetFile extends TTFFile { // createDirectory() } + private int determineTableCount() { + int numTables = 4; //4 req'd tables: head,hhea,hmtx,maxp + if (isCFF()) { + throw new UnsupportedOperationException( + "OpenType fonts with CFF glyphs are not supported"); + } else { + numTables += 2; //1 req'd table: glyf,loca + if (hasCvt()) { + numTables++; + } + if (hasFpgm()) { + numTables++; + } + if (hasPrep()) { + numTables++; + } + } + return numTables; + } + /** * Create the directory table */ private void createDirectory() { - int numTables = 8; - if (hasFpgm()) { - numTables++; - } + int numTables = determineTableCount(); // Create the TrueType header writeByte((byte)0); writeByte((byte)1); @@ -98,10 +115,12 @@ public class TTFSubSetFile extends TTFFile { realSize += 2; // Create space for the table entries - writeString("cvt "); - cvtDirOffset = currentPos; - currentPos += 12; - realSize += 16; + if (hasCvt()) { + writeString("cvt "); + cvtDirOffset = currentPos; + currentPos += 12; + realSize += 16; + } if (hasFpgm()) { writeString("fpgm"); @@ -140,17 +159,19 @@ public class TTFSubSetFile extends TTFFile { currentPos += 12; realSize += 16; - writeString("prep"); - prepDirOffset = currentPos; - currentPos += 12; - realSize += 16; + if (hasPrep()) { + writeString("prep"); + prepDirOffset = currentPos; + currentPos += 12; + realSize += 16; + } } /** * Copy the cvt table as is from original font to subset font */ - private void createCvt(FontFileReader in) throws IOException { + private boolean createCvt(FontFileReader in) throws IOException { TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("cvt "); if (entry != null) { pad4(); @@ -164,21 +185,29 @@ public class TTFSubSetFile extends TTFFile { writeULong(cvtDirOffset + 8, (int)entry.getLength()); currentPos += (int)entry.getLength(); realSize += (int)entry.getLength(); + return true; } else { - throw new IOException("Can't find cvt table"); + return false; + //throw new IOException("Can't find cvt table"); } } + private boolean hasCvt() { + return dirTabs.containsKey("cvt "); + } private boolean hasFpgm() { - return (dirTabs.get("fpgm") != null); + return dirTabs.containsKey("fpgm"); } + private boolean hasPrep() { + return dirTabs.containsKey("prep"); + } /** * Copy the fpgm table as is from original font to subset font */ - private void createFpgm(FontFileReader in) throws IOException { + private boolean createFpgm(FontFileReader in) throws IOException { TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("fpgm"); if (entry != null) { pad4(); @@ -191,9 +220,9 @@ public class TTFSubSetFile extends TTFFile { writeULong(fpgmDirOffset + 8, (int)entry.getLength()); currentPos += (int)entry.getLength(); realSize += (int)entry.getLength(); + return true; } else { - //fpgm table is optional - //throw new IOException("Can't find fpgm table"); + return false; } } @@ -240,7 +269,7 @@ public class TTFSubSetFile extends TTFFile { /** * Copy the prep table as is from original font to subset font */ - private void createPrep(FontFileReader in) throws IOException { + private boolean createPrep(FontFileReader in) throws IOException { TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("prep"); if (entry != null) { pad4(); @@ -254,8 +283,9 @@ public class TTFSubSetFile extends TTFFile { writeULong(prepDirOffset + 8, (int)entry.getLength()); currentPos += (int)entry.getLength(); realSize += (int)entry.getLength(); + return true; } else { - throw new IOException("Can't find prep table"); + return false; } } @@ -640,40 +670,27 @@ public class TTFSubSetFile extends TTFFile { createHmtx(in, glyphs); // Create hmtx table createMaxp(in, glyphs.size()); // copy the maxp table - try { - createCvt(in); // copy the cvt table - } catch (IOException ex) { - // Cvt is optional (only required for OpenType (MS) fonts) - //log.error("TrueType warning: " + ex.getMessage()); - } - - try { - createFpgm(in); // copy fpgm table - } catch (IOException ex) { - // Fpgm is optional (only required for OpenType (MS) fonts) - //log.error("TrueType warning: " + ex.getMessage()); + boolean optionalTableFound; + optionalTableFound = createCvt(in); // copy the cvt table + if (!optionalTableFound) { + // cvt is optional (used in TrueType fonts only) + log.debug("TrueType: ctv table not present. Skipped."); } - try { - createPrep(in); // copy prep table - } catch (IOException ex) { - // Prep is optional (only required for OpenType (MS) fonts) - //log.error("TrueType warning: " + ex.getMessage()); + optionalTableFound = createFpgm(in); // copy fpgm table + if (!optionalTableFound) { + // fpgm is optional (used in TrueType fonts only) + log.debug("TrueType: fpgm table not present. Skipped."); } - try { - createLoca(glyphs.size()); // create empty loca table - } catch (IOException ex) { - // Loca is optional (only required for OpenType (MS) fonts) - //log.error("TrueType warning: " + ex.getMessage()); + optionalTableFound = createPrep(in); // copy prep table + if (!optionalTableFound) { + // prep is optional (used in TrueType fonts only) + log.debug("TrueType: prep table not present. Skipped."); } - try { - createGlyf(in, glyphs); - } catch (IOException ex) { - // Glyf is optional (only required for OpenType (MS) fonts) - //log.error("TrueType warning: " + ex.getMessage()); - } + createLoca(glyphs.size()); // create empty loca table + createGlyf(in, glyphs); //create glyf table and update loca table pad4(); createCheckSumAdjustment(); diff --git a/status.xml b/status.xml index 60f0819c2..63a8a1d89 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Bugfix for handling of optional tables in subset TrueType fonts. This bug caused errors + in various PDF viewers. + Bugfix for invalid numTables entry in subset TrueType fonts if there was no "fpgm" table. -- cgit v1.2.3 From 8155c42f8f57693b3b2f06090aed25a72df2c025 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 30 Jan 2008 16:03:00 +0000 Subject: Removed the Dijkstra stuff as it was moved to Commons. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@616798 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/util/dijkstra/DefaultEdgeDirectory.java | 109 ----------- .../fop/util/dijkstra/DijkstraAlgorithm.java | 215 --------------------- src/java/org/apache/fop/util/dijkstra/Edge.java | 47 ----- .../apache/fop/util/dijkstra/EdgeDirectory.java | 45 ----- src/java/org/apache/fop/util/dijkstra/Vertex.java | 32 --- test/java/org/apache/fop/util/dijkstra/City.java | 57 ------ .../apache/fop/util/dijkstra/DijkstraTestCase.java | 139 ------------- test/java/org/apache/fop/util/dijkstra/Mode.java | 51 ----- .../org/apache/fop/util/dijkstra/TrainRoute.java | 67 ------- 9 files changed, 762 deletions(-) delete mode 100644 src/java/org/apache/fop/util/dijkstra/DefaultEdgeDirectory.java delete mode 100644 src/java/org/apache/fop/util/dijkstra/DijkstraAlgorithm.java delete mode 100644 src/java/org/apache/fop/util/dijkstra/Edge.java delete mode 100644 src/java/org/apache/fop/util/dijkstra/EdgeDirectory.java delete mode 100644 src/java/org/apache/fop/util/dijkstra/Vertex.java delete mode 100644 test/java/org/apache/fop/util/dijkstra/City.java delete mode 100644 test/java/org/apache/fop/util/dijkstra/DijkstraTestCase.java delete mode 100644 test/java/org/apache/fop/util/dijkstra/Mode.java delete mode 100644 test/java/org/apache/fop/util/dijkstra/TrainRoute.java (limited to 'src') diff --git a/src/java/org/apache/fop/util/dijkstra/DefaultEdgeDirectory.java b/src/java/org/apache/fop/util/dijkstra/DefaultEdgeDirectory.java deleted file mode 100644 index 381b356a2..000000000 --- a/src/java/org/apache/fop/util/dijkstra/DefaultEdgeDirectory.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; - -/** - * Default implementation of an edge directory for the {@link DijkstraAlgorithm}. - */ -public class DefaultEdgeDirectory implements EdgeDirectory { - - /** The directory of edges */ - private Map edges = new java.util.HashMap(); - //Map> - - /** - * Adds a new edge between two vertices. - * @param edge the new edge - */ - public void addEdge(Edge edge) { - Map directEdges = (Map)edges.get(edge.getStart()); - if (directEdges == null) { - directEdges = new java.util.HashMap(); - edges.put(edge.getStart(), directEdges); - } - directEdges.put(edge.getEnd(), edge); - } - - /** {@inheritDoc} */ - public int getPenalty(Vertex start, Vertex end) { - Map edgeMap = (Map)edges.get(start); - if (edgeMap != null) { - Edge route = (Edge)edgeMap.get(end); - if (route != null) { - int penalty = route.getPenalty(); - if (penalty < 0) { - throw new IllegalStateException("Penalty must not be negative"); - } - return penalty; - } - } - return 0; - } - - /** {@inheritDoc} */ - public Iterator getDestinations(Vertex origin) { - Map directRoutes = (Map)edges.get(origin); - if (directRoutes != null) { - Iterator iter = directRoutes.keySet().iterator(); - return iter; - } - return Collections.EMPTY_LIST.iterator(); - } - - /** - * Returns an iterator over all edges with the given origin. - * @param origin the origin - * @return an iterator over Edge instances - */ - public Iterator getEdges(Vertex origin) { - Map directRoutes = (Map)edges.get(origin); - if (directRoutes != null) { - Iterator iter = directRoutes.values().iterator(); - return iter; - } - return Collections.EMPTY_LIST.iterator(); - } - - /** - * Returns the best edge (the edge with the lowest penalty) between two given vertices. - * @param start the start vertex - * @param end the end vertex - * @return the best vertex or null if none is found - */ - public Edge getBestEdge(Vertex start, Vertex end) { - Edge best = null; - Iterator iter = getEdges(start); - while (iter.hasNext()) { - Edge edge = (Edge)iter.next(); - if (edge.getEnd().equals(end)) { - if (best == null || edge.getPenalty() < best.getPenalty()) { - best = edge; - } - } - } - return best; - } - - -} diff --git a/src/java/org/apache/fop/util/dijkstra/DijkstraAlgorithm.java b/src/java/org/apache/fop/util/dijkstra/DijkstraAlgorithm.java deleted file mode 100644 index a5b2fe202..000000000 --- a/src/java/org/apache/fop/util/dijkstra/DijkstraAlgorithm.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -import java.util.Comparator; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -/** - * This is an implementation of Dijkstra's algorithm to find the shortest path for a directed - * graph with non-negative edge weights. - * @see WikiPedia on Dijkstra's - * Algorithm - */ -public class DijkstraAlgorithm { - - /** Infinity value for distances. */ - public static final int INFINITE = Integer.MAX_VALUE; - - /** Compares penalties between two possible destinations. */ - private final Comparator penaltyComparator = new Comparator() { - public int compare(Object left, Object right) { - int leftPenalty = getLowestPenalty((Vertex)left); - int rightPenalty = getLowestPenalty((Vertex)right); - if (leftPenalty < rightPenalty) { - return -1; - } else if (leftPenalty == rightPenalty) { - return ((Comparable)left).compareTo(right); - } else { - return 1; - } - } - }; - - /** The directory of edges */ - private EdgeDirectory edgeDirectory; - - /** The priority queue for all vertices under inspection, ordered by penalties/distances. */ - private TreeSet priorityQueue = new TreeSet(penaltyComparator); - //Set - - /** The set of vertices for which the lowest penalty has been found. */ - private Set finishedVertices = new java.util.HashSet(); - //Set - - /** The currently known lowest penalties for all vertices. */ - private Map lowestPenalties = new java.util.HashMap(); - //Map - - /** Map of all predecessors in the spanning tree of best routes. */ - private Map predecessors = new java.util.HashMap(); - //Map - - /** - * Main Constructor. - * @param edgeDirectory the edge directory this instance should work on - */ - public DijkstraAlgorithm(EdgeDirectory edgeDirectory) { - this.edgeDirectory = edgeDirectory; - } - - /** - * Returns the penalty between two vertices. - * @param start the start vertex - * @param end the end vertex - * @return the penalty between two vertices, or 0 if no single edge between the two vertices - * exists. - */ - protected int getPenalty(Vertex start, Vertex end) { - return this.edgeDirectory.getPenalty(start, end); - } - - /** - * Returns an iterator over all valid destinations for a given vertex. - * @param origin the origin from which to search for destinations - * @return the iterator over all valid destinations for a given vertex - */ - protected Iterator getDestinations(Vertex origin) { - return this.edgeDirectory.getDestinations(origin); - } - - private void reset() { - finishedVertices.clear(); - priorityQueue.clear(); - - lowestPenalties.clear(); - predecessors.clear(); - } - - /** - * Run Dijkstra's shortest path algorithm. After this method is finished you can use - * {@link #getPredecessor(Vertex)} to reconstruct the best/shortest path starting from the - * destination backwards. - * @param start the starting vertex - * @param destination the destination vertex. - */ - public void execute(Vertex start, Vertex destination) { - if (start == null || destination == null) { - throw new NullPointerException("start and destination may not be null"); - } - - reset(); - setShortestDistance(start, 0); - priorityQueue.add(start); - - // the current node - Vertex u; - - // extract the vertex with the shortest distance - while (priorityQueue.size() > 0) { - u = (Vertex)priorityQueue.first(); - priorityQueue.remove(u); - - if (destination.equals(u)) { - //Destination reached - break; - } - - finishedVertices.add(u); - relax(u); - } - } - - /** - * Compute new lowest penalties for neighboring vertices. Update the lowest penalties and the - * predecessor map if a better solution is found. - * @param u the vertex to process - */ - private void relax(Vertex u) { - Iterator iter = getDestinations(u); - while (iter.hasNext()) { - Vertex v = (Vertex)iter.next(); - // skip node already settled - if (isFinished(v)) { - continue; - } - - int shortDist = getLowestPenalty(u) + getPenalty(u, v); - - if (shortDist < getLowestPenalty(v)) { - // assign new shortest distance and mark unsettled - setShortestDistance(v, shortDist); - - // assign predecessor in shortest path - setPredecessor(v, u); - } - } - } - - private void setPredecessor(Vertex a, Vertex b) { - predecessors.put(a, b); - } - - /** - * Indicates whether a shortest route to a vertex has been found. - * @param v the vertex - * @return true if the shortest route to this vertex has been found. - */ - private boolean isFinished(Vertex v) { - return finishedVertices.contains(v); - } - - private void setShortestDistance(Vertex vertex, int distance) { - //Remove so it is inserted at the right position after the lowest penalty changes for this - //vertex. - priorityQueue.remove(vertex); - - //Update the lowest penalty. - lowestPenalties.put(vertex, new Integer(distance)); - - //Insert the vertex again at the new position based on the lowest penalty - priorityQueue.add(vertex); - } - - /** - * Returns the lowest penalty from the start point to a given vertex. - * @param vertex the vertex - * @return the lowest penalty or {@link DijkstraAlgorithm#INFINITE} if there is no route to - * the destination. - */ - public int getLowestPenalty(Vertex vertex) { - Integer d = ((Integer)lowestPenalties.get(vertex)); - return (d == null) ? INFINITE : d.intValue(); - } - - /** - * Returns the vertex's predecessor on the shortest path. - * @param vertex the vertex for which to find the predecessor - * @return the vertex's predecessor on the shortest path, or - * null if there is no route to the destination. - */ - public Vertex getPredecessor(Vertex vertex) { - return (Vertex)predecessors.get(vertex); - } - -} diff --git a/src/java/org/apache/fop/util/dijkstra/Edge.java b/src/java/org/apache/fop/util/dijkstra/Edge.java deleted file mode 100644 index f709b9e26..000000000 --- a/src/java/org/apache/fop/util/dijkstra/Edge.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -/** - * Represents an edge (or direct route between two points) for the {@link DijkstraAlgorithm}. - * Implement this class to hold the start and end vertex for an edge and implement the - * getPenalty() method. - */ -public interface Edge { - - /** - * Returns the start vertex of the edge. - * @return the start vertex - */ - Vertex getStart(); - - /** - * Returns the end vertex of the edge. - * @return the end vertex - */ - Vertex getEnd(); - - /** - * Returns the penalty (or distance) for this edge. - * @return the penalty value (must be non-negative) - */ - int getPenalty(); - -} diff --git a/src/java/org/apache/fop/util/dijkstra/EdgeDirectory.java b/src/java/org/apache/fop/util/dijkstra/EdgeDirectory.java deleted file mode 100644 index 6a2dc848b..000000000 --- a/src/java/org/apache/fop/util/dijkstra/EdgeDirectory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -import java.util.Iterator; - -/** - * Represents a directory of edges for use by the {@link DijkstraAlgorithm}. - */ -public interface EdgeDirectory { - - /** - * Returns the penalty between two vertices. - * @param start the start vertex - * @param end the end vertex - * @return the penalty between two vertices, or 0 if no single edge between the two vertices - * exists. - */ - int getPenalty(Vertex start, Vertex end); - - /** - * Returns an iterator over all valid destinations for a given vertex. - * @param origin the origin from which to search for destinations - * @return the iterator over all valid destinations for a given vertex - */ - Iterator getDestinations(Vertex origin); - -} \ No newline at end of file diff --git a/src/java/org/apache/fop/util/dijkstra/Vertex.java b/src/java/org/apache/fop/util/dijkstra/Vertex.java deleted file mode 100644 index 40c41b0b7..000000000 --- a/src/java/org/apache/fop/util/dijkstra/Vertex.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -/** - * Represents a vertex to be used by {@link DijkstraAlgorithm}. If you want to represent a city, - * you can do "public class City implements Vertex". The purpose of this interface is to make - * sure the Vertex implementation implements the Comparable interface so the sorting order is - * well-defined even when two vertices have the same penalty/distance from an origin point. - * Therefore, make sure you implement the compareTo(Object) and - * equals(Object) methods. - */ -public interface Vertex extends Comparable { - -} diff --git a/test/java/org/apache/fop/util/dijkstra/City.java b/test/java/org/apache/fop/util/dijkstra/City.java deleted file mode 100644 index 4562c36c7..000000000 --- a/test/java/org/apache/fop/util/dijkstra/City.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -/** - * Represents a city. - */ -public class City implements Vertex { - - private String name; - - /** - * Main constructor - * @param name the city's name - */ - public City(String name) { - this.name = name; - } - - /** {@inheritDoc} */ - public boolean equals(Object obj) { - return this.name.equals(((City)obj).name); - } - - /** {@inheritDoc} */ - public int hashCode() { - return this.name.hashCode(); - } - - /** {@inheritDoc} */ - public int compareTo(Object obj) { - return this.name.compareTo(((City)obj).name); - } - - /** {@inheritDoc} */ - public String toString() { - return this.name; - } - -} \ No newline at end of file diff --git a/test/java/org/apache/fop/util/dijkstra/DijkstraTestCase.java b/test/java/org/apache/fop/util/dijkstra/DijkstraTestCase.java deleted file mode 100644 index fb56f1f53..000000000 --- a/test/java/org/apache/fop/util/dijkstra/DijkstraTestCase.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -import java.util.Iterator; -import java.util.LinkedList; - -import junit.framework.TestCase; - -/** - * Tests the Dijkstra algorithm implementation. We're comparing best solutions with focus on - * time or distance getting from St. Gallen to Lucerne on Switzerland's railroads. - */ -public class DijkstraTestCase extends TestCase { - - private static final boolean DEBUG = false; - - private static final City ROMANSHORN = new City("Romanshorn"); - private static final City ST_GALLEN = new City("St. Gallen"); - private static final City WINTERTHUR = new City("Winterthur"); - private static final City ZURICH = new City("Zurich"); - private static final City ZUG = new City("Zug"); - private static final City RAPPERSWIL = new City("Rapperswil"); - private static final City ARTH_GOLDAU = new City("Arth-Goldau"); - private static final City LUCERNE = new City("Lucerne"); - - private static final City NOWHERE = new City("nowhere"); - - private DijkstraAlgorithm algo; - private DefaultEdgeDirectory edges; - private Mode mode; - - /** {@inheritDoc} */ - protected void setUp() throws Exception { - super.setUp(); - - edges = new DefaultEdgeDirectory(); - algo = new DijkstraAlgorithm(edges); - mode = new Mode(); - - //St.Gallen - Winterthur - Zurich - Zug - Lucerne: 161 km, 2h 01min - edges.addEdge(new TrainRoute(mode, ST_GALLEN, WINTERTHUR, 61, 39)); - edges.addEdge(new TrainRoute(mode, WINTERTHUR, ZURICH, 31, 31)); - edges.addEdge(new TrainRoute(mode, ZURICH, ZUG, 39, 31)); - edges.addEdge(new TrainRoute(mode, ZUG, LUCERNE, 30, 20)); - - //St.Gallen - Rapperswil - Arth-Goldau - Lucerne: 158km, 2h 18min - edges.addEdge(new TrainRoute(mode, ST_GALLEN, RAPPERSWIL, 72, 57)); - edges.addEdge(new TrainRoute(mode, RAPPERSWIL, ARTH_GOLDAU, 55, 48)); - edges.addEdge(new TrainRoute(mode, ARTH_GOLDAU, LUCERNE, 31, 33)); - - //A detour to make it interesting (St.Gallen - Romanshorn - Winterthur): 89km, 1h 23min - edges.addEdge(new TrainRoute(mode, ST_GALLEN, ROMANSHORN, 30, 32)); - edges.addEdge(new TrainRoute(mode, ROMANSHORN, WINTERTHUR, 59, 51)); - } - - public void testAlgorithmWithDistance() throws Exception { - mode.useDistance(); - City origin = ST_GALLEN; - City destination = LUCERNE; - String route = executeAlgorithm(origin, destination); - - int distance = algo.getLowestPenalty(destination); - - if (DEBUG) { - System.out.println(route + " " + distance + " km"); - } - - assertEquals(158, distance); - assertEquals("St. Gallen - Rapperswil - Arth-Goldau - Lucerne", route); - } - - public void testAlgorithmWithDuration() throws Exception { - mode.useDuration(); - City origin = ST_GALLEN; - City destination = LUCERNE; - String route = executeAlgorithm(origin, destination); - - int duration = algo.getLowestPenalty(destination); - - if (DEBUG) { - System.out.println(route + " " + duration + " minutes"); - } - - assertEquals(121, duration); - assertEquals("St. Gallen - Winterthur - Zurich - Zug - Lucerne", route); - } - - public void testAlgorithmWithNonExistentRoute() throws Exception { - City origin = ST_GALLEN; - City destination = NOWHERE; - algo.execute(origin, destination); - Vertex pred = algo.getPredecessor(destination); - assertNull(pred); - } - - private String executeAlgorithm(City origin, City destination) { - algo.execute(origin, destination); - Vertex prev = destination; - Vertex pred = algo.getPredecessor(destination); - if (pred == null) { - fail("No route found!"); - } - LinkedList stops = new LinkedList(); - stops.addLast(destination); - while ((pred = algo.getPredecessor(prev)) != null) { - stops.addFirst(pred); - prev = pred; - } - StringBuffer sb = new StringBuffer(); - Iterator iter = stops.iterator(); - while (iter.hasNext()) { - if (sb.length() > 0) { - sb.append(" - "); - } - sb.append(iter.next()); - } - String route = sb.toString(); - return route; - } - -} diff --git a/test/java/org/apache/fop/util/dijkstra/Mode.java b/test/java/org/apache/fop/util/dijkstra/Mode.java deleted file mode 100644 index 4e75e57af..000000000 --- a/test/java/org/apache/fop/util/dijkstra/Mode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -/** - * Class to allow easy switching between duration and distance mode. - */ -public class Mode { - - private boolean duration = true; - - /** - * Switch to duration mode. - */ - public void useDuration() { - this.duration = true; - } - - /** - * Switch to distance mode. - */ - public void useDistance() { - this.duration = false; - } - - /** - * Indicates whether to use duration mode or distance mode. - * @return true if duration mode is active, otherwise it's the distance mode. - */ - public boolean isDuration() { - return this.duration; - } - -} diff --git a/test/java/org/apache/fop/util/dijkstra/TrainRoute.java b/test/java/org/apache/fop/util/dijkstra/TrainRoute.java deleted file mode 100644 index 16ad0dc3a..000000000 --- a/test/java/org/apache/fop/util/dijkstra/TrainRoute.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util.dijkstra; - -/** - * Represents a train route with both distance and duration. - */ -public class TrainRoute implements Edge { - - private Mode mode; - private Vertex start; - private Vertex end; - private int distance; - private int minutes; - - /** - * Main constructor. - * @param origin the start city - * @param dest the destination city - * @param distance the distance between the two cities - * @param minutes the duration for the route - */ - public TrainRoute(Mode mode, City origin, City dest, int distance, int minutes) { - this.mode = mode; - this.start = origin; - this.end = dest; - this.distance = distance; - this.minutes = minutes; - } - - /** {@inheritDoc} */ - public int getPenalty() { - if (mode.isDuration()) { - return this.minutes; - } else { - return this.distance; - } - } - - /** {@inheritDoc} */ - public Vertex getEnd() { - return this.end; - } - - /** {@inheritDoc} */ - public Vertex getStart() { - return this.start; - } - -} -- cgit v1.2.3 From 7fd5394fe63a571ed2526c93053c64e3dc71536a Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 1 Feb 2008 11:11:02 +0000 Subject: Implemented drawRenderedImage() which fixes painting of PNG images embedded inside SVG images. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617473 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/svg/PDFGraphics2D.java | 90 +++++++++++--------------- 1 file changed, 38 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index c3c336000..fdc54b48f 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -63,7 +63,10 @@ import org.apache.batik.ext.awt.RenderingHintsKeyExt; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.PatternPaint; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; @@ -92,6 +95,7 @@ import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFText; import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.pdf.ImageRawJPEGAdapter; +import org.apache.fop.render.pdf.ImageRenderedAdapter; import org.apache.fop.util.ColorExt; /** @@ -347,6 +351,14 @@ public class PDFGraphics2D extends AbstractGraphics2D { + PDFNumber.doubleOut(matrix[5], DEC) + " cm\n"); } + private void concatMatrix(AffineTransform transform) { + if (!transform.isIdentity()) { + double[] matrix = new double[6]; + transform.getMatrix(matrix); + concatMatrix(matrix); + } + } + /** * This is mainly used for shading patterns which use the document-global coordinate system * instead of the local one. @@ -1328,63 +1340,37 @@ public class PDFGraphics2D extends AbstractGraphics2D { } } - /** - * Renders a {@link RenderedImage}, - * applying a transform from image - * space into user space before drawing. - * The transformation from user space into device space is done with - * the current Transform in the Graphics2D. - * The specified transformation is applied to the image before the - * transform attribute in the Graphics2D context is applied. - * The rendering attributes applied include the Clip, - * Transform, and Composite attributes. Note - * that no rendering is done if the specified transform is - * noninvertible. - * @param img the image to be rendered - * @param xform the transformation from image space into user space - * @see #transform - * @see #setTransform - * @see #setComposite - * @see #clip - * @see #setClip - */ + /** {@inheritDoc} */ public void drawRenderedImage(RenderedImage img, AffineTransform xform) { - //NYI + preparePainting(); + String key = "TempImage:" + img.toString(); + PDFXObject xObject = pdfDoc.getXObject(key); + if (xObject == null) { + ImageInfo info = new ImageInfo(null, "image/unknown"); + ImageSize size = new ImageSize(img.getWidth(), img.getHeight(), 72); + info.setSize(size); + ImageRendered imgRend = new ImageRendered(info, img, null); + ImageRenderedAdapter adapter = new ImageRenderedAdapter(imgRend, key); + xObject = pdfDoc.addImage(resourceContext, adapter); + } + + // now do any transformation required and add the actual image + // placement instance + currentStream.write("q\n"); + concatMatrix(getTransform()); + Shape imclip = getClip(); + writeClip(imclip); + concatMatrix(xform); + currentStream.write("" + img.getWidth() + " 0 0 " + (-img.getHeight()) + " 0" + + " " + (img.getHeight()) + " cm\n" + + xObject.getName() + " Do\nQ\n"); } - /** - * Renders a - * {@link RenderableImage}, - * applying a transform from image space into user space before drawing. - * The transformation from user space into device space is done with - * the current Transform in the Graphics2D. - * The specified transformation is applied to the image before the - * transform attribute in the Graphics2D context is applied. - * The rendering attributes applied include the Clip, - * Transform, and Composite attributes. Note - * that no rendering is done if the specified transform is - * noninvertible. - *

          - * Rendering hints set on the Graphics2D object might - * be used in rendering the RenderableImage. - * If explicit control is required over specific hints recognized by a - * specific RenderableImage, or if knowledge of which hints - * are used is required, then a RenderedImage should be - * obtained directly from the RenderableImage - * and rendered using - * {@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}. - * @param img the image to be rendered - * @param xform the transformation from image space into user space - * @see #transform - * @see #setTransform - * @see #setComposite - * @see #clip - * @see #setClip - * @see #drawRenderedImage - */ + /** {@inheritDoc} */ public void drawRenderableImage(RenderableImage img, AffineTransform xform) { - //NYI + //TODO Check if this is good enough + drawRenderedImage(img.createDefaultRendering(), xform); } /** -- cgit v1.2.3 From c4f0551dbf87d84fe955565231f6195d418b46a4 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 1 Feb 2008 14:58:30 +0000 Subject: AlphaRasterImage now knows how to deal with TYPE_INT Rasters. Streamlined image handling in Graphics2D. Support natively handling CCITT images in SVG images. Add fallback to device RGB if sRGB isn't set up as the default color space in PDF. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617512 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/AlphaRasterImage.java | 35 ++- .../fop/render/pdf/AbstractImageAdapter.java | 12 +- src/java/org/apache/fop/svg/PDFGraphics2D.java | 237 +++++++-------------- .../org/apache/fop/svg/PDFImageElementBridge.java | 36 ++-- 4 files changed, 133 insertions(+), 187 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/AlphaRasterImage.java b/src/java/org/apache/fop/pdf/AlphaRasterImage.java index be476bdb2..0b83cc3d6 100644 --- a/src/java/org/apache/fop/pdf/AlphaRasterImage.java +++ b/src/java/org/apache/fop/pdf/AlphaRasterImage.java @@ -22,6 +22,8 @@ package org.apache.fop.pdf; 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 @@ public class AlphaRasterImage implements PDFImage { 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} */ diff --git a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java index cd80a6797..d9fd614cc 100644 --- a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java +++ b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java @@ -59,6 +59,9 @@ public abstract class AbstractImageAdapter implements PDFImage { public AbstractImageAdapter(Image image, String key) { this.image = image; this.key = key; + if (log.isDebugEnabled()) { + log.debug("New ImageAdapter created for key: " + key); + } } /** {@inheritDoc} */ @@ -96,11 +99,16 @@ public abstract class AbstractImageAdapter implements PDFImage { pdfICCStream = cs.getICCStream(); } } else { - if (cs == null && "sRGB".equals(desc)) { + if (cs == null && desc.startsWith("sRGB")) { //It's the default sRGB profile which we mapped to DefaultRGB in PDFRenderer cs = doc.getResources().getColorSpace("DefaultRGB"); } - pdfICCStream = cs.getICCStream(); + if (cs != null) { + pdfICCStream = cs.getICCStream(); + } else { + //DefaultRGB hasn't been mapped to sRGB + //(that's the case with a plain PDFGraphics2D) + } } } if (doc.getProfile().getPDFAMode().isPDFA1LevelB()) { diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index fdc54b48f..864809ebe 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -41,7 +41,6 @@ import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; -import java.awt.image.DataBufferInt; import java.awt.image.DirectColorModel; import java.awt.image.ImageObserver; import java.awt.image.Raster; @@ -65,6 +64,7 @@ import org.apache.batik.gvt.PatternPaint; import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; import org.apache.xmlgraphics.image.loader.impl.ImageRendered; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; @@ -86,7 +86,6 @@ import org.apache.fop.pdf.PDFGState; import org.apache.fop.pdf.PDFImage; import org.apache.fop.pdf.PDFImageXObject; import org.apache.fop.pdf.PDFLink; -import org.apache.fop.pdf.PDFName; import org.apache.fop.pdf.PDFNumber; import org.apache.fop.pdf.PDFPattern; import org.apache.fop.pdf.PDFResourceContext; @@ -94,6 +93,7 @@ import org.apache.fop.pdf.PDFResources; import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFText; import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.pdf.ImageRawCCITTFaxAdapter; import org.apache.fop.render.pdf.ImageRawJPEGAdapter; import org.apache.fop.render.pdf.ImageRenderedAdapter; import org.apache.fop.util.ColorExt; @@ -143,10 +143,10 @@ public class PDFGraphics2D extends AbstractGraphics2D { protected int baseLevel = 0; /** - * The count of JPEG images added to document so they recieve + * The count of natively handled images added to document so they receive * unique keys. */ - protected int[] jpegCount = {0}; + protected int nativeCount = 0; /** * The current font information. @@ -232,7 +232,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { this.pageRef = g.pageRef; this.graphicsState = g.graphicsState; this.currentStream = g.currentStream; - this.jpegCount = g.jpegCount; + this.nativeCount = g.nativeCount; this.outputStream = g.outputStream; this.ovFontState = g.ovFontState; } @@ -401,44 +401,41 @@ public class PDFGraphics2D extends AbstractGraphics2D { } /** - * Add a JPEG image directly to the PDF document. - * This is used by the PDFImageElementBridge to draw a JPEG - * directly into the pdf document rather than converting the image into + * Add a natively handled image directly to the PDF document. + * This is used by the PDFImageElementBridge to draw a natively handled image + * (like JPEG or CCITT images) + * directly into the PDF document rather than converting the image into * a bitmap and increasing the size. * - * @param jpeg the jpeg image to draw + * @param image the image to draw * @param x the x position * @param y the y position * @param width the width to draw the image * @param height the height to draw the image */ - public void addJpegImage(ImageRawJPEG jpeg, float x, float y, + void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y, float width, float height) { preparePainting(); - // Need to include hash code as when invoked from FO you - // may have several 'independent' PDFGraphics2D so the - // count is not enough. - String key = "__AddJPEG_" + hashCode() + "_" + jpegCount[0]; - jpegCount[0]++; - PDFImage pdfimage = new ImageRawJPEGAdapter(jpeg, key); - PDFName imageName = this.pdfDoc.addImage(resourceContext, - pdfimage).getName(); - AffineTransform at = getTransform(); - double[] matrix = new double[6]; - at.getMatrix(matrix); - currentStream.write("q\n"); - if (!at.isIdentity()) { - concatMatrix(matrix); + String key = image.getInfo().getOriginalURI(); + if (key == null) { + // Need to include hash code as when invoked from FO you + // may have several 'independent' PDFGraphics2D so the + // count is not enough. + key = "__AddNative_" + hashCode() + "_" + nativeCount; + nativeCount++; } - Shape imclip = getClip(); - writeClip(imclip); - - currentStream.write("" + width + " 0 0 " - + (-height) + " " - + x + " " - + (y + height) + " cm\n" - + imageName + " Do\nQ\n"); - + + PDFImage pdfImage; + if (image instanceof ImageRawJPEG) { + pdfImage = new ImageRawJPEGAdapter((ImageRawJPEG)image, key); + } else if (image instanceof ImageRawCCITTFax) { + pdfImage = new ImageRawCCITTFaxAdapter((ImageRawCCITTFax)image, key); + } else { + throw new IllegalArgumentException( + "Unsupported Image subclass: " + image.getClass().getName()); + } + + PDFXObject xObject = this.pdfDoc.addImage(resourceContext, pdfImage); if (outputStream != null) { try { this.pdfDoc.output(outputStream); @@ -446,6 +443,10 @@ public class PDFGraphics2D extends AbstractGraphics2D { // ignore exception, will be thrown again later } } + + AffineTransform at = new AffineTransform(); + at.translate(x, y); + useXObject(xObject, at, width, height); } /** @@ -492,40 +493,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { BufferedImage.TYPE_INT_ARGB); } - /** - * Draws as much of the specified image as has already been scaled - * to fit inside the specified rectangle. - *

          - * The image is drawn inside the specified rectangle of this - * graphics context's coordinate space, and is scaled if - * necessary. Transparent pixels do not affect whatever pixels - * are already there. - *

          - * This method returns immediately in all cases, even if the - * entire image has not yet been scaled, dithered, and converted - * for the current output device. - * If the current output representation is not yet complete, then - * drawImage returns false. As more of - * the image becomes available, the process that draws the image notifies - * the image observer by calling its imageUpdate method. - *

          - * A scaled version of an image will not necessarily be - * available immediately just because an unscaled version of the - * image has been constructed for this output device. Each size of - * the image may be cached separately and generated from the original - * data in a separate image production sequence. - * @param img the specified image to be drawn. - * @param x the x coordinate. - * @param y the y coordinate. - * @param width the width of the rectangle. - * @param height the height of the rectangle. - * @param observer object to be notified as more of - * the image is converted. - * @return true if the image was drawn - * @see java.awt.Image - * @see java.awt.image.ImageObserver - * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) - */ + /** {@inheritDoc} */ public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { preparePainting(); @@ -533,8 +501,9 @@ public class PDFGraphics2D extends AbstractGraphics2D { // the pdf document. If so, we just reuse the reference; // otherwise we have to build a FopImage and add it to the pdf // document - PDFXObject imageInfo = pdfDoc.getXObject("TempImage:" + img.toString()); - if (imageInfo == null) { + String key = "TempImage:" + img.toString(); + PDFXObject xObject = pdfDoc.getXObject(key); + if (xObject == null) { // OK, have to build and add a PDF image Dimension size = new Dimension(width, height); @@ -553,92 +522,14 @@ public class PDFGraphics2D extends AbstractGraphics2D { } g.dispose(); - final byte[] result = new byte[buf.getWidth() * buf.getHeight() * 3 /*for RGB*/]; - byte[] mask = new byte[buf.getWidth() * buf.getHeight()]; - boolean hasMask = false; - //boolean binaryMask = true; - - Raster raster = buf.getData(); - DataBuffer bd = raster.getDataBuffer(); - - int count = 0; - int maskpos = 0; - int[] iarray; - int i, j, val, alpha; - switch (bd.getDataType()) { - case DataBuffer.TYPE_INT: - int[][] idata = ((DataBufferInt)bd).getBankData(); - for (i = 0; i < idata.length; i++) { - iarray = idata[i]; - for (j = 0; j < iarray.length; j++) { - val = iarray[j]; - alpha = val >>> 24; - mask[maskpos++] = (byte)(alpha & 0xFF); - if (alpha != 255) { - hasMask = true; - } - result[count++] = (byte)((val >> 16) & 0xFF); - result[count++] = (byte)((val >> 8) & 0xFF); - result[count++] = (byte)((val) & 0xFF); - } - } - break; - default: - // error - break; - } - String ref = null; - if (hasMask) { - // if the mask is binary then we could convert it into a bitmask - BitmapImage fopimg = new BitmapImage("TempImageMask:" - + img.toString(), buf.getWidth(), - buf.getHeight(), mask, null); - fopimg.setColorSpace(new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_GRAY)); - PDFImageXObject xobj = pdfDoc.addImage(resourceContext, fopimg); - ref = xobj.referencePDF(); - - if (outputStream != null) { - try { - this.pdfDoc.output(outputStream); - } catch (IOException ioe) { - // ignore exception, will be thrown again later - } - } - } else { - mask = null; - } - - BitmapImage fopimg = new BitmapImage("TempImage:" - + img.toString(), buf.getWidth(), - buf.getHeight(), result, ref); - imageInfo = pdfDoc.addImage(resourceContext, fopimg); - //int xObjectNum = imageInfo.getXNumber(); - - if (outputStream != null) { - try { - this.pdfDoc.output(outputStream); - } catch (IOException ioe) { - // ignore exception, will be thrown again later - } - } + xObject = addRenderedImage(key, buf); } else { - resourceContext.getPDFResources().addXObject(imageInfo); + resourceContext.getPDFResources().addXObject(xObject); } - // now do any transformation required and add the actual image - // placement instance - AffineTransform at = getTransform(); - double[] matrix = new double[6]; - at.getMatrix(matrix); - currentStream.write("q\n"); - if (!at.isIdentity()) { - concatMatrix(matrix); - } - Shape imclip = getClip(); - writeClip(imclip); - currentStream.write("" + width + " 0 0 " + (-height) + " " + x - + " " + (y + height) + " cm\n" - + imageInfo.getName() + " Do\nQ\n"); + AffineTransform at = new AffineTransform(); + at.translate(x, y); + useXObject(xObject, at, width, height); return true; } @@ -1342,18 +1233,24 @@ public class PDFGraphics2D extends AbstractGraphics2D { /** {@inheritDoc} */ public void drawRenderedImage(RenderedImage img, AffineTransform xform) { - preparePainting(); String key = "TempImage:" + img.toString(); + drawInnerRenderedImage(key, img, xform); + } + + /** {@inheritDoc} */ + public void drawInnerRenderedImage(String key, RenderedImage img, AffineTransform xform) { + preparePainting(); PDFXObject xObject = pdfDoc.getXObject(key); if (xObject == null) { - ImageInfo info = new ImageInfo(null, "image/unknown"); - ImageSize size = new ImageSize(img.getWidth(), img.getHeight(), 72); - info.setSize(size); - ImageRendered imgRend = new ImageRendered(info, img, null); - ImageRenderedAdapter adapter = new ImageRenderedAdapter(imgRend, key); - xObject = pdfDoc.addImage(resourceContext, adapter); + xObject = addRenderedImage(key, img); + } else { + resourceContext.getPDFResources().addXObject(xObject); } + useXObject(xObject, xform, img.getWidth(), img.getHeight()); + } + + private void useXObject(PDFXObject xObject, AffineTransform xform, float width, float height) { // now do any transformation required and add the actual image // placement instance currentStream.write("q\n"); @@ -1361,11 +1258,29 @@ public class PDFGraphics2D extends AbstractGraphics2D { Shape imclip = getClip(); writeClip(imclip); concatMatrix(xform); - currentStream.write("" + img.getWidth() + " 0 0 " + (-img.getHeight()) + " 0" - + " " + (img.getHeight()) + " cm\n" + String w = PDFNumber.doubleOut(width, DEC); + String h = PDFNumber.doubleOut(height, DEC); + currentStream.write("" + w + " 0 0 -" + h + " 0 " + h + " cm\n" + xObject.getName() + " Do\nQ\n"); } + private PDFXObject addRenderedImage(String key, RenderedImage img) { + ImageInfo info = new ImageInfo(null, "image/unknown"); + ImageSize size = new ImageSize(img.getWidth(), img.getHeight(), 72); + info.setSize(size); + ImageRendered imgRend = new ImageRendered(info, img, null); + ImageRenderedAdapter adapter = new ImageRenderedAdapter(imgRend, key); + PDFXObject xObject = pdfDoc.addImage(resourceContext, adapter); + if (outputStream != null) { + try { + this.pdfDoc.output(outputStream); + } catch (IOException ioe) { + // ignore exception, will be thrown again later + } + } + return xObject; + } + /** {@inheritDoc} */ public void drawRenderableImage(RenderableImage img, AffineTransform xform) { diff --git a/src/java/org/apache/fop/svg/PDFImageElementBridge.java b/src/java/org/apache/fop/svg/PDFImageElementBridge.java index a2542e86f..c3698b837 100644 --- a/src/java/org/apache/fop/svg/PDFImageElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFImageElementBridge.java @@ -39,6 +39,7 @@ import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; @@ -56,6 +57,7 @@ public class PDFImageElementBridge extends SVGImageElementBridge { private final ImageFlavor[] supportedFlavors = new ImageFlavor[] {ImageFlavor.RAW_JPEG, + ImageFlavor.RAW_CCITTFAX, ImageFlavor.GRAPHICS2D, ImageFlavor.XML_DOM}; /** @@ -90,9 +92,9 @@ public class PDFImageElementBridge extends SVGImageElementBridge { } } if (image instanceof ImageRawJPEG) { - ImageRawJPEG jpegImage = (ImageRawJPEG)image; - specializedNode = new PDFJpegNode(jpegImage, ctx, imageElement, purl); - + specializedNode = new LoaderImageNode(image, ctx, imageElement, purl); + } else if (image instanceof ImageRawCCITTFax) { + specializedNode = new LoaderImageNode(image, ctx, imageElement, purl); } else if (image instanceof ImageGraphics2D) { ImageGraphics2D g2dImage = (ImageGraphics2D)image; specializedNode = new Graphics2DNode(g2dImage); @@ -135,29 +137,29 @@ public class PDFImageElementBridge extends SVGImageElementBridge { /** - * A PDF jpeg node. - * This holds a jpeg image so that it can be drawn into + * An image node for natively handled Image instance. + * This holds a natively handled image so that it can be drawn into * the PDFGraphics2D. */ - public class PDFJpegNode extends AbstractGraphicsNode { + public class LoaderImageNode extends AbstractGraphicsNode { - private ImageRawJPEG jpeg; + private Image image; private BridgeContext ctx; private Element imageElement; private ParsedURL purl; private GraphicsNode origGraphicsNode = null; /** - * Create a new PDF JPEG node for drawing JPEG images - * into pdf graphics. - * @param j the JPEG image + * Create a new image node for drawing natively handled images + * into PDF graphics. + * @param image the JPEG image * @param ctx the bridge context * @param imageElement the SVG image element * @param purl the URL to the image */ - public PDFJpegNode(ImageRawJPEG j, BridgeContext ctx, + public LoaderImageNode(Image image, BridgeContext ctx, Element imageElement, ParsedURL purl) { - this.jpeg = j; + this.image = image; this.ctx = ctx; this.imageElement = imageElement; this.purl = purl; @@ -175,9 +177,9 @@ public class PDFImageElementBridge extends SVGImageElementBridge { float x = 0; float y = 0; try { - float width = jpeg.getSize().getWidthPx(); - float height = jpeg.getSize().getHeightPx(); - pdfg.addJpegImage(jpeg, x, y, width, height); + float width = image.getSize().getWidthPx(); + float height = image.getSize().getHeightPx(); + pdfg.addNativeImage(image, x, y, width, height); } catch (Exception e) { ctx.getUserAgent().displayError(e); } @@ -203,8 +205,8 @@ public class PDFImageElementBridge extends SVGImageElementBridge { /** {@inheritDoc} */ public Rectangle2D getPrimitiveBounds() { return new Rectangle2D.Double(0, 0, - jpeg.getSize().getWidthPx(), - jpeg.getSize().getHeightPx()); + image.getSize().getWidthPx(), + image.getSize().getHeightPx()); } /** {@inheritDoc} */ -- cgit v1.2.3 From 631864454a9b6300bb67a76d9d8eee030951ee69 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 1 Feb 2008 16:02:33 +0000 Subject: Move sRGB installation into the PDF library. That way it can be used in PDFDocumentGraphics2D, too (via AbstractImageAdapter). Ensures correct handling of sRGB images in PDFTranscoder. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617531 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/pdf/PDFICCBasedColorSpace.java | 59 ++++++++++++++++++++ .../fop/render/pdf/AbstractImageAdapter.java | 63 ++++++++++++---------- .../org/apache/fop/render/pdf/PDFRenderer.java | 19 +------ 3 files changed, 95 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFICCBasedColorSpace.java b/src/java/org/apache/fop/pdf/PDFICCBasedColorSpace.java index 7d17bb01f..e0cac0746 100644 --- a/src/java/org/apache/fop/pdf/PDFICCBasedColorSpace.java +++ b/src/java/org/apache/fop/pdf/PDFICCBasedColorSpace.java @@ -19,6 +19,13 @@ package org.apache.fop.pdf; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; + /** * Represents an ICCBased color space in PDF. */ @@ -93,4 +100,56 @@ public class PDFICCBasedColorSpace extends PDFObject implements PDFColorSpace { return sb.toString(); } + /** + * Sets sRGB as the DefaultRGB color space in the PDF document. + * @param pdfDoc the PDF document + * @return the newly installed color space object + */ + public static PDFICCBasedColorSpace setupsRGBAsDefaultRGBColorSpace(PDFDocument pdfDoc) { + PDFICCStream sRGBProfile = setupsRGBColorProfile(pdfDoc); + + //Map sRGB as default RGB profile for DeviceRGB + return pdfDoc.getFactory().makeICCBasedColorSpace(null, "DefaultRGB", sRGBProfile); + } + + /** + * Installs the sRGB color space in the PDF document. + * @param pdfDoc the PDF document + * @return the newly installed color space object + */ + public static PDFICCBasedColorSpace setupsRGBColorSpace(PDFDocument pdfDoc) { + PDFICCStream sRGBProfile = setupsRGBColorProfile(pdfDoc); + + //Map sRGB as default RGB profile for DeviceRGB + return pdfDoc.getFactory().makeICCBasedColorSpace(null, null, sRGBProfile); + } + + /** + * Sets up the sRGB color profile in the PDF document. It does so by trying to + * install a very small ICC profile (~4KB) instead of the very big one (~140KB) + * the Sun JVM uses. + * @param pdfDoc the PDF document + * @return the ICC stream with the sRGB profile + */ + public static PDFICCStream setupsRGBColorProfile(PDFDocument pdfDoc) { + ICC_Profile profile; + PDFICCStream sRGBProfile = pdfDoc.getFactory().makePDFICCStream(); + InputStream in = PDFDocument.class.getResourceAsStream("sRGB Color Space Profile.icm"); + if (in != null) { + try { + profile = ICC_Profile.getInstance(in); + } catch (IOException ioe) { + throw new RuntimeException( + "Unexpected IOException loading the sRGB profile: " + ioe.getMessage()); + } finally { + IOUtils.closeQuietly(in); + } + } else { + // Fallback: Use the sRGB profile from the JRE (about 140KB) + profile = ICC_Profile.getInstance(ColorSpace.CS_sRGB); + } + sRGBProfile.setColorSpace(profile, null); + return sRGBProfile; + } + } diff --git a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java index d9fd614cc..b676ad6d5 100644 --- a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java +++ b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java @@ -84,32 +84,7 @@ public abstract class AbstractImageAdapter implements PDFImage { ICC_Profile prof = image.getICCProfile(); PDFDeviceColorSpace pdfCS = toPDFColorSpace(getImageColorSpace()); if (prof != null) { - boolean defaultsRGB = ColorProfileUtil.isDefaultsRGB(prof); - String desc = ColorProfileUtil.getICCProfileDescription(prof); - if (log.isDebugEnabled()) { - log.debug("Image returns ICC profile: " + desc + ", default sRGB=" + defaultsRGB); - } - PDFICCBasedColorSpace cs = doc.getResources().getICCColorSpaceByProfileName(desc); - if (!defaultsRGB) { - if (cs == null) { - pdfICCStream = doc.getFactory().makePDFICCStream(); - pdfICCStream.setColorSpace(prof, pdfCS); - cs = doc.getFactory().makeICCBasedColorSpace(null, null, pdfICCStream); - } else { - pdfICCStream = cs.getICCStream(); - } - } else { - if (cs == null && desc.startsWith("sRGB")) { - //It's the default sRGB profile which we mapped to DefaultRGB in PDFRenderer - cs = doc.getResources().getColorSpace("DefaultRGB"); - } - if (cs != null) { - pdfICCStream = cs.getICCStream(); - } else { - //DefaultRGB hasn't been mapped to sRGB - //(that's the case with a plain PDFGraphics2D) - } - } + pdfICCStream = setupColorProfile(doc, prof, pdfCS); } if (doc.getProfile().getPDFAMode().isPDFA1LevelB()) { if (pdfCS != null @@ -119,10 +94,42 @@ public abstract class AbstractImageAdapter implements PDFImage { //See PDF/A-1, ISO 19005:1:2005(E), 6.2.3.3 //FOP is currently restricted to DeviceRGB if PDF/A-1 is active. throw new PDFConformanceException( - "PDF/A-1 does not allow mixing DeviceRGB and DeviceCMYK: " - + image.getInfo()); + "PDF/A-1 does not allow mixing DeviceRGB and DeviceCMYK: " + + image.getInfo()); + } + } + } + + private static PDFICCStream setupColorProfile(PDFDocument doc, + ICC_Profile prof, PDFDeviceColorSpace pdfCS) { + boolean defaultsRGB = ColorProfileUtil.isDefaultsRGB(prof); + String desc = ColorProfileUtil.getICCProfileDescription(prof); + if (log.isDebugEnabled()) { + log.debug("Image returns ICC profile: " + desc + ", default sRGB=" + defaultsRGB); + } + PDFICCBasedColorSpace cs = doc.getResources().getICCColorSpaceByProfileName(desc); + PDFICCStream pdfICCStream; + if (!defaultsRGB) { + if (cs == null) { + pdfICCStream = doc.getFactory().makePDFICCStream(); + pdfICCStream.setColorSpace(prof, pdfCS); + cs = doc.getFactory().makeICCBasedColorSpace(null, null, pdfICCStream); + } else { + pdfICCStream = cs.getICCStream(); } + } else { + if (cs == null && desc.startsWith("sRGB")) { + //It's the default sRGB profile which we mapped to DefaultRGB in PDFRenderer + cs = doc.getResources().getColorSpace("DefaultRGB"); + if (cs == null) { + //sRGB hasn't been set up for the PDF document + //so install but don't set to DefaultRGB + cs = PDFICCBasedColorSpace.setupsRGBColorSpace(doc); + } + } + pdfICCStream = cs.getICCStream(); } + return pdfICCStream; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 4d641517a..86c01f673 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -23,7 +23,6 @@ package org.apache.fop.render.pdf; import java.awt.Color; import java.awt.Point; import java.awt.Rectangle; -import java.awt.color.ColorSpace; import java.awt.color.ICC_Profile; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; @@ -391,24 +390,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { if (this.sRGBColorSpace != null) { return; } - ICC_Profile profile; - PDFICCStream sRGBProfile = pdfDoc.getFactory().makePDFICCStream(); - InputStream in = PDFDocument.class.getResourceAsStream("sRGB Color Space Profile.icm"); - if (in != null) { - try { - profile = ICC_Profile.getInstance(in); - } finally { - IOUtils.closeQuietly(in); - } - } else { - //Fallback: Use the sRGB profile from the JRE (about 140KB) - profile = ICC_Profile.getInstance(ColorSpace.CS_sRGB); - } - sRGBProfile.setColorSpace(profile, null); - //Map sRGB as default RGB profile for DeviceRGB - this.sRGBColorSpace = pdfDoc.getFactory().makeICCBasedColorSpace( - null, "DefaultRGB", sRGBProfile); + this.sRGBColorSpace = PDFICCBasedColorSpace.setupsRGBAsDefaultRGBColorSpace(pdfDoc); } private void addDefaultOutputProfile() throws IOException { -- cgit v1.2.3 From 1b95627f0d5a7c91aa9eca17f9edbef78c94be2a Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 1 Feb 2008 16:31:24 +0000 Subject: Add a note about color space overrides which currently aren't supported for natively handled images, yet. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617550 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/svg/PDFImageElementBridge.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/svg/PDFImageElementBridge.java b/src/java/org/apache/fop/svg/PDFImageElementBridge.java index c3698b837..0513c78bb 100644 --- a/src/java/org/apache/fop/svg/PDFImageElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFImageElementBridge.java @@ -79,6 +79,8 @@ public class PDFImageElementBridge extends SVGImageElementBridge { ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext); Image image = manager.getImage(info, supportedFlavors, sessionContext); + //TODO color profile overrides aren't handled, yet! + //ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx); AbstractGraphicsNode specializedNode = null; if (image instanceof ImageXMLDOM) { ImageXMLDOM xmlImage = (ImageXMLDOM)image; -- cgit v1.2.3 From af652eedd409e376e54cea88b4545ddb21b30e0c Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 1 Feb 2008 23:30:13 +0000 Subject: Bugzilla 44343: Fixed a bug when using relative (smaller/larger) font-sizes in combination with percentages. Percentages now resolved as per the spec (XSL-FO 1.1 7.9.4): "A percentage value specifies an absolute font size relative to the parent element's font-size." git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617708 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/fo/properties/FontSizePropertyMaker.java | 19 ++++++++++++++++--- status.xml | 4 ++++ 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java b/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java index 012a80b1a..c7124cc5f 100644 --- a/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java @@ -43,6 +43,19 @@ public class FontSizePropertyMaker super(propId); } + + /** {@inheritDoc} */ + public Property make(PropertyList propertyList, String value, FObj fo) throws PropertyException { + Property p = super.make(propertyList, value, fo); + if (p instanceof PercentLength) { + Property pp = propertyList.getFromParent(this.propId); + p = FixedLength.getInstance( + pp.getLength().getValue() * ((PercentLength)p).getPercentage() / 100, "mpt"); + } + return p; + } + + /** * {@inheritDoc} * Implements the parts of 7.8.4 relevant to relative font sizes @@ -52,12 +65,12 @@ public class FontSizePropertyMaker FObj fo) throws PropertyException { if (p.getEnum() == EN_LARGER || p.getEnum() == EN_SMALLER) { // get the corresponding property from parent - Property pp = propertyList.getFromParent(this.getPropId()); + Property pp = propertyList.getFromParent(this.propId); int baseFontSize = computeClosestAbsoluteFontSize(pp.getLength().getValue()); if (p.getEnum() == EN_LARGER) { - return new FixedLength((int)Math.round((baseFontSize * FONT_SIZE_GROWTH_FACTOR))); + return FixedLength.getInstance((int)Math.round((baseFontSize * FONT_SIZE_GROWTH_FACTOR)), "mpt"); } else { - return new FixedLength((int)Math.round((baseFontSize / FONT_SIZE_GROWTH_FACTOR))); + return FixedLength.getInstance((int)Math.round((baseFontSize / FONT_SIZE_GROWTH_FACTOR)), "mpt"); } } return super.convertProperty(p, propertyList, fo); diff --git a/status.xml b/status.xml index f8f8ace5a..e03893424 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Fixed a bug when using relative font-size (smaller/larger) in combination + with percentages. + Bugfix for handling of optional tables in subset TrueType fonts. This bug caused errors in various PDF viewers. -- cgit v1.2.3 From 3136ea6b046979737260a49fe438a0c9600e0281 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 2 Feb 2008 00:06:29 +0000 Subject: Minor cleanup/improvement: - FontSizePropertyMaker: remove redundant casts (FixedLength already casts the doubles internally) - FixedLength: reduce visibility of 'fishy' convert() method (not used anywhere else) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617716 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/properties/FixedLength.java | 30 ++++++---------------- .../fop/fo/properties/FontSizePropertyMaker.java | 13 +++++++--- 2 files changed, 18 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/FixedLength.java b/src/java/org/apache/fop/fo/properties/FixedLength.java index 2c497094f..28206a12a 100644 --- a/src/java/org/apache/fop/fo/properties/FixedLength.java +++ b/src/java/org/apache/fop/fo/properties/FixedLength.java @@ -69,7 +69,7 @@ public final class FixedLength extends LengthProperty { * @param dvalue quantity of input units * @param unit input unit specifier (in, cm, etc.) */ - protected void convert(double dvalue, String unit) { + private void convert(double dvalue, String unit) { // TODO: the whole routine smells fishy. int assumedResolution = 1; // points/pixel = 72dpi @@ -107,30 +107,22 @@ public final class FixedLength extends LengthProperty { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getValue() { return millipoints; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getValue(PercentBaseContext context) { return millipoints; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public double getNumericValue() { return millipoints; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public double getNumericValue(PercentBaseContext context) { return millipoints; } @@ -143,16 +135,12 @@ public final class FixedLength extends LengthProperty { return true; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String toString() { return millipoints + "mpt"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean equals(Object obj) { if (obj instanceof FixedLength) { return (((FixedLength)obj).millipoints == this.millipoints); @@ -161,9 +149,7 @@ public final class FixedLength extends LengthProperty { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int hashCode() { return millipoints; } diff --git a/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java b/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java index c7124cc5f..acc02dc13 100644 --- a/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java @@ -44,7 +44,12 @@ public class FontSizePropertyMaker } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * Contrary to basic lengths, percentages for font-size can be resolved + * here already: if the property evaluates to a {@link PercentLength}, + * it is immediately replaced by the resolved {@link FixedLength}. + */ public Property make(PropertyList propertyList, String value, FObj fo) throws PropertyException { Property p = super.make(propertyList, value, fo); if (p instanceof PercentLength) { @@ -68,9 +73,11 @@ public class FontSizePropertyMaker Property pp = propertyList.getFromParent(this.propId); int baseFontSize = computeClosestAbsoluteFontSize(pp.getLength().getValue()); if (p.getEnum() == EN_LARGER) { - return FixedLength.getInstance((int)Math.round((baseFontSize * FONT_SIZE_GROWTH_FACTOR)), "mpt"); + return FixedLength.getInstance( + Math.round(baseFontSize * FONT_SIZE_GROWTH_FACTOR), "mpt"); } else { - return FixedLength.getInstance((int)Math.round((baseFontSize / FONT_SIZE_GROWTH_FACTOR)), "mpt"); + return FixedLength.getInstance( + Math.round(baseFontSize / FONT_SIZE_GROWTH_FACTOR), "mpt"); } } return super.convertProperty(p, propertyList, fo); -- cgit v1.2.3 From 6bc6210d90b3c1af0162bb407598cdf5b13a08b4 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 2 Feb 2008 15:13:40 +0000 Subject: Further cleanup/refinement of FixedLength: * improve consistency in use of the PropertyCache remove public constructor -> replaced by getInstance() in a handful of classes * added a sourceResolution parameter to getInstance() and the private constructor to allow better handling of device-dependent units (px) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617812 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/ExternalGraphic.java | 40 +++---- .../fo/properties/BorderWidthPropertyMaker.java | 2 +- .../org/apache/fop/fo/properties/FixedLength.java | 115 ++++++++++++--------- .../fop/fo/properties/FontSizePropertyMaker.java | 6 +- .../fop/fo/properties/IndentPropertyMaker.java | 6 +- .../fop/fo/properties/LengthRangeProperty.java | 8 +- 6 files changed, 91 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java index dd45f585c..03229e4c2 100644 --- a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java +++ b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java @@ -37,7 +37,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.FixedLength; /** - * Class modelling the fo:external-graphic object. + * Class modelling the + * fo:external-graphic object. * This FO node handles the external graphic. It creates an image * inline area that can be added to the area tree. */ @@ -63,9 +64,7 @@ public class ExternalGraphic extends AbstractGraphics { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); src = pList.get(PR_SRC).getString(); @@ -87,15 +86,14 @@ public class ExternalGraphic extends AbstractGraphics { this.intrinsicHeight = info.getSize().getHeightMpt(); int baseline = info.getSize().getBaselinePositionFromBottom(); if (baseline != 0) { - this.intrinsicAlignmentAdjust = new FixedLength(-baseline); + this.intrinsicAlignmentAdjust + = FixedLength.getInstance(-baseline); } } //TODO Report to caller so he can decide to throw an exception } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().image(this); @@ -103,23 +101,19 @@ public class ExternalGraphic extends AbstractGraphics { /** * {@inheritDoc} - * XSL Content Model: empty + *
          XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { invalidChildError(loc, nsURI, localName); } - /** - * @return the "src" property. - */ + /** @return the "src" property */ public String getSrc() { return src; } - /** - * @return Get the resulting URL based on the src property. - */ + /** @return Get the resulting URL based on the src property */ public String getURL() { return url; } @@ -129,30 +123,22 @@ public class ExternalGraphic extends AbstractGraphics { return "external-graphic"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_EXTERNAL_GRAPHIC; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getIntrinsicWidth() { return this.intrinsicWidth; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getIntrinsicHeight() { return this.intrinsicHeight; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Length getIntrinsicAlignmentAdjust() { return this.intrinsicAlignmentAdjust; } diff --git a/src/java/org/apache/fop/fo/properties/BorderWidthPropertyMaker.java b/src/java/org/apache/fop/fo/properties/BorderWidthPropertyMaker.java index b828de285..86986bca5 100644 --- a/src/java/org/apache/fop/fo/properties/BorderWidthPropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/BorderWidthPropertyMaker.java @@ -63,7 +63,7 @@ public class BorderWidthPropertyMaker extends LengthProperty.Maker { // Calculate the values as described in 7.7.20. Property style = propertyList.get(borderStyleId); if (style.getEnum() == Constants.EN_NONE) { - return new FixedLength(0); + return FixedLength.getInstance(0); } return p; } diff --git a/src/java/org/apache/fop/fo/properties/FixedLength.java b/src/java/org/apache/fop/fo/properties/FixedLength.java index 28206a12a..fbd235b30 100644 --- a/src/java/org/apache/fop/fo/properties/FixedLength.java +++ b/src/java/org/apache/fop/fo/properties/FixedLength.java @@ -32,18 +32,40 @@ public final class FixedLength extends LengthProperty { private int millipoints; /** - * Set the length given a number of units and a unit name. + * Set the length given a number of units, a unit name and + * an assumed resolution (used in case the units are pixels) * - * @param numUnits quantity of input units - * @param units input unit specifier (in, cm, etc.) + * @param numUnits quantity of input units + * @param units input unit specifier + * @param res input/source resolution */ - private FixedLength(double numUnits, String units) { - convert(numUnits, units); + private FixedLength(double numUnits, String units, float res) { + this.millipoints = convert(numUnits, units, res); } /** - * Return the cached FixedLength instance corresponding + * Return the cached {@link FixedLength} instance corresponding + * to the computed value in base-units (millipoints). + * + * @param numUnits quantity of input units + * @param units input unit specifier + * @param sourceResolution input/source resolution (= ratio of pixels per pt) + * @return the canonical FixedLength instance corresponding + * to the given number of units and unit specifier + * in the given resolution + */ + public static FixedLength getInstance(double numUnits, + String units, + float sourceResolution) { + return (FixedLength)cache.fetch( + new FixedLength(numUnits, units, sourceResolution)); + + } + + /** + * Return the cached {@link FixedLength} instance corresponding * to the computed value + * This method assumes a source-resolution of 1 (1px = 1pt) * * @param numUnits input units * @param units unit specifier @@ -52,59 +74,56 @@ public final class FixedLength extends LengthProperty { */ public static FixedLength getInstance(double numUnits, String units) { - return (FixedLength) cache.fetch(new FixedLength(numUnits, units)); + return getInstance(numUnits, units, 1.0f); } /** - * @param baseUnits the length as a number of base units (millipoints) + * Return the cached {@link FixedLength} instance corresponding + * to the computed value. + * This method assumes 'millipoints' (non-standard) as units, + * and an implied source-resolution of 1 (1px = 1pt). + * + * @param numUnits input units + * @return the canonical FixedLength instance corresponding + * to the given number of units and unit specifier */ - public FixedLength(int baseUnits) { - millipoints = baseUnits; + public static FixedLength getInstance(double numUnits) { + return getInstance(numUnits, "mpt", 1.0f); + } - + /** * Convert the given length to a dimensionless integer representing * a whole number of base units (milli-points). + * * @param dvalue quantity of input units * @param unit input unit specifier (in, cm, etc.) + * @param res the input/source resolution (in case the unit spec is "px") */ - private void convert(double dvalue, String unit) { - // TODO: the whole routine smells fishy. + private static int convert(double dvalue, String unit, float res) { + // TODO: Maybe this method has a better place in org.apache.fop.util.UnitConv?. - int assumedResolution = 1; // points/pixel = 72dpi - - if (unit.equals("in")) { - dvalue = dvalue * 72; - } else if (unit.equals("cm")) { - dvalue = dvalue * 28.3464567; - } else if (unit.equals("mm")) { - dvalue = dvalue * 2.83464567; - } else if (unit.equals("pt")) { - // Do nothing. - // dvalue = dvalue; - } else if (unit.equals("mpt")) { //mpt is non-standard!!! mpt=millipoints - // TODO: this seems to be wrong. - // Do nothing. - // dvalue = dvalue; - } else if (unit.equals("pc")) { - dvalue = dvalue * 12; - /* - * } else if (unit.equals("em")) { - * dvalue = dvalue * fontsize; - */ - } else if (unit.equals("px")) { - // TODO: get resolution from user agent? - dvalue = dvalue * assumedResolution; - } else { - dvalue = 0; - log.error("Unknown length unit '" + unit + "'"); - } - if (unit.equals("mpt")) { - millipoints = (int)dvalue; + if ("px".equals(unit)) { + //device-dependent units, take the resolution into account + dvalue *= (res * 1000); } else { - millipoints = (int)(dvalue * 1000); + if ("in".equals(unit)) { + dvalue *= 72000; + } else if ("cm".equals(unit)) { + dvalue *= 28346.4567; + } else if ("mm".equals(unit)) { + dvalue *= 2834.64567; + } else if ("pt".equals(unit)) { + dvalue *= 1000; + } else if ("pc".equals(unit)) { + dvalue *= 12000; + } else if (!"mpt".equals(unit)) { + dvalue = 0; + log.error("Unknown length unit '" + unit + "'"); + } } + return (int)dvalue; } /** {@inheritDoc} */ @@ -128,7 +147,7 @@ public final class FixedLength extends LengthProperty { } /** - * Return true since FixedLength are always absolute. + * Return true since a FixedLength is always absolute. * {@inheritDoc} */ public boolean isAbsolute() { @@ -142,11 +161,13 @@ public final class FixedLength extends LengthProperty { /** {@inheritDoc} */ public boolean equals(Object obj) { + if (this == obj) { + return true; + } if (obj instanceof FixedLength) { return (((FixedLength)obj).millipoints == this.millipoints); - } else { - return false; } + return false; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java b/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java index acc02dc13..b641b2abf 100644 --- a/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/FontSizePropertyMaker.java @@ -55,7 +55,7 @@ public class FontSizePropertyMaker if (p instanceof PercentLength) { Property pp = propertyList.getFromParent(this.propId); p = FixedLength.getInstance( - pp.getLength().getValue() * ((PercentLength)p).getPercentage() / 100, "mpt"); + pp.getLength().getValue() * ((PercentLength)p).getPercentage() / 100); } return p; } @@ -74,10 +74,10 @@ public class FontSizePropertyMaker int baseFontSize = computeClosestAbsoluteFontSize(pp.getLength().getValue()); if (p.getEnum() == EN_LARGER) { return FixedLength.getInstance( - Math.round(baseFontSize * FONT_SIZE_GROWTH_FACTOR), "mpt"); + Math.round(baseFontSize * FONT_SIZE_GROWTH_FACTOR)); } else { return FixedLength.getInstance( - Math.round(baseFontSize / FONT_SIZE_GROWTH_FACTOR), "mpt"); + Math.round(baseFontSize / FONT_SIZE_GROWTH_FACTOR)); } } return super.convertProperty(p, propertyList, fo); diff --git a/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java b/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java index ebc1b80f0..b29caba04 100644 --- a/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java @@ -108,7 +108,7 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { //Margin is used Numeric margin = propertyList.get(marginProp).getNumeric(); - Numeric v = new FixedLength(0); + Numeric v = FixedLength.getInstance(0, "mpt"); if (!propertyList.getFObj().generatesReferenceAreas()) { // The inherited_value_of([start|end]-indent) v = NumericOp.addition(v, propertyList.getInherited(baseMaker.propId).getNumeric()); @@ -173,7 +173,7 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { if (isInherited(propertyList) || !marginNearest) { return null; } else { - return new FixedLength(0); + return FixedLength.getInstance(0); } } else { return indent; @@ -182,7 +182,7 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { //Margin is used Numeric margin = propertyList.get(marginProp).getNumeric(); - Numeric v = new FixedLength(0); + Numeric v = FixedLength.getInstance(0); if (isInherited(propertyList)) { // The inherited_value_of([start|end]-indent) v = NumericOp.addition(v, propertyList.getInherited(baseMaker.propId).getNumeric()); diff --git a/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java b/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java index acce6f564..966f51a51 100644 --- a/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java +++ b/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java @@ -65,9 +65,7 @@ public class LengthRangeProperty extends Property implements CompoundDatatype { || (len.isAbsolute() && len.getValue() < 0)); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Property convertProperty(Property p, PropertyList propertyList, FObj fo) throws PropertyException { @@ -84,7 +82,7 @@ public class LengthRangeProperty extends Property implements CompoundDatatype { log.warn(FObj.decorateWithContextInfo( "Replaced negative value (" + len + ") for " + getName() + " with 0mpt", fo)); - p = new FixedLength(0); + p = FixedLength.getInstance(0); } } } @@ -107,7 +105,7 @@ public class LengthRangeProperty extends Property implements CompoundDatatype { log.warn("Replaced negative value (" + len + ") for " + getName() + " with 0mpt"); val.setComponent(subpropertyId, - new FixedLength(0), false); + FixedLength.getInstance(0), false); return baseProperty; } } -- cgit v1.2.3 From 9ed3838a87bc617a7119df4eee47ea6f6f27bc19 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 2 Feb 2008 22:11:12 +0000 Subject: Further improvement in FixedLength: * added a special ZERO_FIXED_LENGTH instance * store only non-zero values in the PropertyCache git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617907 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/properties/BorderWidthPropertyMaker.java | 2 +- src/java/org/apache/fop/fo/properties/FixedLength.java | 9 ++++++++- src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java | 6 +++--- src/java/org/apache/fop/fo/properties/LengthRangeProperty.java | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/BorderWidthPropertyMaker.java b/src/java/org/apache/fop/fo/properties/BorderWidthPropertyMaker.java index 86986bca5..341baca1a 100644 --- a/src/java/org/apache/fop/fo/properties/BorderWidthPropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/BorderWidthPropertyMaker.java @@ -63,7 +63,7 @@ public class BorderWidthPropertyMaker extends LengthProperty.Maker { // Calculate the values as described in 7.7.20. Property style = propertyList.get(borderStyleId); if (style.getEnum() == Constants.EN_NONE) { - return FixedLength.getInstance(0); + return FixedLength.ZERO_FIXED_LENGTH; } return p; } diff --git a/src/java/org/apache/fop/fo/properties/FixedLength.java b/src/java/org/apache/fop/fo/properties/FixedLength.java index fbd235b30..7c4344b53 100644 --- a/src/java/org/apache/fop/fo/properties/FixedLength.java +++ b/src/java/org/apache/fop/fo/properties/FixedLength.java @@ -29,6 +29,9 @@ public final class FixedLength extends LengthProperty { /** cache holding all canonical FixedLength instances */ private static final PropertyCache cache = new PropertyCache(); + /** canonical zero-length instance */ + public static final FixedLength ZERO_FIXED_LENGTH = new FixedLength(0, "mpt", 1.0f); + private int millipoints; /** @@ -57,8 +60,12 @@ public final class FixedLength extends LengthProperty { public static FixedLength getInstance(double numUnits, String units, float sourceResolution) { - return (FixedLength)cache.fetch( + if (numUnits == 0.0) { + return ZERO_FIXED_LENGTH; + } else { + return (FixedLength)cache.fetch( new FixedLength(numUnits, units, sourceResolution)); + } } diff --git a/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java b/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java index b29caba04..75ecb9d24 100644 --- a/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java @@ -108,7 +108,7 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { //Margin is used Numeric margin = propertyList.get(marginProp).getNumeric(); - Numeric v = FixedLength.getInstance(0, "mpt"); + Numeric v = FixedLength.ZERO_FIXED_LENGTH; if (!propertyList.getFObj().generatesReferenceAreas()) { // The inherited_value_of([start|end]-indent) v = NumericOp.addition(v, propertyList.getInherited(baseMaker.propId).getNumeric()); @@ -173,7 +173,7 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { if (isInherited(propertyList) || !marginNearest) { return null; } else { - return FixedLength.getInstance(0); + return FixedLength.ZERO_FIXED_LENGTH; } } else { return indent; @@ -182,7 +182,7 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { //Margin is used Numeric margin = propertyList.get(marginProp).getNumeric(); - Numeric v = FixedLength.getInstance(0); + Numeric v = FixedLength.ZERO_FIXED_LENGTH; if (isInherited(propertyList)) { // The inherited_value_of([start|end]-indent) v = NumericOp.addition(v, propertyList.getInherited(baseMaker.propId).getNumeric()); diff --git a/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java b/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java index 966f51a51..aeab37972 100644 --- a/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java +++ b/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java @@ -82,7 +82,7 @@ public class LengthRangeProperty extends Property implements CompoundDatatype { log.warn(FObj.decorateWithContextInfo( "Replaced negative value (" + len + ") for " + getName() + " with 0mpt", fo)); - p = FixedLength.getInstance(0); + p = FixedLength.ZERO_FIXED_LENGTH; } } } @@ -105,7 +105,7 @@ public class LengthRangeProperty extends Property implements CompoundDatatype { log.warn("Replaced negative value (" + len + ") for " + getName() + " with 0mpt"); val.setComponent(subpropertyId, - FixedLength.getInstance(0), false); + FixedLength.ZERO_FIXED_LENGTH, false); return baseProperty; } } -- cgit v1.2.3 From 8e49549a9f59b5ee87a1c060fa9801916adf153d Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 2 Feb 2008 22:18:30 +0000 Subject: Slight correction for pixel-values: pass the ratio of pixels-per-point into FixedLength.getInstance() git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617909 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/expr/PropertyParser.java | 31 +++++++++++++--------- .../apache/fop/fo/properties/LengthProperty.java | 24 ++++++----------- 2 files changed, 27 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/PropertyParser.java b/src/java/org/apache/fop/fo/expr/PropertyParser.java index 6dcbb0b0a..d8f45790e 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyParser.java +++ b/src/java/org/apache/fop/fo/expr/PropertyParser.java @@ -19,7 +19,6 @@ package org.apache.fop.fo.expr; -import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.Numeric; import org.apache.fop.datatypes.PercentBase; import org.apache.fop.fo.properties.ColorProperty; @@ -266,8 +265,8 @@ public final class PropertyParser extends PropertyTokenizer { * Get the length base value object from the Maker. If null, then * this property can't have % values. Treat it as a real number. */ - double pcval = new Double(currentTokenValue.substring(0, - currentTokenValue.length() - 1)).doubleValue() / 100.0; + double pcval = Double.parseDouble( + currentTokenValue.substring(0, currentTokenValue.length() - 1)) / 100.0; PercentBase pcBase = this.propInfo.getPercentBase(); if (pcBase != null) { if (pcBase.getDimension() == 0) { @@ -287,22 +286,30 @@ public final class PropertyParser extends PropertyTokenizer { // A number plus a valid unit name. int numLen = currentTokenValue.length() - currentUnitLength; String unitPart = currentTokenValue.substring(numLen); - Double numPart = new Double(currentTokenValue.substring(0, - numLen)); - if (unitPart.equals(RELUNIT)) { + double numPart = Double.parseDouble(currentTokenValue.substring(0, numLen)); + if (RELUNIT.equals(unitPart)) { prop = (Property) NumericOp.multiply( - NumberProperty.getInstance(numPart.doubleValue()), + NumberProperty.getInstance(numPart), propInfo.currentFontSize()); } else { - prop = FixedLength.getInstance(numPart.doubleValue(), unitPart); + if ("px".equals(unitPart)) { + //pass the ratio between source-resolution and + //the default resolution of 72dpi + prop = FixedLength.getInstance( + numPart, unitPart, + propInfo.getPropertyList().getFObj() + .getUserAgent().getSourceResolution() / 72.0f); + } else { + //use default resolution of 72dpi + prop = FixedLength.getInstance(numPart, unitPart); + } } break; case TOK_COLORSPEC: - FOUserAgent ua = (propInfo == null) - ? null - : (propInfo.getFO() == null ? null : propInfo.getFO().getUserAgent()); - prop = ColorProperty.getInstance(ua, currentTokenValue); + prop = ColorProperty.getInstance( + propInfo.getPropertyList().getFObj().getUserAgent(), + currentTokenValue); break; case TOK_FUNCTION_LPAR: diff --git a/src/java/org/apache/fop/fo/properties/LengthProperty.java b/src/java/org/apache/fop/fo/properties/LengthProperty.java index 7e7b37e06..495e8d8ea 100644 --- a/src/java/org/apache/fop/fo/properties/LengthProperty.java +++ b/src/java/org/apache/fop/fo/properties/LengthProperty.java @@ -45,9 +45,7 @@ public abstract class LengthProperty extends Property super(propId); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Property convertProperty(Property p, PropertyList propertyList, FObj fo) throws PropertyException { @@ -59,7 +57,9 @@ public abstract class LengthProperty extends Property } if (p instanceof NumberProperty) { //Assume pixels (like in HTML) when there's no unit - return FixedLength.getInstance(p.getNumeric().getNumericValue(), "px"); + return FixedLength.getInstance( + p.getNumeric().getNumericValue(), "px", + propertyList.getFObj().getUserAgent().getSourceResolution() / 72.0f); } Length val = p.getLength(); if (val != null) { @@ -87,30 +87,22 @@ public abstract class LengthProperty extends Property return 0.0; } - /** - * @return the numeric dimension. Length always a dimension of 1. - */ + /** @return the numeric dimension. Length always a dimension of 1 */ public int getDimension() { return 1; } - /** - * @return this.length cast as a Numeric - */ + /** @return this.length cast as a Numeric */ public Numeric getNumeric() { return this; } - /** - * @return this.length - */ + /** @return this.length */ public Length getLength() { return this; } - /** - * @return this.length cast as an Object - */ + /** @return this.length cast as an Object */ public Object getObject() { return this; } -- cgit v1.2.3 From bc7583143625a86bdfd159058fa5b2762f2b64c2 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 3 Feb 2008 12:05:49 +0000 Subject: Added very basic parsing for the xml:lang shorthand. No validation of the specified value, but the language and country properties now do take the shorthand into account to determine their value. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617976 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 8 +-- src/java/org/apache/fop/fo/FOPropertyMapping.java | 6 ++- src/java/org/apache/fop/fo/PropertyList.java | 6 ++- .../fop/fo/properties/XMLLangShorthandParser.java | 61 ++++++++++++++++++++++ status.xml | 3 ++ .../testcases/xml-lang_shorthand-expansion.fo | 35 +++++++++++++ 6 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java create mode 100644 test/fotree/testcases/xml-lang_shorthand-expansion.fo (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 4b6dc024f..27ca74a63 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -1223,7 +1223,7 @@ yes

          yes    
          @@ -5612,9 +5612,9 @@ no no - no   + yes [dev] Very basic parsing; no validation of the specified value.

          XSL-FO Core Function Library Support Table (§5.10)

          diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 695eddc07..434d4acaf 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -66,6 +66,7 @@ import org.apache.fop.fo.properties.TextDecorationProperty; import org.apache.fop.fo.properties.ToBeImplementedProperty; import org.apache.fop.fo.properties.VerticalAlignShorthandParser; import org.apache.fop.fo.properties.WhiteSpaceShorthandParser; +import org.apache.fop.fo.properties.XMLLangShorthandParser; /** * This class creates and returns an array of Property.Maker instances @@ -1060,12 +1061,14 @@ public final class FOPropertyMapping implements Constants { m = new StringProperty.Maker(PR_COUNTRY); m.setInherited(true); m.setDefault("none"); + m.addShorthand(s_generics[PR_XML_LANG]); addPropertyMaker("country", m); // language m = new StringProperty.Maker(PR_LANGUAGE); m.setInherited(true); m.setDefault("none"); + m.addShorthand(s_generics[PR_XML_LANG]); addPropertyMaker("language", m); // script @@ -2722,9 +2725,10 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("white-space", m); // xml:lang - m = new ToBeImplementedProperty.Maker(PR_XML_LANG); + m = new StringProperty.Maker(PR_XML_LANG); m.setInherited(true); m.setDefault(""); + m.setDatatypeParser(new XMLLangShorthandParser()); addPropertyMaker("xml:lang", m); } diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java index 1de74e2f0..3d050efed 100644 --- a/src/java/org/apache/fop/fo/PropertyList.java +++ b/src/java/org/apache/fop/fo/PropertyList.java @@ -310,11 +310,13 @@ public abstract class PropertyList { String attributeNS; FopFactory factory = getFObj().getUserAgent().getFactory(); for (int i = 0; i < attributes.getLength(); i++) { - /* convert all attributes with the same namespace as the fo element for this fObj */ + /* convert all attributes with the same namespace as the fo element + * the "xml:lang" property is a special case */ attributeNS = attributes.getURI(i); attributeName = attributes.getQName(i); attributeValue = attributes.getValue(i); - if (attributeNS == null || attributeNS.length() == 0) { + if (attributeNS == null || attributeNS.length() == 0 + || "xml:lang".equals(attributeName)) { convertAttributeToProperty(attributes, attributeName, attributeValue); } else if (!factory.isNamespaceIgnored(attributeNS)) { ElementMapping mapping = factory.getElementMappingRegistry().getElementMapping( diff --git a/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java b/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java new file mode 100644 index 000000000..69ca372e5 --- /dev/null +++ b/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +/* $Id:$ */ + +package org.apache.fop.fo.properties; + +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.expr.PropertyException; + +public class XMLLangShorthandParser extends GenericShorthandParser { + + private static final char HYPHEN_MINUS = '-'; + + /** {@inheritDoc} */ + public Property getValueForProperty(int propId, + Property property, + PropertyMaker maker, + PropertyList propertyList) + throws PropertyException { + + String shorthandValue = property.getString(); + int hyphenIndex = shorthandValue.indexOf(HYPHEN_MINUS); + if (propId == Constants.PR_LANGUAGE) { + if (hyphenIndex == -1) { + /* only language specified; use the whole property */ + return property; + } else { + /* use only the primary tag */ + return StringProperty.getInstance( + shorthandValue.substring(0, hyphenIndex)); + } + } else if (propId == Constants.PR_COUNTRY) { + if (hyphenIndex != -1) { + int nextHyphenIndex = shorthandValue.indexOf(HYPHEN_MINUS, hyphenIndex + 1); + if (nextHyphenIndex != -1) { + return StringProperty.getInstance( + shorthandValue.substring(hyphenIndex + 1, nextHyphenIndex)); + } else { + return StringProperty.getInstance( + shorthandValue.substring(hyphenIndex + 1)); + } + } + } + return null; + } +} diff --git a/status.xml b/status.xml index e03893424..4615f42d0 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Added very basic parsing for the xml:lang shorthand. + Fixed a bug when using relative font-size (smaller/larger) in combination with percentages. diff --git a/test/fotree/testcases/xml-lang_shorthand-expansion.fo b/test/fotree/testcases/xml-lang_shorthand-expansion.fo new file mode 100644 index 000000000..ed8c13d8f --- /dev/null +++ b/test/fotree/testcases/xml-lang_shorthand-expansion.fo @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + Block 1 + + + + + -- cgit v1.2.3 From 380ae4dae1e2e01e26bbf09f155b40ba199afb84 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 3 Feb 2008 14:11:40 +0000 Subject: Bugzilla 43705: Fixed a bug when the rgb-icc() function was used before the fo:declarations, or in documents without fo:declarations. Function now correctly (?) reverts to the sRGB fallback in those cases. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@617989 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/expr/ICCColorFunction.java | 30 +++++++++++++++++----- status.xml | 5 ++++ 2 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java index ca66aac27..c254f1516 100644 --- a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java @@ -19,6 +19,7 @@ package org.apache.fop.fo.expr; import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.datatypes.PercentBase; import org.apache.fop.fo.pagination.ColorProfile; import org.apache.fop.fo.pagination.Declarations; import org.apache.fop.fo.properties.ColorProperty; @@ -38,6 +39,11 @@ class ICCColorFunction extends FunctionBase { return -4; } + /** {@inheritDoc} */ + public PercentBase getPercentBase() { + return new RGBColorFunction.RGBPercentBase(); + } + /** {@inheritDoc} */ public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { @@ -46,12 +52,24 @@ class ICCColorFunction extends FunctionBase { // Map color profile NCNAME to src from declarations/color-profile element String colorProfileName = args[3].getString(); Declarations decls = pInfo.getFO().getRoot().getDeclarations(); - ColorProfile cp = decls.getColorProfile(colorProfileName); - if (cp == null) { - PropertyException pe = new PropertyException("The " + colorProfileName - + " color profile was not declared"); - pe.setPropertyInfo(pInfo); - throw pe; + ColorProfile cp = null; + if (decls == null) { + //function used in a color-specification + //on a FO occurring: + //a) before the fo:declarations, + //b) or in a document without fo:declarations? + //=> return the sRGB fallback + Property[] rgbArgs = new Property[3]; + System.arraycopy(args, 0, rgbArgs, 0, 3); + return new RGBColorFunction().eval(rgbArgs, pInfo); + } else { + cp = decls.getColorProfile(colorProfileName); + if (cp == null) { + PropertyException pe = new PropertyException("The " + colorProfileName + + " color profile was not declared"); + pe.setPropertyInfo(pInfo); + throw pe; + } } String src = cp.getSrc(); diff --git a/status.xml b/status.xml index 4615f42d0..3cc0f5b46 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,11 @@ + + Fixed a bug when the rgb-icc() function was used either before the fo:declarations, + or in documents without a fo:declarations node. In such cases, the sRGB fallback + is now used to avoid an ugly NullPointerException. + Added very basic parsing for the xml:lang shorthand. -- cgit v1.2.3 From c94bd88c7c3395bb625dbb156639024424641abd Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 5 Feb 2008 12:34:56 +0000 Subject: Change PDFPage to use PDFDictionary in order to make it possible to better set MediaBox/TrimBox/BleedBox. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@618626 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFArray.java | 14 +++ src/java/org/apache/fop/pdf/PDFPage.java | 129 ++++++++------------- .../org/apache/fop/pdf/PDFResourceContext.java | 28 ++--- .../org/apache/fop/pdf/TransitionDictionary.java | 35 +----- 4 files changed, 73 insertions(+), 133 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFArray.java b/src/java/org/apache/fop/pdf/PDFArray.java index ec713b313..466ad7d6a 100644 --- a/src/java/org/apache/fop/pdf/PDFArray.java +++ b/src/java/org/apache/fop/pdf/PDFArray.java @@ -66,6 +66,20 @@ public class PDFArray extends PDFObject { } } + /** + * 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 diff --git a/src/java/org/apache/fop/pdf/PDFPage.java b/src/java/org/apache/fop/pdf/PDFPage.java index 479600536..ee105f39b 100644 --- a/src/java/org/apache/fop/pdf/PDFPage.java +++ b/src/java/org/apache/fop/pdf/PDFPage.java @@ -19,6 +19,8 @@ package org.apache.fop.pdf; +import java.awt.geom.Rectangle2D; + /** * Class representing a /Page object. *

          @@ -29,39 +31,9 @@ package org.apache.fop.pdf; */ public class PDFPage extends PDFResourceContext { - /** - * Holds a reference on the parent PDFPages object. - */ - private String parentRef; - - /** - * the contents stream - */ - protected PDFStream contents; - - /** - * the width of the page in points - */ - protected int pagewidth; - - /** - * the height of the page in points - */ - protected int pageheight; - /** the page index (zero-based) */ protected int pageIndex; - /** - * Duration to display page - */ - protected int duration = -1; - - /** - * Transition dictionary - */ - protected TransitionDictionary trDictionary = null; - /** * Create a /Page object * @@ -77,10 +49,10 @@ public class PDFPage extends PDFResourceContext { /* generic creation of object */ super(resources); + put("Type", new PDFName("Page")); /* set fields using parameters */ - this.contents = contents; - this.pagewidth = pageWidth; - this.pageheight = pageHeight; + setContents(contents); + setSimplePageSize(pageWidth, pageHeight); this.pageIndex = pageIndex; } @@ -97,13 +69,51 @@ public class PDFPage extends PDFResourceContext { this(resources, null, pageWidth, pageHeight, pageIndex); } + private void setSimplePageSize(int width, int height) { + Rectangle2D box = new Rectangle2D.Double(0, 0, width, height); + setMediaBox(box); + setBleedBox(box); //Recommended by PDF/X + setTrimBox(box); //Needed for PDF/X + } + + private PDFArray toPDFArray(Rectangle2D box) { + return new PDFArray(this, new double[] { + box.getX(), box.getY(), box.getMaxX(), box.getMaxY()}); + } + + /** + * Sets the "MediaBox" entry + * @param box the media rectangle + */ + public void setMediaBox(Rectangle2D box) { + put("MediaBox", toPDFArray(box)); + } + + /** + * Sets the "TrimBox" entry + * @param box the trim rectangle + */ + public void setTrimBox(Rectangle2D box) { + put("TrimBox", toPDFArray(box)); + } + + /** + * Sets the "BleedBox" entry + * @param box the bleed rectangle + */ + public void setBleedBox(Rectangle2D box) { + put("BleedBox", toPDFArray(box)); + } + /** * set this page contents * * @param contents the contents of the page */ public void setContents(PDFStream contents) { - this.contents = contents; + if (contents != null) { + put("Contents", new PDFReference(contents)); + } } /** @@ -112,7 +122,7 @@ public class PDFPage extends PDFResourceContext { * @param parent the /Pages object that is this page's parent */ public void setParent(PDFPages parent) { - this.parentRef = parent.referencePDF(); + put("Parent", new PDFReference(parent)); } /** @@ -124,24 +134,8 @@ public class PDFPage extends PDFResourceContext { * @param tr the transition dictionary */ public void setTransition(int dur, TransitionDictionary tr) { - duration = dur; - trDictionary = tr; - } - - /** - * Returns the page width. - * @return the page width - */ - public int getWidth() { - return this.pagewidth; - } - - /** - * Returns the page height. - * @return the page height - */ - public int getHeight() { - return this.pageheight; + put("Dur", new Integer(dur)); + put("Trans", tr); } /** @@ -151,34 +145,5 @@ public class PDFPage extends PDFResourceContext { public int getPageIndex() { return this.pageIndex; } - - /** - * {@inheritDoc} - */ - public String toPDFString() { - StringBuffer sb = new StringBuffer(); - - String box = "[ 0 0 " + getWidth() + " " + getHeight() + " ]"; - sb = sb.append(getObjectID() - + "<< /Type /Page\n" - + "/Parent " + this.parentRef + "\n" - + "/MediaBox " + box + "\n" - + "/TrimBox " + box + "\n" //Needed for PDF/X - + "/BleedBox " + box + "\n" //Recommended by PDF/X - + "/Resources " + this.resources.referencePDF() + "\n" - + "/Contents " + this.contents.referencePDF() + "\n"); - if (this.annotList != null) { - sb = sb.append("/Annots " + this.annotList.referencePDF() + "\n"); - } - if (this.duration != -1) { - sb = sb.append("/Dur " + this.duration + "\n"); - } - if (this.trDictionary != null) { - sb = sb.append("/Trans << " + this.trDictionary.getDictionary() + " >>\n"); - } - - sb = sb.append(">>\nendobj\n"); - return sb.toString(); - } } diff --git a/src/java/org/apache/fop/pdf/PDFResourceContext.java b/src/java/org/apache/fop/pdf/PDFResourceContext.java index aa72f1bbe..6be18ce9d 100644 --- a/src/java/org/apache/fop/pdf/PDFResourceContext.java +++ b/src/java/org/apache/fop/pdf/PDFResourceContext.java @@ -33,17 +33,7 @@ package org.apache.fop.pdf; * to the memory profile this was causing OOM issues. So, we store * only the object ID of the parent, rather than the parent itself. */ -public class PDFResourceContext extends PDFObject { - - /** - * the page's /Resource object - */ - protected PDFResources resources; - - /** - * the list of annotation objects for this page - */ - protected PDFAnnotList annotList; +public class PDFResourceContext extends PDFDictionary { /** * Creates a new ResourceContext. @@ -54,9 +44,7 @@ public class PDFResourceContext extends PDFObject { super(); /* set fields using parameters */ - //this.document = doc; - this.resources = resources; - this.annotList = null; + put("Resources", resources); } /** @@ -65,7 +53,7 @@ public class PDFResourceContext extends PDFObject { * @return the resources in this resource context */ public PDFResources getPDFResources() { - return this.resources; + return (PDFResources)get("Resources"); } /** @@ -74,10 +62,12 @@ public class PDFResourceContext extends PDFObject { * @param annot a PDFAnnotList list of annotations */ public void addAnnotation(PDFObject annot) { - if (this.annotList == null) { - this.annotList = getDocument().getFactory().makeAnnotList(); + PDFAnnotList annotList = getAnnotations(); + if (annotList == null) { + annotList = getDocument().getFactory().makeAnnotList(); + put("Annots", annotList); } - this.annotList.addAnnot(annot); + annotList.addAnnot(annot); } /** @@ -86,7 +76,7 @@ public class PDFResourceContext extends PDFObject { * @return the current annotation list */ public PDFAnnotList getAnnotations() { - return this.annotList; + return (PDFAnnotList)get("Annots"); } /** diff --git a/src/java/org/apache/fop/pdf/TransitionDictionary.java b/src/java/org/apache/fop/pdf/TransitionDictionary.java index bd115bee4..5c779d8fe 100644 --- a/src/java/org/apache/fop/pdf/TransitionDictionary.java +++ b/src/java/org/apache/fop/pdf/TransitionDictionary.java @@ -19,50 +19,21 @@ package org.apache.fop.pdf; -import java.util.Map; -import java.util.Iterator; - /** * Transition Dictionary * This class is used to build a transition dictionary to * specify the transition between pages. */ -public class TransitionDictionary extends PDFObject { - - private Map dictionaryValues; +public class TransitionDictionary extends PDFDictionary { /** * Create a Transition Dictionary * * @param values the dictionary values to output */ - public TransitionDictionary(Map values) { - dictionaryValues = values; + public TransitionDictionary() { + put("Type", new PDFName("Trans")); } - /** - * Get the dictionary. - * This returns the string containing the dictionary values. - * - * @return the string with the dictionary values - */ - public String getDictionary() { - StringBuffer sb = new StringBuffer(); - sb.append("/Type /Trans\n"); - for (Iterator iter = dictionaryValues.keySet().iterator(); iter.hasNext();) { - Object key = iter.next(); - sb.append(key + " " + dictionaryValues.get(key) + "\n"); - } - return sb.toString(); - } - - /** - * there is nothing to return for the toPDF method, as it should not be called - * - * @return an empty string - */ - public byte[] toPDF() { - return new byte[0]; - } } -- cgit v1.2.3 From 36c62fb27612261f81eb8de02f1754a3d662cea4 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 5 Feb 2008 12:35:42 +0000 Subject: FOX_TRANSFORM constant should be static. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@618627 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 285cc5ded..9e13476f6 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -406,7 +406,8 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { } - private final QName FOX_TRANSFORM = new QName(ExtensionElementMapping.URI, "fox:transform"); + private static final QName FOX_TRANSFORM + = new QName(ExtensionElementMapping.URI, "fox:transform"); /** {@inheritDoc} */ protected void renderBlockViewport(BlockViewport bv, List children) { -- cgit v1.2.3 From 448befc115b005dc2a07391182179c686a91d25f Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 6 Feb 2008 14:07:03 +0000 Subject: Bugzilla #36391: Fixed problem with positioning of content when reference-orientation="180" is used. CTM is now correct. It is updated after the height of the content is known. Instead of somehow inverting the element list, I've simply declared this case non-breakable, i.e. I generate one box. Fixed a few other problems mostly occurring when rotating block-container content by 90 or 270 degrees plus a few remaining auto-height handling problems. This involved switching off some sometimes unwanted side-effects from auto-updating the BPD in some area classes. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@618992 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/Block.java | 15 +++- src/java/org/apache/fop/area/BlockViewport.java | 9 ++ src/java/org/apache/fop/area/NormalFlow.java | 4 +- .../fop/layoutmgr/BlockContainerLayoutManager.java | 99 ++++++++++++++-------- test/layoutengine/disabled-testcases.xml | 7 -- ...k-container_absolute-position_display-align.xml | 2 + ...ock-container_absolute-position_no-height_2.xml | 84 ++++++++++++++++++ .../block-container_reference-orientation_2.xml | 91 ++++++++++++++++++++ ...ck-container_reference-orientation_bug36391.xml | 7 +- 9 files changed, 266 insertions(+), 52 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block-container_absolute-position_no-height_2.xml create mode 100644 test/layoutengine/standard-testcases/block-container_reference-orientation_2.xml (limited to 'src') diff --git a/src/java/org/apache/fop/area/Block.java b/src/java/org/apache/fop/area/Block.java index 264a9e690..21fa7c49d 100644 --- a/src/java/org/apache/fop/area/Block.java +++ b/src/java/org/apache/fop/area/Block.java @@ -19,7 +19,6 @@ package org.apache.fop.area; -import java.util.ArrayList; // block areas hold either more block areas or line // areas can also be used as a block spacer @@ -59,6 +58,8 @@ public class Block extends BlockParent { private int stacking = TB; private int positioning = STACK; + protected transient boolean allowBPDUpdate = true; + // a block with may contain the dominant styling info in // terms of most lines or blocks with info @@ -78,7 +79,7 @@ public class Block extends BlockParent { * @param autoHeight increase the height of the block. */ public void addBlock(Block block, boolean autoHeight) { - if (autoHeight) { + if (autoHeight && allowBPDUpdate) { bpd += block.getAllocBPD(); } addChildArea(block); @@ -112,6 +113,14 @@ public class Block extends BlockParent { return positioning; } + /** + * Indicates whether this block is stacked, rather than absolutely positioned. + * @return true if it is stacked + */ + public boolean isStacked() { + return (getPositioning() == Block.STACK || getPositioning() == Block.RELATIVE); + } + /** * @return the start-indent trait */ @@ -119,6 +128,6 @@ public class Block extends BlockParent { Integer startIndent = (Integer)getTrait(Trait.START_INDENT); return (startIndent != null ? startIndent.intValue() : 0); } - + } diff --git a/src/java/org/apache/fop/area/BlockViewport.java b/src/java/org/apache/fop/area/BlockViewport.java index af994afd4..167e7c5b3 100644 --- a/src/java/org/apache/fop/area/BlockViewport.java +++ b/src/java/org/apache/fop/area/BlockViewport.java @@ -34,6 +34,15 @@ public class BlockViewport extends Block { * Create a new block viewport area. */ public BlockViewport() { + this(false); + } + + /** + * Create a new block viewport area. + * @param allowBPDUpdate true allows the BPD to be updated when children are added + */ + public BlockViewport(boolean allowBPDUpdate) { + this.allowBPDUpdate = allowBPDUpdate; } /** diff --git a/src/java/org/apache/fop/area/NormalFlow.java b/src/java/org/apache/fop/area/NormalFlow.java index 715a61cb0..c9fc8380a 100644 --- a/src/java/org/apache/fop/area/NormalFlow.java +++ b/src/java/org/apache/fop/area/NormalFlow.java @@ -37,7 +37,9 @@ public class NormalFlow extends BlockParent { /** {@inheritDoc} */ public void addBlock(Block block) { super.addBlock(block); - bpd += block.getAllocBPD(); + if (block.isStacked()) { + bpd += block.getAllocBPD(); + } } } diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 3d9076efd..fc60b561e 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -65,7 +65,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager private int vpContentBPD; // When viewport should grow with the content. - private boolean autoHeight = true; + private boolean autoHeight = true; + private boolean inlineElementList = false; /* holds the (one-time use) fo:block space-before and -after properties. Large fo:blocks are split @@ -196,6 +197,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return getNextKnuthElementsAbsolute(context, alignment); } + boolean switchedProgressionDirection + = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); autoHeight = false; //boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); int maxbpd = context.getStackLimit().opt; @@ -203,9 +206,13 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (height.getEnum() == EN_AUTO || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { //auto height when height="auto" or "if that dimension is not specified explicitly - //(i.e., it depends on content's blockprogression-dimension)" (XSL 1.0, 7.14.1) + //(i.e., it depends on content's block-progression-dimension)" (XSL 1.0, 7.14.1) allocBPD = maxbpd; autoHeight = true; + if (getBlockContainerFO().getReferenceOrientation() == 0) { + //Cannot easily inline element list when ref-or="180" + inlineElementList = true; + } } else { allocBPD = height.getValue(this); //this is the content-height allocBPD += getBPIndents(); @@ -229,19 +236,14 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager contentRectOffsetY += getBlockContainerFO() .getCommonBorderPaddingBackground().getPaddingBefore(false, this); - Rectangle2D rect = new Rectangle2D.Double( - contentRectOffsetX, contentRectOffsetY, - getContentAreaIPD(), getContentAreaBPD()); - relDims = new FODimension(0, 0); - absoluteCTM = CTM.getCTMandRelDims(getBlockContainerFO().getReferenceOrientation(), - getBlockContainerFO().getWritingMode(), rect, relDims); + updateRelDims(contentRectOffsetX, contentRectOffsetY, autoHeight); int availableIPD = referenceIPD - getIPIndents(); - if (rect.getWidth() > availableIPD) { + if (getContentAreaIPD() > availableIPD) { log.warn(FONode.decorateWithContextInfo( "The extent in inline-progression-direction (width) of a block-container is" + " bigger than the available space (" - + rect.getWidth() + "mpt > " + context.getRefIPD() + "mpt)", + + getContentAreaIPD() + "mpt > " + context.getRefIPD() + "mpt)", getBlockContainerFO())); } @@ -268,7 +270,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); firstVisibleMarkServed = true; - if (autoHeight) { + if (autoHeight && inlineElementList) { //Spaces, border and padding to be repeated at each break addPendingMarks(context); @@ -356,6 +358,16 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); breaker.doLayout(relDims.bpd, autoHeight); boolean contentOverflows = breaker.isOverflow(); + if (autoHeight) { + //Update content BPD now that it is known + int newHeight = breaker.deferredAlg.totalWidth; + if (switchedProgressionDirection) { + setContentAreaIPD(newHeight); + } else { + vpContentBPD = newHeight; + } + updateRelDims(contentRectOffsetX, contentRectOffsetY, false); + } Position bcPosition = new BlockContainerPosition(this, breaker); returnList.add(new KnuthBox(vpContentBPD, notifyPos(bcPosition), false)); @@ -385,6 +397,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager private LinkedList getNextKnuthElementsAbsolute(LayoutContext context, int alignment) { autoHeight = false; + boolean switchedProgressionDirection + = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); Point offset = getAbsOffset(); int allocBPD, allocIPD; if (height.getEnum() == EN_AUTO @@ -432,7 +446,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } else { int maxbpd = context.getStackLimit().opt; allocBPD = maxbpd; - autoHeight = true; + if (!switchedProgressionDirection) { + autoHeight = true; + } } } else { allocBPD = height.getValue(this); //this is the content-height @@ -474,6 +490,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager */ allocIPD = 0; } + if (switchedProgressionDirection) { + autoHeight = true; + } } } else { allocIPD = width.getValue(this); //this is the content-width @@ -483,29 +502,29 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager vpContentBPD = allocBPD - getBPIndents(); setContentAreaIPD(allocIPD - getIPIndents()); - double contentRectOffsetX = 0; - double contentRectOffsetY = 0; - - Rectangle2D rect = new Rectangle2D.Double( - contentRectOffsetX, contentRectOffsetY, - getContentAreaIPD(), vpContentBPD); - relDims = new FODimension(0, 0); - absoluteCTM = CTM.getCTMandRelDims( - getBlockContainerFO().getReferenceOrientation(), - getBlockContainerFO().getWritingMode(), - rect, relDims); + updateRelDims(0, 0, autoHeight); MinOptMax range = new MinOptMax(relDims.ipd); BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); breaker.doLayout((autoHeight ? 0 : relDims.bpd), autoHeight); boolean contentOverflows = breaker.isOverflow(); + if (autoHeight) { + //Update content BPD now that it is known + int newHeight = breaker.deferredAlg.totalWidth; + if (switchedProgressionDirection) { + setContentAreaIPD(newHeight); + } else { + vpContentBPD = newHeight; + } + updateRelDims(0, 0, false); + } LinkedList returnList = new LinkedList(); if (!breaker.isEmpty()) { Position bcPosition = new BlockContainerPosition(this, breaker); returnList.add(new KnuthBox(0, notifyPos(bcPosition), false)); //TODO Maybe check for page overflow when autoHeight=true - if (!autoHeight & (contentOverflows/*usedBPD > relDims.bpd*/)) { + if (!autoHeight & (contentOverflows)) { log.warn("Contents overflow block-container viewport: clipping"); if (getBlockContainerFO().getOverflow() == EN_ERROR_IF_OVERFLOW) { //TODO Throw layout exception @@ -516,6 +535,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager setFinished(true); return returnList; } + + private void updateRelDims(double xOffset, double yOffset, boolean skipAutoHeight) { + Rectangle2D rect = new Rectangle2D.Double( + xOffset, yOffset, + getContentAreaIPD(), + this.vpContentBPD); + relDims = new FODimension(0, 0); + absoluteCTM = CTM.getCTMandRelDims( + getBlockContainerFO().getReferenceOrientation(), + getBlockContainerFO().getWritingMode(), + rect, relDims); + } private class BlockContainerPosition extends NonLeafPosition { @@ -854,13 +885,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager */ public Area getParentArea(Area childArea) { if (referenceArea == null) { - viewportBlockArea = new BlockViewport(); + boolean switchedProgressionDirection + = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); + boolean allowBPDUpdate = autoHeight && !switchedProgressionDirection; + + viewportBlockArea = new BlockViewport(allowBPDUpdate); viewportBlockArea.addTrait(Trait.IS_VIEWPORT_AREA, Boolean.TRUE); + viewportBlockArea.setIPD(getContentAreaIPD()); - if (autoHeight) { + if (allowBPDUpdate) { viewportBlockArea.setBPD(0); } else { - viewportBlockArea.setBPD(getContentAreaBPD()); + viewportBlockArea.setBPD(this.vpContentBPD); } transferForeignAttributes(viewportBlockArea); @@ -941,16 +977,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager getBlockContainerFO().getCommonBorderPaddingBackground(), this); - // Fake a 0 height for absolute positioned blocks. - int saveBPD = viewportBlockArea.getBPD(); - if (viewportBlockArea.getPositioning() == Block.ABSOLUTE) { - viewportBlockArea.setBPD(0); - } super.flush(); - // Restore the right height. - if (viewportBlockArea.getPositioning() == Block.ABSOLUTE) { - viewportBlockArea.setBPD(saveBPD); - } } /** {@inheritDoc} */ diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index 5f5672ae7..15ac8aa48 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -26,13 +26,6 @@ is not sized correctly if it wraps an image that is higher than the nominal line. - - Bugzilla #36391: reference-orientation - block-container_reference-orientation_bug36391.xml - There's a problem involving nested block-containers - and reference-orientation 180/-180. - http://issues.apache.org/bugzilla/show_bug.cgi?id=36391 - Auto-height block-containers produce fences block-container_space-before_space-after_3.xml diff --git a/test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml b/test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml index 667d2a37c..42aaee529 100644 --- a/test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml +++ b/test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml @@ -56,6 +56,8 @@ + + diff --git a/test/layoutengine/standard-testcases/block-container_absolute-position_no-height_2.xml b/test/layoutengine/standard-testcases/block-container_absolute-position_no-height_2.xml new file mode 100644 index 000000000..3c987fec8 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_absolute-position_no-height_2.xml @@ -0,0 +1,84 @@ + + + + + +

          + This test checks absolutely positioned block-containers where the content-bpd isn't specified. +

          + + + + + + + + + + + + ABC + ABC + + + ABC + ABC + + + ABC + ABC + + + ABC + ABC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/block-container_reference-orientation_2.xml b/test/layoutengine/standard-testcases/block-container_reference-orientation_2.xml new file mode 100644 index 000000000..60400410d --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_reference-orientation_2.xml @@ -0,0 +1,91 @@ + + + + + +

          + This test checks the element lists of in-flow block-containers with reference orientation. +

          +
          + + + + + + + + + + + ABC + ABC + + EOPS + + + + + + ABC + ABC + + EOPS + + + + + + ABC + ABC + + EOPS + + + + + + + + + + + + + + 3 + + + + + + + + 3 + + + + + + + + + 3 + + +
          diff --git a/test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml b/test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml index 615fb28e1..7b1bfc793 100644 --- a/test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml +++ b/test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml @@ -90,13 +90,10 @@ - - + - + -- cgit v1.2.3 From 575826b283fa659929204c63905e05fe2e2cf5f5 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 7 Feb 2008 14:02:44 +0000 Subject: Added an option to disable the default sRGB profile in PDF output for those who don't care about color fidelity, but care about PDF file size. Note that this option is not possible if PDF/A, PDF/X or an output profile is used. Makes simple PDFs about 4KB smaller. Ha! git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@619417 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/configuration.xml | 18 +++++- src/documentation/content/xdocs/trunk/output.xml | 2 +- .../org/apache/fop/render/pdf/PDFRenderer.java | 31 +++++++++-- .../fop/render/pdf/PDFRendererConfigurator.java | 5 ++ status.xml | 4 ++ test/java/org/apache/fop/StandardTestSuite.java | 8 ++- .../fop/render/pdf/PDFsRGBSettingsTestCase.java | 64 ++++++++++++++++++++++ 7 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 test/java/org/apache/fop/render/pdf/PDFsRGBSettingsTestCase.java (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/configuration.xml b/src/documentation/content/xdocs/trunk/configuration.xml index 410b17098..e82a6e862 100644 --- a/src/documentation/content/xdocs/trunk/configuration.xml +++ b/src/documentation/content/xdocs/trunk/configuration.xml @@ -277,7 +277,23 @@ C:\FOP\Color\EuropeISOCoatedFOGRA27.icc ]]> + ]]> +

          + Some people don't have high requirements on color fidelity but instead want the smallest + PDF file sizes possible. In this case it's possible to disable the default sRGB color space + which XSL-FO requires. This will cause RGB colors to be generated as device-specific RGB. + Please note that this option is unavailable (and will cause an error) if you enable + PDF/A or PDF/X functionality or if you specify an output profile. This setting will make the + PDF about 4KB smaller. To disable the sRGB color space add the following setting: +

          + + true + + ]]>
    Special Settings for the PostScript Renderer diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index 663168a3c..d6021414f 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -105,7 +105,7 @@ out = proc.getOutputStream();]]>
    Post-processing

    - FOP does not currently support several desirable PDF features: XMP metadata and watermarks. + FOP does not currently support several desirable PDF features: watermarks and signatures. One workaround is to use Adobe Acrobat (the full version, not the Reader) to process the file manually or with scripting that it supports.

    diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 86c01f673..09c6fbed4 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -147,6 +147,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { public static final String PDF_X_MODE = "pdf-x-mode"; /** Rendering Options key for the ICC profile for the output intent. */ public static final String KEY_OUTPUT_PROFILE = "output-profile"; + /** + * Rendering Options key for disabling the sRGB color space (only possible if no PDF/A or + * PDF/X profile is active). + */ + public static final String KEY_DISABLE_SRGB_COLORSPACE = "disable-srgb-colorspace"; /** Controls whether comments are written to the PDF stream. */ protected static final boolean WRITE_COMMENTS = true; @@ -233,10 +238,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** the ICC stream used as output profile by this document for PDF/A and PDF/X functionality. */ protected PDFICCStream outputProfile; - /** the ICC stream for the sRGB color space. */ - //protected PDFICCStream sRGBProfile; /** the default sRGB color space. */ protected PDFICCBasedColorSpace sRGBColorSpace; + /** controls whether the sRGB color space should be installed */ + protected boolean disableSRGBColorSpace = false; /** Optional URI to an output profile to be used. */ protected String outputProfileURI; @@ -344,6 +349,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { if (s != null) { this.outputProfileURI = s; } + setting = agent.getRendererOptions().get(KEY_DISABLE_SRGB_COLORSPACE); + if (setting != null) { + this.disableSRGBColorSpace = booleanValueOf(setting); + } } /** @@ -387,11 +396,21 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } private void addsRGBColorSpace() throws IOException { - if (this.sRGBColorSpace != null) { - return; + if (disableSRGBColorSpace) { + if (this.pdfAMode != PDFAMode.DISABLED + || this.pdfXMode != PDFXMode.DISABLED + || this.outputProfileURI != null) { + throw new IllegalStateException("It is not possible to disable the sRGB color" + + " space if PDF/A or PDF/X functionality is enabled or an" + + " output profile is set!"); + } + } else { + if (this.sRGBColorSpace != null) { + return; + } + //Map sRGB as default RGB profile for DeviceRGB + this.sRGBColorSpace = PDFICCBasedColorSpace.setupsRGBAsDefaultRGBColorSpace(pdfDoc); } - //Map sRGB as default RGB profile for DeviceRGB - this.sRGBColorSpace = PDFICCBasedColorSpace.setupsRGBAsDefaultRGBColorSpace(pdfDoc); } private void addDefaultOutputProfile() throws IOException { diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java index aec094e3b..2fce8859a 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java @@ -24,6 +24,7 @@ import java.util.Map; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.pdf.PDFAMode; @@ -81,6 +82,10 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator { if (s != null) { pdfRenderer.setOutputProfileURI(s); } + Configuration child = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); + if (child != null) { + pdfRenderer.disableSRGBColorSpace = child.getValueAsBoolean(false); + } } } diff --git a/status.xml b/status.xml index 3cc0f5b46..49b238a38 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Added an option to disable the default sRGB profile in PDF output for those who + don't care about color fidelity, but care about PDF file size. + Fixed a bug when the rgb-icc() function was used either before the fo:declarations, or in documents without a fo:declarations node. In such cases, the sRGB fallback diff --git a/test/java/org/apache/fop/StandardTestSuite.java b/test/java/org/apache/fop/StandardTestSuite.java index 4066e00a0..648f3d5d1 100644 --- a/test/java/org/apache/fop/StandardTestSuite.java +++ b/test/java/org/apache/fop/StandardTestSuite.java @@ -19,14 +19,15 @@ package org.apache.fop; +import junit.framework.Test; +import junit.framework.TestSuite; + import org.apache.fop.render.pdf.PDFAConformanceTestCase; import org.apache.fop.render.pdf.PDFCMapTestCase; import org.apache.fop.render.pdf.PDFEncodingTestCase; +import org.apache.fop.render.pdf.PDFsRGBSettingsTestCase; import org.apache.fop.render.rtf.RichTextFormatTestSuite; -import junit.framework.Test; -import junit.framework.TestSuite; - /** * Test suite for basic functionality of FOP. */ @@ -45,6 +46,7 @@ public class StandardTestSuite { suite.addTest(new TestSuite(PDFAConformanceTestCase.class)); suite.addTest(new TestSuite(PDFEncodingTestCase.class)); suite.addTest(new TestSuite(PDFCMapTestCase.class)); + suite.addTest(new TestSuite(PDFsRGBSettingsTestCase.class)); suite.addTest(RichTextFormatTestSuite.suite()); //$JUnit-END$ return suite; diff --git a/test/java/org/apache/fop/render/pdf/PDFsRGBSettingsTestCase.java b/test/java/org/apache/fop/render/pdf/PDFsRGBSettingsTestCase.java new file mode 100644 index 000000000..45f982b00 --- /dev/null +++ b/test/java/org/apache/fop/render/pdf/PDFsRGBSettingsTestCase.java @@ -0,0 +1,64 @@ +/* + * 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.render.pdf; + +import java.io.File; + +import org.apache.fop.apps.FOUserAgent; + +/** + * Tests the disables-srgb-colorspace setting. + */ +public class PDFsRGBSettingsTestCase extends BasePDFTestCase { + + private File foBaseDir = new File("test/xml/pdf-a"); + + /** + * Main constructor + * @param name name of the test case + */ + public PDFsRGBSettingsTestCase(String name) { + super(name); + } + + private FOUserAgent getUserAgent(boolean enablePDFA) { + final FOUserAgent a = fopFactory.newFOUserAgent(); + if (enablePDFA) { + a.getRendererOptions().put("pdf-a-mode", "PDF/A-1b"); + } + a.getRendererOptions().put("disable-srgb-colorspace", Boolean.TRUE); + return a; + } + + /** + * Verify that the PDFRenderer complains if PDF/A or PDF/X is used when sRGB is disabled. + * @throws Exception if the test fails + */ + public void testPDFAWithDisabledSRGB() throws Exception { + File foFile = new File(foBaseDir, "minimal-pdf-a.fo"); + try { + convertFO(foFile, getUserAgent(true), false); + fail("PDFRenderer must fail if PDF/A is active!"); + } catch (IllegalStateException e) { + //exception expected! + } + } + +} -- cgit v1.2.3 From b3c8c500256e67344c6b4cc91c045a04e8e65e36 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 7 Feb 2008 15:42:03 +0000 Subject: Bugfix for date formatting with negative time zones in the PDF's Info object. Update of xmlgraphics-commons-1.3.jar because of a similar bug with formatting dates in XMP. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@619461 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.3svn.jar | Bin 499126 -> 499250 bytes src/java/org/apache/fop/pdf/PDFObject.java | 51 +++++++++++------- status.xml | 3 ++ test/java/org/apache/fop/UtilityCodeTestSuite.java | 8 +-- .../java/org/apache/fop/pdf/PDFObjectTestCase.java | 59 +++++++++++++++++++++ 5 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 test/java/org/apache/fop/pdf/PDFObjectTestCase.java (limited to 'src') diff --git a/lib/xmlgraphics-commons-1.3svn.jar b/lib/xmlgraphics-commons-1.3svn.jar index ea00555ef..0abad1c33 100644 Binary files a/lib/xmlgraphics-commons-1.3svn.jar and b/lib/xmlgraphics-commons-1.3svn.jar differ diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java index f791791b7..d43ae71f1 100644 --- a/src/java/org/apache/fop/pdf/PDFObject.java +++ b/src/java/org/apache/fop/pdf/PDFObject.java @@ -26,6 +26,7 @@ import java.io.Writer; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; +import java.util.Locale; import java.util.TimeZone; import org.apache.commons.logging.Log; @@ -327,33 +328,34 @@ public abstract class PDFObject implements PDFWritable { } /** Formatting pattern for PDF date */ - protected static final SimpleDateFormat DATE_FORMAT - = new SimpleDateFormat("'D:'yyyyMMddHHmmss"); + protected static final SimpleDateFormat DATE_FORMAT; + static { + DATE_FORMAT = new SimpleDateFormat("'D:'yyyyMMddHHmmss", Locale.ENGLISH); + DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); + } + /** * Formats a date/time according to the PDF specification * (D:YYYYMMDDHHmmSSOHH'mm'). * @param time date/time value to format + * @param tz the time zone * @return the requested String representation */ - protected String formatDateTime(Date time) { - StringBuffer sb = new StringBuffer(); - sb.append(DATE_FORMAT.format(time)); - TimeZone tz = TimeZone.getDefault(); - Calendar cal = Calendar.getInstance(); + protected String formatDateTime(Date time, TimeZone tz) { + Calendar cal = Calendar.getInstance(tz, Locale.ENGLISH); cal.setTime(time); - int era = cal.get(Calendar.ERA); - int year = cal.get(Calendar.YEAR); - int month = cal.get(Calendar.MONTH); - int day = cal.get(Calendar.DAY_OF_MONTH); - int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); - int milliseconds = cal.get(Calendar.HOUR_OF_DAY) * 1000 * 60 * 60; - milliseconds += cal.get(Calendar.MINUTE) * 1000 * 60; - milliseconds += cal.get(Calendar.SECOND) * 1000; - milliseconds += cal.get(Calendar.MILLISECOND); + int offset = cal.get(Calendar.ZONE_OFFSET); + offset += cal.get(Calendar.DST_OFFSET); + + //DateFormat is operating on GMT so adjust for time zone offset + Date dt1 = new Date(time.getTime() + offset); + StringBuffer sb = new StringBuffer(); + sb.append(DATE_FORMAT.format(dt1)); + + offset /= (1000 * 60); //Convert to minutes - int offset = tz.getOffset(era, year, month, day, dayOfWeek, milliseconds); if (offset == 0) { sb.append('Z'); } else { @@ -362,9 +364,8 @@ public abstract class PDFObject implements PDFWritable { } else { sb.append('-'); } - final int HOUR = (1000 * 60 * 60); - int offsetHour = Math.abs(offset / HOUR); - int offsetMinutes = (offset - (offsetHour * HOUR)) / (1000 * 60); + int offsetHour = Math.abs(offset / 60); + int offsetMinutes = Math.abs(offset % 60); if (offsetHour < 10) { sb.append('0'); } @@ -379,4 +380,14 @@ public abstract class PDFObject implements PDFWritable { return sb.toString(); } + /** + * Formats a date/time according to the PDF specification. + * (D:YYYYMMDDHHmmSSOHH'mm'). + * @param time date/time value to format + * @return the requested String representation + */ + protected String formatDateTime(Date time) { + return formatDateTime(time, TimeZone.getDefault()); + } + } diff --git a/status.xml b/status.xml index 49b238a38..3b177b6f6 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Bugfix for date formatting with negative time zones in the PDF's Info object. + Added an option to disable the default sRGB profile in PDF output for those who don't care about color fidelity, but care about PDF file size. diff --git a/test/java/org/apache/fop/UtilityCodeTestSuite.java b/test/java/org/apache/fop/UtilityCodeTestSuite.java index 679e16ce7..19d7d0266 100644 --- a/test/java/org/apache/fop/UtilityCodeTestSuite.java +++ b/test/java/org/apache/fop/UtilityCodeTestSuite.java @@ -19,6 +19,10 @@ package org.apache.fop; +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.fop.pdf.PDFObjectTestCase; import org.apache.fop.traits.BorderPropsTestCase; import org.apache.fop.traits.TraitColorTestCase; import org.apache.fop.util.DataURIResolverTestCase; @@ -26,9 +30,6 @@ import org.apache.fop.util.ElementListUtilsTestCase; import org.apache.fop.util.PDFNumberTestCase; import org.apache.fop.util.UnitConvTestCase; -import junit.framework.Test; -import junit.framework.TestSuite; - /** * Test suite for FOP's utility classes. */ @@ -43,6 +44,7 @@ public class UtilityCodeTestSuite { "Test suite for FOP's utility classes"); //$JUnit-BEGIN$ suite.addTest(new TestSuite(PDFNumberTestCase.class)); + suite.addTest(new TestSuite(PDFObjectTestCase.class)); suite.addTest(new TestSuite(UnitConvTestCase.class)); suite.addTest(new TestSuite(TraitColorTestCase.class)); suite.addTest(new TestSuite(BorderPropsTestCase.class)); diff --git a/test/java/org/apache/fop/pdf/PDFObjectTestCase.java b/test/java/org/apache/fop/pdf/PDFObjectTestCase.java new file mode 100644 index 000000000..96ac728bd --- /dev/null +++ b/test/java/org/apache/fop/pdf/PDFObjectTestCase.java @@ -0,0 +1,59 @@ +/* + * 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.pdf; + +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import junit.framework.TestCase; + +/** + * Tests the PDFObject class. + */ +public class PDFObjectTestCase extends TestCase { + + /** + * Tests date/time formatting in PDFObject. + * @throws Exception if an error occurs + */ + public void testDateFormatting() throws Exception { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.ENGLISH); + cal.set(2008, Calendar.FEBRUARY, 07, 15, 11, 07); + cal.set(Calendar.MILLISECOND, 0); + Date dt = cal.getTime(); + + MyPDFObject obj = new MyPDFObject(); + String s = obj.formatDateTime(dt, TimeZone.getTimeZone("GMT")); + assertEquals("D:20080207151107Z", s); + s = obj.formatDateTime(dt, TimeZone.getTimeZone("GMT+02:00")); + assertEquals("D:20080207171107+02'00'", s); + s = obj.formatDateTime(dt, TimeZone.getTimeZone("GMT+02:30")); + assertEquals("D:20080207174107+02'30'", s); + s = obj.formatDateTime(dt, TimeZone.getTimeZone("GMT-08:00")); + assertEquals("D:20080207071107-08'00'", s); + } + + private class MyPDFObject extends PDFObject { + + } + +} -- cgit v1.2.3 From e3d7d048142f35bf93b0ba9f1294124de49be34e Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 7 Feb 2008 22:32:27 +0000 Subject: Tweak: early percentage resolution by the parser (if the base is known and absolute). Reduces the number of PercentLength instances in favor of cached FixedLengths. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@619670 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/datatypes/LengthBase.java | 12 ++++++++++++ src/java/org/apache/fop/fo/expr/PropertyParser.java | 14 +++++++++++++- .../apache/fop/fo/properties/LineHeightPropertyMaker.java | 13 ++++++++++++- test/fotree/testcases/font-shorthand-test.fo | 10 +++++----- 4 files changed, 42 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/datatypes/LengthBase.java b/src/java/org/apache/fop/datatypes/LengthBase.java index 684685509..8a321f2c6 100644 --- a/src/java/org/apache/fop/datatypes/LengthBase.java +++ b/src/java/org/apache/fop/datatypes/LengthBase.java @@ -130,5 +130,17 @@ public class LengthBase implements PercentBase { return baseLen; } + /** {@inheritDoc} */ + public String toString() { + return super.toString() + + "[fo=" + fobj + "," + + "baseType=" + baseType + "," + + "baseLength=" + baseLength + "]"; + } + + /**@return the base length as a {@link Length} */ + public Length getBaseLength() { + return baseLength; + } } diff --git a/src/java/org/apache/fop/fo/expr/PropertyParser.java b/src/java/org/apache/fop/fo/expr/PropertyParser.java index d8f45790e..cd3393ef3 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyParser.java +++ b/src/java/org/apache/fop/fo/expr/PropertyParser.java @@ -19,6 +19,8 @@ package org.apache.fop.fo.expr; +import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.Numeric; import org.apache.fop.datatypes.PercentBase; import org.apache.fop.fo.properties.ColorProperty; @@ -43,7 +45,7 @@ public final class PropertyParser extends PropertyTokenizer { private static final String RELUNIT = "em"; private static final HashMap FUNCTION_TABLE = new HashMap(); - + static { // Initialize the HashMap of XSL-defined functions FUNCTION_TABLE.put("ceiling", new CeilingFunction()); @@ -272,6 +274,16 @@ public final class PropertyParser extends PropertyTokenizer { if (pcBase.getDimension() == 0) { prop = NumberProperty.getInstance(pcval * pcBase.getBaseValue()); } else if (pcBase.getDimension() == 1) { + if (pcBase instanceof LengthBase) { + //If the base of the percentage is known + //and absolute, it can be resolved by the + //parser + Length base = ((LengthBase)pcBase).getBaseLength(); + if (base != null && base.isAbsolute()) { + prop = FixedLength.getInstance(pcval * base.getValue()); + break; + } + } prop = new PercentLength(pcval, pcBase); } else { throw new PropertyException("Illegal percent dimension value"); diff --git a/src/java/org/apache/fop/fo/properties/LineHeightPropertyMaker.java b/src/java/org/apache/fop/fo/properties/LineHeightPropertyMaker.java index dcb8fd176..dd57502d8 100644 --- a/src/java/org/apache/fop/fo/properties/LineHeightPropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/LineHeightPropertyMaker.java @@ -19,6 +19,8 @@ package org.apache.fop.fo.properties; +import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; @@ -85,7 +87,16 @@ public class LineHeightPropertyMaker extends SpaceProperty.Maker { FObj fo) throws PropertyException { Numeric numval = p.getNumeric(); if (numval != null && numval.getDimension() == 0) { - p = new PercentLength(numval.getNumericValue(), getPercentBase(propertyList)); + if (getPercentBase(propertyList) instanceof LengthBase) { + Length base = ((LengthBase)getPercentBase(propertyList)).getBaseLength(); + if (base != null && base.isAbsolute()) { + p = FixedLength.getInstance( + numval.getNumericValue() * base.getNumericValue()); + } else { + p = new PercentLength( + numval.getNumericValue(), getPercentBase(propertyList)); + } + } Property spaceProp = super.convertProperty(p, propertyList, fo); spaceProp.setSpecifiedValue(String.valueOf(numval.getNumericValue())); return spaceProp; diff --git a/test/fotree/testcases/font-shorthand-test.fo b/test/fotree/testcases/font-shorthand-test.fo index b6666087f..e574b3b24 100644 --- a/test/fotree/testcases/font-shorthand-test.fo +++ b/test/fotree/testcases/font-shorthand-test.fo @@ -29,7 +29,7 @@ - + @@ -37,7 +37,7 @@ - + Test font shorthand @@ -46,7 +46,7 @@ - + Test font shorthand @@ -55,7 +55,7 @@ - + Test font shorthand @@ -65,7 +65,7 @@ - + Test font shorthand inheritance -- cgit v1.2.3 From 8786f3b949673f898cbc4de203e2320e74f2f050 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 7 Feb 2008 22:41:26 +0000 Subject: Tweak: modify PercentLength.toString() to return a value that facilitates debugging. Moved the original code to a getString() implementation, which is now used by the fotree test suite. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@619674 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fo/properties/PercentLength.java | 24 ++++++++++++---------- .../apache/fop/fotreetest/ext/AssertElement.java | 8 +++++++- 2 files changed, 20 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/PercentLength.java b/src/java/org/apache/fop/fo/properties/PercentLength.java index e63d527a7..82f5e60f9 100644 --- a/src/java/org/apache/fop/fo/properties/PercentLength.java +++ b/src/java/org/apache/fop/fo/properties/PercentLength.java @@ -80,16 +80,12 @@ public class PercentLength extends LengthProperty { return false; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public double getNumericValue() { return getNumericValue(null); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public double getNumericValue(PercentBaseContext context) { try { resolvedValue = factor * lbase.getBaseLength(context); @@ -99,6 +95,11 @@ public class PercentLength extends LengthProperty { return 0; } } + + /** {@inheritDoc} */ + public String getString() { + return (factor * 100.0) + "%"; + } /** * Return the length of this PercentLength. @@ -108,9 +109,7 @@ public class PercentLength extends LengthProperty { return (int) getNumericValue(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getValue(PercentBaseContext context) { return (int) getNumericValue(context); } @@ -119,8 +118,11 @@ public class PercentLength extends LengthProperty { * @return the String equivalent of this */ public String toString() { - // TODO: What about the base value? - return (new Double(factor * 100.0).toString()) + "%"; + StringBuffer sb = + new StringBuffer(PercentLength.class.getName()) + .append("[factor=").append(factor) + .append(",lbase=").append(lbase).append("]"); + return sb.toString(); } } diff --git a/test/java/org/apache/fop/fotreetest/ext/AssertElement.java b/test/java/org/apache/fop/fotreetest/ext/AssertElement.java index 38bc0eb00..b141c8f4a 100644 --- a/test/java/org/apache/fop/fotreetest/ext/AssertElement.java +++ b/test/java/org/apache/fop/fotreetest/ext/AssertElement.java @@ -27,6 +27,7 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthPairProperty; import org.apache.fop.fo.properties.LengthRangeProperty; +import org.apache.fop.fo.properties.PercentLength; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.fotreetest.ResultCollector; @@ -91,7 +92,12 @@ public class AssertElement extends TestObj { prop = sp.getComponent(FOPropertyMapping.getSubPropertyId(component)); } } - String s = String.valueOf(prop); + String s; + if (prop instanceof PercentLength) { + s = ((PercentLength)prop).getString(); + } else { + s = String.valueOf(prop); + } String expected = attlist.getValue("expected"); if (!expected.equals(s)) { collector.notifyException( -- cgit v1.2.3 From 48a9185a60b9374fe0f132fe83d758527ec01788 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 8 Feb 2008 12:11:04 +0000 Subject: Removed the 900 penalty mechanism which anyway almost always produced visually bad results. Now the first step for a row is computed so that each cell starting on it can contribute some content. Used a similar mechanism to replace backtracking: the current row is now allowed to grow as long as there is not enough space on the current page to make the next row fit. The next row is "delayed", so this mechanism is called "row-delaying" git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@619854 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 310 +++++++----- .../org/apache/fop/layoutmgr/table/CellPart.java | 12 +- .../org/apache/fop/layoutmgr/table/RowPainter.java | 15 +- .../layoutmgr/table/TableContentLayoutManager.java | 4 +- .../fop/layoutmgr/table/TableContentPosition.java | 25 +- .../apache/fop/layoutmgr/table/TableStepper.java | 420 +++++++++++------ .../standard-testcases/table-body_basic_2.xml | 4 - ...table_border-collapse_collapse_conditionals.xml | 6 +- .../table_border-collapse_collapse_omitHF.xml | 6 +- ...e_border-collapse_separate_border-spacing_2.xml | 40 +- .../standard-testcases/table_border_padding_2.xml | 12 +- .../standard-testcases/table_bug36403.xml | 17 +- .../standard-testcases/table_bug37270.xml | 4 +- .../standard-testcases/table_empty-cells.xml | 12 +- .../standard-testcases/table_row-delay.xml | 437 +++++++++++++++++ .../table_row-delay_fixed-row-height.xml | 161 +++++++ .../table_row-delay_header-footer.xml | 525 +++++++++++++++++++++ .../table_space-before_space-after_1.xml | 9 +- 18 files changed, 1675 insertions(+), 344 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table_row-delay.xml create mode 100644 test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml create mode 100644 test/layoutengine/standard-testcases/table_row-delay_header-footer.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 4321c32b8..671204dfe 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -22,6 +22,8 @@ package org.apache.fop.layoutmgr.table; import java.util.List; import java.util.ListIterator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; @@ -36,6 +38,9 @@ import org.apache.fop.layoutmgr.KnuthPenalty; * A cell playing in the construction of steps for a row-group. */ class ActiveCell { + + private static Log log = LogFactory.getLog(ActiveCell.class); + private PrimaryGridUnit pgu; /** Knuth elements for this active cell. */ private List elementList; @@ -45,29 +50,36 @@ class ActiveCell { private int endRowIndex; /** Length of the Knuth elements not yet included in the steps. */ private int remainingLength; - /** Heights of the rows (in the row-group) preceding the one where this cell starts. */ - private int previousRowsLength; /** Total length of this cell's content plus the lengths of the previous rows. */ private int totalLength; /** Length of the Knuth elements already included in the steps. */ private int includedLength; - private int borderBeforeNormal; - private int borderBeforeLeading; - private int borderAfterNormal; - private int borderAfterTrailing; private int paddingBeforeNormal; private int paddingBeforeLeading; private int paddingAfterNormal; private int paddingAfterTrailing; + private int bpBeforeNormal; + private int bpBeforeLeading; + private int bpAfterNormal; + private int bpAfterTrailing; + + /** True if the next CellPart that will be created will be the last one for this cell. */ + private boolean lastCellPart; + private boolean keepWithNextSignal; private int spanIndex = 0; - private CellPart lastCellPart; private Step previousStep; private Step nextStep; + /** + * The step following nextStep. Computing it early allows to calculate + * {@link Step#condBeforeContentLength}, thus to easily determine the remaining + * length. That also helps for {@link #increaseCurrentStep(int)}. + */ + private Step afterNextStep; /** * Auxiliary class to store all the informations related to a breaking step. @@ -84,16 +96,13 @@ class ActiveCell { /** Length of the penalty ending this step, if any. */ private int penaltyLength; /** - * Length of the optional content for the next step. That is, content that will - * not appear if the next step starts a new page. + * Length of the optional content at the beginning of the step. That is, content + * that will not appear if this step starts a new page. */ - private int nextCondBeforeContentLength; + private int condBeforeContentLength; Step(int contentLength) { this.contentLength = contentLength; - // TODO necessary if a cell part must be created while this cell hasn't - // contributed any content yet. To be removed along with the 900-penalty - // mechanism this.end = -1; } @@ -107,7 +116,12 @@ class ActiveCell { this.contentLength = other.contentLength; this.totalLength = other.totalLength; this.penaltyLength = other.penaltyLength; - this.nextCondBeforeContentLength = other.nextCondBeforeContentLength; + this.condBeforeContentLength = other.condBeforeContentLength; + } + + /** {@inheritDoc} */ + public String toString() { + return "Step: start=" + start + " end=" + end + " length=" + totalLength; } } @@ -116,16 +130,17 @@ class ActiveCell { this.pgu = pgu; CommonBorderPaddingBackground bordersPaddings = pgu.getCell() .getCommonBorderPaddingBackground(); - borderBeforeNormal = pgu.getBeforeBorderWidth(0, ConditionalBorder.NORMAL); - borderBeforeLeading = pgu.getBeforeBorderWidth(0, ConditionalBorder.REST); - borderAfterNormal = pgu.getAfterBorderWidth(ConditionalBorder.NORMAL); - borderAfterTrailing = pgu.getAfterBorderWidth(0, ConditionalBorder.REST); TableCellLayoutManager cellLM = pgu.getCellLM(); paddingBeforeNormal = bordersPaddings.getPaddingBefore(false, cellLM); paddingBeforeLeading = bordersPaddings.getPaddingBefore(true, cellLM); paddingAfterNormal = bordersPaddings.getPaddingAfter(false, cellLM); paddingAfterTrailing = bordersPaddings.getPaddingAfter(true, cellLM); - + bpBeforeNormal = paddingBeforeNormal + + pgu.getBeforeBorderWidth(0, ConditionalBorder.NORMAL); + bpBeforeLeading = paddingBeforeLeading + + pgu.getBeforeBorderWidth(0, ConditionalBorder.REST); + bpAfterNormal = paddingAfterNormal + pgu.getAfterBorderWidth(ConditionalBorder.NORMAL); + bpAfterTrailing = paddingAfterTrailing + pgu.getAfterBorderWidth(0, ConditionalBorder.REST); boolean makeBoxForWholeRow = false; if (row.getExplicitHeight().min > 0) { boolean contentsSmaller = ElementListUtils.removeLegalBreaks( @@ -142,23 +157,29 @@ class ActiveCell { elementList = new java.util.ArrayList(1); int height = row.getHeight().opt; height -= 2 * tableLM.getHalfBorderSeparationBPD(); - height -= borderBeforeNormal + borderAfterNormal; // TODO conditionals - height -= paddingBeforeNormal + paddingAfterNormal; + height -= bpBeforeNormal + bpAfterNormal; elementList.add(new KnuthBoxCellWithBPD(height)); } else { elementList = pgu.getElements(); } knuthIter = elementList.listIterator(); includedLength = -1; // Avoid troubles with cells having content of zero length - this.previousRowsLength = previousRowsLength; totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1; keepWithNextSignal = false; remainingLength = totalLength - previousRowsLength; - nextStep = new Step(previousRowsLength); - previousStep = new Step(nextStep); - goToNextLegalBreak(); + afterNextStep = new Step(previousRowsLength); + previousStep = new Step(afterNextStep); + gotoNextLegalBreak(); + nextStep = new Step(afterNextStep); + if (afterNextStep.end < elementList.size() - 1) { + gotoNextLegalBreak(); + } + } + + PrimaryGridUnit getPrimaryGridUnit() { + return pgu; } /** @@ -175,31 +196,30 @@ class ActiveCell { * Returns the length of this cell's content not yet included in the steps, plus the * cell's borders and paddings if applicable. * - * @param activeRowIndex index of the row currently considered - * @return the remaining length, or zero if the cell doesn't end on the given row. + * @return the remaining length, zero if the cell is finished */ - int getRemainingHeight(int activeRowIndex) { - if (!endsOnRow(activeRowIndex)) { - return 0; - } else if (includedLength == totalLength) { + int getRemainingLength() { + if (includedInLastStep() && (nextStep.end == elementList.size() - 1)) { + // The cell is finished return 0; } else { - return borderBeforeLeading + paddingBeforeLeading + remainingLength - + paddingAfterNormal + borderAfterNormal; + return bpBeforeLeading + remainingLength + bpAfterNormal; } } - private void goToNextLegalBreak() { - nextStep.penaltyLength = 0; + private void gotoNextLegalBreak() { + afterNextStep.penaltyLength = 0; + afterNextStep.condBeforeContentLength = 0; boolean breakFound = false; boolean prevIsBox = false; + boolean boxFound = false; while (!breakFound && knuthIter.hasNext()) { KnuthElement el = (KnuthElement) knuthIter.next(); if (el.isPenalty()) { prevIsBox = false; if (el.getP() < KnuthElement.INFINITE) { // First legal break point - nextStep.penaltyLength = el.getW(); + afterNextStep.penaltyLength = el.getW(); breakFound = true; } } else if (el.isGlue()) { @@ -207,24 +227,83 @@ class ActiveCell { // Second legal break point breakFound = true; } else { - nextStep.contentLength += el.getW(); + afterNextStep.contentLength += el.getW(); + if (!boxFound) { + afterNextStep.condBeforeContentLength += el.getW(); + } } prevIsBox = false; } else { prevIsBox = true; - nextStep.contentLength += el.getW(); + boxFound = true; + afterNextStep.contentLength += el.getW(); } } - nextStep.end = knuthIter.nextIndex() - 1; - if (nextStep.end == elementList.size() - 1) { - // TODO wait that every cell on the row has finished before including border-after!! - nextStep.totalLength = borderBeforeNormal + paddingBeforeNormal - + nextStep.contentLength + nextStep.penaltyLength - + paddingAfterNormal + borderAfterNormal; - } else { - nextStep.totalLength = borderBeforeNormal + paddingBeforeNormal - + nextStep.contentLength + nextStep.penaltyLength - + paddingAfterTrailing + borderAfterTrailing; + afterNextStep.end = knuthIter.nextIndex() - 1; + afterNextStep.totalLength = bpBeforeNormal + + afterNextStep.contentLength + afterNextStep.penaltyLength + + bpAfterTrailing; + } + + /** + * Returns the minimal step that is needed for this cell to contribute some content. + * + * @return the step for this cell's first legal break + */ + int getFirstStep() { + log.debug(this + ": min first step = " + nextStep.totalLength); + return nextStep.totalLength; + } + + /** + * Returns the last step for this cell. + * + * @return the step including all of the cell's content plus the normal borders and paddings + */ + int getLastStep() { + assert nextStep.end == elementList.size() - 1; + assert nextStep.contentLength == totalLength && nextStep.penaltyLength == 0; + int lastStep = bpBeforeNormal + totalLength + bpAfterNormal; + log.debug(this + ": last step = " + lastStep); + return lastStep; + } + + /** + * Increases the next step up to the given limit. + * + * @param limit the length up to which the next step is allowed to increase + * @see #signalRowFirstStep(int) + * @see #signalRowLastStep(int) + */ + private void increaseCurrentStep(int limit) { + while (afterNextStep.totalLength <= limit) { + nextStep.set(afterNextStep); + if (afterNextStep.end >= elementList.size() - 1) { + break; + } + gotoNextLegalBreak(); + } + } + + /** + * Gets the selected first step for the current row. If this cell's first step is + * smaller, then it may be able to add some more of its content, since there will be + * no break before the given step anyway. + * + * @param firstStep the current row's first step + */ + void signalRowFirstStep(int firstStep) { + increaseCurrentStep(firstStep); + if (log.isTraceEnabled()) { + log.trace(this + ": first step increased to " + nextStep.totalLength); + } + } + + /** See {@link #signalRowFirstStep(int)}. */ + void signalRowLastStep(int lastStep) { + increaseCurrentStep(lastStep); + if (log.isTraceEnabled()) { + log.trace(this + ": next step increased to " + nextStep.totalLength); } } @@ -236,11 +315,15 @@ class ActiveCell { int getNextStep() { if (includedInLastStep()) { previousStep.set(nextStep); - nextStep.start = nextStep.end + 1; - if (!knuthIter.hasNext()) { + if (nextStep.end >= elementList.size() - 1) { + nextStep.start = elementList.size(); return -1; } else { - goToNextLegalBreak(); + nextStep.set(afterNextStep); + nextStep.start = previousStep.end + 1; + if (afterNextStep.end < elementList.size() - 1) { + gotoNextLegalBreak(); + } } } return nextStep.totalLength; @@ -255,52 +338,49 @@ class ActiveCell { * its own step may be included or not. * * @param minStep length of the chosen next step - * @return */ - boolean signalMinStep(int minStep) { + void signalNextStep(int minStep) { if (nextStep.totalLength <= minStep) { includedLength = nextStep.contentLength; - computeRemainingLength(); - return false; - } else { - return borderBeforeNormal + paddingBeforeNormal + previousRowsLength - + paddingAfterTrailing + borderAfterTrailing > minStep; + remainingLength = totalLength - includedLength - afterNextStep.condBeforeContentLength; } } - void endRow(int rowIndex) { - if (endsOnRow(rowIndex)) { - int bpAfterNormal = paddingAfterNormal + borderAfterNormal; - int bpAfterLast = paddingAfterNormal - + pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING); - lastCellPart.setLast(bpAfterNormal, bpAfterLast); - } else { - spanIndex++; - borderBeforeLeading = pgu.getBeforeBorderWidth(spanIndex, ConditionalBorder.REST); - borderAfterTrailing = pgu.getAfterBorderWidth(spanIndex, ConditionalBorder.REST); - } + /** + * Receives indication that the next row is about to start, and that (collapse) + * borders must be updated accordingly. + */ + void nextRowStarts() { + spanIndex++; + // Subtract the old value of bpAfterTrailing... + nextStep.totalLength -= bpAfterTrailing; + afterNextStep.totalLength -= bpAfterTrailing; + + bpAfterTrailing = paddingAfterTrailing + + pgu.getAfterBorderWidth(spanIndex, ConditionalBorder.REST); + + // ... and add the new one + nextStep.totalLength += bpAfterTrailing; + afterNextStep.totalLength += bpAfterTrailing; + // TODO if the new after border is greater than the previous one the next step may + // increase further than the row's first step, which can lead to wrong output in + // some cases } /** - * Computes the length of the cell's content after the current legal break. Discards - * every glue or penalty following the break if needed. The cell's borders and - * paddings are not considered here. + * Receives indication that the current row is ending, and that (collapse) borders + * must be updated accordingly. + * + * @param rowIndex the index of the ending row */ - private void computeRemainingLength() { - remainingLength = totalLength - nextStep.contentLength; - nextStep.nextCondBeforeContentLength = 0; - // Save the current location in the element list - int oldIndex = knuthIter.nextIndex(); - KnuthElement el; - while (knuthIter.hasNext() && !(el = (KnuthElement) knuthIter.next()).isBox()) { - if (el.isGlue()) { - remainingLength -= el.getW(); - nextStep.nextCondBeforeContentLength += el.getW(); - } - } - // Reset the iterator to the current location - while (knuthIter.nextIndex() > oldIndex) { - knuthIter.previous(); + void endRow(int rowIndex) { + if (endsOnRow(rowIndex)) { + bpAfterTrailing = paddingAfterNormal + + pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING); + lastCellPart = true; + } else { + bpBeforeLeading = paddingBeforeLeading + + pgu.getBeforeBorderWidth(spanIndex + 1, ConditionalBorder.REST); } } @@ -316,21 +396,14 @@ class ActiveCell { } /** - * Returns true if this cell has already started to contribute some content to the steps. + * Returns true if this cell would be finished after the given step. That is, it would + * be included in the step and the end of its content would be reached. * - * @return true if this cell's first step is inferior or equal to the current one + * @param step the next step + * @return true if this cell finishes at the given step */ - boolean hasStarted() { - return includedLength >= 0; - } - - /** - * Returns true if this cell has contributed all of its content to the steps. - * - * @return true if the end of this cell is reached - */ - boolean isFinished() { - return includedInLastStep() && (nextStep.end == elementList.size() - 1); + boolean finishes(int step) { + return nextStep.totalLength <= step && (nextStep.end == elementList.size() - 1); } /** @@ -348,39 +421,31 @@ class ActiveCell { keepWithNextSignal = true; } } - int bpBeforeNormal; int bpBeforeFirst; - int bpAfterNormal; - int bpAfterLast; if (nextStep.start == 0) { - bpBeforeNormal = borderBeforeNormal + paddingBeforeNormal; bpBeforeFirst = pgu.getBeforeBorderWidth(0, ConditionalBorder.LEADING_TRAILING) + paddingBeforeNormal; } else { - bpBeforeNormal = 0; - bpBeforeFirst = borderBeforeLeading + paddingBeforeLeading; + bpBeforeFirst = bpBeforeLeading; } - bpAfterNormal = 0; - bpAfterLast = paddingAfterTrailing + borderAfterTrailing; - int length = nextStep.contentLength - previousStep.contentLength - - previousStep.nextCondBeforeContentLength; + int length = nextStep.contentLength - nextStep.condBeforeContentLength + - previousStep.contentLength; if (!includedInLastStep() || nextStep.start == elementList.size()) { - lastCellPart = new CellPart(pgu, nextStep.start, previousStep.end, + return new CellPart(pgu, nextStep.start, previousStep.end, lastCellPart, 0, 0, previousStep.penaltyLength, - bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterLast); + bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing); } else if (nextStep.start == 0 && nextStep.end == 0 && elementList.size() == 1 && elementList.get(0) instanceof KnuthBoxCellWithBPD) { //Special case: Cell with fixed BPD - lastCellPart = new CellPart(pgu, 0, pgu.getElements().size() - 1, - previousStep.nextCondBeforeContentLength, length, nextStep.penaltyLength, - bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterLast); + return new CellPart(pgu, 0, pgu.getElements().size() - 1, lastCellPart, + nextStep.condBeforeContentLength, length, nextStep.penaltyLength, + bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing); } else { - lastCellPart = new CellPart(pgu, nextStep.start, nextStep.end, - previousStep.nextCondBeforeContentLength, length, nextStep.penaltyLength, - bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterLast); + return new CellPart(pgu, nextStep.start, nextStep.end, lastCellPart, + nextStep.condBeforeContentLength, length, nextStep.penaltyLength, + bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing); } - return lastCellPart; } boolean isLastForcedBreak() { @@ -395,6 +460,13 @@ class ActiveCell { return keepWithNextSignal; } + + /** {@inheritDoc} */ + public String toString() { + return "Cell " + (pgu.getRowIndex() + 1) + "." + (pgu.getColIndex() + 1); + } + + /** * Marker class denoting table cells fitting in just one box (no legal break inside). */ diff --git a/src/java/org/apache/fop/layoutmgr/table/CellPart.java b/src/java/org/apache/fop/layoutmgr/table/CellPart.java index f6c292f97..2adb543a9 100644 --- a/src/java/org/apache/fop/layoutmgr/table/CellPart.java +++ b/src/java/org/apache/fop/layoutmgr/table/CellPart.java @@ -49,6 +49,7 @@ class CellPart { * @param pgu Primary grid unit * @param start starting element * @param end ending element + * @param last true if this cell part is the last one for the cell * @param condBeforeContentLength length of the additional content that will have to * be displayed if this part will be the first one on the page * @param length length of the content represented by this cell part @@ -58,16 +59,17 @@ class CellPart { * @param bpBeforeFirst width of (possibly optional) border- and padding-before if * this part will be the first one on the page * @param bpAfterNormal width of border- and padding-after in the normal case - * @param bpAfterFirst width of (possibly optional) border- and padding-after if this + * @param bpAfterLast width of (possibly optional) border- and padding-after if this * part will be the last one on the page */ - protected CellPart(PrimaryGridUnit pgu, int start, int end, + protected CellPart(PrimaryGridUnit pgu, int start, int end, boolean last, int condBeforeContentLength, int length, int condAfterContentLength, int bpBeforeNormal, int bpBeforeFirst, int bpAfterNormal, int bpAfterLast) { this.pgu = pgu; this.start = start; this.end = end; + this.isLast = last; this.condBeforeContentLength = condBeforeContentLength; this.length = length; this.condAfterContentLength = condAfterContentLength; @@ -87,12 +89,6 @@ class CellPart { return isLast; } - void setLast(int bpNormal, int bpLast) { - isLast = true; - bpAfterNormal = bpNormal; - bpAfterLast = bpLast; - } - int getBorderPaddingBefore(boolean firstOnPage) { if (firstOnPage) { return bpBeforeFirst; diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 54ac4867a..26880faea 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -96,14 +96,19 @@ class RowPainter { * @param tcpos a position representing the row fragment */ void handleTableContentPosition(TableContentPosition tcpos) { - if (tcpos.row != currentRow && currentRow != null) { - addAreasAndFlushRow(false, false); - } if (log.isDebugEnabled()) { log.debug("===handleTableContentPosition(" + tcpos); } - rowFO = tcpos.row.getTableRow(); - currentRow = tcpos.row; + if (currentRow == null) { + currentRow = tcpos.getNewPageRow(); + } else { + EffRow row = tcpos.getRow(); + if (row.getIndex() > currentRow.getIndex()) { + addAreasAndFlushRow(false, false); + currentRow = row; + } + } + rowFO = currentRow.getTableRow(); if (firstRowIndex < 0) { firstRowIndex = currentRow.getIndex(); if (firstRowOnPageIndex < 0) { diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 1c748a5cf..baf1bd369 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -403,12 +403,12 @@ public class TableContentLayoutManager implements PercentBaseContext { body = part.pgu.getBody(); } if (tcpos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP) - && tcpos.row.getFlag(EffRow.FIRST_IN_PART)) { + && tcpos.getRow().getFlag(EffRow.FIRST_IN_PART)) { firstPos = true; } if (tcpos.getFlag(TableContentPosition.LAST_IN_ROWGROUP) - && tcpos.row.getFlag(EffRow.LAST_IN_PART)) { + && tcpos.getRow().getFlag(EffRow.LAST_IN_PART)) { log.trace("LAST_IN_ROWGROUP + LAST_IN_PART"); handleMarkersAndPositions(lst, body, firstPos, true, painter); //reset diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java index 68f55d88f..e702c58a9 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java @@ -39,10 +39,12 @@ class TableContentPosition extends Position { /** 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 +56,27 @@ class TableContentPosition extends Position { 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; } /** diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 3e038604a..aa35d0aee 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -52,51 +52,62 @@ public class TableStepper { /** 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 + * Main constructor + * @param tclm The parent TableContentLayoutManager */ - private EffRow getActiveRow() { - return rowGroup[activeRowIndex]; + 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 +122,34 @@ public class TableStepper { 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 +158,68 @@ public class TableStepper { /** * 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 */; + 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)); + } + } + boolean forcedBreak = false; int breakClass = -1; //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(); } } + CellPart part = activeCell.createCellPart(); + cellParts.add(part); 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,48 +236,29 @@ public class TableStepper { } int p = 0; - boolean allCellsHaveContributed = true; signalKeepWithNext = false; for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); - allCellsHaveContributed &= activeCell.hasStarted(); signalKeepWithNext |= 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) { - 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!"); - } p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0) } + if (rowHeightSmallerThanFirstStep) { + rowHeightSmallerThanFirstStep = false; + p = KnuthPenalty.INFINITE; + } returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, 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; - } + step = getNextStep(); + } while (step >= 0); 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. @@ -268,23 +271,77 @@ public class TableStepper { } /** - * 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 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 size of the increment, -1 if no next step is available (end of row-group reached) + * @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 +352,149 @@ public class TableStepper { 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) { 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; + activeCell.signalNextStep(step); + } + } + + /** + * Determines if the given step will finish the current row, and if so switch to the + * last step for this row. + *

    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.

    + *

    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.

    + * + * @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) { + TableRow rowFO = rowGroup[activeRowIndex].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; + activateCells(nextActiveCells, activeRowIndex + 1); + rowFO = rowGroup[activeRowIndex + 1].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)); + } + 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 */ diff --git a/test/layoutengine/standard-testcases/table-body_basic_2.xml b/test/layoutengine/standard-testcases/table-body_basic_2.xml index dbea5e4dd..0e7b1fbd1 100644 --- a/test/layoutengine/standard-testcases/table-body_basic_2.xml +++ b/test/layoutengine/standard-testcases/table-body_basic_2.xml @@ -63,10 +63,6 @@ - - - - diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_conditionals.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_conditionals.xml index a653be423..37eed9dd0 100644 --- a/test/layoutengine/standard-testcases/table_border-collapse_collapse_conditionals.xml +++ b/test/layoutengine/standard-testcases/table_border-collapse_collapse_conditionals.xml @@ -34,9 +34,9 @@ Before the table diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_omitHF.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_omitHF.xml index d13b257c9..db873b4a4 100644 --- a/test/layoutengine/standard-testcases/table_border-collapse_collapse_omitHF.xml +++ b/test/layoutengine/standard-testcases/table_border-collapse_collapse_omitHF.xml @@ -34,9 +34,9 @@ Before the table diff --git a/test/layoutengine/standard-testcases/table_border-collapse_separate_border-spacing_2.xml b/test/layoutengine/standard-testcases/table_border-collapse_separate_border-spacing_2.xml index 52f0de812..b66379be3 100644 --- a/test/layoutengine/standard-testcases/table_border-collapse_separate_border-spacing_2.xml +++ b/test/layoutengine/standard-testcases/table_border-collapse_separate_border-spacing_2.xml @@ -134,19 +134,17 @@ - - - - - - - - - + - - + + + + + + + + @@ -156,19 +154,17 @@ - - - - - - - - - + - - + + + + + + + + diff --git a/test/layoutengine/standard-testcases/table_border_padding_2.xml b/test/layoutengine/standard-testcases/table_border_padding_2.xml index 0e9a9e21f..590c455f8 100644 --- a/test/layoutengine/standard-testcases/table_border_padding_2.xml +++ b/test/layoutengine/standard-testcases/table_border_padding_2.xml @@ -97,17 +97,16 @@ and threw it up on high and caught it; and this ball was her favorite plaything. - - + - + - + @@ -124,7 +123,6 @@ and threw it up on high and caught it; and this ball was her favorite plaything. 8 8 8 - 8 @@ -148,10 +146,8 @@ and threw it up on high and caught it; and this ball was her favorite plaything. - - - + diff --git a/test/layoutengine/standard-testcases/table_bug36403.xml b/test/layoutengine/standard-testcases/table_bug36403.xml index ee2116b50..1626a6f8d 100644 --- a/test/layoutengine/standard-testcases/table_bug36403.xml +++ b/test/layoutengine/standard-testcases/table_bug36403.xml @@ -79,22 +79,17 @@ - - - - + 3 - - - + - - - - + + + + 3 diff --git a/test/layoutengine/standard-testcases/table_bug37270.xml b/test/layoutengine/standard-testcases/table_bug37270.xml index e2554d40a..0d4d3dae1 100644 --- a/test/layoutengine/standard-testcases/table_bug37270.xml +++ b/test/layoutengine/standard-testcases/table_bug37270.xml @@ -73,9 +73,9 @@ - + - + 3 diff --git a/test/layoutengine/standard-testcases/table_empty-cells.xml b/test/layoutengine/standard-testcases/table_empty-cells.xml index e9911fb4b..a8ea5a5c7 100644 --- a/test/layoutengine/standard-testcases/table_empty-cells.xml +++ b/test/layoutengine/standard-testcases/table_empty-cells.xml @@ -87,15 +87,19 @@ 6 - - - + - 16 + + + + + + + 10 diff --git a/test/layoutengine/standard-testcases/table_row-delay.xml b/test/layoutengine/standard-testcases/table_row-delay.xml new file mode 100644 index 000000000..a5d88cf46 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_row-delay.xml @@ -0,0 +1,437 @@ + + + + + +

    + Tests for the row delaying mechanism. +

    +
    + + + + + + + + + + + + 1. Before the table. + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + + + Cell 1.2 + + + Cell 1.3 + + + + + Cell 2.2 + + + Cell 2.3 + Cell 2.3 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + Cell 3.3 + Cell 3.3 + + + + + + + + + + + 2. Before the table. + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + Cell 1.1 Line 5 + Cell 1.1 Line 6 + + + Cell 1.2 + + + Cell 1.3 Line 1 + Cell 1.3 Line 2 + Cell 1.3 Line 3 + Cell 1.3 Line 4 + Cell 1.3 Line 5 + Cell 1.3 Line 6 + + + + + Cell 2.2 + Cell 2.2 + + + + + + + + + + + 3. Before the table. + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + Cell 1.1 Line 5 + Cell 1.1 Line 6 + + + Cell 1.2 + + + Cell 1.3 Line 1 + Cell 1.3 Line 2 + Cell 1.3 Line 3 + Cell 1.3 Line 4 + Cell 1.3 Line 5 + Cell 1.3 Line 6 + + + + + Cell 2.2 + Cell 2.2 + + + + + + + + + + + 4. Before the table. + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + Cell 1.1 Line 5 + Cell 1.1 Line 6 + + + Cell 1.2 + + + Cell 1.3 Line 1 + Cell 1.3 Line 2 + Cell 1.3 Line 3 + Cell 1.3 Line 4 + Cell 1.3 Line 5 + Cell 1.3 Line 6 + + + + + Cell 2.2 + Cell 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml b/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml new file mode 100644 index 000000000..70990de62 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml @@ -0,0 +1,161 @@ + + + + + +

    + Tests the row delaying mechanism when a row has a forced height. +

    +
    + + + + + + + + + + + Before the table. + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + Cell 1.1 Line 5 + Cell 1.1 Line 6 + + + Cell 1.2 + + + Cell 1.3 Line 1 + Cell 1.3 Line 2 + Cell 1.3 Line 3 + Cell 1.3 Line 4 + Cell 1.3 Line 5 + Cell 1.3 Line 6 + + + + + Cell 2.2 + Cell 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + 3 + + +
    diff --git a/test/layoutengine/standard-testcases/table_row-delay_header-footer.xml b/test/layoutengine/standard-testcases/table_row-delay_header-footer.xml new file mode 100644 index 000000000..e36f53834 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_row-delay_header-footer.xml @@ -0,0 +1,525 @@ + + + + + +

    + Tests the row delaying mechanism in presence of headers and footers. +

    +
    + + + + + + + + + + + + 1. Before the table. + + + + + Header 1.1 + + + Header 1.2 + + + Header 1.3 + + + + + Footer 1.1 + + + Footer 1.2 + + + Footer 1.3 + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + + + Cell 1.2 + + + Cell 1.3 + + + + + Cell 2.2 + + + Cell 2.3 + Cell 2.3 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + Cell 3.3 + Cell 3.3 + + + + + + + + + + + 2. Before the table. + + + + + Header 1.1 + + + Header 1.2 + + + Header 1.3 + + + + + Footer 1.1 + + + Footer 1.2 + + + Footer 1.3 + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + Cell 1.1 Line 5 + Cell 1.1 Line 6 + + + Cell 1.2 + + + Cell 1.3 Line 1 + Cell 1.3 Line 2 + Cell 1.3 Line 3 + Cell 1.3 Line 4 + Cell 1.3 Line 5 + Cell 1.3 Line 6 + + + + + Cell 2.2 + Cell 2.2 + + + + + + + + + + + 3. Before the table. + + + + + Header 1.1 + + + Header 1.2 + + + Header 1.3 + + + + + Footer 1.1 + + + Footer 1.2 + + + Footer 1.3 + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + Cell 1.1 Line 5 + Cell 1.1 Line 6 + + + Cell 1.2 + + + Cell 1.3 Line 1 + Cell 1.3 Line 2 + Cell 1.3 Line 3 + Cell 1.3 Line 4 + Cell 1.3 Line 5 + Cell 1.3 Line 6 + + + + + Cell 2.2 + Cell 2.2 + + + + + + + + + + + 4. Before the table. + + + + + Header 1.1 + + + Header 1.2 + + + Header 1.3 + + + + + Footer 1.1 + + + Footer 1.2 + + + Footer 1.3 + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + Cell 1.1 Line 5 + Cell 1.1 Line 6 + + + Cell 1.2 + + + Cell 1.3 Line 1 + Cell 1.3 Line 2 + Cell 1.3 Line 3 + Cell 1.3 Line 4 + Cell 1.3 Line 5 + Cell 1.3 Line 6 + + + + + Cell 2.2 + Cell 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table_space-before_space-after_1.xml b/test/layoutengine/standard-testcases/table_space-before_space-after_1.xml index 8b0f18359..6c05f3514 100644 --- a/test/layoutengine/standard-testcases/table_space-before_space-after_1.xml +++ b/test/layoutengine/standard-testcases/table_space-before_space-after_1.xml @@ -95,11 +95,11 @@ Two blocks, testing conditionality="discard". - + - + - + @@ -110,7 +110,6 @@ Two blocks, testing conditionality="discard". 2 2 2 - 2 @@ -137,8 +136,6 @@ Two blocks, testing conditionality="discard".
    - - -- cgit v1.2.3 From 28408f6194234ad3273eb072209fa90f2aada369 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 8 Feb 2008 12:14:01 +0000 Subject: Also display the column index in the toString method git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@619856 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 4c4ffa9ce..cff3c2ac1 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -302,6 +302,7 @@ public class PrimaryGridUnit extends GridUnit { public String toString() { StringBuffer sb = new StringBuffer(super.toString()); sb.append(" rowIndex=").append(rowIndex); + sb.append(" colIndex=").append(colIndex); return sb.toString(); } -- cgit v1.2.3 From 18cafe4f20b84321b9788c110a2a08b17d51737d Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 8 Feb 2008 13:23:47 +0000 Subject: Added missing width for Euro glyph. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@619870 13f79535-47bb-0310-9956-ffa450edef68 --- src/codegen/fonts/Symbol.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/codegen/fonts/Symbol.xml b/src/codegen/fonts/Symbol.xml index 90685eb5b..c0dce043a 100644 --- a/src/codegen/fonts/Symbol.xml +++ b/src/codegen/fonts/Symbol.xml @@ -124,6 +124,7 @@ + -- cgit v1.2.3 From 308f50089a6a3248549e761f4941a7cf1eb622b4 Mon Sep 17 00:00:00 2001 From: Simon Pepping Date: Fri, 8 Feb 2008 19:20:27 +0000 Subject: In addKnuthElementsForBorderPaddingXXX, if the returnlist is a BlockKnuthSequence, the border and padding should be added to the first or last paragraph inside it, but it is too late to do that now. At least, avoid adding it to the bpd sequence. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@619979 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/layoutmgr/inline/InlineLayoutManager.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index b10e41132..b449b6689 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -548,6 +548,14 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { */ protected void addKnuthElementsForBorderPaddingStart(List returnList) { //Border and Padding (start) + /** + * If the returnlist is a BlockKnuthSequence, the border and padding should be added + * to the first paragraph inside it, but it is too late to do that now. + * At least, avoid adding it to the bpd sequence. + */ + if (returnList instanceof BlockKnuthSequence) { + return; + } CommonBorderPaddingBackground borderAndPadding = fobj.getCommonBorderPaddingBackground(); if (borderAndPadding != null) { int ipStart = borderAndPadding.getBorderStartWidth(false) @@ -564,6 +572,14 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { */ protected void addKnuthElementsForBorderPaddingEnd(List returnList) { //Border and Padding (after) + /** + * If the returnlist is a BlockKnuthSequence, the border and padding should be added + * to the last paragraph inside it, but it is too late to do that now. + * At least, avoid adding it to the bpd sequence. + */ + if (returnList instanceof BlockKnuthSequence) { + return; + } CommonBorderPaddingBackground borderAndPadding = fobj.getCommonBorderPaddingBackground(); if (borderAndPadding != null) { int ipEnd = borderAndPadding.getBorderEndWidth(false) -- cgit v1.2.3 From 7ee30cf256088a4cc15e94915e84ba9b7fb8c790 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 10 Feb 2008 12:31:46 +0000 Subject: Some minor tweaks: * added convenience shortcut to PropertyInfo to get to the user agent. * replaced occurrences to use the shortcut in PropertyParser and RGBColorFunction. * PropertyParser -> 0% of a length always yields FixedLength.ZERO_FIXED_LENGTH git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620272 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/expr/PropertyInfo.java | 12 ++++++++++++ src/java/org/apache/fop/fo/expr/PropertyParser.java | 9 ++++++--- src/java/org/apache/fop/fo/expr/RGBColorFunction.java | 10 ++++------ 3 files changed, 22 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/PropertyInfo.java b/src/java/org/apache/fop/fo/expr/PropertyInfo.java index 491be64fc..039e8783e 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyInfo.java +++ b/src/java/org/apache/fop/fo/expr/PropertyInfo.java @@ -21,6 +21,7 @@ package org.apache.fop.fo.expr; import java.util.Stack; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.PercentBase; import org.apache.fop.fo.Constants; @@ -114,6 +115,17 @@ public class PropertyInfo { } } + /** + * Convenience shortcut to get a reference to the FOUserAgent + * + * @return the FOUserAgent + */ + protected FOUserAgent getUserAgent() { + return (plist.getFObj() != null) + ? plist.getFObj().getUserAgent() + : null; + } + private PercentBase getFunctionPercentBase() { if (stkFunction != null) { Function f = (Function)stkFunction.peek(); diff --git a/src/java/org/apache/fop/fo/expr/PropertyParser.java b/src/java/org/apache/fop/fo/expr/PropertyParser.java index cd3393ef3..c63142773 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyParser.java +++ b/src/java/org/apache/fop/fo/expr/PropertyParser.java @@ -275,6 +275,11 @@ public final class PropertyParser extends PropertyTokenizer { prop = NumberProperty.getInstance(pcval * pcBase.getBaseValue()); } else if (pcBase.getDimension() == 1) { if (pcBase instanceof LengthBase) { + if (pcval == 0.0) { + prop = FixedLength.ZERO_FIXED_LENGTH; + break; + } + //If the base of the percentage is known //and absolute, it can be resolved by the //parser @@ -319,9 +324,7 @@ public final class PropertyParser extends PropertyTokenizer { break; case TOK_COLORSPEC: - prop = ColorProperty.getInstance( - propInfo.getPropertyList().getFObj().getUserAgent(), - currentTokenValue); + prop = ColorProperty.getInstance(propInfo.getUserAgent(), currentTokenValue); break; case TOK_FUNCTION_LPAR: diff --git a/src/java/org/apache/fop/fo/expr/RGBColorFunction.java b/src/java/org/apache/fop/fo/expr/RGBColorFunction.java index 9b3287154..ba39662eb 100644 --- a/src/java/org/apache/fop/fo/expr/RGBColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/RGBColorFunction.java @@ -19,7 +19,6 @@ package org.apache.fop.fo.expr; -import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.datatypes.PercentBase; import org.apache.fop.fo.properties.ColorProperty; @@ -47,14 +46,13 @@ class RGBColorFunction extends FunctionBase { /** {@inheritDoc} */ public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { - FOUserAgent ua = (pInfo == null) - ? null - : (pInfo.getFO() == null ? null : pInfo.getFO().getUserAgent()); - return ColorProperty.getInstance(ua, "rgb(" + args[0] + "," + args[1] + "," + args[2] + ")"); + return ColorProperty.getInstance(pInfo.getUserAgent(), + "rgb(" + args[0] + "," + + args[1] + "," + args[2] + ")"); } - static class RGBPercentBase implements PercentBase { + private static class RGBPercentBase implements PercentBase { public int getDimension() { return 0; } -- cgit v1.2.3 From 2d84b6d1ed7b09a95cad0305e8377f397e455f8f Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 10 Feb 2008 12:50:47 +0000 Subject: Revisit background-position shorthand implementation: always convert to percentages (more possibilities/precision). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620276 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 24 +++- .../fo/properties/BackgroundPositionShorthand.java | 126 +++++++++++++++++++++ .../BackgroundPositionShorthandParser.java | 61 ---------- .../background-position-shorthand-test.fo | 36 ++++-- 4 files changed, 171 insertions(+), 76 deletions(-) create mode 100644 src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java delete mode 100644 src/java/org/apache/fop/fo/properties/BackgroundPositionShorthandParser.java (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 434d4acaf..b78ec49c4 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -26,7 +26,7 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.flow.table.TableFObj.ColumnNumberPropertyMaker; -import org.apache.fop.fo.properties.BackgroundPositionShorthandParser; +import org.apache.fop.fo.properties.BackgroundPositionShorthand; import org.apache.fop.fo.properties.BorderSpacingShorthandParser; import org.apache.fop.fo.properties.BorderWidthPropertyMaker; import org.apache.fop.fo.properties.BoxPropShorthandParser; @@ -2534,15 +2534,33 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("background", m); // background-position - m = new ListProperty.Maker(PR_BACKGROUND_POSITION); + m = new BackgroundPositionShorthand.Maker(PR_BACKGROUND_POSITION); m.setInherited(false); m.addKeyword("left", "0% 50%"); + m.addKeyword("left center", "0% 50%"); + m.addKeyword("center left", "0% 50%"); m.addKeyword("right", "100% 50%"); + m.addKeyword("right center", "100% 50%"); + m.addKeyword("center right", "100% 50%"); m.addKeyword("center", "50% 50%"); + m.addKeyword("center center", "50% 50%"); m.addKeyword("top", "50% 0%"); + m.addKeyword("top center", "50% 0%"); + m.addKeyword("center top", "50% 0%"); m.addKeyword("bottom", "50% 100%"); + m.addKeyword("bottom center", "50% 100%"); + m.addKeyword("center bottom", "50% 100%"); + m.addKeyword("top left", "0% 0%"); + m.addKeyword("left top", "0% 0%"); + m.addKeyword("top right", "100% 0%"); + m.addKeyword("right top", "100% 0%"); + m.addKeyword("bottom left", "0% 100%"); + m.addKeyword("left bottom", "0% 100%"); + m.addKeyword("bottom right", "100% 100%"); + m.addKeyword("right bottom", "100% 100%"); m.setDefault("0% 0%"); - m.setDatatypeParser(new BackgroundPositionShorthandParser()); + m.setPercentBase(LengthBase.CUSTOM_BASE); + m.setDatatypeParser(new BackgroundPositionShorthand.Parser()); addPropertyMaker("background-position", m); // border diff --git a/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java b/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java new file mode 100644 index 000000000..ba2ee7c60 --- /dev/null +++ b/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.properties; + +import java.util.List; + +import org.apache.fop.datatypes.PercentBase; +import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.expr.PropertyException; + +/** + * Class encapsulating functionality for the getDimension() returns 1. + */ + public PercentBase getP‘rcentBase() { + return new PercentBase() { + /** {@inheritDoc} */ + public int getBaseLength(PercentBaseContext context) throws PropertyException { + return 0; + } + + /** {@inheritDoc} */ + public double getBaseValue() { + return 0; + } + + /** {@inheritDoc} */ + public int getDimension() { + return 1; + } + + }; + } + } + + /** + * Inner class to provide shorthand parsing capabilities + * + */ + public static class Parser extends GenericShorthandParser { + + /** {@inheritDoc} */ + public Property getValueForProperty(int propId, + Property property, + PropertyMaker maker, + PropertyList propertyList) + throws PropertyException { + + int index = -1; + List propList = property.getList(); + if (propId == Constants.PR_BACKGROUND_POSITION_HORIZONTAL) { + index = 0; + } else if (propId == Constants.PR_BACKGROUND_POSITION_VERTICAL) { + index = 1; + } + if (index >= 0) { + return maker.convertProperty( + (Property) propList.get(index), + propertyList, + propertyList.getFObj()); + } // else: invalid index? shouldn't happen... + return null; + } + } + +} diff --git a/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthandParser.java b/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthandParser.java deleted file mode 100644 index 76c934234..000000000 --- a/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthandParser.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.fo.properties; - -import java.util.List; -import org.apache.fop.fo.Constants; -import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.expr.PropertyException; - -/** - * A shorthand parser for the background-position shorthand - */ - -public class BackgroundPositionShorthandParser extends GenericShorthandParser { - - /** - * {@inheritDoc} - */ - public Property getValueForProperty(int propId, - Property property, - PropertyMaker maker, - PropertyList propertyList) - throws PropertyException { - - int index = -1; - List propList = property.getList(); - if (propId == Constants.PR_BACKGROUND_POSITION_HORIZONTAL) { - index = 0; - } else if (propId == Constants.PR_BACKGROUND_POSITION_VERTICAL) { - index = 1; - if (propList.size() == 1) { - /* only background-position-horizontal specified - * through the shorthand: - * background-position-vertical=50% (see: XSL-FO 1.0 -- 7.29.2) - */ - return maker.make(propertyList, "50%", propertyList.getParentFObj()); - } - } - if (index >= 0) { - return (Property) propList.get(index); - } // else: invalid index? shouldn't happen... - return null; - } -} diff --git a/test/fotree/testcases/background-position-shorthand-test.fo b/test/fotree/testcases/background-position-shorthand-test.fo index 6ef374544..6bc793535 100644 --- a/test/fotree/testcases/background-position-shorthand-test.fo +++ b/test/fotree/testcases/background-position-shorthand-test.fo @@ -25,48 +25,60 @@ - - + + Test background-position shorthand: initial values - - + + Test background-position shorthand: "50% 50%" - + Test background-position shorthand: "2in 50%" - + Test background-position shorthand: "100%" - - + + Test background-position shorthand: "top center" - - + + Test background-position shorthand: "right bottom" - - + + Test background-position shorthand: "inherit" + + + + Test background-position shorthand: "top right" + + + + + Test background-position shorthand: "center" + -- cgit v1.2.3 From 0a64e43af52c6d8af108ba97c719817ae82a710f Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 10 Feb 2008 13:01:07 +0000 Subject: Tweak: wrap numeric values internally in Integers or Longs if possible, Doubles only if necessary. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620277 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fo/properties/NumberProperty.java | 44 ++++++++++++++-------- 1 file changed, 29 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/NumberProperty.java b/src/java/org/apache/fop/fo/properties/NumberProperty.java index 2dd65e1ce..087429dba 100644 --- a/src/java/org/apache/fop/fo/properties/NumberProperty.java +++ b/src/java/org/apache/fop/fo/properties/NumberProperty.java @@ -61,7 +61,7 @@ public final class NumberProperty extends Property implements Numeric { } Number val = p.getNumber(); if (val != null) { - return new NumberProperty(val); + return getInstance(val.doubleValue()); } return convertPropertyDatatype(p, propertyList, fo); } @@ -73,41 +73,55 @@ public final class NumberProperty extends Property implements Numeric { private final Number number; - /** - * Constructor for Number input - * @param num Number object value for property - */ - private NumberProperty(Number num) { - this.number = num; - } - /** * Constructor for double input * @param num double numeric value for property */ - protected NumberProperty(double num) { - this.number = new Double(num); + private NumberProperty(double num) { + //Store the number as an int or a long, + //if possible + if ((num >= 0 && num == Math.floor(num)) + || num == Math.ceil(num)) { + if (num < Integer.MAX_VALUE) { + this.number = new Integer((int)num); + } else { + this.number = new Long((long)num); + } + } else { + this.number = new Double(num); + } } /** * Constructor for integer input * @param num integer numeric value for property */ - protected NumberProperty(int num) { + private NumberProperty(int num) { this.number = new Integer(num); } /** * Returns the canonical NumberProperty instance * corresponding to the given Number - * @param num the base Number + * @param num the base Double * @return the canonical NumberProperty */ - public static NumberProperty getInstance(Number num) { + public static NumberProperty getInstance(Double num) { return (NumberProperty)cache.fetch( - new NumberProperty(num)); + new NumberProperty(num.doubleValue())); } + /** + * Returns the canonical NumberProperty instance + * corresponding to the given Integer + * @param num the base Integer + * @return the canonical NumberProperty + */ + public static NumberProperty getInstance(Integer num) { + return (NumberProperty)cache.fetch( + new NumberProperty(num.intValue())); + } + /** * Returns the canonical NumberProperty instance * corresponding to the given double -- cgit v1.2.3 From c3993e40d6b45d70b8c7296529bb60d8bbcda885 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 10 Feb 2008 13:07:34 +0000 Subject: Missing file from r620272 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620278 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/expr/ICCColorFunction.java | 42 +++++++++++++++------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java index c254f1516..5bd9d145d 100644 --- a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java @@ -18,8 +18,8 @@ /* $Id$ */ package org.apache.fop.fo.expr; -import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.PercentBase; +import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.pagination.ColorProfile; import org.apache.fop.fo.pagination.Declarations; import org.apache.fop.fo.properties.ColorProperty; @@ -41,14 +41,12 @@ class ICCColorFunction extends FunctionBase { /** {@inheritDoc} */ public PercentBase getPercentBase() { - return new RGBColorFunction.RGBPercentBase(); + return new ICCPercentBase(); } /** {@inheritDoc} */ public Property eval(Property[] args, PropertyInfo pInfo) throws PropertyException { - StringBuffer sb = new StringBuffer(); - // Map color profile NCNAME to src from declarations/color-profile element String colorProfileName = args[3].getString(); Declarations decls = pInfo.getFO().getRoot().getDeclarations(); @@ -75,21 +73,39 @@ class ICCColorFunction extends FunctionBase { // rgb-icc is replaced with fop-rgb-icc which has an extra fifth argument containing the // color profile src attribute as it is defined in the color-profile declarations element. - sb.append("fop-rgb-icc(" + args[0]); - for (int ix = 1; ix < args.length; ix++) { + StringBuffer sb = new StringBuffer(); + sb.append("fop-rgb-icc("); + for (int ix = 0; ix < args.length; ix++) { if (ix == 3) { - sb.append("," + colorProfileName); - sb.append(",\"" + src + "\""); + sb.append(',').append(colorProfileName); + sb.append(',').append(src); } else { - sb.append("," + args[ix]); + if (ix > 0) { + sb.append(','); + } + sb.append(args[ix]); } } sb.append(")"); - FOUserAgent ua = (pInfo == null - ? null - : (pInfo.getFO() == null ? null : pInfo.getFO().getUserAgent())); - return ColorProperty.getInstance(ua, sb.toString()); + + return ColorProperty.getInstance(pInfo.getUserAgent(), sb.toString()); } + private static final class ICCPercentBase implements PercentBase { + + /** {@inheritDoc} */ + public int getBaseLength(PercentBaseContext context) throws PropertyException { + return 0; + } + + /** {@inheritDoc} */ + public double getBaseValue() { + return 255f; + } + /** {@inheritDoc} */ + public int getDimension() { + return 0; + } + } } -- cgit v1.2.3 From 4b584311505ac639952ec29d9983161b5682b80a Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 10 Feb 2008 13:17:20 +0000 Subject: Correction/Rectification of changes made in r617989: * adjustment in ColorUtil to cater for the change * added check to the color_1.xml testcase, checking for bug 43705 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620283 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/util/ColorUtil.java | 284 +++++++++++------------ test/layoutengine/standard-testcases/color_1.xml | 5 +- 2 files changed, 135 insertions(+), 154 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/util/ColorUtil.java b/src/java/org/apache/fop/util/ColorUtil.java index 37762b1e8..bb014b2af 100644 --- a/src/java/org/apache/fop/util/ColorUtil.java +++ b/src/java/org/apache/fop/util/ColorUtil.java @@ -22,10 +22,7 @@ package org.apache.fop.util; import java.awt.Color; import java.awt.color.ColorSpace; import java.util.Collections; -import java.util.LinkedList; -import java.util.List; import java.util.Map; -import java.util.StringTokenizer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -167,30 +164,28 @@ public final class ColorUtil { try { if (poss != -1 && pose != -1) { value = value.substring(poss + 1, pose); - StringTokenizer st = new StringTokenizer(value, ","); - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - red = Float.parseFloat(str.substring(2)) / 255f; + String[] args = value.split(","); + if (args.length != 3) { + throw new PropertyException( + "Invalid number of arguments for a java.awt.Color: " + value); } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - green = Float.parseFloat(str.substring(2)) / 255f; - } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - blue = Float.parseFloat(str.substring(2)) / 255f; - } else { - throw new NumberFormatException(); - } - if ((red < 0.0 || red > 1.0) || (green < 0.0 || green > 1.0) + + red = Float.parseFloat(args[0].trim().substring(2)) / 255f; + green = Float.parseFloat(args[1].trim().substring(2)) / 255f; + blue = Float.parseFloat(args[2].trim().substring(2)) / 255f; + if ((red < 0.0 || red > 1.0) + || (green < 0.0 || green > 1.0) || (blue < 0.0 || blue > 1.0)) { throw new PropertyException("Color values out of range"); } } else { - throw new NullPointerException(); + throw new IllegalArgumentException( + "Invalid format for a java.awt.Color: " + value); } + } catch (PropertyException pe) { + throw pe; } catch (Exception e) { - throw new PropertyException("Unknown color format: " + value); + throw new PropertyException(e); } return new Color(red, green, blue); } @@ -210,44 +205,46 @@ public final class ColorUtil { int pose = value.indexOf(")"); if (poss != -1 && pose != -1) { value = value.substring(poss + 1, pose); - StringTokenizer st = new StringTokenizer(value, ","); try { + String[] args = value.split(","); + if (args.length != 3) { + throw new PropertyException( + "Invalid number of arguments: rgb(" + value + ")"); + } float red = 0.0f, green = 0.0f, blue = 0.0f; - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - if (str.endsWith("%")) { - red = Float.parseFloat(str.substring(0, - str.length() - 1)) / 100.0f; - } else { - red = Float.parseFloat(str) / 255f; - } + String str = args[0].trim(); + if (str.endsWith("%")) { + red = Float.parseFloat(str.substring(0, + str.length() - 1)) / 100f; + } else { + red = Float.parseFloat(str) / 255f; } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - if (str.endsWith("%")) { - green = Float.parseFloat(str.substring(0, - str.length() - 1)) / 100.0f; - } else { - green = Float.parseFloat(str) / 255f; - } + str = args[1].trim(); + if (str.endsWith("%")) { + green = Float.parseFloat(str.substring(0, + str.length() - 1)) / 100f; + } else { + green = Float.parseFloat(str) / 255f; } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - if (str.endsWith("%")) { - blue = Float.parseFloat(str.substring(0, - str.length() - 1)) / 100.0f; - } else { - blue = Float.parseFloat(str) / 255f; - } + str = args[2].trim(); + if (str.endsWith("%")) { + blue = Float.parseFloat(str.substring(0, + str.length() - 1)) / 100f; + } else { + blue = Float.parseFloat(str) / 255f; } - if ((red < 0.0 || red > 1.0) || (green < 0.0 || green > 1.0) + if ((red < 0.0 || red > 1.0) + || (green < 0.0 || green > 1.0) || (blue < 0.0 || blue > 1.0)) { throw new PropertyException("Color values out of range"); } parsedColor = new Color(red, green, blue); + } catch (PropertyException pe) { + //simply re-throw + throw pe; } catch (Exception e) { - throw new PropertyException( - "Arguments to rgb() must be [0..255] or [0%..100%]"); + //wrap in a PropertyException + throw new PropertyException(e); } } else { throw new PropertyException("Unknown color format: " + value @@ -269,29 +266,28 @@ public final class ColorUtil { Color parsedColor = null; try { int len = value.length(); - if ((len >= 4) && (len <= 5)) { - // note: divide by 15 so F = FF = 1 and so on - float red = Integer.parseInt(value.substring(1, 2), 16) / 15f; - float green = Integer.parseInt(value.substring(2, 3), 16) / 15f; - float blue = Integer.parseInt(value.substring(3, 4), 16) / 15f; - float alpha = 1.0f; - if (len == 5) { - alpha = Integer.parseInt(value.substring(4), 16) / 15f; - } - parsedColor = new Color(red, green, blue, alpha); + int alpha; + if (len == 5 || len == 9) { + alpha = Integer.parseInt( + value.substring((len == 5) ? 3 : 7), 16); + } else { + alpha = 0xFF; + } + int red = 0, green = 0, blue = 0; + if ((len == 4) || (len == 5)) { + //multiply by 0x11 = 17 = 255/15 + red = Integer.parseInt(value.substring(1, 2), 16) * 0x11; + green = Integer.parseInt(value.substring(2, 3), 16) * 0x11; + blue = Integer.parseInt(value.substring(3, 4), 16) *0X11; } else if ((len == 7) || (len == 9)) { - int red = Integer.parseInt(value.substring(1, 3), 16); - int green = Integer.parseInt(value.substring(3, 5), 16); - int blue = Integer.parseInt(value.substring(5, 7), 16); - int alpha = 255; - if (len == 9) { - alpha = Integer.parseInt(value.substring(7), 16); - } - parsedColor = new Color(red, green, blue, alpha); + red = Integer.parseInt(value.substring(1, 3), 16); + green = Integer.parseInt(value.substring(3, 5), 16); + blue = Integer.parseInt(value.substring(5, 7), 16); } else { throw new NumberFormatException(); } - } catch (NumberFormatException e) { + parsedColor = new Color(red, green, blue, alpha); + } catch (Exception e) { throw new PropertyException("Unknown color format: " + value + ". Must be #RGB. #RGBA, #RRGGBB, or #RRGGBBAA"); } @@ -311,79 +307,65 @@ public final class ColorUtil { int poss = value.indexOf("("); int pose = value.indexOf(")"); if (poss != -1 && pose != -1) { - value = value.substring(poss + 1, pose); - StringTokenizer st = new StringTokenizer(value, ","); + String[] args = value.substring(poss + 1, pose).split(","); + try { - float red = 0.0f, green = 0.0f, blue = 0.0f; - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - red = Float.parseFloat(str); - } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - green = Float.parseFloat(str); + if (args.length < 5) { + throw new PropertyException("Too few arguments for rgb-icc() function"); } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - blue = Float.parseFloat(str); - } - /* Verify rgb replacement arguments */ - if ((red < 0.0 || red > 1.0) - || (green < 0.0 || green > 1.0) - || (blue < 0.0 || blue > 1.0)) { - throw new PropertyException("Color values out of range"); - } /* Get and verify ICC profile name */ - String iccProfileName = null; - if (st.hasMoreTokens()) { - iccProfileName = st.nextToken().trim(); - } - if (iccProfileName == null || iccProfileName.length() == 0) { + String iccProfileName = args[3].trim(); + if (iccProfileName == null || "".equals(iccProfileName)) { throw new PropertyException("ICC profile name missing"); } /* Get and verify ICC profile source */ - String iccProfileSrc = null; - if (st.hasMoreTokens()) { - iccProfileSrc = st.nextToken().trim(); - // Strip quotes - iccProfileSrc = iccProfileSrc.substring(1, iccProfileSrc.length() - 1); - } - if (iccProfileSrc == null || iccProfileSrc.length() == 0) { + String iccProfileSrc = args[4].trim(); + if (iccProfileSrc == null || "".equals(iccProfileSrc)) { throw new PropertyException("ICC profile source missing"); } /* ICC profile arguments */ - List iccArgList = new LinkedList(); - while (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - iccArgList.add(new Float(str)); - } - /* Copy ICC profile arguments from list to array */ - float[] iccComponents = new float[iccArgList.size()]; - for (int ix = 0; ix < iccArgList.size(); ix++) { - iccComponents[ix] = ((Float)iccArgList.get(ix)).floatValue(); + float[] iccComponents = new float[args.length - 5]; + for (int ix = 4; ++ix < args.length;) { + iccComponents[ix - 5] = Float.parseFloat(args[ix].trim()); } /* Ask FOP factory to get ColorSpace for the specified ICC profile source */ ColorSpace colorSpace = (foUserAgent != null ? foUserAgent.getFactory().getColorSpace( foUserAgent.getBaseURL(), iccProfileSrc) : null); + + float red = 0, green = 0, blue = 0; + red = Float.parseFloat(args[0].trim()); + green = Float.parseFloat(args[1].trim()); + blue = Float.parseFloat(args[2].trim());; + /* Verify rgb replacement arguments */ + if ((red < 0 || red > 255) + || (green < 0 || green > 255) + || (blue < 0 || blue > 255)) { + throw new PropertyException("Color values out of range. " + + "Arguments to rgb-icc() must be [0..255] or [0%..100%]"); + } + if (colorSpace != null) { // ColorSpace available - create ColorExt (keeps track of replacement rgb // values for possible later colorTOsRGBString call - parsedColor = ColorExt.createFromFoRgbIcc(red, green, blue, + parsedColor = ColorExt.createFromFoRgbIcc(red/255, green/255, blue/255, iccProfileName, iccProfileSrc, colorSpace, iccComponents); } else { // ICC profile could not be loaded - use rgb replacement values */ log.warn("Color profile '" + iccProfileSrc + "' not found. Using rgb replacement values."); - parsedColor = new Color(red, green, blue); + parsedColor = new Color((int)red, (int)green, (int)blue); } + } catch (PropertyException pe) { + //simply re-throw + throw pe; } catch (Exception e) { - throw new PropertyException( - "Arguments to rgb-icc() must be [0..255] or [0%..100%]"); + //wrap in a PropertyException + throw new PropertyException(e); } } else { throw new PropertyException("Unknown color format: " + value - + ". Must be fop-rgb-icc(r,g,b,NCNAME,\"src\",....)"); + + ". Must be fop-rgb-icc(r,g,b,NCNAME,src,....)"); } return parsedColor; } @@ -403,61 +385,58 @@ public final class ColorUtil { int pose = value.indexOf(")"); if (poss != -1 && pose != -1) { value = value.substring(poss + 1, pose); - StringTokenizer st = new StringTokenizer(value, ","); + String[] args = value.split(","); try { + if (args.length != 4) { + throw new PropertyException( + "Invalid number of arguments: cmyk(" + value + ")"); + } float cyan = 0.0f, magenta = 0.0f, yellow = 0.0f, black = 0.0f; - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - if (str.endsWith("%")) { - cyan = Float.parseFloat(str.substring(0, - str.length() - 1)) / 100.0f; - } else { - cyan = Float.parseFloat(str); - } + String str = args[0].trim(); + if (str.endsWith("%")) { + cyan = Float.parseFloat(str.substring(0, + str.length() - 1)) / 100.0f; + } else { + cyan = Float.parseFloat(str); + } + str = args[1].trim(); + if (str.endsWith("%")) { + magenta = Float.parseFloat(str.substring(0, + str.length() - 1)) / 100.0f; + } else { + magenta = Float.parseFloat(str); } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - if (str.endsWith("%")) { - magenta = Float.parseFloat(str.substring(0, - str.length() - 1)) / 100.0f; - } else { - magenta = Float.parseFloat(str); - } + str = args[2].trim(); + if (str.endsWith("%")) { + yellow = Float.parseFloat(str.substring(0, + str.length() - 1)) / 100.0f; + } else { + yellow = Float.parseFloat(str); } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - if (str.endsWith("%")) { - yellow = Float.parseFloat(str.substring(0, - str.length() - 1)) / 100.0f; - } else { - yellow = Float.parseFloat(str); - } + str = args[3].trim(); + if (str.endsWith("%")) { + black = Float.parseFloat(str.substring(0, + str.length() - 1)) / 100.0f; + } else { + black = Float.parseFloat(str); } - if (st.hasMoreTokens()) { - String str = st.nextToken().trim(); - if (str.endsWith("%")) { - black = Float.parseFloat(str.substring(0, - str.length() - 1)) / 100.0f; - } else { - black = Float.parseFloat(str); - } - } + if ((cyan < 0.0 || cyan > 1.0) || (magenta < 0.0 || magenta > 1.0) || (yellow < 0.0 || yellow > 1.0) || (black < 0.0 || black > 1.0)) { - throw new PropertyException("Color values out of range"); + throw new PropertyException("Color values out of range" + + "Arguments to cmyk() must be in the range [0%-100%] or [0.0-1.0]"); } float[] cmyk = new float[] {cyan, magenta, yellow, black}; CMYKColorSpace cmykCs = CMYKColorSpace.getInstance(); float[] rgb = cmykCs.toRGB(cmyk); parsedColor = ColorExt.createFromFoRgbIcc(rgb[0], rgb[1], rgb[2], null, "#CMYK", cmykCs, cmyk); - - + } catch (PropertyException pe) { + throw pe; } catch (Exception e) { - throw new PropertyException( - "Arguments to cmyk() must be in the range [0%-100%] or [0.0-1.0]"); + throw new PropertyException(e); } } else { throw new PropertyException("Unknown color format: " + value @@ -668,7 +647,6 @@ public final class ColorUtil { colorMap.put("whitesmoke", new Color(245, 245, 245)); colorMap.put("yellow", new Color(255, 255, 0)); colorMap.put("yellowgreen", new Color(154, 205, 50)); - colorMap.put("transparent", new Color(0, 0, 0, 0)); } diff --git a/test/layoutengine/standard-testcases/color_1.xml b/test/layoutengine/standard-testcases/color_1.xml index 1e4e96cc8..55ab47b01 100644 --- a/test/layoutengine/standard-testcases/color_1.xml +++ b/test/layoutengine/standard-testcases/color_1.xml @@ -26,7 +26,7 @@ - + @@ -47,6 +47,9 @@ + + -- cgit v1.2.3 From c29d8e5488fa1b749647f2e5f35129271b2dae48 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 10 Feb 2008 13:42:39 +0000 Subject: Bugzilla 41631: Percentage resolution for arguments to proportional-column-width() git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620285 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/expr/PPColWidthFunction.java | 29 ++++++++++++++++++++ status.xml | 3 +++ ...lumn_column-width_proportional-column-width.xml | 31 ++++++++++++++++++++++ 3 files changed, 63 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/PPColWidthFunction.java b/src/java/org/apache/fop/fo/expr/PPColWidthFunction.java index 08ec34732..394035b49 100644 --- a/src/java/org/apache/fop/fo/expr/PPColWidthFunction.java +++ b/src/java/org/apache/fop/fo/expr/PPColWidthFunction.java @@ -19,6 +19,8 @@ package org.apache.fop.fo.expr; +import org.apache.fop.datatypes.PercentBase; +import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.properties.Property; @@ -38,6 +40,13 @@ public class PPColWidthFunction extends FunctionBase { return 1; } + /** + * @return the {@link PercentBase} for the proportional-column-width() + * function + */ + public PercentBase getPercentBase() { + return new PPColWidthPercentBase(); + } /** * * @param args array of arguments for this function @@ -69,4 +78,24 @@ public class PPColWidthFunction extends FunctionBase { return new TableColLength(d.doubleValue(), pInfo.getFO()); } + private static class PPColWidthPercentBase implements PercentBase { + + /** {@inheritDoc} */ + public int getBaseLength(PercentBaseContext context) throws PropertyException { + return 0; + } + + /** {@inheritDoc} */ + public double getBaseValue() { + //make sure percentage-arguments are interpreted + //as numerics (1% = 1 * 0.01) + return 1; + } + + /** {@inheritDoc} */ + public int getDimension() { + return 0; + } + + } } diff --git a/status.xml b/status.xml index ed4300589..20b9cfca1 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Added correct percentage resolution for arguments to the proportional-column-width() function. + Bugfix for date formatting with negative time zones in the PDF's Info object. This affected PDF/A compliance. diff --git a/test/layoutengine/standard-testcases/table-column_column-width_proportional-column-width.xml b/test/layoutengine/standard-testcases/table-column_column-width_proportional-column-width.xml index d35d7c45f..e5f2f4f93 100644 --- a/test/layoutengine/standard-testcases/table-column_column-width_proportional-column-width.xml +++ b/test/layoutengine/standard-testcases/table-column_column-width_proportional-column-width.xml @@ -67,6 +67,24 @@ + + + + + + + + cell1% + + + cell2% + + + cell3% + + + + @@ -95,5 +113,18 @@ + + + + + + + + + + + + + -- cgit v1.2.3 From c7d1a19cab78c16211f006a220bcb882cb207144 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 11 Feb 2008 18:10:09 +0000 Subject: Added full support for breaks inside table-cell elements git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620558 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 27 +- .../apache/fop/layoutmgr/table/TableStepper.java | 49 +- status.xml | 3 + .../table-cell_break-after_inside.xml | 1138 ++++++++++++++++++++ .../table-cell_break-before_inside.xml | 1138 ++++++++++++++++++++ .../standard-testcases/table-cell_breaks.xml | 201 ++++ 6 files changed, 2542 insertions(+), 14 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table-cell_break-after_inside.xml create mode 100644 test/layoutengine/standard-testcases/table-cell_break-before_inside.xml create mode 100644 test/layoutengine/standard-testcases/table-cell_breaks.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 671204dfe..485c63ea2 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -24,6 +24,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; @@ -95,6 +96,13 @@ class ActiveCell { private int totalLength; /** Length of the penalty ending this step, if any. */ private int penaltyLength; + /** + * One of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, + * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, + * {@link Constants#EN_ODD_PAGE}. Set to auto if the break isn't at a penalty + * element. + */ + private int breakClass; /** * Length of the optional content at the beginning of the step. That is, content * that will not appear if this step starts a new page. @@ -117,6 +125,7 @@ class ActiveCell { this.totalLength = other.totalLength; this.penaltyLength = other.penaltyLength; this.condBeforeContentLength = other.condBeforeContentLength; + this.breakClass = other.breakClass; } /** {@inheritDoc} */ @@ -210,6 +219,7 @@ class ActiveCell { private void gotoNextLegalBreak() { afterNextStep.penaltyLength = 0; afterNextStep.condBeforeContentLength = 0; + afterNextStep.breakClass = Constants.EN_AUTO; boolean breakFound = false; boolean prevIsBox = false; boolean boxFound = false; @@ -219,8 +229,12 @@ class ActiveCell { prevIsBox = false; if (el.getP() < KnuthElement.INFINITE) { // First legal break point - afterNextStep.penaltyLength = el.getW(); breakFound = true; + afterNextStep.penaltyLength = el.getW(); + KnuthPenalty p = (KnuthPenalty) el; + if (p.isForcedBreak()) { + afterNextStep.breakClass = p.getBreakClass(); + } } } else if (el.isGlue()) { if (prevIsBox) { @@ -276,7 +290,7 @@ class ActiveCell { * @see #signalRowLastStep(int) */ private void increaseCurrentStep(int limit) { - while (afterNextStep.totalLength <= limit) { + while (afterNextStep.totalLength <= limit && nextStep.breakClass == Constants.EN_AUTO) { nextStep.set(afterNextStep); if (afterNextStep.end >= elementList.size() - 1) { break; @@ -338,11 +352,18 @@ class ActiveCell { * its own step may be included or not. * * @param minStep length of the chosen next step + * @return the break class of the step, if any. One of {@link Constants#EN_AUTO}, + * {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, + * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}. EN_AUTO if this + * cell's step is not included in the next step. */ - void signalNextStep(int minStep) { + int signalNextStep(int minStep) { if (nextStep.totalLength <= minStep) { includedLength = nextStep.contentLength; remainingLength = totalLength - includedLength - afterNextStep.condBeforeContentLength; + return nextStep.breakClass; + } else { + return Constants.EN_AUTO; } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index aa35d0aee..4eff1e931 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -84,6 +84,13 @@ public class TableStepper { */ private boolean rowHeightSmallerThanFirstStep; + /** + * 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 int nextBreakClass; /** * Main constructor @@ -190,18 +197,10 @@ public class TableStepper { } } - boolean forcedBreak = false; - int breakClass = -1; //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(); - if (activeCell.contributesContent()) { - forcedBreak = activeCell.isLastForcedBreak(); - if (forcedBreak) { - breakClass = activeCell.getLastBreakClass(); - } - } CellPart part = activeCell.createCellPart(); cellParts.add(part); if (returnList.size() == 0 && part.isFirstPart() @@ -244,14 +243,15 @@ public class TableStepper { if (signalKeepWithNext || getTableLM().mustKeepTogether()) { p = KnuthPenalty.INFINITE; } - if (forcedBreak) { + if (nextBreakClass != Constants.EN_AUTO) { + log.trace("Forced break encountered"); p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0) } if (rowHeightSmallerThanFirstStep) { rowHeightSmallerThanFirstStep = false; p = KnuthPenalty.INFINITE; } - returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context)); + returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, nextBreakClass, context)); if (penaltyOrGlueLen < 0) { returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true)); } @@ -378,9 +378,36 @@ public class TableStepper { * @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(); - activeCell.signalNextStep(step); + nextBreakClass = compareBreakClasses(nextBreakClass, activeCell.signalNextStep(step)); + } + } + + // TODO replace that with a proper 1.5 enumeration ASAP + // TODO this has nothing to do here + private static int getBreakClassPriority(int breakClass) { + switch (breakClass) { + case Constants.EN_AUTO: return 0; + case Constants.EN_COLUMN: return 1; + case Constants.EN_PAGE: return 2; + case Constants.EN_EVEN_PAGE: return 3; + case Constants.EN_ODD_PAGE: return 3; + default: throw new IllegalArgumentException(); + } + } + + // TODO even-page and odd-page can't be compared to each other and instead create a + // conflict situation. For now the first encountered break will win, but eventually + // some warning message should be sent to the user. + private static int compareBreakClasses(int b1, int b2) { + int p1 = getBreakClassPriority(b1); + int p2 = getBreakClassPriority(b2); + if (p1 < p2) { + return b2; + } else { + return b1; } } diff --git a/status.xml b/status.xml index 20b9cfca1..2eaf1a553 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,9 @@ + + Added full support for breaks inside the cells of a table. + Added correct percentage resolution for arguments to the proportional-column-width() function. diff --git a/test/layoutengine/standard-testcases/table-cell_break-after_inside.xml b/test/layoutengine/standard-testcases/table-cell_break-after_inside.xml new file mode 100644 index 000000000..670858565 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_break-after_inside.xml @@ -0,0 +1,1138 @@ + + + + + +

    + This test checks that break-after set on blocks in table-cells works correctly in various + conditions: when headers/footers shall be repeated at page breaks or not, in the separate or + collapsing border model, etc. +

    +
    + + + + + + + + + + + + 1. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 2. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 3. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 4. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 5. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 6. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 7. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 8. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_break-before_inside.xml b/test/layoutengine/standard-testcases/table-cell_break-before_inside.xml new file mode 100644 index 000000000..780d60015 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_break-before_inside.xml @@ -0,0 +1,1138 @@ + + + + + +

    + This test checks that break-before set on table-rows work correctly in various conditions: + when headers/footers shall be repeated at page breaks or not, in the separate or collapsing + border model, etc. +

    +
    + + + + + + + + + + + + 1. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + After the table + + + + + + + 2. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 3. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 4. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 5. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 6. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 7. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 8. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_breaks.xml b/test/layoutengine/standard-testcases/table-cell_breaks.xml new file mode 100644 index 000000000..1bdb2449f --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_breaks.xml @@ -0,0 +1,201 @@ + + + + + +

    + This test checks that breaks collaborate nicely with the increasing of steps, when the first + step of a row is computed or when applied to row-spanning cells once the end of the current + row is reached. +

    +
    + + + + + + + + + + + + 1. Before the table + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + + + Cell 1.2 Line 1 + Cell 1.2 Line 2 + Cell 1.2 Line 3 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + After the table + + + + + + + 2. Before the table + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + + + Cell 1.2 Line 1 + Cell 1.2 Line 2 + + + + + Cell 2.2 Line 1 + Cell 2.2 Line 2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -- cgit v1.2.3 From 28fdd605495cae8fd2abe6819d232015c548649e Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 11 Feb 2008 18:11:09 +0000 Subject: Fixed illegal character in the file git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620559 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java b/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java index ba2ee7c60..de74d4be6 100644 --- a/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java +++ b/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java @@ -72,7 +72,7 @@ public class BackgroundPositionShorthand extends ListProperty { * Returns a {@link org.apache.fop.datatypes.PercentBase} whose * getDimension() returns 1. */ - public PercentBase getP‘rcentBase() { + public PercentBase getPercentBase() { return new PercentBase() { /** {@inheritDoc} */ public int getBaseLength(PercentBaseContext context) throws PropertyException { -- cgit v1.2.3 From 3f8c5ac143bcd70b1ae1df7dc79b4b8fe33605eb Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 11 Feb 2008 18:18:13 +0000 Subject: Better javadoc for break class git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620565 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/BreakElement.java | 18 +++++++++++++++--- src/java/org/apache/fop/layoutmgr/KnuthPenalty.java | 6 ++++-- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/BreakElement.java b/src/java/org/apache/fop/layoutmgr/BreakElement.java index 20e4f7a76..3ccfbf616 100644 --- a/src/java/org/apache/fop/layoutmgr/BreakElement.java +++ b/src/java/org/apache/fop/layoutmgr/BreakElement.java @@ -46,10 +46,13 @@ public class BreakElement extends UnresolvedListElement { /** * Constructor for hard breaks. + * * @param position the Position instance needed by the addAreas stage of the LMs. * @param penaltyWidth the penalty width * @param penaltyValue the penalty value for the penalty element to be constructed - * @param breakClass the break class of this penalty (one of the break-* constants) + * @param breakClass the break class of this penalty (one of {@link Constants#EN_AUTO}, + * {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, + * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}) * @param context the layout context which contains the pending conditional elements */ public BreakElement(Position position, int penaltyWidth, int penaltyValue, @@ -96,14 +99,23 @@ public class BreakElement extends UnresolvedListElement { return penaltyValue == -KnuthElement.INFINITE; } - /** @return the break class of this penalty (one of the break-* constants) */ + /** + * Returns the break class of this penalty. + * + * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, + * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, + * {@link Constants#EN_ODD_PAGE} + */ public int getBreakClass() { return breakClass; } /** * Sets the break class. - * @param breakClass the new break class + * + * @param breakClass one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, + * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, + * {@link Constants#EN_ODD_PAGE} */ public void setBreakClass(int breakClass) { this.breakClass = breakClass; diff --git a/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java b/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java index 3c7dace5f..ecaeac627 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java @@ -65,11 +65,13 @@ public class KnuthPenalty extends KnuthElement { /** * Create a new KnuthPenalty. - * + * * @param w the width of this penalty * @param p the penalty value of this penalty * @param f is this penalty flagged? - * @param iBreakClass the break class of this penalty (one of the break-* constants) + * @param iBreakClass the break class of this penalty (one of + * {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, + * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}) * @param pos the Position stored in this penalty * @param bAux is this penalty auxiliary? */ -- cgit v1.2.3 From 160c3e76529e7d665e0899d50821140751faed7c Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 11 Feb 2008 18:36:14 +0000 Subject: Missing file from r620283 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620570 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/expr/PropertyException.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/PropertyException.java b/src/java/org/apache/fop/fo/expr/PropertyException.java index d9a0b2edd..16055a738 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyException.java +++ b/src/java/org/apache/fop/fo/expr/PropertyException.java @@ -35,12 +35,23 @@ public class PropertyException extends FOPException { super(detail); } + /** + * Constructor + * @param the Exception causing this PropertyException + */ + public PropertyException(Exception cause) { + super(cause); + if (cause instanceof PropertyException) { + this.propertyName = ((PropertyException)cause).propertyName; + } + } + /** * Sets the property context information. * @param propInfo the property info instance */ public void setPropertyInfo(PropertyInfo propInfo) { - setLocator(propInfo.getFO().getLocator()); + setLocator(propInfo.getPropertyList().getFObj().getLocator()); propertyName = propInfo.getPropertyMaker().getName(); } -- cgit v1.2.3 From 4de57c512a5284ae37e510f4ae616e090c8027cb Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 12 Feb 2008 08:23:04 +0000 Subject: Bugzilla #44393: Recognize the newly used EN_AUTO constant for break values. Other LMs generate a -1 value for this case. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620723 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/PageBreaker.java | 4 +++- test/layoutengine/disabled-testcases.xml | 6 ------ .../standard-testcases/region-body_column-count_bug37468.xml | 4 ++-- 3 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index cfc4b55bf..cf830a7ec 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -470,7 +470,9 @@ public class PageBreaker extends AbstractBreaker { } else if (breakVal == Constants.EN_NONE) { curPage.getPageViewport().createSpan(false); return; - } else if (breakVal == Constants.EN_COLUMN || breakVal <= 0) { + } else if (breakVal == Constants.EN_COLUMN + || breakVal <= 0 + || breakVal == Constants.EN_AUTO) { PageViewport pv = curPage.getPageViewport(); //Check if previous page was spanned diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index feecd3a6f..15ac8aa48 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -305,10 +305,4 @@ A soft hyphen should be a preferred as break compared to a normal hyphenation point but is not. - - Wrong fo.Constants values used for break classes - region-body_column-count_bug37468.xml - Bugzilla #44393: the Constants.EN_AUTO break class isn't properly recognized by - PageBreaker. - diff --git a/test/layoutengine/standard-testcases/region-body_column-count_bug37468.xml b/test/layoutengine/standard-testcases/region-body_column-count_bug37468.xml index 3bde6f331..37835e37b 100644 --- a/test/layoutengine/standard-testcases/region-body_column-count_bug37468.xml +++ b/test/layoutengine/standard-testcases/region-body_column-count_bug37468.xml @@ -34,8 +34,8 @@ - - + + -- cgit v1.2.3 From 670a123bd85dfec3d0ae773a623c35bac1012d79 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 12 Feb 2008 10:45:50 +0000 Subject: Simplification. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@620750 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/AbstractBreaker.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index f4e9cb633..54fd315b1 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -25,6 +25,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.Constants; import org.apache.fop.traits.MinOptMax; @@ -560,10 +561,8 @@ public abstract class AbstractBreaker { nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn); Position breakPosition = null; - if (((KnuthElement) returnedList.getLast()).isPenalty() - && ((KnuthPenalty) returnedList.getLast()).getP() == -KnuthElement.INFINITE) { - KnuthPenalty breakPenalty = (KnuthPenalty) returnedList - .removeLast(); + if (((KnuthElement) returnedList.getLast()).isForcedBreak()) { + KnuthPenalty breakPenalty = (KnuthPenalty)returnedList.removeLast(); breakPosition = breakPenalty.getPosition(); switch (breakPenalty.getBreakClass()) { case Constants.EN_PAGE: -- cgit v1.2.3 From 575be874323e7ae9fc5a37cc4501a203bde0e85a Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Wed, 13 Feb 2008 09:35:01 +0000 Subject: Ensured all SVN properties are set equally git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627324 13f79535-47bb-0310-9956-ffa450edef68 --- fixsvnprops.sh | 4 + src/documentation/content/xdocs/0.93/index.xml | 2 +- src/documentation/content/xdocs/0.93/pdfa.xml | 2 +- src/documentation/content/xdocs/0.94/index.xml | 2 +- src/documentation/content/xdocs/0.94/pdfa.xml | 2 +- src/documentation/content/xdocs/trunk/index.xml | 2 +- src/documentation/content/xdocs/trunk/pdfa.xml | 2 +- .../block_hyphenation-ladder-count.xml | 710 +++++++++--------- .../inline_border_padding_hyphenate.xml | 800 ++++++++++----------- .../inline_border_padding_hyphenate_de.xml | 800 ++++++++++----------- .../basic-link_background-image.xml | 98 +-- .../block-container_padding_percentages.xml | 108 +-- ...ck-container_reference-orientation_bug36391.xml | 208 +++--- .../block_break-after_bug40230.xml | 2 +- .../standard-testcases/block_font-stretch.xml | 112 +-- .../standard-testcases/block_line-height.xml | 248 +++---- .../block_line-stacking-strategy_1.xml | 330 ++++----- .../block_linefeed-treatment.xml | 162 ++--- .../standard-testcases/block_margin_inherit.xml | 154 ++-- .../block_margin_percentages.xml | 154 ++-- .../standard-testcases/block_padding_2.xml | 224 +++--- .../block_padding_percentages.xml | 108 +-- .../block_space-before_space-after_3.xml | 112 +-- .../standard-testcases/block_text-align_1.xml | 248 +++---- .../standard-testcases/block_text-align_2.xml | 104 +-- .../block_white-space-collapse_1.xml | 304 ++++---- .../block_white-space-collapse_2.xml | 284 ++++---- .../block_white-space-treatment_1.xml | 162 ++--- .../block_white-space-treatment_2.xml | 192 ++--- .../block_white-space_nbsp_1.xml | 212 +++--- .../standard-testcases/block_wrap-option.xml | 116 +-- .../character_background-color.xml | 88 +-- .../character_background-image.xml | 98 +-- .../character_border_padding.xml | 198 ++--- .../character_vertical-align.xml | 120 ++-- .../standard-testcases/external-graphic_bmp.xml | 114 +-- ...ternal-graphic_content-height_content-width.xml | 100 +-- .../standard-testcases/external-graphic_eps.xml | 98 +-- .../standard-testcases/external-graphic_gif.xml | 98 +-- .../standard-testcases/external-graphic_jpeg.xml | 114 +-- .../external-graphic_oversized.xml | 106 +-- .../standard-testcases/external-graphic_png.xml | 116 +-- .../external-graphic_src_uri.xml | 166 ++--- .../standard-testcases/external-graphic_svg.xml | 164 ++--- .../standard-testcases/external-graphic_tiff.xml | 146 ++-- .../standard-testcases/fox_external-document_1.xml | 106 +-- .../standard-testcases/fox_external-document_2.xml | 162 ++--- .../inline-container_border_padding.xml | 172 ++--- .../inline_alignment-adjust_1.xml | 184 ++--- .../inline_alignment-adjust_2.xml | 198 ++--- .../inline_alignment-baseline_1.xml | 184 ++--- .../inline_alignment-baseline_2.xml | 234 +++--- .../inline_alignment-baseline_3.xml | 184 ++--- .../inline_alignment-baseline_4.xml | 464 ++++++------ .../standard-testcases/inline_background-color.xml | 266 +++---- .../standard-testcases/inline_background-image.xml | 98 +-- .../standard-testcases/inline_baseline-shift_1.xml | 330 ++++----- .../standard-testcases/inline_baseline-shift_2.xml | 346 ++++----- .../standard-testcases/inline_baseline-shift_3.xml | 422 +++++------ .../standard-testcases/inline_baseline-shift_4.xml | 370 +++++----- .../inline_block_nested_bug36248.xml | 120 ++-- .../standard-testcases/inline_border_padding.xml | 282 ++++---- .../inline_border_padding_block_nested_1.xml | 268 +++---- .../inline_border_padding_block_nested_2.xml | 360 +++++----- .../inline_border_padding_conditionality_1.xml | 798 ++++++++++---------- .../inline_border_padding_conditionality_2.xml | 624 ++++++++-------- .../inline_dominant-baseline_1.xml | 258 +++---- .../inline_dominant-baseline_2.xml | 258 +++---- .../inline_dominant-baseline_3.xml | 232 +++--- .../standard-testcases/inline_keep-together.xml | 118 +-- .../standard-testcases/inline_vertical-align_1.xml | 378 +++++----- .../standard-testcases/inline_vertical-align_2.xml | 244 +++---- .../standard-testcases/leader-alignment.xml | 136 ++-- .../leader_alignment-baseline.xml | 342 ++++----- .../standard-testcases/leader_background-color.xml | 164 ++--- .../standard-testcases/leader_border_padding.xml | 578 +++++++-------- .../leader_leader-pattern_dots.xml | 2 +- .../leader_leader-pattern_rule.xml | 2 +- .../leader_leader-pattern_space.xml | 2 +- .../leader_leader-pattern_use-content.xml | 352 ++++----- .../leader_leader-pattern_use-content_bug.xml | 116 +-- .../standard-testcases/leader_text-align.xml | 318 ++++---- .../layoutengine/standard-testcases/leader_toc.xml | 310 ++++---- .../list-block_background-image.xml | 168 ++--- .../list-block_padding_percentages.xml | 152 ++-- .../list-item_background-image.xml | 168 ++--- .../list-item_padding_percentages.xml | 158 ++-- .../layoutengine/standard-testcases/marker_bug.xml | 138 ++-- .../standard-testcases/page-breaking_6.xml | 124 ++-- .../page-height_indefinite_simple.xml | 106 +-- .../page-number-citation_background-color.xml | 88 +-- .../page-number-citation_background-image.xml | 100 +-- .../page-number-citation_border_padding.xml | 198 ++--- .../page-number-citation_vertical-align.xml | 120 ++-- .../page-number_background-color.xml | 88 +-- .../page-number_background-image.xml | 98 +-- .../page-number_border_padding.xml | 198 ++--- .../page-number_initial-page-number_2.xml | 108 +-- .../page-number_vertical-align.xml | 120 ++-- .../standard-testcases/ps-extension_2.xml | 190 ++--- .../region-body_column-count_bug36356.xml | 120 ++-- ...e-master_margin_region-body_margin_relative.xml | 214 +++--- ...e-orientation_0_region-body_margin_relative.xml | 224 +++--- ...writing-mode_rl_region-body_margin_relative.xml | 226 +++--- ...orientation_180_region-body_margin_relative.xml | 226 +++--- ...writing-mode_rl_region-body_margin_relative.xml | 226 +++--- ...orientation_270_region-body_margin_relative.xml | 226 +++--- ...writing-mode_rl_region-body_margin_relative.xml | 226 +++--- ...-orientation_90_region-body_margin_relative.xml | 226 +++--- ...writing-mode_rl_region-body_margin_relative.xml | 226 +++--- ...writing-mode_rl_region-body_writing-mode-lr.xml | 228 +++--- .../table-body_background-image.xml | 220 +++--- .../table-cell_background-image.xml | 262 +++---- .../table-cell_block_margin_percentage.xml | 164 ++--- .../table-cell_padding_percentages.xml | 130 ++-- .../table-header_background-image.xml | 202 +++--- .../table-row_background-image.xml | 178 ++--- .../standard-testcases/table_background-image.xml | 226 +++--- .../table_padding_percentages.xml | 152 ++-- .../standard-testcases/table_width.xml | 196 ++--- 120 files changed, 12050 insertions(+), 12046 deletions(-) create mode 100755 fixsvnprops.sh (limited to 'src') diff --git a/fixsvnprops.sh b/fixsvnprops.sh new file mode 100755 index 000000000..6e8181df7 --- /dev/null +++ b/fixsvnprops.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +find . -name \*.java -or -name \*.xml -exec svn ps svn:keywords "Revision Id" '{}' \; +find . -name \*.java -or -name \*.xml -exec svn ps svn:eol-style native '{}' \; diff --git a/src/documentation/content/xdocs/0.93/index.xml b/src/documentation/content/xdocs/0.93/index.xml index 32d46cf0f..3542e1d5f 100644 --- a/src/documentation/content/xdocs/0.93/index.xml +++ b/src/documentation/content/xdocs/0.93/index.xml @@ -20,7 +20,7 @@
    Apache FOP Version 0.93 - $Revision: 201586 $ + $Revision$
    diff --git a/src/documentation/content/xdocs/0.93/pdfa.xml b/src/documentation/content/xdocs/0.93/pdfa.xml index 505a10805..64bd5dc91 100644 --- a/src/documentation/content/xdocs/0.93/pdfa.xml +++ b/src/documentation/content/xdocs/0.93/pdfa.xml @@ -20,7 +20,7 @@
    PDF/A (ISO 19005) - $Revision: 389563 $ + $Revision$ diff --git a/src/documentation/content/xdocs/0.94/index.xml b/src/documentation/content/xdocs/0.94/index.xml index 750047678..ba5b1af15 100644 --- a/src/documentation/content/xdocs/0.94/index.xml +++ b/src/documentation/content/xdocs/0.94/index.xml @@ -20,7 +20,7 @@
    Apache FOP Version 0.94 - $Revision: 201586 $ + $Revision$
    diff --git a/src/documentation/content/xdocs/0.94/pdfa.xml b/src/documentation/content/xdocs/0.94/pdfa.xml index 49ffbeb71..1b3b75561 100644 --- a/src/documentation/content/xdocs/0.94/pdfa.xml +++ b/src/documentation/content/xdocs/0.94/pdfa.xml @@ -20,7 +20,7 @@
    PDF/A (ISO 19005) - $Revision: 389563 $ + $Revision$ diff --git a/src/documentation/content/xdocs/trunk/index.xml b/src/documentation/content/xdocs/trunk/index.xml index 80092d054..c152701ad 100644 --- a/src/documentation/content/xdocs/trunk/index.xml +++ b/src/documentation/content/xdocs/trunk/index.xml @@ -20,7 +20,7 @@
    Apache FOP Trunk (Development code) - $Revision: 201586 $ + $Revision$
    diff --git a/src/documentation/content/xdocs/trunk/pdfa.xml b/src/documentation/content/xdocs/trunk/pdfa.xml index 49ffbeb71..1b3b75561 100644 --- a/src/documentation/content/xdocs/trunk/pdfa.xml +++ b/src/documentation/content/xdocs/trunk/pdfa.xml @@ -20,7 +20,7 @@
    PDF/A (ISO 19005) - $Revision: 389563 $ + $Revision$ diff --git a/test/layoutengine/hyphenation-testcases/block_hyphenation-ladder-count.xml b/test/layoutengine/hyphenation-testcases/block_hyphenation-ladder-count.xml index af79c559b..8a0d4e4c2 100755 --- a/test/layoutengine/hyphenation-testcases/block_hyphenation-ladder-count.xml +++ b/test/layoutengine/hyphenation-testcases/block_hyphenation-ladder-count.xml @@ -1,355 +1,355 @@ - - - - - -

    - Checks hyphenation for various languages -

    -
    - - - - - - - - - - - - - - - - - - US English hypenation-ladder-count="no-limit" - - - This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a - W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from - another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its - widespread deployment. This enhances the functionality and interoperability of the Web. - - - - US English hypenation-ladder-count="1" - - - This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a - W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from - another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its - widespread deployment. This enhances the functionality and interoperability of the Web. - - - - US English hypenation-ladder-count="2" - - - This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a - W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from - another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its - widespread deployment. This enhances the functionality and interoperability of the Web. - - - - US English hypenation-ladder-count="3" - - - This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a - W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from - another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its - widespread deployment. This enhances the functionality and interoperability of the Web. - - - - US English hypenation-ladder-count="4" - - - This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a - W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from - another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its - widespread deployment. This enhances the functionality and interoperability of the Web. - - - - German hypenation-ladder-count="no-limit" - - - - 1. Warum TEI? - Die Verwendungszeit elektronischer Editionen wird von mehreren - Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu - ihrer Darstellung verwendet werden, der etwas längeren der - Betriebssysteme, unter denen die Darstellungsprogramme laufen, - der logischen Einrichtung des Datenträgers, auf dem sich die - Edition befindet, und dessen physischer Dauer. - - - - German hypenation-ladder-count="1" - - - - 1. Warum TEI? - Die Verwendungszeit elektronischer Editionen wird von mehreren - Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu - ihrer Darstellung verwendet werden, der etwas längeren der - Betriebssysteme, unter denen die Darstellungsprogramme laufen, - der logischen Einrichtung des Datenträgers, auf dem sich die - Edition befindet, und dessen physischer Dauer. - - - - German hypenation-ladder-count="2" - - - - 1. Warum TEI? - Die Verwendungszeit elektronischer Editionen wird von mehreren - Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu - ihrer Darstellung verwendet werden, der etwas längeren der - Betriebssysteme, unter denen die Darstellungsprogramme laufen, - der logischen Einrichtung des Datenträgers, auf dem sich die - Edition befindet, und dessen physischer Dauer. - - - - German hypenation-ladder-count="3" - - - - 1. Warum TEI? - Die Verwendungszeit elektronischer Editionen wird von mehreren - Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu - ihrer Darstellung verwendet werden, der etwas längeren der - Betriebssysteme, unter denen die Darstellungsprogramme laufen, - der logischen Einrichtung des Datenträgers, auf dem sich die - Edition befindet, und dessen physischer Dauer. - - - - German hypenation-ladder-count="4" - - - - 1. Warum TEI? - Die Verwendungszeit elektronischer Editionen wird von mehreren - Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu - ihrer Darstellung verwendet werden, der etwas längeren der - Betriebssysteme, unter denen die Darstellungsprogramme laufen, - der logischen Einrichtung des Datenträgers, auf dem sich die - Edition befindet, und dessen physischer Dauer. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + Checks hyphenation for various languages +

    +
    + + + + + + + + + + + + + + + + + + US English hypenation-ladder-count="no-limit" + + + This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a + W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from + another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its + widespread deployment. This enhances the functionality and interoperability of the Web. + + + + US English hypenation-ladder-count="1" + + + This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a + W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from + another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its + widespread deployment. This enhances the functionality and interoperability of the Web. + + + + US English hypenation-ladder-count="2" + + + This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a + W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from + another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its + widespread deployment. This enhances the functionality and interoperability of the Web. + + + + US English hypenation-ladder-count="3" + + + This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a + W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from + another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its + widespread deployment. This enhances the functionality and interoperability of the Web. + + + + US English hypenation-ladder-count="4" + + + This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a + W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from + another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its + widespread deployment. This enhances the functionality and interoperability of the Web. + + + + German hypenation-ladder-count="no-limit" + + + + 1. Warum TEI? + Die Verwendungszeit elektronischer Editionen wird von mehreren + Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu + ihrer Darstellung verwendet werden, der etwas längeren der + Betriebssysteme, unter denen die Darstellungsprogramme laufen, + der logischen Einrichtung des Datenträgers, auf dem sich die + Edition befindet, und dessen physischer Dauer. + + + + German hypenation-ladder-count="1" + + + + 1. Warum TEI? + Die Verwendungszeit elektronischer Editionen wird von mehreren + Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu + ihrer Darstellung verwendet werden, der etwas längeren der + Betriebssysteme, unter denen die Darstellungsprogramme laufen, + der logischen Einrichtung des Datenträgers, auf dem sich die + Edition befindet, und dessen physischer Dauer. + + + + German hypenation-ladder-count="2" + + + + 1. Warum TEI? + Die Verwendungszeit elektronischer Editionen wird von mehreren + Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu + ihrer Darstellung verwendet werden, der etwas längeren der + Betriebssysteme, unter denen die Darstellungsprogramme laufen, + der logischen Einrichtung des Datenträgers, auf dem sich die + Edition befindet, und dessen physischer Dauer. + + + + German hypenation-ladder-count="3" + + + + 1. Warum TEI? + Die Verwendungszeit elektronischer Editionen wird von mehreren + Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu + ihrer Darstellung verwendet werden, der etwas längeren der + Betriebssysteme, unter denen die Darstellungsprogramme laufen, + der logischen Einrichtung des Datenträgers, auf dem sich die + Edition befindet, und dessen physischer Dauer. + + + + German hypenation-ladder-count="4" + + + + 1. Warum TEI? + Die Verwendungszeit elektronischer Editionen wird von mehreren + Faktoren verkürzt: der kurzen Lebensdauer der Programme, die zu + ihrer Darstellung verwendet werden, der etwas längeren der + Betriebssysteme, unter denen die Darstellungsprogramme laufen, + der logischen Einrichtung des Datenträgers, auf dem sich die + Edition befindet, und dessen physischer Dauer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/hyphenation-testcases/inline_border_padding_hyphenate.xml b/test/layoutengine/hyphenation-testcases/inline_border_padding_hyphenate.xml index cf4c1818a..4c1c81189 100755 --- a/test/layoutengine/hyphenation-testcases/inline_border_padding_hyphenate.xml +++ b/test/layoutengine/hyphenation-testcases/inline_border_padding_hyphenate.xml @@ -1,400 +1,400 @@ - - - - - -

    - This test checks fo:inlines with border and padding properties and hyphenation. -

    -
    - - - - - - - - - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="start" .conditionality="discard". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="end" .conditionality="discard". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="justify" .conditionality="discard". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="center" .conditionality="discard". - - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="start" .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="end" .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="justify" .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="center" .conditionality="retain". - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:inlines with border and padding properties and hyphenation. +

    +
    + + + + + + + + + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="start" .conditionality="discard". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="end" .conditionality="discard". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="justify" .conditionality="discard". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="center" .conditionality="discard". + + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="start" .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="end" .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="justify" .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="center" .conditionality="retain". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/hyphenation-testcases/inline_border_padding_hyphenate_de.xml b/test/layoutengine/hyphenation-testcases/inline_border_padding_hyphenate_de.xml index 0e058d9e8..6eda5a058 100755 --- a/test/layoutengine/hyphenation-testcases/inline_border_padding_hyphenate_de.xml +++ b/test/layoutengine/hyphenation-testcases/inline_border_padding_hyphenate_de.xml @@ -1,400 +1,400 @@ - - - - - -

    - This test checks inlines with border and padding properties and hyphenation. -

    -
    - - - - - - - - - - - Multi-line fo:inline - Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz - Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft - text-align="start" .conditionality="discard". - - - Multi-line fo:inline - Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz - Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft - text-align="end" .conditionality="discard". - - - Multi-line fo:inline - Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz - Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft - text-align="justify" .conditionality="discard". - - - Multi-line fo:inline - Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz - Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft - text-align="center" .conditionality="discard". - - - - Multi-line fo:inline - Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz - Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft - text-align="start" .conditionality="retain". - - - Multi-line fo:inline - Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz - Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft - text-align="end" .conditionality="retain". - - - Multi-line fo:inline - Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz - Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft - text-align="justify" .conditionality="retain". - - - Multi-line fo:inline - Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz - Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft - text-align="center" .conditionality="retain". - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inlines with border and padding properties and hyphenation. +

    +
    + + + + + + + + + + + Multi-line fo:inline + Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz + Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft + text-align="start" .conditionality="discard". + + + Multi-line fo:inline + Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz + Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft + text-align="end" .conditionality="discard". + + + Multi-line fo:inline + Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz + Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft + text-align="justify" .conditionality="discard". + + + Multi-line fo:inline + Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz + Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft + text-align="center" .conditionality="discard". + + + + Multi-line fo:inline + Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz + Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft + text-align="start" .conditionality="retain". + + + Multi-line fo:inline + Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz + Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft + text-align="end" .conditionality="retain". + + + Multi-line fo:inline + Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz + Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft + text-align="justify" .conditionality="retain". + + + Multi-line fo:inline + Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz + Donaudampfschiffahrtselektrizitaetenhauptbetriebswerkbauunterbeamtengesellschaft + text-align="center" .conditionality="retain". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_background-image.xml b/test/layoutengine/standard-testcases/basic-link_background-image.xml index 88b5a4daf..36aefb963 100644 --- a/test/layoutengine/standard-testcases/basic-link_background-image.xml +++ b/test/layoutengine/standard-testcases/basic-link_background-image.xml @@ -1,49 +1,49 @@ - - - - - -

    - This test checks background image on a fo:basic-link. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - Why is FOP so cool? - - - - - - - - - - -
    + + + + + +

    + This test checks background image on a fo:basic-link. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + Why is FOP so cool? + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block-container_padding_percentages.xml b/test/layoutengine/standard-testcases/block-container_padding_percentages.xml index 4173b0c3c..f82c3f985 100644 --- a/test/layoutengine/standard-testcases/block-container_padding_percentages.xml +++ b/test/layoutengine/standard-testcases/block-container_padding_percentages.xml @@ -1,54 +1,54 @@ - - - - - -

    - This test checks relative padding on block containers. -

    -
    - - - - - - - - - - - margin not specified padding="5%" on this 2x1in yellow container - - - margin="0pt" padding="5%" on this 2x1in blue container - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative padding on block containers. +

    +
    + + + + + + + + + + + margin not specified padding="5%" on this 2x1in yellow container + + + margin="0pt" padding="5%" on this 2x1in blue container + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml b/test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml index 7b1bfc793..95cf2fb13 100644 --- a/test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml +++ b/test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml @@ -1,104 +1,104 @@ - - - - - -

    - This test checks in-flow block-containers with reference orientation. - Special case with nested block-containers from Bugzilla #36391. -

    -
    - - - - - - - - - - Reference orientation : 0 - - - ABC - - - Reference orientation : 90 - - - ABC - - - Reference orientation : -270 - - - ABC - - - Reference orientation : 180 - - - ABC - - - Reference orientation : -180 - - - ABC - - - Reference orientation : 270 - - - ABC - - - Reference orientation : -90 - - - ABC - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks in-flow block-containers with reference orientation. + Special case with nested block-containers from Bugzilla #36391. +

    +
    + + + + + + + + + + Reference orientation : 0 + + + ABC + + + Reference orientation : 90 + + + ABC + + + Reference orientation : -270 + + + ABC + + + Reference orientation : 180 + + + ABC + + + Reference orientation : -180 + + + ABC + + + Reference orientation : 270 + + + ABC + + + Reference orientation : -90 + + + ABC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_break-after_bug40230.xml b/test/layoutengine/standard-testcases/block_break-after_bug40230.xml index 15c66482f..129836159 100644 --- a/test/layoutengine/standard-testcases/block_break-after_bug40230.xml +++ b/test/layoutengine/standard-testcases/block_break-after_bug40230.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - +

    diff --git a/test/layoutengine/standard-testcases/block_font-stretch.xml b/test/layoutengine/standard-testcases/block_font-stretch.xml index 9f006d580..d3c11fb00 100644 --- a/test/layoutengine/standard-testcases/block_font-stretch.xml +++ b/test/layoutengine/standard-testcases/block_font-stretch.xml @@ -1,56 +1,56 @@ - - - - - -

    - This test checks font stretches. -

    -
    - - - - - - - - - - font-family="serif" font-stretch not given - font-family="serif" font-stretch="ultra-condensed" - font-family="serif" font-stretch="narrower" - - font-family="serif" font-stretch="extra-condensed" - font-family="serif" font-stretch="condensed" - font-family="serif" font-stretch="semi-condensed" - font-family="serif" font-stretch="normal" - font-family="serif" font-stretch="semi-expanded" - font-family="serif" font-stretch="expanded" - font-family="serif" font-stretch="extra-expanded" - font-family="serif" font-stretch="ultra-expanded" - font-family="serif" font-stretch="wider" - - font-family="serif" font-stretch="narrower" - font-family="serif" font-stretch="wider" - - - - - - -
    + + + + + +

    + This test checks font stretches. +

    +
    + + + + + + + + + + font-family="serif" font-stretch not given + font-family="serif" font-stretch="ultra-condensed" + font-family="serif" font-stretch="narrower" + + font-family="serif" font-stretch="extra-condensed" + font-family="serif" font-stretch="condensed" + font-family="serif" font-stretch="semi-condensed" + font-family="serif" font-stretch="normal" + font-family="serif" font-stretch="semi-expanded" + font-family="serif" font-stretch="expanded" + font-family="serif" font-stretch="extra-expanded" + font-family="serif" font-stretch="ultra-expanded" + font-family="serif" font-stretch="wider" + + font-family="serif" font-stretch="narrower" + font-family="serif" font-stretch="wider" + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_line-height.xml b/test/layoutengine/standard-testcases/block_line-height.xml index 10b8fcdc6..ef859dce6 100644 --- a/test/layoutengine/standard-testcases/block_line-height.xml +++ b/test/layoutengine/standard-testcases/block_line-height.xml @@ -1,124 +1,124 @@ - - - - - -

    - This test checks line height and its special inheritance behaviour -

    -
    - - - - - - - - - - line-height="normal" - font-size="larger" - line height grows - font-size="smaller" - line height shrinks - - line-height="150%" - font-size="larger" - line height same as above - font-size="smaller" - line height same as above - - line-height="20pt" - font-size="larger" - line height same as above - font-size="smaller" - line height same as above - - line-height="1.5" - font-size="larger" - line height grows - font-size="smaller" - line height shrinks - - line-height="150% - 5pt" - font-size="larger" - line height same as above - font-size="smaller" - line height same as above - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks line height and its special inheritance behaviour +

    +
    + + + + + + + + + + line-height="normal" + font-size="larger" - line height grows + font-size="smaller" - line height shrinks + + line-height="150%" + font-size="larger" - line height same as above + font-size="smaller" - line height same as above + + line-height="20pt" + font-size="larger" - line height same as above + font-size="smaller" - line height same as above + + line-height="1.5" + font-size="larger" - line height grows + font-size="smaller" - line height shrinks + + line-height="150% - 5pt" + font-size="larger" - line height same as above + font-size="smaller" - line height same as above + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_line-stacking-strategy_1.xml b/test/layoutengine/standard-testcases/block_line-stacking-strategy_1.xml index a29c974f9..df4839475 100644 --- a/test/layoutengine/standard-testcases/block_line-stacking-strategy_1.xml +++ b/test/layoutengine/standard-testcases/block_line-stacking-strategy_1.xml @@ -1,165 +1,165 @@ - - - - - -

    - This test checks line-stacking-strategy font-height against inlines of different sizes. -

    -
    - - - - - - - - - - - Before - bigger - - After - - - Before - bigger with b & p - - After - - - Before - sub - sub - sub - - After - - - Before - super - super - super - - After - - - Before - super - sub - super - sub - super - - After - - - Before - sub - super - sub - super - sub - - After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks line-stacking-strategy font-height against inlines of different sizes. +

    +
    + + + + + + + + + + + Before + bigger + + After + + + Before + bigger with b & p + + After + + + Before + sub + sub + sub + + After + + + Before + super + super + super + + After + + + Before + super + sub + super + sub + super + + After + + + Before + sub + super + sub + super + sub + + After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_linefeed-treatment.xml b/test/layoutengine/standard-testcases/block_linefeed-treatment.xml index 23686bb10..ac60a457f 100644 --- a/test/layoutengine/standard-testcases/block_linefeed-treatment.xml +++ b/test/layoutengine/standard-testcases/block_linefeed-treatment.xml @@ -1,81 +1,81 @@ - - - - - -

    - This test checks white space handling for linefeed-treatment. - This currently fails because - a) Preserved linefeeds in fo:character are not handled correctly - b) ZWSP are not handled correctly -

    -
    - - - - - - - - - - -treat-as-space -alllinefeeds - - -ignore -alllinefeeds - - -preserve -alllinefeeds - - -treat-as-zero-width-space -alllinefeeds - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks white space handling for linefeed-treatment. + This currently fails because + a) Preserved linefeeds in fo:character are not handled correctly + b) ZWSP are not handled correctly +

    +
    + + + + + + + + + + +treat-as-space +alllinefeeds + + +ignore +alllinefeeds + + +preserve +alllinefeeds + + +treat-as-zero-width-space +alllinefeeds + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_margin_inherit.xml b/test/layoutengine/standard-testcases/block_margin_inherit.xml index 4466dbd34..86877c66a 100644 --- a/test/layoutengine/standard-testcases/block_margin_inherit.xml +++ b/test/layoutengine/standard-testcases/block_margin_inherit.xml @@ -1,77 +1,77 @@ - - - - - -

    - This test checks margin percentages on fo:block with explict inheritance. -

    -
    - - - - - - - - - - - - margin="inherit" - should have the same margin as the enclosing block - - - Yellow block has margin="5%" - 18pt margin based on 5in page width - - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks margin percentages on fo:block with explict inheritance. +

    +
    + + + + + + + + + + + + margin="inherit" - should have the same margin as the enclosing block + + + Yellow block has margin="5%" - 18pt margin based on 5in page width + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_margin_percentages.xml b/test/layoutengine/standard-testcases/block_margin_percentages.xml index 7f5e947b4..d3ce921c5 100644 --- a/test/layoutengine/standard-testcases/block_margin_percentages.xml +++ b/test/layoutengine/standard-testcases/block_margin_percentages.xml @@ -1,77 +1,77 @@ - - - - - -

    - This test checks margin percentages on fo:block. -

    -
    - - - - - - - - - - - - margin="5%" - should have the slightly smaller margin than the enclosing block - - - Yellow block has margin="5%" - 18pt margin based on 5in page width - - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks margin percentages on fo:block. +

    +
    + + + + + + + + + + + + margin="5%" - should have the slightly smaller margin than the enclosing block + + + Yellow block has margin="5%" - 18pt margin based on 5in page width + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_padding_2.xml b/test/layoutengine/standard-testcases/block_padding_2.xml index 40e14dd80..31f7826a6 100644 --- a/test/layoutengine/standard-testcases/block_padding_2.xml +++ b/test/layoutengine/standard-testcases/block_padding_2.xml @@ -1,112 +1,112 @@ - - - - - -

    - This test checks non-conditional before- and after-padding in break-situations. -

    -
    - - - - - - - - - - - line1 - line2 - line3 - line4 - line5 - line6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 3 - - -
    + + + + + +

    + This test checks non-conditional before- and after-padding in break-situations. +

    +
    + + + + + + + + + + + line1 + line2 + line3 + line4 + line5 + line6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 3 + + +
    diff --git a/test/layoutengine/standard-testcases/block_padding_percentages.xml b/test/layoutengine/standard-testcases/block_padding_percentages.xml index 326f2a744..991f1f85d 100644 --- a/test/layoutengine/standard-testcases/block_padding_percentages.xml +++ b/test/layoutengine/standard-testcases/block_padding_percentages.xml @@ -1,54 +1,54 @@ - - - - - -

    - This test checks relative padding on blocks. -

    -
    - - - - - - - - - - - margin not specified padding="5%" - - - margin="0pt" padding="5%" - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative padding on blocks. +

    +
    + + + + + + + + + + + margin not specified padding="5%" + + + margin="0pt" padding="5%" + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_space-before_space-after_3.xml b/test/layoutengine/standard-testcases/block_space-before_space-after_3.xml index 9c49df822..5898cbff2 100644 --- a/test/layoutengine/standard-testcases/block_space-before_space-after_3.xml +++ b/test/layoutengine/standard-testcases/block_space-before_space-after_3.xml @@ -1,56 +1,56 @@ - - - - - -

    - This test checks block-level space properties. This is the space-resolution example in "4.3.1 Space-resolution Rules". -

    -
    - - - - - - - - - - - - - In olden times when wishing still helped one, there lived a king whose daughters - - - - - - - - - - - - - - - - 3 - - -
    + + + + + +

    + This test checks block-level space properties. This is the space-resolution example in "4.3.1 Space-resolution Rules". +

    +
    + + + + + + + + + + + + + In olden times when wishing still helped one, there lived a king whose daughters + + + + + + + + + + + + + + + + 3 + + +
    diff --git a/test/layoutengine/standard-testcases/block_text-align_1.xml b/test/layoutengine/standard-testcases/block_text-align_1.xml index e91c997f1..675438112 100644 --- a/test/layoutengine/standard-testcases/block_text-align_1.xml +++ b/test/layoutengine/standard-testcases/block_text-align_1.xml @@ -1,124 +1,124 @@ - - - - - -

    - This test checks text-align and text-align-last. -

    -
    - - - - - - - - - - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks text-align and text-align-last. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi suscipit, risus ac congue suscipit, tortor nibh cursus mauris, quis feugiat nunc ante sit amet ante. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_text-align_2.xml b/test/layoutengine/standard-testcases/block_text-align_2.xml index 691f1ee87..e05d1e3ee 100644 --- a/test/layoutengine/standard-testcases/block_text-align_2.xml +++ b/test/layoutengine/standard-testcases/block_text-align_2.xml @@ -1,52 +1,52 @@ - - - - - -

    - This test checks text-align and text-align-last in special conditions. -

    -
    - - - - - - - - - - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - - - - - - - - - - - - -
    + + + + + +

    + This test checks text-align and text-align-last in special conditions. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_white-space-collapse_1.xml b/test/layoutengine/standard-testcases/block_white-space-collapse_1.xml index 600958f2f..2f9edece8 100644 --- a/test/layoutengine/standard-testcases/block_white-space-collapse_1.xml +++ b/test/layoutengine/standard-testcases/block_white-space-collapse_1.xml @@ -1,152 +1,152 @@ - - - - - -

    - This test checks basic white space handling for white-space-collapse="true". -

    -
    - - - - - - - - - - - spaces - before - and - after - each - word - and - linefeeds - everywhere - - - - nested block level - - - nested block level - - - - - inline level - - - inline level - - - - block level - - inline level - - block - - inline level - - block level - - - - inline level - - nested inline level - - - - - - - nested inline level - - inline level - - - - block level - - - nested inline level - - inline level - - block level - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks basic white space handling for white-space-collapse="true". +

    +
    + + + + + + + + + + + spaces + before + and + after + each + word + and + linefeeds + everywhere + + + + nested block level + + + nested block level + + + + + inline level + + + inline level + + + + block level + + inline level + + block + + inline level + + block level + + + + inline level + + nested inline level + + + + + + + nested inline level + + inline level + + + + block level + + + nested inline level + + inline level + + block level + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_white-space-collapse_2.xml b/test/layoutengine/standard-testcases/block_white-space-collapse_2.xml index 792e858ea..dbb092417 100644 --- a/test/layoutengine/standard-testcases/block_white-space-collapse_2.xml +++ b/test/layoutengine/standard-testcases/block_white-space-collapse_2.xml @@ -1,142 +1,142 @@ - - - - - -

    - This test checks basic white space handling for white-space-collapse="false". -

    -
    - - - - - - - - - - - spaces - before - and - after - each - word - and - linefeeds - everywhere - - - - nested block level - - - nested block level - - - - - inline level - - - inline level - - - - block level - - inline level - - block - - inline level - - block level - - - - inline level - - nested inline level - - - - - - - nested inline level - - inline level - - - - block level - - - nested inline level - - inline level - - block level - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks basic white space handling for white-space-collapse="false". +

    +
    + + + + + + + + + + + spaces + before + and + after + each + word + and + linefeeds + everywhere + + + + nested block level + + + nested block level + + + + + inline level + + + inline level + + + + block level + + inline level + + block + + inline level + + block level + + + + inline level + + nested inline level + + + + + + + nested inline level + + inline level + + + + block level + + + nested inline level + + inline level + + block level + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_white-space-treatment_1.xml b/test/layoutengine/standard-testcases/block_white-space-treatment_1.xml index d81c61ddb..845a812c9 100644 --- a/test/layoutengine/standard-testcases/block_white-space-treatment_1.xml +++ b/test/layoutengine/standard-testcases/block_white-space-treatment_1.xml @@ -1,81 +1,81 @@ - - - - - -

    - This test checks white space handling for white-space-treatment - with white-space-collapse="true". -

    -
    - - - - - - - - - - - ignore-if-surrounding-linefeed - all - spaces - - - ignore - all - spaces - - - preserve - all - spaces - - - ignore-if-before-linefeed - all - spaces - - - ignore-if-after-linefeed - all - spaces - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks white space handling for white-space-treatment + with white-space-collapse="true". +

    +
    + + + + + + + + + + + ignore-if-surrounding-linefeed + all + spaces + + + ignore + all + spaces + + + preserve + all + spaces + + + ignore-if-before-linefeed + all + spaces + + + ignore-if-after-linefeed + all + spaces + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_white-space-treatment_2.xml b/test/layoutengine/standard-testcases/block_white-space-treatment_2.xml index 1fd3b409a..e5f702a45 100644 --- a/test/layoutengine/standard-testcases/block_white-space-treatment_2.xml +++ b/test/layoutengine/standard-testcases/block_white-space-treatment_2.xml @@ -1,96 +1,96 @@ - - - - - -

    - This test checks white space handling for white-space-treatment - with white-space-collapse="false". -

    -
    - - - - - - - - - - - ignore-if-surrounding-linefeed - all - spaces - - - ignore - all - spaces - - - preserve - all - spaces - - - ignore-if-before-linefeed - all - spaces - - - ignore-if-after-linefeed - all - spaces - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks white space handling for white-space-treatment + with white-space-collapse="false". +

    +
    + + + + + + + + + + + ignore-if-surrounding-linefeed + all + spaces + + + ignore + all + spaces + + + preserve + all + spaces + + + ignore-if-before-linefeed + all + spaces + + + ignore-if-after-linefeed + all + spaces + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_white-space_nbsp_1.xml b/test/layoutengine/standard-testcases/block_white-space_nbsp_1.xml index b7e490b47..72e73fc64 100644 --- a/test/layoutengine/standard-testcases/block_white-space_nbsp_1.xml +++ b/test/layoutengine/standard-testcases/block_white-space_nbsp_1.xml @@ -1,106 +1,106 @@ - - - - - -

    - This test checks non breaking white space (nbsp). -

    -
    - - - - - - - - - -  single nbsp around  -   -   after  empty  line   -  single nbsp around  - - - - - - - - - - - - - - - - - - - - - - - - - - 3 - - - - - 3 - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - 3 - - - -
    + + + + + +

    + This test checks non breaking white space (nbsp). +

    +
    + + + + + + + + + +  single nbsp around  +   +   after  empty  line   +  single nbsp around  + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + 3 + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + 3 + + + +
    diff --git a/test/layoutengine/standard-testcases/block_wrap-option.xml b/test/layoutengine/standard-testcases/block_wrap-option.xml index bb2e75130..d6584ee4a 100644 --- a/test/layoutengine/standard-testcases/block_wrap-option.xml +++ b/test/layoutengine/standard-testcases/block_wrap-option.xml @@ -1,58 +1,58 @@ - - - - - -

    - This test checks the wrap-option property on fo:block. -

    -
    - - - - - - - - - - - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas et ligula. Suspendisse faucibus. Donec porta risus vitae turpis. - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas et ligula. Suspendisse faucibus. Donec porta risus vitae turpis. - - - - - - - - - - - - - - - - - - - 3 - - -
    + + + + + +

    + This test checks the wrap-option property on fo:block. +

    +
    + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas et ligula. Suspendisse faucibus. Donec porta risus vitae turpis. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas et ligula. Suspendisse faucibus. Donec porta risus vitae turpis. + + + + + + + + + + + + + + + + + + + 3 + + +
    diff --git a/test/layoutengine/standard-testcases/character_background-color.xml b/test/layoutengine/standard-testcases/character_background-color.xml index 241d73f1f..f9ea30690 100644 --- a/test/layoutengine/standard-testcases/character_background-color.xml +++ b/test/layoutengine/standard-testcases/character_background-color.xml @@ -1,44 +1,44 @@ - - - - - -

    - This test checks fo:character with background-color property. -

    -
    - - - - - - - - - - - To mphasize a character highlight it. - - - - - - - - -
    + + + + + +

    + This test checks fo:character with background-color property. +

    +
    + + + + + + + + + + + To mphasize a character highlight it. + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/character_background-image.xml b/test/layoutengine/standard-testcases/character_background-image.xml index 67e9e8162..b887315f2 100644 --- a/test/layoutengine/standard-testcases/character_background-image.xml +++ b/test/layoutengine/standard-testcases/character_background-image.xml @@ -1,49 +1,49 @@ - - - - - -

    - This test checks fo:character with background-image property. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:character with background-image property. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/character_border_padding.xml b/test/layoutengine/standard-testcases/character_border_padding.xml index 465a4f1a7..57c5f4907 100644 --- a/test/layoutengine/standard-testcases/character_border_padding.xml +++ b/test/layoutengine/standard-testcases/character_border_padding.xml @@ -1,99 +1,99 @@ - - - - - -

    - This test checks fo:character with border and padding properties. -

    -
    - - - - - - - - - - - To mphasize a letter we give it a 1pt border. - - - To really mphasize a letter we give it a 5pt border and padding. - - - To onfuse give it unsymmetric borders and padding. - - - Big order but a smaller font. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:character with border and padding properties. +

    +
    + + + + + + + + + + + To mphasize a letter we give it a 1pt border. + + + To really mphasize a letter we give it a 5pt border and padding. + + + To onfuse give it unsymmetric borders and padding. + + + Big order but a smaller font. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/character_vertical-align.xml b/test/layoutengine/standard-testcases/character_vertical-align.xml index e01d4c0a3..91653f8d6 100644 --- a/test/layoutengine/standard-testcases/character_vertical-align.xml +++ b/test/layoutengine/standard-testcases/character_vertical-align.xml @@ -1,60 +1,60 @@ - - - - - -

    - This test checks fo:character with vertical-align property. -

    -
    - - - - - - - - - - - vertical-alignnot specified - - - vertical-alignbaseline - - - vertical-aligntop - - - vertical-alignmiddle - - - vertical-alignbottom - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:character with vertical-align property. +

    +
    + + + + + + + + + + + vertical-alignnot specified + + + vertical-alignbaseline + + + vertical-aligntop + + + vertical-alignmiddle + + + vertical-alignbottom + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_bmp.xml b/test/layoutengine/standard-testcases/external-graphic_bmp.xml index 2482b1dbd..4e1a2d4b9 100644 --- a/test/layoutengine/standard-testcases/external-graphic_bmp.xml +++ b/test/layoutengine/standard-testcases/external-graphic_bmp.xml @@ -1,57 +1,57 @@ - - - - - -

    - This test checks external-graphics. -

    -
    - - - - - - - - - - BMP external-graphic 300dpi - - EOG - - BMP external-graphic 72dpi - - EOG - - EOF - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics. +

    +
    + + + + + + + + + + BMP external-graphic 300dpi + + EOG + + BMP external-graphic 72dpi + + EOG + + EOF + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_content-height_content-width.xml b/test/layoutengine/standard-testcases/external-graphic_content-height_content-width.xml index e32e4d080..cac54e853 100644 --- a/test/layoutengine/standard-testcases/external-graphic_content-height_content-width.xml +++ b/test/layoutengine/standard-testcases/external-graphic_content-height_content-width.xml @@ -1,50 +1,50 @@ - - - - - -

    - This test checks external-graphics with relative content-height -

    -
    - - - - - - - - - - plain external-graphic - - EOG - - EOF - - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics with relative content-height +

    +
    + + + + + + + + + + plain external-graphic + + EOG + + EOF + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_eps.xml b/test/layoutengine/standard-testcases/external-graphic_eps.xml index 5ffb4b410..3a4af488b 100644 --- a/test/layoutengine/standard-testcases/external-graphic_eps.xml +++ b/test/layoutengine/standard-testcases/external-graphic_eps.xml @@ -1,49 +1,49 @@ - - - - - -

    - This test checks external-graphics. -

    -
    - - - - - - - - - - EPS external-graphic - - EOG - - EOF - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics. +

    +
    + + + + + + + + + + EPS external-graphic + + EOG + + EOF + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_gif.xml b/test/layoutengine/standard-testcases/external-graphic_gif.xml index b500313a0..a3cbd300e 100644 --- a/test/layoutengine/standard-testcases/external-graphic_gif.xml +++ b/test/layoutengine/standard-testcases/external-graphic_gif.xml @@ -1,49 +1,49 @@ - - - - - -

    - This test checks external-graphics. -

    -
    - - - - - - - - - - GIF external-graphic - - EOG - - EOF - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics. +

    +
    + + + + + + + + + + GIF external-graphic + + EOG + + EOF + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_jpeg.xml b/test/layoutengine/standard-testcases/external-graphic_jpeg.xml index 10f52f8fa..a669145b4 100644 --- a/test/layoutengine/standard-testcases/external-graphic_jpeg.xml +++ b/test/layoutengine/standard-testcases/external-graphic_jpeg.xml @@ -1,57 +1,57 @@ - - - - - -

    - This test checks external-graphics. -

    -
    - - - - - - - - - - JPEG external-graphic 300dpi - - EOG - - JPEG external-graphic 72dpi - - EOG - - EOF - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics. +

    +
    + + + + + + + + + + JPEG external-graphic 300dpi + + EOG + + JPEG external-graphic 72dpi + + EOG + + EOF + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_oversized.xml b/test/layoutengine/standard-testcases/external-graphic_oversized.xml index e423acd17..3d8f85d1d 100644 --- a/test/layoutengine/standard-testcases/external-graphic_oversized.xml +++ b/test/layoutengine/standard-testcases/external-graphic_oversized.xml @@ -1,53 +1,53 @@ - - - - - -

    - This test checks external-graphics. An oversized image is to be squeezed into page using min/opt/max values. -

    -
    - - - - - - - - - - This first block is only to force an infinite loop if the image is not scaled down. - - - - - EOF - - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics. An oversized image is to be squeezed into page using min/opt/max values. +

    +
    + + + + + + + + + + This first block is only to force an infinite loop if the image is not scaled down. + + + + + EOF + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_png.xml b/test/layoutengine/standard-testcases/external-graphic_png.xml index aae0daef9..da8c1807f 100644 --- a/test/layoutengine/standard-testcases/external-graphic_png.xml +++ b/test/layoutengine/standard-testcases/external-graphic_png.xml @@ -1,58 +1,58 @@ - - - - - -

    - This test checks external-graphics. -

    -
    - - - - - - - - - - PNG external-graphic 300dpi - - EOG - - PNG external-graphic 72dpi - - EOG - - EOF - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics. +

    +
    + + + + + + + + + + PNG external-graphic 300dpi + + EOG + + PNG external-graphic 72dpi + + EOG + + EOF + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_src_uri.xml b/test/layoutengine/standard-testcases/external-graphic_src_uri.xml index cd1dc91fe..1b28fe8f2 100644 --- a/test/layoutengine/standard-testcases/external-graphic_src_uri.xml +++ b/test/layoutengine/standard-testcases/external-graphic_src_uri.xml @@ -1,83 +1,83 @@ - - - - - -

    - This test checks URI references to external-graphics. -

    -
    - - - - - - - - - - plain external-graphic (relative URI) - - EOG - - plain external-graphic (relative URI with scheme) - - EOG - - - plain external-graphic (relative URI using url(...) function) - - EOG - - plain external-graphic (absolute HTTP URI) - - EOG - - EOF - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks URI references to external-graphics. +

    +
    + + + + + + + + + + plain external-graphic (relative URI) + + EOG + + plain external-graphic (relative URI with scheme) + + EOG + + + plain external-graphic (relative URI using url(...) function) + + EOG + + plain external-graphic (absolute HTTP URI) + + EOG + + EOF + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_svg.xml b/test/layoutengine/standard-testcases/external-graphic_svg.xml index a9d6a048a..80c3e5afc 100644 --- a/test/layoutengine/standard-testcases/external-graphic_svg.xml +++ b/test/layoutengine/standard-testcases/external-graphic_svg.xml @@ -1,82 +1,82 @@ - - - - - -

    - This test checks external-graphics. -

    -
    - - - - - - - - - - 2 inch wide SVG external-graphic on LHS - - EOG - - 4 inch wide SVG external-graphic on RHS - - EOG - - 6 inch wide SVG external-graphic in center, non-uniformly squeezed to a height of 4in. - - EOG - - SVG external-graphic with an intrinsic size (16ptx16pt) - - EOG - - EOF - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics. +

    +
    + + + + + + + + + + 2 inch wide SVG external-graphic on LHS + + EOG + + 4 inch wide SVG external-graphic on RHS + + EOG + + 6 inch wide SVG external-graphic in center, non-uniformly squeezed to a height of 4in. + + EOG + + SVG external-graphic with an intrinsic size (16ptx16pt) + + EOG + + EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/external-graphic_tiff.xml b/test/layoutengine/standard-testcases/external-graphic_tiff.xml index 719e64bf4..63ad60d66 100644 --- a/test/layoutengine/standard-testcases/external-graphic_tiff.xml +++ b/test/layoutengine/standard-testcases/external-graphic_tiff.xml @@ -1,73 +1,73 @@ - - - - - -

    - This test checks external-graphics. -

    -
    - - - - - - - - - - TIFF external-graphic 300dpi - - EOG - - TIFF external-graphic 72dpi - - EOG - - TIFF external-graphic (CCITT group 4 encoding) - - EOG - - TIFF external-graphic (CCITT group 4 encoding, multiple strips) - - EOG - - EOF - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks external-graphics. +

    +
    + + + + + + + + + + TIFF external-graphic 300dpi + + EOG + + TIFF external-graphic 72dpi + + EOG + + TIFF external-graphic (CCITT group 4 encoding) + + EOG + + TIFF external-graphic (CCITT group 4 encoding, multiple strips) + + EOG + + EOF + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/fox_external-document_1.xml b/test/layoutengine/standard-testcases/fox_external-document_1.xml index 4b31809ab..1780202a6 100644 --- a/test/layoutengine/standard-testcases/fox_external-document_1.xml +++ b/test/layoutengine/standard-testcases/fox_external-document_1.xml @@ -1,53 +1,53 @@ - - - - - -

    - This test checks the basics of fox:external-document. -

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks the basics of fox:external-document. +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/fox_external-document_2.xml b/test/layoutengine/standard-testcases/fox_external-document_2.xml index abd5fd2bf..365af5b21 100644 --- a/test/layoutengine/standard-testcases/fox_external-document_2.xml +++ b/test/layoutengine/standard-testcases/fox_external-document_2.xml @@ -1,81 +1,81 @@ - - - - - -

    - This test checks fox:external-document. -

    -
    - - - - - - - - - - - - Just a normal page-sequence in between... - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fox:external-document. +

    +
    + + + + + + + + + + + + Just a normal page-sequence in between... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline-container_border_padding.xml b/test/layoutengine/standard-testcases/inline-container_border_padding.xml index a667b86f1..cfa6f9075 100644 --- a/test/layoutengine/standard-testcases/inline-container_border_padding.xml +++ b/test/layoutengine/standard-testcases/inline-container_border_padding.xml @@ -1,86 +1,86 @@ - - - - - -

    - This test checks the borders and the like for instream-foreign-object. -

    -
    - - - - - - - - - - - Before - inside the container - after - - - BC - inside the container - AC - - - In both blocks we have a setting of border-width="5pt 10pt 20pt 15pt" padding="15pt 20pt 10pt 5pt" on the i-f-o. - In the first block the i-f-o determines the height of the line in the 2nd block the font is bigger than the i-f-o. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks the borders and the like for instream-foreign-object. +

    +
    + + + + + + + + + + + Before + inside the container + after + + + BC + inside the container + AC + + + In both blocks we have a setting of border-width="5pt 10pt 20pt 15pt" padding="15pt 20pt 10pt 5pt" on the i-f-o. + In the first block the i-f-o determines the height of the line in the 2nd block the font is bigger than the i-f-o. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_alignment-adjust_1.xml b/test/layoutengine/standard-testcases/inline_alignment-adjust_1.xml index bf8b5ab39..f6736fcd7 100644 --- a/test/layoutengine/standard-testcases/inline_alignment-adjust_1.xml +++ b/test/layoutengine/standard-testcases/inline_alignment-adjust_1.xml @@ -1,92 +1,92 @@ - - - - - -

    - This test checks inline level alignment-adjust. -

    -
    - - - - - - - - - - - Before alignment-adjust not specified After - - - Before alignment-adjust="auto" After - - - Before alignment-adjust="baseline" After - - - Before alignment-adjust="before-edge" After - - - Before alignment-adjust="text-before-edge" After - - - Before alignment-adjust="central" After - - - Before alignment-adjust="middle" After - - - Before alignment-adjust="after-edge" After - - - Before alignment-adjust="text-after-edge" After - - - Before alignment-adjust="ideographic" After - - - Before alignment-adjust="alphabetic" After - - - Before alignment-adjust="hanging" After - - - Before alignment-adjust="mathematical" After - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level alignment-adjust. +

    +
    + + + + + + + + + + + Before alignment-adjust not specified After + + + Before alignment-adjust="auto" After + + + Before alignment-adjust="baseline" After + + + Before alignment-adjust="before-edge" After + + + Before alignment-adjust="text-before-edge" After + + + Before alignment-adjust="central" After + + + Before alignment-adjust="middle" After + + + Before alignment-adjust="after-edge" After + + + Before alignment-adjust="text-after-edge" After + + + Before alignment-adjust="ideographic" After + + + Before alignment-adjust="alphabetic" After + + + Before alignment-adjust="hanging" After + + + Before alignment-adjust="mathematical" After + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_alignment-adjust_2.xml b/test/layoutengine/standard-testcases/inline_alignment-adjust_2.xml index 501e76bd8..0254f6c20 100644 --- a/test/layoutengine/standard-testcases/inline_alignment-adjust_2.xml +++ b/test/layoutengine/standard-testcases/inline_alignment-adjust_2.xml @@ -1,99 +1,99 @@ - - - - - -

    - This test checks inline level alignment-adjust. -

    -
    - - - - - - - - - - - Before alignment-adjust="0pt" After - - - Before alignment-adjust="0%" After - - - Before alignment-adjust="3pt" After - - - Before alignment-adjust="-3pt" After - - - Before alignment-adjust="30%" After - - - Before alignment-adjust="-30%" After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level alignment-adjust. +

    +
    + + + + + + + + + + + Before alignment-adjust="0pt" After + + + Before alignment-adjust="0%" After + + + Before alignment-adjust="3pt" After + + + Before alignment-adjust="-3pt" After + + + Before alignment-adjust="30%" After + + + Before alignment-adjust="-30%" After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_alignment-baseline_1.xml b/test/layoutengine/standard-testcases/inline_alignment-baseline_1.xml index 03f9da676..6f0377adc 100644 --- a/test/layoutengine/standard-testcases/inline_alignment-baseline_1.xml +++ b/test/layoutengine/standard-testcases/inline_alignment-baseline_1.xml @@ -1,92 +1,92 @@ - - - - - -

    - This test checks inline level alignment-baseline. -

    -
    - - - - - - - - - - - Before alignment-baseline not specified After - - - Before alignment-baseline="auto" After - - - Before alignment-baseline="baseline" After - - - Before alignment-baseline="before-edge" After - - - Before alignment-baseline="text-before-edge" After - - - Before alignment-baseline="central" After - - - Before alignment-baseline="middle" After - - - Before alignment-baseline="after-edge" After - - - Before alignment-baseline="text-after-edge" After - - - Before alignment-baseline="ideographic" After - - - Before alignment-baseline="alphabetic" After - - - Before alignment-baseline="hanging" After - - - Before alignment-baseline="mathematical" After - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level alignment-baseline. +

    +
    + + + + + + + + + + + Before alignment-baseline not specified After + + + Before alignment-baseline="auto" After + + + Before alignment-baseline="baseline" After + + + Before alignment-baseline="before-edge" After + + + Before alignment-baseline="text-before-edge" After + + + Before alignment-baseline="central" After + + + Before alignment-baseline="middle" After + + + Before alignment-baseline="after-edge" After + + + Before alignment-baseline="text-after-edge" After + + + Before alignment-baseline="ideographic" After + + + Before alignment-baseline="alphabetic" After + + + Before alignment-baseline="hanging" After + + + Before alignment-baseline="mathematical" After + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_alignment-baseline_2.xml b/test/layoutengine/standard-testcases/inline_alignment-baseline_2.xml index d1274be73..1c77feb4c 100644 --- a/test/layoutengine/standard-testcases/inline_alignment-baseline_2.xml +++ b/test/layoutengine/standard-testcases/inline_alignment-baseline_2.xml @@ -1,117 +1,117 @@ - - - - - -

    - This test checks inline level alignment-baseline. -

    -
    - - - - - - - - - - - Before alignment-baseline not specified After - - - Before alignment-baseline="auto" After - - - Before alignment-baseline="baseline" After - - - Before alignment-baseline="before-edge" After - - - Before alignment-baseline="text-before-edge" After - - - Before alignment-baseline="central" After - - - Before alignment-baseline="middle" After - - - Before alignment-baseline="after-edge" After - - - Before alignment-baseline="text-after-edge" After - - - Before alignment-baseline="ideographic" After - - - Before alignment-baseline="alphabetic" After - - - Before alignment-baseline="hanging" After - - - Before alignment-baseline="mathematical" After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level alignment-baseline. +

    +
    + + + + + + + + + + + Before alignment-baseline not specified After + + + Before alignment-baseline="auto" After + + + Before alignment-baseline="baseline" After + + + Before alignment-baseline="before-edge" After + + + Before alignment-baseline="text-before-edge" After + + + Before alignment-baseline="central" After + + + Before alignment-baseline="middle" After + + + Before alignment-baseline="after-edge" After + + + Before alignment-baseline="text-after-edge" After + + + Before alignment-baseline="ideographic" After + + + Before alignment-baseline="alphabetic" After + + + Before alignment-baseline="hanging" After + + + Before alignment-baseline="mathematical" After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_alignment-baseline_3.xml b/test/layoutengine/standard-testcases/inline_alignment-baseline_3.xml index 10948938b..51ba74b68 100644 --- a/test/layoutengine/standard-testcases/inline_alignment-baseline_3.xml +++ b/test/layoutengine/standard-testcases/inline_alignment-baseline_3.xml @@ -1,92 +1,92 @@ - - - - - -

    - This test checks inline level alignment-baseline. -

    -
    - - - - - - - - - - - Before alignment-baseline not specified After - - - Before alignment-baseline="auto" After - - - Before alignment-baseline="baseline" After - - - Before alignment-baseline="before-edge" After - - - Before alignment-baseline="text-before-edge" After - - - Before alignment-baseline="central" After - - - Before alignment-baseline="middle" After - - - Before alignment-baseline="after-edge" After - - - Before alignment-baseline="text-after-edge" After - - - Before alignment-baseline="ideographic" After - - - Before alignment-baseline="alphabetic" After - - - Before alignment-baseline="hanging" After - - - Before alignment-baseline="mathematical" After - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level alignment-baseline. +

    +
    + + + + + + + + + + + Before alignment-baseline not specified After + + + Before alignment-baseline="auto" After + + + Before alignment-baseline="baseline" After + + + Before alignment-baseline="before-edge" After + + + Before alignment-baseline="text-before-edge" After + + + Before alignment-baseline="central" After + + + Before alignment-baseline="middle" After + + + Before alignment-baseline="after-edge" After + + + Before alignment-baseline="text-after-edge" After + + + Before alignment-baseline="ideographic" After + + + Before alignment-baseline="alphabetic" After + + + Before alignment-baseline="hanging" After + + + Before alignment-baseline="mathematical" After + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_alignment-baseline_4.xml b/test/layoutengine/standard-testcases/inline_alignment-baseline_4.xml index 6400c4da5..adf427196 100644 --- a/test/layoutengine/standard-testcases/inline_alignment-baseline_4.xml +++ b/test/layoutengine/standard-testcases/inline_alignment-baseline_4.xml @@ -1,232 +1,232 @@ - - - - - -

    - This test checks inline level alignment-baseline for nested inlines. -

    -
    - - - - - - - - - - Big - alphabetic - alphabetic - - Big Baseline table unchanged - - Big - alphabetic - alphabetic - - Big Baseline table changed - - Big - hanging - middle - - Big Baseline table unchanged - - Big - hanging - middle - - Big Baseline table changed - - Big - text-before-edge - after-edge - - Big Baseline table unchanged - - Big - text-before-edge - after-edge - - Big Baseline table changed - - Big - central - text-before-edge - alphabetic - - - Big Baseline table unchanged - - Big - central - text-before-edge - alphabetic - - - Big Baseline table changed - - Big - central - text-before-edge - alphabetic - - - Big Baseline table changed twice - - Big - before-edge - after-edge - - Big This is over constraint - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level alignment-baseline for nested inlines. +

    +
    + + + + + + + + + + Big + alphabetic + alphabetic + + Big Baseline table unchanged + + Big + alphabetic + alphabetic + + Big Baseline table changed + + Big + hanging + middle + + Big Baseline table unchanged + + Big + hanging + middle + + Big Baseline table changed + + Big + text-before-edge + after-edge + + Big Baseline table unchanged + + Big + text-before-edge + after-edge + + Big Baseline table changed + + Big + central + text-before-edge + alphabetic + + + Big Baseline table unchanged + + Big + central + text-before-edge + alphabetic + + + Big Baseline table changed + + Big + central + text-before-edge + alphabetic + + + Big Baseline table changed twice + + Big + before-edge + after-edge + + Big This is over constraint + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_background-color.xml b/test/layoutengine/standard-testcases/inline_background-color.xml index 7b488ee4c..eda86cf8f 100644 --- a/test/layoutengine/standard-testcases/inline_background-color.xml +++ b/test/layoutengine/standard-testcases/inline_background-color.xml @@ -1,133 +1,133 @@ - - - - - -

    - This test checks fo:inline with background-color properties. -

    -
    - - - - - - - - - - - To emphasize a phrase highlight it. - - - To emphasize a phrase highlight it with text-align="end". - - - To emphasize a phrase highlight it with text-align="justify". - - - To emphasize a phrase highlight it with text-align="center". - - - This demonstrates a long inline - which stretches over multiple lines to - show how the highlight extends from line to line while - correctly honouring the text-align (not specified) property - back to normal - - - This demonstrates a long inline - which stretches over multiple lines to - show how the highlight extends from line to line while - correctly honouring the text-align="end" property - back to normal - - - This demonstrates a long inline - which stretches over multiple lines to - show how the highlight extends from line to line while - correctly honouring the text-align="justify" property - back to normal - - - This demonstrates a long inline - which stretches over multiple lines to - show how the highlight extends from line to line while - correctly honouring the text-align="center" property - back to normal - - - Nested inline highlights - this is 10pt text - nested within is 14pt text - followed by 10pt text - back to normal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:inline with background-color properties. +

    +
    + + + + + + + + + + + To emphasize a phrase highlight it. + + + To emphasize a phrase highlight it with text-align="end". + + + To emphasize a phrase highlight it with text-align="justify". + + + To emphasize a phrase highlight it with text-align="center". + + + This demonstrates a long inline + which stretches over multiple lines to + show how the highlight extends from line to line while + correctly honouring the text-align (not specified) property + back to normal + + + This demonstrates a long inline + which stretches over multiple lines to + show how the highlight extends from line to line while + correctly honouring the text-align="end" property + back to normal + + + This demonstrates a long inline + which stretches over multiple lines to + show how the highlight extends from line to line while + correctly honouring the text-align="justify" property + back to normal + + + This demonstrates a long inline + which stretches over multiple lines to + show how the highlight extends from line to line while + correctly honouring the text-align="center" property + back to normal + + + Nested inline highlights + this is 10pt text + nested within is 14pt text + followed by 10pt text + back to normal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_background-image.xml b/test/layoutengine/standard-testcases/inline_background-image.xml index 5e60e20cf..165b28c14 100644 --- a/test/layoutengine/standard-testcases/inline_background-image.xml +++ b/test/layoutengine/standard-testcases/inline_background-image.xml @@ -1,49 +1,49 @@ - - - - - -

    - This test checks background image on a fo:inline. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - Why is FOP so cool? - - - - - - - - - - -
    + + + + + +

    + This test checks background image on a fo:inline. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + Why is FOP so cool? + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_baseline-shift_1.xml b/test/layoutengine/standard-testcases/inline_baseline-shift_1.xml index 66b4b7bdf..eb064b9b8 100644 --- a/test/layoutengine/standard-testcases/inline_baseline-shift_1.xml +++ b/test/layoutengine/standard-testcases/inline_baseline-shift_1.xml @@ -1,165 +1,165 @@ - - - - - -

    - This test checks inline level baseline-shift. -

    -
    - - - - - - - - - - - Before - baseline-shift="baseline" - After - - - Before - baseline-shift="sub" - After - - - Before - baseline-shift="super" - After - - - Before - baseline-shift="0pt" - After - - - Before - baseline-shift="0%" - After - - - Before - baseline-shift="3pt" - After - - - Before - baseline-shift="-3pt" - After - - - Before - baseline-shift="30%" - After - - - Before - baseline-shift="-30%" - After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level baseline-shift. +

    +
    + + + + + + + + + + + Before + baseline-shift="baseline" + After + + + Before + baseline-shift="sub" + After + + + Before + baseline-shift="super" + After + + + Before + baseline-shift="0pt" + After + + + Before + baseline-shift="0%" + After + + + Before + baseline-shift="3pt" + After + + + Before + baseline-shift="-3pt" + After + + + Before + baseline-shift="30%" + After + + + Before + baseline-shift="-30%" + After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_baseline-shift_2.xml b/test/layoutengine/standard-testcases/inline_baseline-shift_2.xml index 0af4f3683..77b1812eb 100644 --- a/test/layoutengine/standard-testcases/inline_baseline-shift_2.xml +++ b/test/layoutengine/standard-testcases/inline_baseline-shift_2.xml @@ -1,173 +1,173 @@ - - - - - -

    - This test checks inline level baseline-shift. -

    -
    - - - - - - - - - - - Before - sub - sub - sub - - After - - - Before - sub - super - sub - - After - - - Before - super - super - super - - After - - - Before - super - sub - super - - After - - - Before - 30% - -50% - 30% - - After - - - Before - super - sub - super - sub - super - - After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - + + + + + +

    + This test checks inline level baseline-shift. +

    +
    + + + + + + + + + + + Before + sub + sub + sub + + After + + + Before + sub + super + sub + + After + + + Before + super + super + super + + After + + + Before + super + sub + super + + After + + + Before + 30% + -50% + 30% + + After + + + Before + super + sub + super + sub + super + + After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + diff --git a/test/layoutengine/standard-testcases/inline_baseline-shift_3.xml b/test/layoutengine/standard-testcases/inline_baseline-shift_3.xml index 46649aac8..f79efbb57 100644 --- a/test/layoutengine/standard-testcases/inline_baseline-shift_3.xml +++ b/test/layoutengine/standard-testcases/inline_baseline-shift_3.xml @@ -1,211 +1,211 @@ - - - - - -

    - This test checks inline level baseline-shift. -

    -
    - - - - - - - - - - - Before - middle - sub - middle - - After Baseline table changed - - - Before - middle - super - middle - - After Baseline table changed - - - Before - text-after-edge - 30% - text-after-edge - - After Baseline table changed - - - Before - text-before-edge - -50% - text-before-edge - - After Baseline table changed - - - Before - middle - sub - middle - - After Baseline table unchanged - - - Before - middle - super - middle - - After Baseline table unchanged - - - Before - text-after-edge - 30% - text-after-edge - - After Baseline table unchanged - - - Before - text-before-edge - -50% - text-before-edge - - After Baseline table unchanged - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level baseline-shift. +

    +
    + + + + + + + + + + + Before + middle + sub + middle + + After Baseline table changed + + + Before + middle + super + middle + + After Baseline table changed + + + Before + text-after-edge + 30% + text-after-edge + + After Baseline table changed + + + Before + text-before-edge + -50% + text-before-edge + + After Baseline table changed + + + Before + middle + sub + middle + + After Baseline table unchanged + + + Before + middle + super + middle + + After Baseline table unchanged + + + Before + text-after-edge + 30% + text-after-edge + + After Baseline table unchanged + + + Before + text-before-edge + -50% + text-before-edge + + After Baseline table unchanged + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_baseline-shift_4.xml b/test/layoutengine/standard-testcases/inline_baseline-shift_4.xml index 81566bac0..6be9d6f81 100644 --- a/test/layoutengine/standard-testcases/inline_baseline-shift_4.xml +++ b/test/layoutengine/standard-testcases/inline_baseline-shift_4.xml @@ -1,185 +1,185 @@ - - - - - -

    - This test checks inline level baseline-shift. -

    -
    - - - - - - - - - - - Before - 6pt central - - central - - After - - - Before - -6pt central - - central - - After - - - Before - sub - text-before-edge - Baseline unchanged - central - - After - - - Before - super - text-after-edge - Baseline unchanged - central - - After - - - Before - sub - text-before-edge - Baseline changed - central - - After - - - Before - super - text-after-edge - Baseline changed - central - - After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level baseline-shift. +

    +
    + + + + + + + + + + + Before + 6pt central + + central + + After + + + Before + -6pt central + + central + + After + + + Before + sub + text-before-edge + Baseline unchanged + central + + After + + + Before + super + text-after-edge + Baseline unchanged + central + + After + + + Before + sub + text-before-edge + Baseline changed + central + + After + + + Before + super + text-after-edge + Baseline changed + central + + After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_block_nested_bug36248.xml b/test/layoutengine/standard-testcases/inline_block_nested_bug36248.xml index d9e19b0c8..d6ae38578 100644 --- a/test/layoutengine/standard-testcases/inline_block_nested_bug36248.xml +++ b/test/layoutengine/standard-testcases/inline_block_nested_bug36248.xml @@ -1,60 +1,60 @@ - - - - - -

    - This test checks fo:inline and nested nodes. Regression test for Bugzilla #36248. -

    -
    - - - - - - - - - - normalnormal - normalnormal - normalnormal - normalnormal - normal - - - - - - - -normal - normalnormal - normalwrappednormal - normalTODO: bidi-override is missing herenormal - normalnested inlinenormal - normalblabla? yawn.normal - - - - - - - - -
    + + + + + +

    + This test checks fo:inline and nested nodes. Regression test for Bugzilla #36248. +

    +
    + + + + + + + + + + normalnormal + normalnormal + normalnormal + normalnormal + normal + + + + + + + +normal + normalnormal + normalwrappednormal + normalTODO: bidi-override is missing herenormal + normalnested inlinenormal + normalblabla? yawn.normal + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_border_padding.xml b/test/layoutengine/standard-testcases/inline_border_padding.xml index a0197c319..9748b26dd 100644 --- a/test/layoutengine/standard-testcases/inline_border_padding.xml +++ b/test/layoutengine/standard-testcases/inline_border_padding.xml @@ -1,141 +1,141 @@ - - - - - -

    - This test checks inlines with border and padding properties. -

    -
    - - - - - - - - - - - To emphasize a word we give it a 1pt border and a background. - - - Demonstrates a big border inline with border="solid 5pt red" padding="5pt" extending over the small allocation rectangle to the top and bottom. - - - Demonstrates unsymmetric borders and padding but the baselines should align. - - - Big border with a smaller font but the baselines should align. - - - This demonstrates correct line breaking of a fo:inline because it does fit nicely.. - This demonstrates correct line breaking of a fo:inline because it does fit nicely.. - Not really as we started a fo:inline with border/padding just before the word "nicely" which forces it to the next line. - - - Demonstrates nested - inlines - finishing together - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inlines with border and padding properties. +

    +
    + + + + + + + + + + + To emphasize a word we give it a 1pt border and a background. + + + Demonstrates a big border inline with border="solid 5pt red" padding="5pt" extending over the small allocation rectangle to the top and bottom. + + + Demonstrates unsymmetric borders and padding but the baselines should align. + + + Big border with a smaller font but the baselines should align. + + + This demonstrates correct line breaking of a fo:inline because it does fit nicely.. + This demonstrates correct line breaking of a fo:inline because it does fit nicely.. + Not really as we started a fo:inline with border/padding just before the word "nicely" which forces it to the next line. + + + Demonstrates nested + inlines + finishing together + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_border_padding_block_nested_1.xml b/test/layoutengine/standard-testcases/inline_border_padding_block_nested_1.xml index 95083a9e0..3d48ee79a 100644 --- a/test/layoutengine/standard-testcases/inline_border_padding_block_nested_1.xml +++ b/test/layoutengine/standard-testcases/inline_border_padding_block_nested_1.xml @@ -1,134 +1,134 @@ - - - - - -

    - This test checks fo:inlines with border and padding properties and nested inner blocks. -

    -
    - - - - - - - - - - - Before inline - starting with a block - after block - After inline - - - Before inline - before block - having a block at the end of an inline - After inline - - - Before inline - before block - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - after block - After inline - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:inlines with border and padding properties and nested inner blocks. +

    +
    + + + + + + + + + + + Before inline + starting with a block + after block + After inline + + + Before inline + before block + having a block at the end of an inline + After inline + + + Before inline + before block + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + after block + After inline + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_border_padding_block_nested_2.xml b/test/layoutengine/standard-testcases/inline_border_padding_block_nested_2.xml index f606da4b4..a22f23fda 100644 --- a/test/layoutengine/standard-testcases/inline_border_padding_block_nested_2.xml +++ b/test/layoutengine/standard-testcases/inline_border_padding_block_nested_2.xml @@ -1,180 +1,180 @@ - - - - - -

    - This test checks fo:inlines with border and padding properties and nested inner blocks. -

    -
    - - - - - - - - - - - Before inline - starting with a block - after block - After inline with conditionality="retain" - - - Before inline - before block - having a block at the end of an inline - After inline with conditionality="retain" - - - Before inline - before block - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - after block - After inline with conditionality="retain" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:inlines with border and padding properties and nested inner blocks. +

    +
    + + + + + + + + + + + Before inline + starting with a block + after block + After inline with conditionality="retain" + + + Before inline + before block + having a block at the end of an inline + After inline with conditionality="retain" + + + Before inline + before block + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + after block + After inline with conditionality="retain" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_border_padding_conditionality_1.xml b/test/layoutengine/standard-testcases/inline_border_padding_conditionality_1.xml index aa5e3d44b..2f10ed281 100644 --- a/test/layoutengine/standard-testcases/inline_border_padding_conditionality_1.xml +++ b/test/layoutengine/standard-testcases/inline_border_padding_conditionality_1.xml @@ -1,399 +1,399 @@ - - - - - -

    - This test checks fo:inlines with border and padding properties and conditionality. -

    -
    - - - - - - - - - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align not set .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="end" .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="justify" .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="center" .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align not set .conditionality="discard". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="end" .conditionality="discard". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="justify" .conditionality="discard". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="center" .conditionality="discard". - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:inlines with border and padding properties and conditionality. +

    +
    + + + + + + + + + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align not set .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="end" .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="justify" .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="center" .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align not set .conditionality="discard". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="end" .conditionality="discard". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="justify" .conditionality="discard". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="center" .conditionality="discard". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml b/test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml index d6e594ec1..122713e3d 100644 --- a/test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml +++ b/test/layoutengine/standard-testcases/inline_border_padding_conditionality_2.xml @@ -1,312 +1,312 @@ - - - - - -

    - This test checks fo:inlines with border and padding properties and conditionality retain. -

    -
    - - - - - - - - - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align not set padding .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="end" padding .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="justify" padding .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - text-align="center" padding .conditionality="retain". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, - they are not certain, and as far as they are certain, - they do not refer to reality - Albert Einstein - text-align="center" .conditionality="retain" linefeed-treatment="preserve". - - - Multi-line fo:inline - As far as the laws of mathematics refer to reality, - they are not certain, and as far as they are certain, - they do not refer to reality - Albert Einstein - text-align="center" .conditionality="discard" linefeed-treatment="preserve". - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:inlines with border and padding properties and conditionality retain. +

    +
    + + + + + + + + + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align not set padding .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="end" padding .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="justify" padding .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + text-align="center" padding .conditionality="retain". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, + they are not certain, and as far as they are certain, + they do not refer to reality - Albert Einstein + text-align="center" .conditionality="retain" linefeed-treatment="preserve". + + + Multi-line fo:inline + As far as the laws of mathematics refer to reality, + they are not certain, and as far as they are certain, + they do not refer to reality - Albert Einstein + text-align="center" .conditionality="discard" linefeed-treatment="preserve". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_dominant-baseline_1.xml b/test/layoutengine/standard-testcases/inline_dominant-baseline_1.xml index 8a170e5a7..00f475ff7 100644 --- a/test/layoutengine/standard-testcases/inline_dominant-baseline_1.xml +++ b/test/layoutengine/standard-testcases/inline_dominant-baseline_1.xml @@ -1,129 +1,129 @@ - - - - - -

    - This test checks inline level dominant-baseline. -

    -
    - - - - - - - - - - - Before dominant-baseline="auto" After - - - Before dominant-baseline="no-change" After - - - Before dominant-baseline="ideographic" After - - - Before dominant-baseline="alphabetic" After - - - Before dominant-baseline="hanging" After - - - Before dominant-baseline="mathematical" After - - - Before dominant-baseline="central" After - - - Before dominant-baseline="middle" After - - - Before dominant-baseline="text-after-edge" After - - - Before dominant-baseline="text-before-edge" After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level dominant-baseline. +

    +
    + + + + + + + + + + + Before dominant-baseline="auto" After + + + Before dominant-baseline="no-change" After + + + Before dominant-baseline="ideographic" After + + + Before dominant-baseline="alphabetic" After + + + Before dominant-baseline="hanging" After + + + Before dominant-baseline="mathematical" After + + + Before dominant-baseline="central" After + + + Before dominant-baseline="middle" After + + + Before dominant-baseline="text-after-edge" After + + + Before dominant-baseline="text-before-edge" After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_dominant-baseline_2.xml b/test/layoutengine/standard-testcases/inline_dominant-baseline_2.xml index 20b6c2363..15266cfde 100644 --- a/test/layoutengine/standard-testcases/inline_dominant-baseline_2.xml +++ b/test/layoutengine/standard-testcases/inline_dominant-baseline_2.xml @@ -1,129 +1,129 @@ - - - - - -

    - This test checks inline level dominant-baseline. -

    -
    - - - - - - - - - - - Before dominant-baseline="auto" After - - - Before dominant-baseline="no-change" After - - - Before dominant-baseline="ideographic" After - - - Before dominant-baseline="alphabetic" After - - - Before dominant-baseline="hanging" After - - - Before dominant-baseline="mathematical" After - - - Before dominant-baseline="central" After - - - Before dominant-baseline="middle" After - - - Before dominant-baseline="text-after-edge" After - - - Before dominant-baseline="text-before-edge" After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level dominant-baseline. +

    +
    + + + + + + + + + + + Before dominant-baseline="auto" After + + + Before dominant-baseline="no-change" After + + + Before dominant-baseline="ideographic" After + + + Before dominant-baseline="alphabetic" After + + + Before dominant-baseline="hanging" After + + + Before dominant-baseline="mathematical" After + + + Before dominant-baseline="central" After + + + Before dominant-baseline="middle" After + + + Before dominant-baseline="text-after-edge" After + + + Before dominant-baseline="text-before-edge" After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_dominant-baseline_3.xml b/test/layoutengine/standard-testcases/inline_dominant-baseline_3.xml index 836cf48e3..6bab34f97 100644 --- a/test/layoutengine/standard-testcases/inline_dominant-baseline_3.xml +++ b/test/layoutengine/standard-testcases/inline_dominant-baseline_3.xml @@ -1,116 +1,116 @@ - - - - - -

    - This test checks inline level dominant-baseline. -

    -
    - - - - - - - - - - - Before - central - Baseline changed - - After - - - Before - text-before-edge - Baseline changed - - After - - - Before - text-after-edge - Baseline changed - - After - - - Before - middle - hanging - Baseline changed - - - - After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level dominant-baseline. +

    +
    + + + + + + + + + + + Before + central + Baseline changed + + After + + + Before + text-before-edge + Baseline changed + + After + + + Before + text-after-edge + Baseline changed + + After + + + Before + middle + hanging + Baseline changed + + + + After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_keep-together.xml b/test/layoutengine/standard-testcases/inline_keep-together.xml index af9317815..6ec4ce603 100644 --- a/test/layoutengine/standard-testcases/inline_keep-together.xml +++ b/test/layoutengine/standard-testcases/inline_keep-together.xml @@ -1,59 +1,59 @@ - - - - - -

    - This test checks keep-together.within-line. -

    -

    - This test builds on the results from page-breaking_6.xml. -

    -
    - - - - - - - - - - - This is Blah blah blah blah! - This is Blah blah blah blah! - This is Blah blah blah blah! - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks keep-together.within-line. +

    +

    + This test builds on the results from page-breaking_6.xml. +

    +
    + + + + + + + + + + + This is Blah blah blah blah! + This is Blah blah blah blah! + This is Blah blah blah blah! + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_vertical-align_1.xml b/test/layoutengine/standard-testcases/inline_vertical-align_1.xml index c3ec1ac76..59842acfb 100644 --- a/test/layoutengine/standard-testcases/inline_vertical-align_1.xml +++ b/test/layoutengine/standard-testcases/inline_vertical-align_1.xml @@ -1,189 +1,189 @@ - - - - - -

    - This test checks inline level vertical align. -

    -
    - - - - - - - - - - - Before vertical-align not specified After - - - Before vertical-align="baseline" After - - - Before vertical-align="top" After - - - Before vertical-align="text-top" After - - - Before vertical-align="middle" After - - - Before vertical-align="text-bottom" After - - - Before vertical-align="bottom" After - - - Before vertical-align="super" After - - - Before vertical-align="sub" After - - - Before vertical-align="3pt" After - - - Before vertical-align="-3pt" After - - - Before vertical-align="50%" After - - - Before vertical-align="-50%" After - - - Before vertical-align="super" After - - - Before vertical-align="sub" After - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level vertical align. +

    +
    + + + + + + + + + + + Before vertical-align not specified After + + + Before vertical-align="baseline" After + + + Before vertical-align="top" After + + + Before vertical-align="text-top" After + + + Before vertical-align="middle" After + + + Before vertical-align="text-bottom" After + + + Before vertical-align="bottom" After + + + Before vertical-align="super" After + + + Before vertical-align="sub" After + + + Before vertical-align="3pt" After + + + Before vertical-align="-3pt" After + + + Before vertical-align="50%" After + + + Before vertical-align="-50%" After + + + Before vertical-align="super" After + + + Before vertical-align="sub" After + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_vertical-align_2.xml b/test/layoutengine/standard-testcases/inline_vertical-align_2.xml index 7019ba603..e013f5e92 100644 --- a/test/layoutengine/standard-testcases/inline_vertical-align_2.xml +++ b/test/layoutengine/standard-testcases/inline_vertical-align_2.xml @@ -1,122 +1,122 @@ - - - - - -

    - This test checks inline level vertical align. - This example is taken from the spec section 7.13. -

    -
    - - - - - - - - - - - This is a longer line that provides a context for the line with images aligned on it. - Before edge , - after edge , - middle , - none . - And this is a line of text that follows the line with the objects aligned on it. - - - This is a longer line that provides a context for the line with images aligned on it. - Before edge , - after edge , - middle . - And this is a line of text that follows the line with the objects aligned on it. - - - This is a longer line that provides a context for the line with images aligned on it. - Before edge , - after edge . - And this is a line of text that follows the line with the objects aligned on it. - - - This is a longer line that provides a context for the line with images aligned on it. - Before edge , - after edge . - And this is a line of text that follows the line with the objects aligned on it. - - - This is a longer line that provides a context for the line with images aligned on it. - Before edge , - after edge , - middle . - And this is a line of text that follows the line with the objects aligned on it. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks inline level vertical align. + This example is taken from the spec section 7.13. +

    +
    + + + + + + + + + + + This is a longer line that provides a context for the line with images aligned on it. + Before edge , + after edge , + middle , + none . + And this is a line of text that follows the line with the objects aligned on it. + + + This is a longer line that provides a context for the line with images aligned on it. + Before edge , + after edge , + middle . + And this is a line of text that follows the line with the objects aligned on it. + + + This is a longer line that provides a context for the line with images aligned on it. + Before edge , + after edge . + And this is a line of text that follows the line with the objects aligned on it. + + + This is a longer line that provides a context for the line with images aligned on it. + Before edge , + after edge . + And this is a line of text that follows the line with the objects aligned on it. + + + This is a longer line that provides a context for the line with images aligned on it. + Before edge , + after edge , + middle . + And this is a line of text that follows the line with the objects aligned on it. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader-alignment.xml b/test/layoutengine/standard-testcases/leader-alignment.xml index 3f36afc30..abc354150 100644 --- a/test/layoutengine/standard-testcases/leader-alignment.xml +++ b/test/layoutengine/standard-testcases/leader-alignment.xml @@ -1,68 +1,68 @@ - - - - - -

    - This test checks leaders -

    -
    - - - - - - - - - - - margin="0pt" padding-left="10mm" - - - padding-left="10mm" - - - - leader-alignment="page" - - - - leader-alignment="page" - - - - leader-alignment="reference-area" - - leader-alignment="reference-area" Leader-pattern is aligned as if it began on the current reference-area's content-rectangle start-edge. - - - - - - - -
    + + + + + +

    + This test checks leaders +

    +
    + + + + + + + + + + + margin="0pt" padding-left="10mm" + + + padding-left="10mm" + + + + leader-alignment="page" + + + + leader-alignment="page" + + + + leader-alignment="reference-area" + + leader-alignment="reference-area" Leader-pattern is aligned as if it began on the current reference-area's content-rectangle start-edge. + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_alignment-baseline.xml b/test/layoutengine/standard-testcases/leader_alignment-baseline.xml index 352da3efc..8173667fe 100644 --- a/test/layoutengine/standard-testcases/leader_alignment-baseline.xml +++ b/test/layoutengine/standard-testcases/leader_alignment-baseline.xml @@ -1,171 +1,171 @@ - - - - - -

    - This test checks fo:leader with different alignment-baseline values. -

    -
    - - - - - - - - - - - - dots baseline - - - - rule solid baseline - - - - rule double baseline - - - - - - - dots before-edge - - - - rule solid before-edge - - - - rule double before-edge - - - - - - - dots middle - - - - rule solid middle - - - - rule double middle - - - - - - - dots after-edge - - - - rule solid after-edge - - - - rule double after-edge - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:leader with different alignment-baseline values. +

    +
    + + + + + + + + + + + + dots baseline + + + + rule solid baseline + + + + rule double baseline + + + + + + + dots before-edge + + + + rule solid before-edge + + + + rule double before-edge + + + + + + + dots middle + + + + rule solid middle + + + + rule double middle + + + + + + + dots after-edge + + + + rule solid after-edge + + + + rule double after-edge + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_background-color.xml b/test/layoutengine/standard-testcases/leader_background-color.xml index 25b046045..78262ca3c 100644 --- a/test/layoutengine/standard-testcases/leader_background-color.xml +++ b/test/layoutengine/standard-testcases/leader_background-color.xml @@ -1,82 +1,82 @@ - - - - - -

    - This test checks fo:leader with background-color -

    -
    - - - - - - - - - - - - dots yellow background - - - - rule solid yellow background - - - - rule double yellow background - - - - space yellow background - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:leader with background-color +

    +
    + + + + + + + + + + + + dots yellow background + + + + rule solid yellow background + + + + rule double yellow background + + + + space yellow background + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_border_padding.xml b/test/layoutengine/standard-testcases/leader_border_padding.xml index b028d5014..e2bd0c231 100644 --- a/test/layoutengine/standard-testcases/leader_border_padding.xml +++ b/test/layoutengine/standard-testcases/leader_border_padding.xml @@ -1,289 +1,289 @@ - - - - - -

    - This test checks fo:leader with border and padding -

    -
    - - - - - - - - - - - - dots solid 1pt red border - - - - rule solid solid 1pt red border - - - - rule double solid 1pt red border - - - - space solid 1pt red border - - - x - use-content x solid 1pt red border - - - - dots solid 5pt red border 5pt padding - - - - rule solid solid 5pt red border 5pt padding - - - - rule double solid 5pt red border 5pt padding - - - - space solid 5pt red border 5pt padding - - - x - use-content x solid 5pt red border 5pt padding - - - - dots uneven border and padding - - - - rule solid uneven border and padding - - - - rule double uneven border and padding - - - - space uneven border and padding - - - x - use-content x uneven border and padding - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:leader with border and padding +

    +
    + + + + + + + + + + + + dots solid 1pt red border + + + + rule solid solid 1pt red border + + + + rule double solid 1pt red border + + + + space solid 1pt red border + + + x + use-content x solid 1pt red border + + + + dots solid 5pt red border 5pt padding + + + + rule solid solid 5pt red border 5pt padding + + + + rule double solid 5pt red border 5pt padding + + + + space solid 5pt red border 5pt padding + + + x + use-content x solid 5pt red border 5pt padding + + + + dots uneven border and padding + + + + rule solid uneven border and padding + + + + rule double uneven border and padding + + + + space uneven border and padding + + + x + use-content x uneven border and padding + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_dots.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_dots.xml index 1a0cc8d96..4410f7e33 100644 --- a/test/layoutengine/standard-testcases/leader_leader-pattern_dots.xml +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_dots.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - +

    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_rule.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_rule.xml index 4dce8be6c..438f8f980 100644 --- a/test/layoutengine/standard-testcases/leader_leader-pattern_rule.xml +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_rule.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - +

    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_space.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_space.xml index 8948ccb65..2e7387f08 100644 --- a/test/layoutengine/standard-testcases/leader_leader-pattern_space.xml +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_space.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - +

    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_use-content.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_use-content.xml index a3bf802dd..c98bd4511 100644 --- a/test/layoutengine/standard-testcases/leader_leader-pattern_use-content.xml +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_use-content.xml @@ -1,176 +1,176 @@ - - - - - -

    - This test checks leaders with leader-pattern="use-content" -

    -
    - - - - - - - - - - - x - Content is "x" - - - => - Content is "=>" with background - - - ~ - Content is "~" with leader-pattern-width="12pt" - - - * - Content is "*" with leader-pattern-width="12pt" and border - - - ++ - Content is "++" with l-p-w="12pt" and border small font - - - - - - - - - Content is svg 10 x 10 - - - - - - - - - Content is svg 20 x 10 which is wider than the leader-length - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks leaders with leader-pattern="use-content" +

    +
    + + + + + + + + + + + x + Content is "x" + + + => + Content is "=>" with background + + + ~ + Content is "~" with leader-pattern-width="12pt" + + + * + Content is "*" with leader-pattern-width="12pt" and border + + + ++ + Content is "++" with l-p-w="12pt" and border small font + + + + + + + + + Content is svg 10 x 10 + + + + + + + + + Content is svg 20 x 10 which is wider than the leader-length + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_use-content_bug.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_use-content_bug.xml index c79ee28c7..26d20aa9c 100644 --- a/test/layoutengine/standard-testcases/leader_leader-pattern_use-content_bug.xml +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_use-content_bug.xml @@ -1,58 +1,58 @@ - - - - - -

    - This test demonstrates a bug with fo:leader use-content -

    -
    - - - - - - - - - - - x - use-content x font-size="24pt" - - - x - use-content x solid 5pt red border 5pt padding - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test demonstrates a bug with fo:leader use-content +

    +
    + + + + + + + + + + + x + use-content x font-size="24pt" + + + x + use-content x solid 5pt red border 5pt padding + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_text-align.xml b/test/layoutengine/standard-testcases/leader_text-align.xml index 2316bf15b..7dbe067fc 100644 --- a/test/layoutengine/standard-testcases/leader_text-align.xml +++ b/test/layoutengine/standard-testcases/leader_text-align.xml @@ -1,159 +1,159 @@ - - - - - -

    - This test checks fo:leader with different text-align -

    -
    - - - - - - - - - - - - dots - - - - rule double - - - - space - - - x - use-content x - - - - dots text-align-last="justify" - - - - rule double text-align-last="justify" - - - - space text-align-last="justify" - - - x - use-content x text-align-last="justify" - - - - dots text-align-last="end" - - - - rule double text-align-last="end" - - - - space text-align-last="end" - - - x - use-content x text-align-last="end" - - - - dots text-align-last="center" - - - - rule double text-align-last="center" - - - - space text-align-last="center" - - - x - use-content x text-align-last="center" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:leader with different text-align +

    +
    + + + + + + + + + + + + dots + + + + rule double + + + + space + + + x + use-content x + + + + dots text-align-last="justify" + + + + rule double text-align-last="justify" + + + + space text-align-last="justify" + + + x + use-content x text-align-last="justify" + + + + dots text-align-last="end" + + + + rule double text-align-last="end" + + + + space text-align-last="end" + + + x + use-content x text-align-last="end" + + + + dots text-align-last="center" + + + + rule double text-align-last="center" + + + + space text-align-last="center" + + + x + use-content x text-align-last="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_toc.xml b/test/layoutengine/standard-testcases/leader_toc.xml index b970bfedf..a1197d046 100644 --- a/test/layoutengine/standard-testcases/leader_toc.xml +++ b/test/layoutengine/standard-testcases/leader_toc.xml @@ -1,155 +1,155 @@ - - - - - -

    - This test checks fo:leader in a typical table of content scenario. - This example is taken from the spec section 6.6.1.1.4 -

    -
    - - - - - - - - - - - 1. Chapter - - - - - - - 1.1 Section - - - - - - - 1.2 Section - - - - - - - 2. Chapter - - - - - - - 2.1 Section - - - - - - - 2.2 Section - - - - - - - 1. Chapter - - - Text - - - 1.1 Section - - - Text - - - 1.2 Section - - - Text - - - 2. Chapter - - - Text - - - 2.1 Section - - - Text - - - 2.2 Section - - - Text - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:leader in a typical table of content scenario. + This example is taken from the spec section 6.6.1.1.4 +

    +
    + + + + + + + + + + + 1. Chapter + + + + + + + 1.1 Section + + + + + + + 1.2 Section + + + + + + + 2. Chapter + + + + + + + 2.1 Section + + + + + + + 2.2 Section + + + + + + + 1. Chapter + + + Text + + + 1.1 Section + + + Text + + + 1.2 Section + + + Text + + + 2. Chapter + + + Text + + + 2.1 Section + + + Text + + + 2.2 Section + + + Text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/list-block_background-image.xml b/test/layoutengine/standard-testcases/list-block_background-image.xml index 431ab3edd..0dc92102b 100644 --- a/test/layoutengine/standard-testcases/list-block_background-image.xml +++ b/test/layoutengine/standard-testcases/list-block_background-image.xml @@ -1,84 +1,84 @@ - - - - - -

    - This test checks background image on lists (list-block). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - label 1 - - - - body 1: The whole list should have a centered background. - The whole list should have a centered background. - The whole list should have a centered background. - - - - - - label 2 - - - - body 2: The whole list should have a centered background. - The whole list should have a centered background. - The whole list should have a centered background. - - - - - - label 3 - - - - body 3: The whole list should have a centered background. - The whole list should have a centered background. - The whole list should have a centered background. - - - - - - - - - - - - - -
    + + + + + +

    + This test checks background image on lists (list-block). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + label 1 + + + + body 1: The whole list should have a centered background. + The whole list should have a centered background. + The whole list should have a centered background. + + + + + + label 2 + + + + body 2: The whole list should have a centered background. + The whole list should have a centered background. + The whole list should have a centered background. + + + + + + label 3 + + + + body 3: The whole list should have a centered background. + The whole list should have a centered background. + The whole list should have a centered background. + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/list-block_padding_percentages.xml b/test/layoutengine/standard-testcases/list-block_padding_percentages.xml index 2300eb84e..4e1ff165a 100644 --- a/test/layoutengine/standard-testcases/list-block_padding_percentages.xml +++ b/test/layoutengine/standard-testcases/list-block_padding_percentages.xml @@ -1,76 +1,76 @@ - - - - - -

    - This test checks relative padding on lists (list-block). -

    -
    - - - - - - - - - - - - - label 1 - - - - body 1: The whole list should have a 5% padding shown in yellow. - - - - - - label 2 - - - - body 2: The whole list should have a 5% padding shown in yellow. - - - - - - label 3 - - - - body 3: The whole list should have a 5% padding shown in yellow. - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative padding on lists (list-block). +

    +
    + + + + + + + + + + + + + label 1 + + + + body 1: The whole list should have a 5% padding shown in yellow. + + + + + + label 2 + + + + body 2: The whole list should have a 5% padding shown in yellow. + + + + + + label 3 + + + + body 3: The whole list should have a 5% padding shown in yellow. + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/list-item_background-image.xml b/test/layoutengine/standard-testcases/list-item_background-image.xml index c6d7263a0..e1f4a27b7 100644 --- a/test/layoutengine/standard-testcases/list-item_background-image.xml +++ b/test/layoutengine/standard-testcases/list-item_background-image.xml @@ -1,84 +1,84 @@ - - - - - -

    - This test checks background image on lists (list-item). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - label 1 - - - - body 1: We should have a background centered within this whole list item. - We should have a background centered within this whole list item. - We should have a background centered within this whole list item. - - - - - - label 2 - - - - body 2: We should have no background on this list item. - We should have no background on this list item. - We should have no background on this list item. - - - - - - label 3 - - - - body 3: We should have no background on this list item. - We should have no background on this list item. - We should have no background on this list item. - - - - - - - - - - - - - -
    + + + + + +

    + This test checks background image on lists (list-item). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + label 1 + + + + body 1: We should have a background centered within this whole list item. + We should have a background centered within this whole list item. + We should have a background centered within this whole list item. + + + + + + label 2 + + + + body 2: We should have no background on this list item. + We should have no background on this list item. + We should have no background on this list item. + + + + + + label 3 + + + + body 3: We should have no background on this list item. + We should have no background on this list item. + We should have no background on this list item. + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/list-item_padding_percentages.xml b/test/layoutengine/standard-testcases/list-item_padding_percentages.xml index 713bbdf36..768e25d90 100644 --- a/test/layoutengine/standard-testcases/list-item_padding_percentages.xml +++ b/test/layoutengine/standard-testcases/list-item_padding_percentages.xml @@ -1,79 +1,79 @@ - - - - - -

    - This test checks relative padding widths on lists (list-item). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - label 1 - - - - body 1: We should have 5% padding around this whole yellow list item. - - - - - - label 2 - - - - body 2: We should have no padding around this whole list item. - - - - - - label 3 - - - - body 3: We should have no padding around this whole list item. - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative padding widths on lists (list-item). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + label 1 + + + + body 1: We should have 5% padding around this whole yellow list item. + + + + + + label 2 + + + + body 2: We should have no padding around this whole list item. + + + + + + label 3 + + + + body 3: We should have no padding around this whole list item. + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/marker_bug.xml b/test/layoutengine/standard-testcases/marker_bug.xml index a0c0ab5a4..2c60c7c6e 100644 --- a/test/layoutengine/standard-testcases/marker_bug.xml +++ b/test/layoutengine/standard-testcases/marker_bug.xml @@ -1,69 +1,69 @@ - - - - - -

    - This test checks for a bug with markers where white space is not removed. -

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - First marker with whitespace around - - - - Second marker with no whitespace around - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks for a bug with markers where white space is not removed. +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + First marker with whitespace around + + + + Second marker with no whitespace around + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-breaking_6.xml b/test/layoutengine/standard-testcases/page-breaking_6.xml index 59fe119b7..63549eb1d 100644 --- a/test/layoutengine/standard-testcases/page-breaking_6.xml +++ b/test/layoutengine/standard-testcases/page-breaking_6.xml @@ -1,62 +1,62 @@ - - - - - -

    - This test checks breaking behaviour in environments where there is not much space. -

    -
    - - - - - - - - - - - This is some test text! - Bla bla 1234567890. - Bla bla 12345678901234567890. - This is Blah-blah-blah-blah! - This is BLah-blah-blah-blah! - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks breaking behaviour in environments where there is not much space. +

    +
    + + + + + + + + + + + This is some test text! + Bla bla 1234567890. + Bla bla 12345678901234567890. + This is Blah-blah-blah-blah! + This is BLah-blah-blah-blah! + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-height_indefinite_simple.xml b/test/layoutengine/standard-testcases/page-height_indefinite_simple.xml index 64dedc079..256f86622 100644 --- a/test/layoutengine/standard-testcases/page-height_indefinite_simple.xml +++ b/test/layoutengine/standard-testcases/page-height_indefinite_simple.xml @@ -1,53 +1,53 @@ - - - - - -

    - Simple test for page-height="indefinite". The page-heights should - correspond to the sum of the line-heights of the laid out blocks. -

    -
    - - - - - - - - - - page1 - block1 - page1 - block2 - page1 - block3 - page2 - block1 - page2 - block2 - page2 - block3 - page3 - block3 - page3 - block2 - page3 - block3 - - - - - - - - - -
    + + + + + +

    + Simple test for page-height="indefinite". The page-heights should + correspond to the sum of the line-heights of the laid out blocks. +

    +
    + + + + + + + + + + page1 - block1 + page1 - block2 + page1 - block3 + page2 - block1 + page2 - block2 + page2 - block3 + page3 - block3 + page3 - block2 + page3 - block3 + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number-citation_background-color.xml b/test/layoutengine/standard-testcases/page-number-citation_background-color.xml index 2a6853990..c3f845b79 100644 --- a/test/layoutengine/standard-testcases/page-number-citation_background-color.xml +++ b/test/layoutengine/standard-testcases/page-number-citation_background-color.xml @@ -1,44 +1,44 @@ - - - - - -

    - This test checks fo:page-number-citation with background-color property. -

    -
    - - - - - - - - - - - To emphasize a page number citation highlight it. - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number-citation with background-color property. +

    +
    + + + + + + + + + + + To emphasize a page number citation highlight it. + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number-citation_background-image.xml b/test/layoutengine/standard-testcases/page-number-citation_background-image.xml index 20246526e..503d506d9 100644 --- a/test/layoutengine/standard-testcases/page-number-citation_background-image.xml +++ b/test/layoutengine/standard-testcases/page-number-citation_background-image.xml @@ -1,50 +1,50 @@ - - - - - -

    - This test checks fo:page-number-citation with background-image property. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - Page number citation - Page number citation - - - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number-citation with background-image property. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + Page number citation + Page number citation + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number-citation_border_padding.xml b/test/layoutengine/standard-testcases/page-number-citation_border_padding.xml index a92c4d9c3..c27be1fd7 100644 --- a/test/layoutengine/standard-testcases/page-number-citation_border_padding.xml +++ b/test/layoutengine/standard-testcases/page-number-citation_border_padding.xml @@ -1,99 +1,99 @@ - - - - - -

    - This test checks fo:page-number-citation with border and padding properties. -

    -
    - - - - - - - - - - - Page number citation with a 1pt border. - - - Page number citation with 5pt border and padding. - - - Page number citation with unsymmetric borders and padding. - - - Page number citation with border and padding in a smaller font. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number-citation with border and padding properties. +

    +
    + + + + + + + + + + + Page number citation with a 1pt border. + + + Page number citation with 5pt border and padding. + + + Page number citation with unsymmetric borders and padding. + + + Page number citation with border and padding in a smaller font. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number-citation_vertical-align.xml b/test/layoutengine/standard-testcases/page-number-citation_vertical-align.xml index 0c443dbf7..2bc794446 100644 --- a/test/layoutengine/standard-testcases/page-number-citation_vertical-align.xml +++ b/test/layoutengine/standard-testcases/page-number-citation_vertical-align.xml @@ -1,60 +1,60 @@ - - - - - -

    - This test checks fo:page-number-citation with vertical-align property. -

    -
    - - - - - - - - - - - Page citation vertical-align not specified - - - Page citation vertical-align="baseline" - - - Page citation vertical-align="top" - - - Page citation vertical-align="middle" - - - Page citation vertical-align="bottom" - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number-citation with vertical-align property. +

    +
    + + + + + + + + + + + Page citation vertical-align not specified + + + Page citation vertical-align="baseline" + + + Page citation vertical-align="top" + + + Page citation vertical-align="middle" + + + Page citation vertical-align="bottom" + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number_background-color.xml b/test/layoutengine/standard-testcases/page-number_background-color.xml index f7f61b770..0d23848e4 100644 --- a/test/layoutengine/standard-testcases/page-number_background-color.xml +++ b/test/layoutengine/standard-testcases/page-number_background-color.xml @@ -1,44 +1,44 @@ - - - - - -

    - This test checks fo:page-number with background-color property. -

    -
    - - - - - - - - - - - To emphasize a page number highlight it. - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number with background-color property. +

    +
    + + + + + + + + + + + To emphasize a page number highlight it. + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number_background-image.xml b/test/layoutengine/standard-testcases/page-number_background-image.xml index 1835fd287..d11a2d3da 100644 --- a/test/layoutengine/standard-testcases/page-number_background-image.xml +++ b/test/layoutengine/standard-testcases/page-number_background-image.xml @@ -1,49 +1,49 @@ - - - - - -

    - This test checks fo:page-number with background-image property. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - Page - Page - - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number with background-image property. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + Page + Page + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number_border_padding.xml b/test/layoutengine/standard-testcases/page-number_border_padding.xml index 9bbacc8a6..36f7c5db2 100644 --- a/test/layoutengine/standard-testcases/page-number_border_padding.xml +++ b/test/layoutengine/standard-testcases/page-number_border_padding.xml @@ -1,99 +1,99 @@ - - - - - -

    - This test checks fo:page-number with border and padding properties. -

    -
    - - - - - - - - - - - Page number with a 1pt border. - - - Page number with 5pt border and padding. - - - Page number with unsymmetric borders and padding. - - - Page number with border and padding in a smaller font. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number with border and padding properties. +

    +
    + + + + + + + + + + + Page number with a 1pt border. + + + Page number with 5pt border and padding. + + + Page number with unsymmetric borders and padding. + + + Page number with border and padding in a smaller font. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number_initial-page-number_2.xml b/test/layoutengine/standard-testcases/page-number_initial-page-number_2.xml index d743ef769..597bb9226 100644 --- a/test/layoutengine/standard-testcases/page-number_initial-page-number_2.xml +++ b/test/layoutengine/standard-testcases/page-number_initial-page-number_2.xml @@ -1,54 +1,54 @@ - - - - - -

    - This test checks fo:page-number. -

    -
    - - - - - - - - - - 9 10 - page: -><- - page: -><- - page: -><- - page: -><- - page: -><- - page: -><- - page: -><- - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number. +

    +
    + + + + + + + + + + 9 10 + page: -><- + page: -><- + page: -><- + page: -><- + page: -><- + page: -><- + page: -><- + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number_vertical-align.xml b/test/layoutengine/standard-testcases/page-number_vertical-align.xml index 7a85a821d..f02b04096 100644 --- a/test/layoutengine/standard-testcases/page-number_vertical-align.xml +++ b/test/layoutengine/standard-testcases/page-number_vertical-align.xml @@ -1,60 +1,60 @@ - - - - - -

    - This test checks fo:page-number with vertical-align property. -

    -
    - - - - - - - - - - - Page vertical-align not specified - - - Page vertical-align="baseline" - - - Page vertical-align="top" - - - Page vertical-align="middle" - - - Page vertical-align="bottom" - - - - - - - - - - - - -
    + + + + + +

    + This test checks fo:page-number with vertical-align property. +

    +
    + + + + + + + + + + + Page vertical-align not specified + + + Page vertical-align="baseline" + + + Page vertical-align="top" + + + Page vertical-align="middle" + + + Page vertical-align="bottom" + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/ps-extension_2.xml b/test/layoutengine/standard-testcases/ps-extension_2.xml index 036c19fd6..9fadd9845 100644 --- a/test/layoutengine/standard-testcases/ps-extension_2.xml +++ b/test/layoutengine/standard-testcases/ps-extension_2.xml @@ -1,95 +1,95 @@ - - - - - -

    - This test checks the PostScript extension for custom setpagedevice calls and comments. - The extension attachments need to show up in the area tree XML so the AreaTreeParser can fully restore the area tree. -

    -
    - - - - - > ]]> - A4 before page - A4 after page - - - - > ]]> - A4a before page 1 - A4a after page 1 - A4a before page 2 - A4a after page 2 - - - - - - - - - - > ]]> - header comment 1 - footer comment 1 - header comment 2 - footer comment 2 - - - - Hello World! - - Hello World! - - Hello World! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks the PostScript extension for custom setpagedevice calls and comments. + The extension attachments need to show up in the area tree XML so the AreaTreeParser can fully restore the area tree. +

    +
    + + + + + > ]]> + A4 before page + A4 after page + + + + > ]]> + A4a before page 1 + A4a after page 1 + A4a before page 2 + A4a after page 2 + + + + + + + + + + > ]]> + header comment 1 + footer comment 1 + header comment 2 + footer comment 2 + + + + Hello World! + + Hello World! + + Hello World! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/region-body_column-count_bug36356.xml b/test/layoutengine/standard-testcases/region-body_column-count_bug36356.xml index cd02fe183..c9f72ba30 100644 --- a/test/layoutengine/standard-testcases/region-body_column-count_bug36356.xml +++ b/test/layoutengine/standard-testcases/region-body_column-count_bug36356.xml @@ -1,60 +1,60 @@ - - - - - -

    - This test checks multi-column documents. Checks a problem described in Bugzilla #36356. - The balancing algorithm does not seem to always find the right breaking points. -

    -
    - - - - - - - - - - - line1 - line2 - line3 - line4 - line5 - line6 - - - This line is spanned over all columns. - - - line1 - line2 - line3 - - - - - - - - - - -
    + + + + + +

    + This test checks multi-column documents. Checks a problem described in Bugzilla #36356. + The balancing algorithm does not seem to always find the right breaking points. +

    +
    + + + + + + + + + + + line1 + line2 + line3 + line4 + line5 + line6 + + + This line is spanned over all columns. + + + line1 + line2 + line3 + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_margin_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_margin_region-body_margin_relative.xml index 5a4077bb4..1dfe99990 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_margin_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_margin_region-body_margin_relative.xml @@ -1,107 +1,107 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margins on all regions and the page master. - The page size is 5in x 3in. This gives top and bottom margins of 0.25in and - left and right margins 0.15in. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margins on all regions and the page master. + The page size is 5in x 3in. This gives top and bottom margins of 0.25in and + left and right margins 0.15in. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_region-body_margin_relative.xml index cffbf14e8..2d63815b5 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_region-body_margin_relative.xml @@ -1,112 +1,112 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference not rotated. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference not rotated. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_writing-mode_rl_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_writing-mode_rl_region-body_margin_relative.xml index 3c5171d28..e594a211e 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_writing-mode_rl_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_writing-mode_rl_region-body_margin_relative.xml @@ -1,113 +1,113 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference not rotated - and a rl writing-mode. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference not rotated + and a rl writing-mode. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_region-body_margin_relative.xml index e7980afdc..4a3054a9a 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_region-body_margin_relative.xml @@ -1,113 +1,113 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 180 degrees. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated by + 180 degrees. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_writing-mode_rl_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_writing-mode_rl_region-body_margin_relative.xml index b18878a1f..b9a26ce7c 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_writing-mode_rl_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_writing-mode_rl_region-body_margin_relative.xml @@ -1,113 +1,113 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 180 degrees and a rl writing-mode. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated by + 180 degrees and a rl writing-mode. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_region-body_margin_relative.xml index 7646d1d29..7d7196ece 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_region-body_margin_relative.xml @@ -1,113 +1,113 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 270 degrees. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated by + 270 degrees. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_writing-mode_rl_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_writing-mode_rl_region-body_margin_relative.xml index 26880f095..93b37467b 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_writing-mode_rl_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_writing-mode_rl_region-body_margin_relative.xml @@ -1,113 +1,113 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 270 degrees and a rl writing-mode. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated by + 270 degrees and a rl writing-mode. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_region-body_margin_relative.xml index 01c0eaecd..ab6a58400 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_region-body_margin_relative.xml @@ -1,113 +1,113 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 90 degrees. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated by + 90 degrees. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_writing-mode_rl_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_writing-mode_rl_region-body_margin_relative.xml index bbf2a022d..8c98329f7 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_writing-mode_rl_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_writing-mode_rl_region-body_margin_relative.xml @@ -1,113 +1,113 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t - - - - - r e g i o n e n d - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 90 degrees and a rl writing-mode. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t + + + + + r e g i o n e n d + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated by + 90 degrees and a rl writing-mode. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_writing-mode_rl_region-body_writing-mode-lr.xml b/test/layoutengine/standard-testcases/simple-page-master_writing-mode_rl_region-body_writing-mode-lr.xml index 4de877c91..68db2454e 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_writing-mode_rl_region-body_writing-mode-lr.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_writing-mode_rl_region-body_writing-mode-lr.xml @@ -1,114 +1,114 @@ - - - - - -

    - This test checks relative margin on region (region-body). -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - r e g i o n b e f o r e - - - - - r e g i o n a f t e r - - - - - r e g i o n s t a r t top - bottom - - - - - r e g i o n e n d top - bottom - - - - - Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference not rotated - and a rl writing-mode on the page master, a normal writing mode on the region-body - and tb writing mode on start and end regions. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative margin on region (region-body). +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + r e g i o n b e f o r e + + + + + r e g i o n a f t e r + + + + + r e g i o n s t a r t top - bottom + + + + + r e g i o n e n d top - bottom + + + + + Demonstrates relative 5% margin on the page master, 10% margin on regions before + and end and 5% margin on regions start and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference not rotated + and a rl writing-mode on the page master, a normal writing mode on the region-body + and tb writing mode on start and end regions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-body_background-image.xml b/test/layoutengine/standard-testcases/table-body_background-image.xml index ffe122098..2a9aa9362 100644 --- a/test/layoutengine/standard-testcases/table-body_background-image.xml +++ b/test/layoutengine/standard-testcases/table-body_background-image.xml @@ -1,110 +1,110 @@ - - - - - -

    - This test checks background image on a fo:table-body. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - - - Header Col 1 - - - Header Col 2 - - - Header Col 3 - - - - - - - Row 1 Col 1 - - - Row 1 Col 2 - - - Row 1 Col 3 - - - - - Row 2 Col 1 - - - Row 2 Col 2 - - - Row 2 Col 3 - - - - - Row 3 Col 1 - - - Row 3 Col 2 - - - Row 3 Col 3 - - - - - Row 4 Col 1 - - - Row 4 Col 2 - - - Row 4 Col 3 - - - - - Table with centered background image on body - - - - - - - -
    + + + + + +

    + This test checks background image on a fo:table-body. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + + + Header Col 1 + + + Header Col 2 + + + Header Col 3 + + + + + + + Row 1 Col 1 + + + Row 1 Col 2 + + + Row 1 Col 3 + + + + + Row 2 Col 1 + + + Row 2 Col 2 + + + Row 2 Col 3 + + + + + Row 3 Col 1 + + + Row 3 Col 2 + + + Row 3 Col 3 + + + + + Row 4 Col 1 + + + Row 4 Col 2 + + + Row 4 Col 3 + + + + + Table with centered background image on body + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_background-image.xml b/test/layoutengine/standard-testcases/table-cell_background-image.xml index 047728243..1c4587b25 100644 --- a/test/layoutengine/standard-testcases/table-cell_background-image.xml +++ b/test/layoutengine/standard-testcases/table-cell_background-image.xml @@ -1,131 +1,131 @@ - - - - - -

    - This test checks relative positioned background images on a fo:table-cell. -

    -
    - - ../../resources/images/box1.png - - - - - - - - - - - - - - - - - - image in top right corner - - - image in center right - - - image in bottom right corner - - - - - image in top center - - - image in center - - - image in bottom center - - - - - image in top left - - - image in center left - - - image in bottom left - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative positioned background images on a fo:table-cell. +

    +
    + + ../../resources/images/box1.png + + + + + + + + + + + + + + + + + + image in top right corner + + + image in center right + + + image in bottom right corner + + + + + image in top center + + + image in center + + + image in bottom center + + + + + image in top left + + + image in center left + + + image in bottom left + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_block_margin_percentage.xml b/test/layoutengine/standard-testcases/table-cell_block_margin_percentage.xml index 84504cbc4..84aa38538 100644 --- a/test/layoutengine/standard-testcases/table-cell_block_margin_percentage.xml +++ b/test/layoutengine/standard-testcases/table-cell_block_margin_percentage.xml @@ -1,82 +1,82 @@ - - - - - -

    - This test checks basic tables with percentages in cells. -

    -
    - - - - - - - - - - - - - - - - cell1 - - - cell2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks basic tables with percentages in cells. +

    +
    + + + + + + + + + + + + + + + + cell1 + + + cell2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_padding_percentages.xml b/test/layoutengine/standard-testcases/table-cell_padding_percentages.xml index 2cc55afad..3608b47f1 100644 --- a/test/layoutengine/standard-testcases/table-cell_padding_percentages.xml +++ b/test/layoutengine/standard-testcases/table-cell_padding_percentages.xml @@ -1,65 +1,65 @@ - - - - - -

    - This test checks relative padding on a fo:table-cell. -

    -
    - - - - - - - - - - - - - - - - - Row 1 Col 1 - - - Row 1 Col 2 - - - Row 1 Col 3 - - - - - Table a yellow cell having 2% padding. - - - - - - - - - - - - -
    + + + + + +

    + This test checks relative padding on a fo:table-cell. +

    +
    + + + + + + + + + + + + + + + + + Row 1 Col 1 + + + Row 1 Col 2 + + + Row 1 Col 3 + + + + + Table a yellow cell having 2% padding. + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-header_background-image.xml b/test/layoutengine/standard-testcases/table-header_background-image.xml index f4867c9da..f74c13b0d 100644 --- a/test/layoutengine/standard-testcases/table-header_background-image.xml +++ b/test/layoutengine/standard-testcases/table-header_background-image.xml @@ -1,101 +1,101 @@ - - - - - -

    - This test checks background image on a fo:table-header and footer. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - - - Header Col 1 - - - Header Col 2 - - - Header Col 3 - - - - - - - Footer Col 1 - - - Footer Col 2 - - - Footer Col 3 - - - - - - - Row 1 Col 1 - - - Row 1 Col 2 - - - Row 1 Col 3 - - - - - Row 2 Col 1 - - - Row 2 Col 2 - - - Row 2 Col 3 - - - - - Table with centered background image in header and footer - - - - - - - -
    + + + + + +

    + This test checks background image on a fo:table-header and footer. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + + + Header Col 1 + + + Header Col 2 + + + Header Col 3 + + + + + + + Footer Col 1 + + + Footer Col 2 + + + Footer Col 3 + + + + + + + Row 1 Col 1 + + + Row 1 Col 2 + + + Row 1 Col 3 + + + + + Row 2 Col 1 + + + Row 2 Col 2 + + + Row 2 Col 3 + + + + + Table with centered background image in header and footer + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-row_background-image.xml b/test/layoutengine/standard-testcases/table-row_background-image.xml index eec4b6e17..fa29f1b8e 100644 --- a/test/layoutengine/standard-testcases/table-row_background-image.xml +++ b/test/layoutengine/standard-testcases/table-row_background-image.xml @@ -1,89 +1,89 @@ - - - - - -

    - This test checks background image on a fo:table-row. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - - - Header Col 1 - - - Header Col 2 - - - Header Col 3 - - - - - - - Row 1 Col 1 - - - Row 1 Col 2 - - - Row 1 Col 3 - - - - - Row 2 Col 1 - - - Row 2 Col 2 - - - Row 2 Col 3 - - - - - Table with centered background image on row 1 - - - - - - - - - -
    + + + + + +

    + This test checks background image on a fo:table-row. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + + + Header Col 1 + + + Header Col 2 + + + Header Col 3 + + + + + + + Row 1 Col 1 + + + Row 1 Col 2 + + + Row 1 Col 3 + + + + + Row 2 Col 1 + + + Row 2 Col 2 + + + Row 2 Col 3 + + + + + Table with centered background image on row 1 + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table_background-image.xml b/test/layoutengine/standard-testcases/table_background-image.xml index 0b808638e..3efce48e6 100644 --- a/test/layoutengine/standard-testcases/table_background-image.xml +++ b/test/layoutengine/standard-testcases/table_background-image.xml @@ -1,113 +1,113 @@ - - - - - -

    - This test checks background image on a fo:table. -

    -
    - - ../../resources/images/bgimg300dpi.jpg - - - - - - - - - - - - - - - - - - Header Col 1 - - - Header Col 2 - - - Header Col 3 - - - - - - - Row 1 Col 1 - - - Row 1 Col 2 - - - Row 1 Col 3 - - - - - Row 2 Col 1 - - - Row 2 Col 2 - - - Row 2 Col 3 - - - - - Row 3 Col 1 - - - Row 3 Col 2 - - - Row 3 Col 3 - - - - - Row 4 Col 1 - - - Row 4 Col 2 - - - Row 4 Col 3 - - - - - Table with centered background image - - - - - - - -
    + + + + + +

    + This test checks background image on a fo:table. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + + + + + + + Header Col 1 + + + Header Col 2 + + + Header Col 3 + + + + + + + Row 1 Col 1 + + + Row 1 Col 2 + + + Row 1 Col 3 + + + + + Row 2 Col 1 + + + Row 2 Col 2 + + + Row 2 Col 3 + + + + + Row 3 Col 1 + + + Row 3 Col 2 + + + Row 3 Col 3 + + + + + Row 4 Col 1 + + + Row 4 Col 2 + + + Row 4 Col 3 + + + + + Table with centered background image + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table_padding_percentages.xml b/test/layoutengine/standard-testcases/table_padding_percentages.xml index 69c8f19b4..9d4041b17 100644 --- a/test/layoutengine/standard-testcases/table_padding_percentages.xml +++ b/test/layoutengine/standard-testcases/table_padding_percentages.xml @@ -1,76 +1,76 @@ - - - - - -

    - This test checks relative padding on a fo:table. -

    -
    - - - - - - - - - - - - - - - - - Header Col 1 - - - Header Col 2 - - - Header Col 3 - - - - - - - Row 1 Col 1 - - - Row 1 Col 2 - - - Row 1 Col 3 - - - - - Table on yellow background with 5% padding - - - - - - - - - -
    + + + + + +

    + This test checks relative padding on a fo:table. +

    +
    + + + + + + + + + + + + + + + + + Header Col 1 + + + Header Col 2 + + + Header Col 3 + + + + + + + Row 1 Col 1 + + + Row 1 Col 2 + + + Row 1 Col 3 + + + + + Table on yellow background with 5% padding + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table_width.xml b/test/layoutengine/standard-testcases/table_width.xml index b5151d31b..d15739671 100644 --- a/test/layoutengine/standard-testcases/table_width.xml +++ b/test/layoutengine/standard-testcases/table_width.xml @@ -1,98 +1,98 @@ - - - - - -

    - This test checks table width in certain situations. -

    -
    - - - - - - - - - - - - - - - - - - - cell1 - - - cell2 - - - - - - - - - - - - - - - cell1 - - - cell2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    + + + + + +

    + This test checks table width in certain situations. +

    +
    + + + + + + + + + + + + + + + + + + + cell1 + + + cell2 + + + + + + + + + + + + + + + cell1 + + + cell2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -- cgit v1.2.3 From f265c0e1c1566a2a3afeb0fa2641cf3a81598da3 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Wed, 13 Feb 2008 12:03:30 +0000 Subject: Ensured all SVN properties are set equally git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627367 13f79535-47bb-0310-9956-ffa450edef68 --- .../embedding/java/embedding/ExampleAWTViewer.java | 226 ++++---- .../java/embedding/ExampleFO2OldStylePrint.java | 254 ++++----- .../java/embedding/intermediate/ExampleConcat.java | 2 +- .../java/embedding/intermediate/ExampleStamp.java | 2 +- fixsvnprops.sh | 7 +- src/java/org/apache/fop/Version.java | 2 +- src/java/org/apache/fop/apps/FopFactory.java | 2 +- .../apache/fop/apps/FopFactoryConfigurator.java | 2 +- .../org/apache/fop/apps/FormattingResults.java | 170 +++--- src/java/org/apache/fop/apps/MimeConstants.java | 160 +++--- .../org/apache/fop/apps/PageSequenceResults.java | 118 ++-- src/java/org/apache/fop/area/inline/SpaceArea.java | 118 ++-- src/java/org/apache/fop/area/inline/WordArea.java | 144 ++--- .../apache/fop/fo/properties/ColorProperty.java | 2 +- src/java/org/apache/fop/fonts/CachedFontInfo.java | 2 +- src/java/org/apache/fop/fonts/FontCache.java | 2 +- .../fop/fonts/autodetect/FontInfoFinder.java | 2 +- .../fop/fonts/autodetect/MacFontDirFinder.java | 2 +- .../fop/fonts/autodetect/NativeFontDirFinder.java | 2 +- .../fop/fonts/autodetect/UnixFontDirFinder.java | 2 +- .../fop/fonts/autodetect/WindowsFontDirFinder.java | 2 +- .../apache/fop/fonts/truetype/TTFFontLoader.java | 258 ++++----- .../apache/fop/fonts/type1/Type1FontLoader.java | 184 +++--- src/java/org/apache/fop/image/EmfImage.java | 102 ++-- .../org/apache/fop/image/analyser/EMFReader.java | 324 +++++------ .../BalancingColumnBreakingAlgorithm.java | 214 +++---- .../fop/layoutmgr/inline/WrapperLayoutManager.java | 162 +++--- .../fop/render/AbstractFOEventHandlerMaker.java | 138 ++--- .../fop/render/AbstractRendererConfigurator.java | 2 +- .../apache/fop/render/AbstractRendererMaker.java | 142 ++--- .../org/apache/fop/render/Graphics2DAdapter.java | 100 ++-- .../apache/fop/render/Graphics2DImagePainter.java | 58 +- src/java/org/apache/fop/render/ImageAdapter.java | 94 ++-- .../fop/render/PrintRendererConfigurator.java | 2 +- .../apache/fop/render/RendererConfigurator.java | 2 +- .../apache/fop/render/XMLHandlerConfigurator.java | 2 +- .../org/apache/fop/render/XMLHandlerRegistry.java | 332 +++++------ .../org/apache/fop/render/afp/AFPGraphics2D.java | 2 +- .../fop/render/afp/AFPGraphicsConfiguration.java | 2 +- .../apache/fop/render/afp/AFPGraphicsDevice.java | 2 +- src/java/org/apache/fop/render/afp/AFPInfo.java | 2 +- .../org/apache/fop/render/afp/AFPPageFonts.java | 2 +- .../fop/render/afp/AFPRendererConfigurator.java | 2 +- .../org/apache/fop/render/afp/AFPSVGHandler.java | 2 +- src/java/org/apache/fop/render/afp/AFPState.java | 2 +- .../fop/render/afp/AFPTextElementBridge.java | 2 +- .../org/apache/fop/render/afp/AFPTextPainter.java | 2 +- .../render/afp/extensions/AFPExtensionHandler.java | 242 ++++---- .../afp/extensions/AFPExtensionHandlerFactory.java | 82 +-- .../fop/render/afp/modca/AbstractDataObject.java | 2 +- .../afp/modca/AbstractStructuredAFPObject.java | 2 +- .../render/afp/modca/GraphicsDataDescriptor.java | 2 +- .../fop/render/afp/modca/GraphicsObject.java | 2 +- .../fop/render/afp/modca/PreparedAFPObject.java | 2 +- .../afp/modca/goca/AbstractGraphicsContainer.java | 2 +- .../afp/modca/goca/AbstractGraphicsCoord.java | 2 +- .../afp/modca/goca/AbstractPreparedAFPObject.java | 2 +- .../fop/render/afp/modca/goca/GraphicsArea.java | 2 +- .../fop/render/afp/modca/goca/GraphicsBox.java | 2 +- .../afp/modca/goca/GraphicsChainedSegment.java | 2 +- .../fop/render/afp/modca/goca/GraphicsData.java | 2 +- .../fop/render/afp/modca/goca/GraphicsFillet.java | 2 +- .../fop/render/afp/modca/goca/GraphicsFullArc.java | 2 +- .../render/afp/modca/goca/GraphicsImageBegin.java | 2 +- .../render/afp/modca/goca/GraphicsImageData.java | 2 +- .../render/afp/modca/goca/GraphicsImageEnd.java | 2 +- .../fop/render/afp/modca/goca/GraphicsLine.java | 2 +- .../afp/modca/goca/GraphicsSetArcParameters.java | 2 +- .../afp/modca/goca/GraphicsSetCharacterSet.java | 2 +- .../afp/modca/goca/GraphicsSetCurrentPosition.java | 2 +- .../render/afp/modca/goca/GraphicsSetLineType.java | 2 +- .../afp/modca/goca/GraphicsSetLineWidth.java | 2 +- .../afp/modca/goca/GraphicsSetPatternSymbol.java | 2 +- .../afp/modca/goca/GraphicsSetProcessColor.java | 2 +- .../fop/render/afp/modca/goca/GraphicsString.java | 2 +- .../apache/fop/render/awt/AWTRendererMaker.java | 100 ++-- .../fop/render/bitmap/MultiFileRenderingUtil.java | 150 ++--- .../apache/fop/render/bitmap/PNGRendererMaker.java | 114 ++-- .../render/bitmap/TIFFRendererConfigurator.java | 2 +- .../fop/render/bitmap/TIFFRendererMaker.java | 110 ++-- .../fop/render/java2d/Java2DGraphics2DAdapter.java | 164 +++--- .../render/java2d/Java2DRendererConfigurator.java | 2 +- .../fop/render/pcl/PCLRendererConfigurator.java | 2 +- .../apache/fop/render/pcl/PCLRendererMaker.java | 114 ++-- .../render/pcl/extensions/PCLElementMapping.java | 2 +- .../fop/render/pdf/PDFGraphics2DAdapter.java | 260 ++++----- .../apache/fop/render/pdf/PDFRendererMaker.java | 110 ++-- .../fop/render/print/PrintRendererMaker.java | 112 ++-- .../org/apache/fop/render/ps/PSDictionary.java | 624 ++++++++++----------- .../fop/render/ps/PSDictionaryFormatException.java | 74 +-- .../apache/fop/render/ps/PSGraphics2DAdapter.java | 210 +++---- .../fop/render/ps/PSPageDeviceDictionary.java | 220 ++++---- .../fop/render/ps/PSRendererConfigurator.java | 2 +- .../org/apache/fop/render/ps/PSRendererMaker.java | 108 ++-- .../ps/extensions/AbstractPSExtensionElement.java | 266 ++++----- .../ps/extensions/PSExtensionAttachment.java | 220 ++++---- .../render/ps/extensions/PSExtensionHandler.java | 2 +- .../fop/render/ps/extensions/PSSetPageDevice.java | 228 ++++---- .../ps/extensions/PSSetPageDeviceElement.java | 190 +++---- .../fop/render/rtf/RTFFOEventHandlerMaker.java | 132 ++--- .../rtf/rtflib/rtfdoc/IBorderAttributes.java | 234 ++++---- .../fop/render/txt/TXTRendererConfigurator.java | 2 +- .../apache/fop/render/txt/TXTRendererMaker.java | 108 ++-- .../apache/fop/render/xml/XMLRendererMaker.java | 112 ++-- src/java/org/apache/fop/util/LogUtil.java | 2 +- src/java/org/apache/fop/util/QName.java | 276 ++++----- src/java/org/apache/fop/util/UnitConv.java | 2 +- .../fop/render/mif/MIFFOEventHandlerMaker.java | 104 ++-- .../apache/fop/render/svg/SVGRendererMaker.java | 100 ++-- test/java/org/apache/fop/StandardTestSuite.java | 2 +- .../apache/fop/config/BaseUserConfigTestCase.java | 2 +- .../org/apache/fop/render/pdf/PDFCMapTestCase.java | 2 +- 112 files changed, 4101 insertions(+), 4098 deletions(-) (limited to 'src') diff --git a/examples/embedding/java/embedding/ExampleAWTViewer.java b/examples/embedding/java/embedding/ExampleAWTViewer.java index 17b789cc7..716ea1487 100644 --- a/examples/embedding/java/embedding/ExampleAWTViewer.java +++ b/examples/embedding/java/embedding/ExampleAWTViewer.java @@ -1,113 +1,113 @@ -/* - * 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 embedding; - -//Java -import java.io.File; -import java.io.IOException; - -//JAXP -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerException; -import javax.xml.transform.Source; -import javax.xml.transform.Result; -import javax.xml.transform.stream.StreamSource; -import javax.xml.transform.sax.SAXResult; - -//Avalon -import org.apache.avalon.framework.ExceptionUtil; - -//FOP -import org.apache.fop.apps.FOPException; -import org.apache.fop.apps.Fop; -import org.apache.fop.apps.FopFactory; -import org.apache.fop.apps.MimeConstants; - -/** - * This class demonstrates the use of the AWT Viewer. - */ -public class ExampleAWTViewer { - - // configure fopFactory as desired - private FopFactory fopFactory = FopFactory.newInstance(); - - /** - * Display an FO file in the AWT Preview. - * @param fo the FO file - * @throws IOException In case of an I/O problem - * @throws FOPException In case of a problem during layout - * @throws TransformerException In case of a problem during XML processing - */ - public void viewFO(File fo) - throws IOException, FOPException, TransformerException { - - //Setup FOP - Fop fop = fopFactory.newFop(MimeConstants.MIME_FOP_AWT_PREVIEW); - - try { - - //Load XSL-FO file (you can also do an XSL transformation here) - TransformerFactory factory = TransformerFactory.newInstance(); - Transformer transformer = factory.newTransformer(); - Source src = new StreamSource(fo); - Result res = new SAXResult(fop.getDefaultHandler()); - transformer.transform(src, res); - - } catch (Exception e) { - if (e instanceof FOPException) { - throw (FOPException)e; - } - throw new FOPException(e); - } - } - - /** - * Main method. - * @param args the command-line arguments - */ - public static void main(String[] args) { - try { - System.out.println("FOP ExampleAWTViewer\n"); - System.out.println("Preparing..."); - - //Setup directories - File baseDir = new File("."); - File outDir = new File(baseDir, "out"); - outDir.mkdirs(); - - //Setup input and output files - File fofile = new File(baseDir, "xml/fo/helloworld.fo"); - - System.out.println("Input: XSL-FO (" + fofile + ")"); - System.out.println("Output: AWT Viewer"); - System.out.println(); - System.out.println("Starting AWT Viewer..."); - - ExampleAWTViewer app = new ExampleAWTViewer(); - app.viewFO(fofile); - - System.out.println("Success!"); - } catch (Exception e) { - System.err.println(ExceptionUtil.printStackTrace(e)); - System.exit(-1); - } - } -} +/* + * 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 embedding; + +//Java +import java.io.File; +import java.io.IOException; + +//JAXP +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerException; +import javax.xml.transform.Source; +import javax.xml.transform.Result; +import javax.xml.transform.stream.StreamSource; +import javax.xml.transform.sax.SAXResult; + +//Avalon +import org.apache.avalon.framework.ExceptionUtil; + +//FOP +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; + +/** + * This class demonstrates the use of the AWT Viewer. + */ +public class ExampleAWTViewer { + + // configure fopFactory as desired + private FopFactory fopFactory = FopFactory.newInstance(); + + /** + * Display an FO file in the AWT Preview. + * @param fo the FO file + * @throws IOException In case of an I/O problem + * @throws FOPException In case of a problem during layout + * @throws TransformerException In case of a problem during XML processing + */ + public void viewFO(File fo) + throws IOException, FOPException, TransformerException { + + //Setup FOP + Fop fop = fopFactory.newFop(MimeConstants.MIME_FOP_AWT_PREVIEW); + + try { + + //Load XSL-FO file (you can also do an XSL transformation here) + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(); + Source src = new StreamSource(fo); + Result res = new SAXResult(fop.getDefaultHandler()); + transformer.transform(src, res); + + } catch (Exception e) { + if (e instanceof FOPException) { + throw (FOPException)e; + } + throw new FOPException(e); + } + } + + /** + * Main method. + * @param args the command-line arguments + */ + public static void main(String[] args) { + try { + System.out.println("FOP ExampleAWTViewer\n"); + System.out.println("Preparing..."); + + //Setup directories + File baseDir = new File("."); + File outDir = new File(baseDir, "out"); + outDir.mkdirs(); + + //Setup input and output files + File fofile = new File(baseDir, "xml/fo/helloworld.fo"); + + System.out.println("Input: XSL-FO (" + fofile + ")"); + System.out.println("Output: AWT Viewer"); + System.out.println(); + System.out.println("Starting AWT Viewer..."); + + ExampleAWTViewer app = new ExampleAWTViewer(); + app.viewFO(fofile); + + System.out.println("Success!"); + } catch (Exception e) { + System.err.println(ExceptionUtil.printStackTrace(e)); + System.exit(-1); + } + } +} diff --git a/examples/embedding/java/embedding/ExampleFO2OldStylePrint.java b/examples/embedding/java/embedding/ExampleFO2OldStylePrint.java index 8d8ecd465..588d2c5d7 100644 --- a/examples/embedding/java/embedding/ExampleFO2OldStylePrint.java +++ b/examples/embedding/java/embedding/ExampleFO2OldStylePrint.java @@ -1,127 +1,127 @@ -/* - * 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 embedding; - -// Java -import java.awt.print.PrinterJob; -import java.io.File; -import java.io.IOException; - -//JAXP -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.Source; -import javax.xml.transform.Result; -import javax.xml.transform.stream.StreamSource; -import javax.xml.transform.sax.SAXResult; - - -// FOP -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.Fop; -import org.apache.fop.apps.FOPException; -import org.apache.fop.apps.FopFactory; -import org.apache.fop.render.print.PrintRenderer; - -/** - * This class demonstrates printing an FO file to a PrinterJob instance. - */ -public class ExampleFO2OldStylePrint { - - // configure fopFactory as desired - private FopFactory fopFactory = FopFactory.newInstance(); - - /** - * Prints an FO file using an old-style PrinterJob. - * @param fo the FO file - * @throws IOException In case of an I/O problem - * @throws FOPException In case of a FOP problem - */ - public void printFO(File fo) throws IOException, FOPException { - - //Set up PrinterJob instance - PrinterJob printerJob = PrinterJob.getPrinterJob(); - printerJob.setJobName("FOP Printing Example"); - - try { - //Set up a custom user agent so we can supply our own renderer instance - FOUserAgent userAgent = fopFactory.newFOUserAgent(); - - //Set up our own PrintRenderer instance so we can supply a special PrinterJob instance. - PrintRenderer renderer = new PrintRenderer(printerJob); - renderer.setUserAgent(userAgent); - - userAgent.setRendererOverride(renderer); - - // Construct fop with desired output format (here, it is set through the user agent) - Fop fop = fopFactory.newFop(userAgent); - - // Setup JAXP using identity transformer - TransformerFactory factory = TransformerFactory.newInstance(); - Transformer transformer = factory.newTransformer(); // identity transformer - - // Setup input stream - Source src = new StreamSource(fo); - - // Resulting SAX events (the generated FO) must be piped through to FOP - Result res = new SAXResult(fop.getDefaultHandler()); - - // Start XSLT transformation and FOP processing - transformer.transform(src, res); - - } catch (Exception e) { - e.printStackTrace(System.err); - System.exit(-1); - } - } - - - /** - * Main method. - * @param args command-line arguments - */ - public static void main(String[] args) { - try { - System.out.println("FOP ExampleFO2OldStylePrint\n"); - System.out.println("Preparing..."); - - //Setup directories - File baseDir = new File("."); - File outDir = new File(baseDir, "out"); - outDir.mkdirs(); - - //Setup input and output files - File fofile = new File(baseDir, "xml/fo/helloworld.fo"); - - System.out.println("Input: XSL-FO (" + fofile + ")"); - System.out.println("Output: old-style printing using PrinterJob"); - System.out.println(); - System.out.println("Transforming..."); - - ExampleFO2OldStylePrint app = new ExampleFO2OldStylePrint(); - app.printFO(fofile); - - System.out.println("Success!"); - } catch (Exception e) { - e.printStackTrace(System.err); - System.exit(-1); - } - } -} +/* + * 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 embedding; + +// Java +import java.awt.print.PrinterJob; +import java.io.File; +import java.io.IOException; + +//JAXP +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.Source; +import javax.xml.transform.Result; +import javax.xml.transform.stream.StreamSource; +import javax.xml.transform.sax.SAXResult; + + +// FOP +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.render.print.PrintRenderer; + +/** + * This class demonstrates printing an FO file to a PrinterJob instance. + */ +public class ExampleFO2OldStylePrint { + + // configure fopFactory as desired + private FopFactory fopFactory = FopFactory.newInstance(); + + /** + * Prints an FO file using an old-style PrinterJob. + * @param fo the FO file + * @throws IOException In case of an I/O problem + * @throws FOPException In case of a FOP problem + */ + public void printFO(File fo) throws IOException, FOPException { + + //Set up PrinterJob instance + PrinterJob printerJob = PrinterJob.getPrinterJob(); + printerJob.setJobName("FOP Printing Example"); + + try { + //Set up a custom user agent so we can supply our own renderer instance + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + //Set up our own PrintRenderer instance so we can supply a special PrinterJob instance. + PrintRenderer renderer = new PrintRenderer(printerJob); + renderer.setUserAgent(userAgent); + + userAgent.setRendererOverride(renderer); + + // Construct fop with desired output format (here, it is set through the user agent) + Fop fop = fopFactory.newFop(userAgent); + + // Setup JAXP using identity transformer + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(); // identity transformer + + // Setup input stream + Source src = new StreamSource(fo); + + // Resulting SAX events (the generated FO) must be piped through to FOP + Result res = new SAXResult(fop.getDefaultHandler()); + + // Start XSLT transformation and FOP processing + transformer.transform(src, res); + + } catch (Exception e) { + e.printStackTrace(System.err); + System.exit(-1); + } + } + + + /** + * Main method. + * @param args command-line arguments + */ + public static void main(String[] args) { + try { + System.out.println("FOP ExampleFO2OldStylePrint\n"); + System.out.println("Preparing..."); + + //Setup directories + File baseDir = new File("."); + File outDir = new File(baseDir, "out"); + outDir.mkdirs(); + + //Setup input and output files + File fofile = new File(baseDir, "xml/fo/helloworld.fo"); + + System.out.println("Input: XSL-FO (" + fofile + ")"); + System.out.println("Output: old-style printing using PrinterJob"); + System.out.println(); + System.out.println("Transforming..."); + + ExampleFO2OldStylePrint app = new ExampleFO2OldStylePrint(); + app.printFO(fofile); + + System.out.println("Success!"); + } catch (Exception e) { + e.printStackTrace(System.err); + System.exit(-1); + } + } +} diff --git a/examples/embedding/java/embedding/intermediate/ExampleConcat.java b/examples/embedding/java/embedding/intermediate/ExampleConcat.java index 3f179f966..07790309d 100644 --- a/examples/embedding/java/embedding/intermediate/ExampleConcat.java +++ b/examples/embedding/java/embedding/intermediate/ExampleConcat.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: ExampleDOM2PDF.java 332791 2005-11-12 15:58:07Z jeremias $ */ +/* $Id$ */ package embedding.intermediate; diff --git a/examples/embedding/java/embedding/intermediate/ExampleStamp.java b/examples/embedding/java/embedding/intermediate/ExampleStamp.java index c34da9024..b1b0b77e7 100644 --- a/examples/embedding/java/embedding/intermediate/ExampleStamp.java +++ b/examples/embedding/java/embedding/intermediate/ExampleStamp.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: ExampleDOM2PDF.java 332791 2005-11-12 15:58:07Z jeremias $ */ +/* $Id$ */ package embedding.intermediate; diff --git a/fixsvnprops.sh b/fixsvnprops.sh index 6e8181df7..c5688a238 100755 --- a/fixsvnprops.sh +++ b/fixsvnprops.sh @@ -1,4 +1,7 @@ #!/bin/sh -find . -name \*.java -or -name \*.xml -exec svn ps svn:keywords "Revision Id" '{}' \; -find . -name \*.java -or -name \*.xml -exec svn ps svn:eol-style native '{}' \; +find . -name \*.java -exec svn ps svn:keywords "Id" '{}' \; +find . -name \*.xml -exec svn ps svn:keywords "Revision Id" '{}' \; +find . -name \*.java -exec svn ps svn:eol-style native '{}' \; +find . -name \*.xml -exec svn ps svn:eol-style native '{}' \; + diff --git a/src/java/org/apache/fop/Version.java b/src/java/org/apache/fop/Version.java index 7e421ad29..4545d071e 100644 --- a/src/java/org/apache/fop/Version.java +++ b/src/java/org/apache/fop/Version.java @@ -41,7 +41,7 @@ public final class Version { if (version == null) { //Fallback if FOP is used in a development environment String headURL - = "$HeadURL$"; + = "$HeadURL: http://svn.apache.org/repos/asf/xmlgraphics/fop/trunk/src/java/org/apache/fop/Version.java $"; version = headURL; final String pathPrefix = "/xmlgraphics/fop/"; int pos = version.indexOf(pathPrefix); diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index dc94d92fb..de4c43626 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.apps; diff --git a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java index d708cd989..4d4f8d3eb 100644 --- a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java +++ b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.apps; diff --git a/src/java/org/apache/fop/apps/FormattingResults.java b/src/java/org/apache/fop/apps/FormattingResults.java index 86ac72a97..af421f4ac 100644 --- a/src/java/org/apache/fop/apps/FormattingResults.java +++ b/src/java/org/apache/fop/apps/FormattingResults.java @@ -1,85 +1,85 @@ -/* - * 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.apps; - -import java.util.List; - -import org.apache.fop.fo.pagination.AbstractPageSequence; - -/** - * Class for reporting back formatting results to the calling application. - */ -public class FormattingResults { - - private int pageCount = 0; - private List pageSequences = null; - - /** - * Constructor for the FormattingResults object - */ - public FormattingResults() { - } - - /** - * Gets the number of pages rendered - * - * @return The number of pages overall - */ - public int getPageCount() { - return this.pageCount; - } - - /** - * Gets the results for the individual page-sequences. - * - * @return A List with PageSequenceResults objects - */ - public List getPageSequences() { - return this.pageSequences; - } - - /** - * Resets this object - */ - public void reset() { - this.pageCount = 0; - if (this.pageSequences != null) { - this.pageSequences.clear(); - } - } - - /** - * Reports the result of one page sequence rendering - * back into this object. - * - * @param pageSequence the page sequence which just completed rendering - * @param pageCount the number of pages rendered for that PageSequence - */ - public void haveFormattedPageSequence(AbstractPageSequence pageSequence, int pageCount) { - this.pageCount += pageCount; - if (this.pageSequences == null) { - this.pageSequences = new java.util.ArrayList(); - } - this.pageSequences.add( - new PageSequenceResults(pageSequence.getId(), - pageCount)); - } -} - +/* + * 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.apps; + +import java.util.List; + +import org.apache.fop.fo.pagination.AbstractPageSequence; + +/** + * Class for reporting back formatting results to the calling application. + */ +public class FormattingResults { + + private int pageCount = 0; + private List pageSequences = null; + + /** + * Constructor for the FormattingResults object + */ + public FormattingResults() { + } + + /** + * Gets the number of pages rendered + * + * @return The number of pages overall + */ + public int getPageCount() { + return this.pageCount; + } + + /** + * Gets the results for the individual page-sequences. + * + * @return A List with PageSequenceResults objects + */ + public List getPageSequences() { + return this.pageSequences; + } + + /** + * Resets this object + */ + public void reset() { + this.pageCount = 0; + if (this.pageSequences != null) { + this.pageSequences.clear(); + } + } + + /** + * Reports the result of one page sequence rendering + * back into this object. + * + * @param pageSequence the page sequence which just completed rendering + * @param pageCount the number of pages rendered for that PageSequence + */ + public void haveFormattedPageSequence(AbstractPageSequence pageSequence, int pageCount) { + this.pageCount += pageCount; + if (this.pageSequences == null) { + this.pageSequences = new java.util.ArrayList(); + } + this.pageSequences.add( + new PageSequenceResults(pageSequence.getId(), + pageCount)); + } +} + diff --git a/src/java/org/apache/fop/apps/MimeConstants.java b/src/java/org/apache/fop/apps/MimeConstants.java index b17998393..31bdaaab1 100644 --- a/src/java/org/apache/fop/apps/MimeConstants.java +++ b/src/java/org/apache/fop/apps/MimeConstants.java @@ -1,80 +1,80 @@ -/* - * 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.apps; - -/** - * Frequently used MIME types for various file formats used when working with Apache FOP. - */ -public interface MimeConstants { - - /** Portable Document Format */ - String MIME_PDF = "application/pdf"; - - /** PostScript */ - String MIME_POSTSCRIPT = "application/postscript"; - /** Encapsulated PostScript (same MIME type as PostScript) */ - String MIME_EPS = MIME_POSTSCRIPT; - - /** HP's PCL */ - String MIME_PCL = "application/x-pcl"; - /** HP's PCL (alternative MIME type) */ - String MIME_PCL_ALT = "application/vnd.hp-PCL"; - - /** IBM's AFP */ - String MIME_AFP = "application/x-afp"; - /** IBM's AFP (alternative MIME type) */ - String MIME_AFP_ALT = "application/vnd.ibm.modcap"; - - /** Plain text */ - String MIME_PLAIN_TEXT = "text/plain"; - - /** Rich text format */ - String MIME_RTF = "application/rtf"; - /** Rich text format (alternative 1) */ - String MIME_RTF_ALT1 = "text/richtext"; - /** Rich text format (alternative 2) */ - String MIME_RTF_ALT2 = "text/rtf"; - - /** FrameMaker's MIF */ - String MIME_MIF = "application/mif"; - - /** Structured Vector Graphics */ - String MIME_SVG = "image/svg+xml"; - - /** GIF images */ - String MIME_GIF = "image/gif"; - /** PNG images */ - String MIME_PNG = "image/png"; - /** JPEG images */ - String MIME_JPEG = "image/jpeg"; - /** TIFF images */ - String MIME_TIFF = "image/tiff"; - - /** Apache FOP's AWT preview (non-standard MIME type) */ - String MIME_FOP_AWT_PREVIEW = "application/X-fop-awt-preview"; - /** Apache FOP's Direct Printing (non-standard MIME type) */ - String MIME_FOP_PRINT = "application/X-fop-print"; - /** Apache FOP's area tree XML */ - String MIME_FOP_AREA_TREE = "application/X-fop-areatree"; - - /** Proposed but non-registered MIME type for XSL-FO */ - String MIME_XSL_FO = "text/xsl"; - -} +/* + * 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.apps; + +/** + * Frequently used MIME types for various file formats used when working with Apache FOP. + */ +public interface MimeConstants { + + /** Portable Document Format */ + String MIME_PDF = "application/pdf"; + + /** PostScript */ + String MIME_POSTSCRIPT = "application/postscript"; + /** Encapsulated PostScript (same MIME type as PostScript) */ + String MIME_EPS = MIME_POSTSCRIPT; + + /** HP's PCL */ + String MIME_PCL = "application/x-pcl"; + /** HP's PCL (alternative MIME type) */ + String MIME_PCL_ALT = "application/vnd.hp-PCL"; + + /** IBM's AFP */ + String MIME_AFP = "application/x-afp"; + /** IBM's AFP (alternative MIME type) */ + String MIME_AFP_ALT = "application/vnd.ibm.modcap"; + + /** Plain text */ + String MIME_PLAIN_TEXT = "text/plain"; + + /** Rich text format */ + String MIME_RTF = "application/rtf"; + /** Rich text format (alternative 1) */ + String MIME_RTF_ALT1 = "text/richtext"; + /** Rich text format (alternative 2) */ + String MIME_RTF_ALT2 = "text/rtf"; + + /** FrameMaker's MIF */ + String MIME_MIF = "application/mif"; + + /** Structured Vector Graphics */ + String MIME_SVG = "image/svg+xml"; + + /** GIF images */ + String MIME_GIF = "image/gif"; + /** PNG images */ + String MIME_PNG = "image/png"; + /** JPEG images */ + String MIME_JPEG = "image/jpeg"; + /** TIFF images */ + String MIME_TIFF = "image/tiff"; + + /** Apache FOP's AWT preview (non-standard MIME type) */ + String MIME_FOP_AWT_PREVIEW = "application/X-fop-awt-preview"; + /** Apache FOP's Direct Printing (non-standard MIME type) */ + String MIME_FOP_PRINT = "application/X-fop-print"; + /** Apache FOP's area tree XML */ + String MIME_FOP_AREA_TREE = "application/X-fop-areatree"; + + /** Proposed but non-registered MIME type for XSL-FO */ + String MIME_XSL_FO = "text/xsl"; + +} diff --git a/src/java/org/apache/fop/apps/PageSequenceResults.java b/src/java/org/apache/fop/apps/PageSequenceResults.java index ae873b5e3..16c74f66b 100644 --- a/src/java/org/apache/fop/apps/PageSequenceResults.java +++ b/src/java/org/apache/fop/apps/PageSequenceResults.java @@ -1,59 +1,59 @@ -/* - * 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.apps; - -/** - * Class for reporting back formatting results to the calling application. This - * particular class is used to report the results of a single page-sequence. - */ -public class PageSequenceResults { - - private String id; - private int pageCount; - - /** - * Constructor for the PageSequenceResults object - * - * @param id ID of the page-sequence, if available - * @param pageCount The number of resulting pages - */ - public PageSequenceResults(String id, int pageCount) { - this.id = id; - this.pageCount = pageCount; - } - - /** - * Gets the ID of the page-sequence if one was specified. - * - * @return The ID - */ - public String getID() { - return this.id; - } - - /** - * Gets the number of pages that resulted by processing the page-sequence. - * - * @return The number of pages generated - */ - public int getPageCount() { - return this.pageCount; - } -} +/* + * 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.apps; + +/** + * Class for reporting back formatting results to the calling application. This + * particular class is used to report the results of a single page-sequence. + */ +public class PageSequenceResults { + + private String id; + private int pageCount; + + /** + * Constructor for the PageSequenceResults object + * + * @param id ID of the page-sequence, if available + * @param pageCount The number of resulting pages + */ + public PageSequenceResults(String id, int pageCount) { + this.id = id; + this.pageCount = pageCount; + } + + /** + * Gets the ID of the page-sequence if one was specified. + * + * @return The ID + */ + public String getID() { + return this.id; + } + + /** + * Gets the number of pages that resulted by processing the page-sequence. + * + * @return The number of pages generated + */ + public int getPageCount() { + return this.pageCount; + } +} diff --git a/src/java/org/apache/fop/area/inline/SpaceArea.java b/src/java/org/apache/fop/area/inline/SpaceArea.java index 2dcf3d188..9481795a4 100644 --- a/src/java/org/apache/fop/area/inline/SpaceArea.java +++ b/src/java/org/apache/fop/area/inline/SpaceArea.java @@ -1,59 +1,59 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ -package org.apache.fop.area.inline; - -/** - * A space - */ -public class SpaceArea extends InlineArea { - - /** - * The space for this space area - */ - protected String space; - - /** - * Is this space adjustable? - */ - protected boolean isAdjustable; - - /** - * Create a space area - * @param s the space character - * @param o the offset for the next area - * @param a is this space adjustable? - */ - public SpaceArea(char s, int o, boolean a) { - space = new String() + s; - offset = o; - isAdjustable = a; - } - - /** - * @return Returns the space. - */ - public String getSpace() { - return new String(space); - } - - /** @return true if the space is adjustable (WRT word-space processing) */ - public boolean isAdjustable() { - return this.isAdjustable; - } -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ +package org.apache.fop.area.inline; + +/** + * A space + */ +public class SpaceArea extends InlineArea { + + /** + * The space for this space area + */ + protected String space; + + /** + * Is this space adjustable? + */ + protected boolean isAdjustable; + + /** + * Create a space area + * @param s the space character + * @param o the offset for the next area + * @param a is this space adjustable? + */ + public SpaceArea(char s, int o, boolean a) { + space = new String() + s; + offset = o; + isAdjustable = a; + } + + /** + * @return Returns the space. + */ + public String getSpace() { + return new String(space); + } + + /** @return true if the space is adjustable (WRT word-space processing) */ + public boolean isAdjustable() { + return this.isAdjustable; + } +} diff --git a/src/java/org/apache/fop/area/inline/WordArea.java b/src/java/org/apache/fop/area/inline/WordArea.java index a592bdd80..1f5fa2037 100644 --- a/src/java/org/apache/fop/area/inline/WordArea.java +++ b/src/java/org/apache/fop/area/inline/WordArea.java @@ -1,72 +1,72 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ -package org.apache.fop.area.inline; - -/** - * A string of characters without spaces - */ -public class WordArea extends InlineArea { - - /** The text for this word area */ - protected String word; - - /** The correction offset for the next area */ - protected int offset = 0; - - /** An array of width for adjusting the individual letters (optional) */ - protected int[] letterAdjust; - - /** - * Create a word area - * @param w the word string - * @param o the offset for the next area - * @param la the letter adjust array (may be null) - */ - public WordArea(String w, int o, int[] la) { - word = w; - offset = o; - this.letterAdjust = la; - } - - /** - * @return Returns the word. - */ - public String getWord() { - return word; - } - - /** - * @return Returns the offset. - */ - public int getOffset() { - return offset; - } - /** - * @param o The offset to set. - */ - public void setOffset(int o) { - offset = o; - } - - /** @return the array of letter adjust widths */ - public int[] getLetterAdjustArray() { - return this.letterAdjust; - } - -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ +package org.apache.fop.area.inline; + +/** + * A string of characters without spaces + */ +public class WordArea extends InlineArea { + + /** The text for this word area */ + protected String word; + + /** The correction offset for the next area */ + protected int offset = 0; + + /** An array of width for adjusting the individual letters (optional) */ + protected int[] letterAdjust; + + /** + * Create a word area + * @param w the word string + * @param o the offset for the next area + * @param la the letter adjust array (may be null) + */ + public WordArea(String w, int o, int[] la) { + word = w; + offset = o; + this.letterAdjust = la; + } + + /** + * @return Returns the word. + */ + public String getWord() { + return word; + } + + /** + * @return Returns the offset. + */ + public int getOffset() { + return offset; + } + /** + * @param o The offset to set. + */ + public void setOffset(int o) { + offset = o; + } + + /** @return the array of letter adjust widths */ + public int[] getLetterAdjustArray() { + return this.letterAdjust; + } + +} diff --git a/src/java/org/apache/fop/fo/properties/ColorProperty.java b/src/java/org/apache/fop/fo/properties/ColorProperty.java index d961ec3a3..de648420b 100644 --- a/src/java/org/apache/fop/fo/properties/ColorProperty.java +++ b/src/java/org/apache/fop/fo/properties/ColorProperty.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: ColorTypeProperty.java 377045 2006-02-11 20:23:47Z jeremias $ */ +/* $Id$ */ package org.apache.fop.fo.properties; diff --git a/src/java/org/apache/fop/fonts/CachedFontInfo.java b/src/java/org/apache/fop/fonts/CachedFontInfo.java index 35fec529c..3de3cfd4e 100644 --- a/src/java/org/apache/fop/fonts/CachedFontInfo.java +++ b/src/java/org/apache/fop/fonts/CachedFontInfo.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts; diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index 036ec724e..efd7ea603 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts; diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index 7c0b4fcfa..aaefc789b 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.autodetect; diff --git a/src/java/org/apache/fop/fonts/autodetect/MacFontDirFinder.java b/src/java/org/apache/fop/fonts/autodetect/MacFontDirFinder.java index 60d3fd7d3..8083eebb8 100644 --- a/src/java/org/apache/fop/fonts/autodetect/MacFontDirFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/MacFontDirFinder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.autodetect; diff --git a/src/java/org/apache/fop/fonts/autodetect/NativeFontDirFinder.java b/src/java/org/apache/fop/fonts/autodetect/NativeFontDirFinder.java index 0c885ce7d..5339d541b 100644 --- a/src/java/org/apache/fop/fonts/autodetect/NativeFontDirFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/NativeFontDirFinder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.autodetect; diff --git a/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java b/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java index 0d02c6daf..55a7ae1c0 100644 --- a/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.autodetect; diff --git a/src/java/org/apache/fop/fonts/autodetect/WindowsFontDirFinder.java b/src/java/org/apache/fop/fonts/autodetect/WindowsFontDirFinder.java index bcb4ebb99..d87d22708 100644 --- a/src/java/org/apache/fop/fonts/autodetect/WindowsFontDirFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/WindowsFontDirFinder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.autodetect; diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index 53f091f59..58267571e 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -1,129 +1,129 @@ -/* - * 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.fonts.truetype; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.fop.fonts.BFEntry; -import org.apache.fop.fonts.CIDFontType; -import org.apache.fop.fonts.FontLoader; -import org.apache.fop.fonts.FontResolver; -import org.apache.fop.fonts.MultiByteFont; - -/** - * Loads a font into memory directly from the original font file. - */ -public class TTFFontLoader extends FontLoader { - - private MultiByteFont multiFont; - - /** - * Default constructor - * @param fontFileURI the URI representing the font file - * @param in the InputStream to load the font from - * @param resolver the FontResolver for font URI resolution - */ - public TTFFontLoader(String fontFileURI, InputStream in, FontResolver resolver) { - super(fontFileURI, in, resolver); - } - - /** - * {@inheritDoc} - */ - protected void read() throws IOException { - TTFFile ttf = new TTFFile(); - FontFileReader reader = new FontFileReader(in); - boolean supported = ttf.readFont(reader, null); - if (!supported) { - throw new IOException("Could not load TrueType font: " + fontFileURI); - } - if (ttf.isCFF()) { - throw new UnsupportedOperationException( - "OpenType fonts with CFF data are not supported, yet"); - } - multiFont = new MultiByteFont(); - multiFont.setResolver(this.resolver); - returnFont = multiFont; - - returnFont.setFontName(ttf.getPostScriptName()); - returnFont.setFullName(ttf.getFullName()); - returnFont.setFamilyNames(ttf.getFamilyNames()); - returnFont.setFontSubFamilyName(ttf.getSubFamilyName()); - //multiFont.setTTCName(ttcName) - returnFont.setCapHeight(ttf.getCapHeight()); - returnFont.setXHeight(ttf.getXHeight()); - returnFont.setAscender(ttf.getLowerCaseAscent()); - returnFont.setDescender(ttf.getLowerCaseDescent()); - returnFont.setFontBBox(ttf.getFontBBox()); - //returnFont.setFirstChar(ttf.getFirstChar();) - returnFont.setFlags(ttf.getFlags()); - returnFont.setStemV(Integer.parseInt(ttf.getStemV())); //not used for TTF - returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle())); - returnFont.setMissingWidth(0); - - multiFont.setCIDType(CIDFontType.CIDTYPE2); - int[] wx = ttf.getWidths(); - multiFont.setWidthArray(wx); - List entries = ttf.getCMaps(); - BFEntry[] bfentries = new BFEntry[entries.size()]; - int pos = 0; - Iterator iter = ttf.getCMaps().listIterator(); - while (iter.hasNext()) { - TTFCmapEntry ce = (TTFCmapEntry)iter.next(); - bfentries[pos] = new BFEntry(ce.getUnicodeStart(), ce.getUnicodeEnd(), - ce.getGlyphStartIndex()); - pos++; - } - multiFont.setBFEntries(bfentries); - copyKerning(ttf, true); - multiFont.setEmbedFileName(this.fontFileURI); - loaded = true; - } - - /** - * Copy kerning information. - */ - private void copyKerning(TTFFile ttf, boolean isCid) { - - // Get kerning - Iterator iter; - if (isCid) { - iter = ttf.getKerning().keySet().iterator(); - } else { - iter = ttf.getAnsiKerning().keySet().iterator(); - } - - while (iter.hasNext()) { - Integer kpx1 = (Integer)iter.next(); - - Map h2; - if (isCid) { - h2 = (Map)ttf.getKerning().get(kpx1); - } else { - h2 = (Map)ttf.getAnsiKerning().get(kpx1); - } - returnFont.putKerningEntry(kpx1, h2); - } - } -} +/* + * 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.fonts.truetype; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.fop.fonts.BFEntry; +import org.apache.fop.fonts.CIDFontType; +import org.apache.fop.fonts.FontLoader; +import org.apache.fop.fonts.FontResolver; +import org.apache.fop.fonts.MultiByteFont; + +/** + * Loads a font into memory directly from the original font file. + */ +public class TTFFontLoader extends FontLoader { + + private MultiByteFont multiFont; + + /** + * Default constructor + * @param fontFileURI the URI representing the font file + * @param in the InputStream to load the font from + * @param resolver the FontResolver for font URI resolution + */ + public TTFFontLoader(String fontFileURI, InputStream in, FontResolver resolver) { + super(fontFileURI, in, resolver); + } + + /** + * {@inheritDoc} + */ + protected void read() throws IOException { + TTFFile ttf = new TTFFile(); + FontFileReader reader = new FontFileReader(in); + boolean supported = ttf.readFont(reader, null); + if (!supported) { + throw new IOException("Could not load TrueType font: " + fontFileURI); + } + if (ttf.isCFF()) { + throw new UnsupportedOperationException( + "OpenType fonts with CFF data are not supported, yet"); + } + multiFont = new MultiByteFont(); + multiFont.setResolver(this.resolver); + returnFont = multiFont; + + returnFont.setFontName(ttf.getPostScriptName()); + returnFont.setFullName(ttf.getFullName()); + returnFont.setFamilyNames(ttf.getFamilyNames()); + returnFont.setFontSubFamilyName(ttf.getSubFamilyName()); + //multiFont.setTTCName(ttcName) + returnFont.setCapHeight(ttf.getCapHeight()); + returnFont.setXHeight(ttf.getXHeight()); + returnFont.setAscender(ttf.getLowerCaseAscent()); + returnFont.setDescender(ttf.getLowerCaseDescent()); + returnFont.setFontBBox(ttf.getFontBBox()); + //returnFont.setFirstChar(ttf.getFirstChar();) + returnFont.setFlags(ttf.getFlags()); + returnFont.setStemV(Integer.parseInt(ttf.getStemV())); //not used for TTF + returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle())); + returnFont.setMissingWidth(0); + + multiFont.setCIDType(CIDFontType.CIDTYPE2); + int[] wx = ttf.getWidths(); + multiFont.setWidthArray(wx); + List entries = ttf.getCMaps(); + BFEntry[] bfentries = new BFEntry[entries.size()]; + int pos = 0; + Iterator iter = ttf.getCMaps().listIterator(); + while (iter.hasNext()) { + TTFCmapEntry ce = (TTFCmapEntry)iter.next(); + bfentries[pos] = new BFEntry(ce.getUnicodeStart(), ce.getUnicodeEnd(), + ce.getGlyphStartIndex()); + pos++; + } + multiFont.setBFEntries(bfentries); + copyKerning(ttf, true); + multiFont.setEmbedFileName(this.fontFileURI); + loaded = true; + } + + /** + * Copy kerning information. + */ + private void copyKerning(TTFFile ttf, boolean isCid) { + + // Get kerning + Iterator iter; + if (isCid) { + iter = ttf.getKerning().keySet().iterator(); + } else { + iter = ttf.getAnsiKerning().keySet().iterator(); + } + + while (iter.hasNext()) { + Integer kpx1 = (Integer)iter.next(); + + Map h2; + if (isCid) { + h2 = (Map)ttf.getKerning().get(kpx1); + } else { + h2 = (Map)ttf.getAnsiKerning().get(kpx1); + } + returnFont.putKerningEntry(kpx1, h2); + } + } +} diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 63962321c..1a1f691b2 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -1,92 +1,92 @@ -/* - * 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.fonts.type1; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Set; - -import org.apache.fop.fonts.FontLoader; -import org.apache.fop.fonts.FontResolver; -import org.apache.fop.fonts.FontType; -import org.apache.fop.fonts.SingleByteFont; - -/** - * Loads a Type 1 font into memory directly from the original font file. - */ -public class Type1FontLoader extends FontLoader { - - private PFMFile pfm; - private SingleByteFont singleFont; - - /** - * Constructs a new Type 1 font loader. - * @param fontFileURI the URI to the PFB file of a Type 1 font - * @param in the InputStream reading the PFM file of a Type 1 font - * @param resolver the font resolver used to resolve URIs - * @throws IOException In case of an I/O error - */ - public Type1FontLoader(String fontFileURI, InputStream in, FontResolver resolver) - throws IOException { - super(fontFileURI, in, resolver); - } - - /** - * {@inheritDoc} - */ - protected void read() throws IOException { - pfm = new PFMFile(); - pfm.load(in); - singleFont = new SingleByteFont(); - singleFont.setFontType(FontType.TYPE1); - if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { - singleFont.setEncoding(pfm.getCharSetName() + "Encoding"); - } else { - log.warn("The PFM reports an unsupported encoding (" - + pfm.getCharSetName() + "). The font may not work as expected."); - singleFont.setEncoding("WinAnsiEncoding"); //Try fallback, no guarantees! - } - singleFont.setResolver(this.resolver); - returnFont = singleFont; - returnFont.setFontName(pfm.getPostscriptName()); - String fullName = pfm.getPostscriptName(); - fullName = fullName.replace('-', ' '); //Hack! Try to emulate full name - returnFont.setFullName(fullName); //should be afm.getFullName()!! - //TODO not accurate: we need FullName from the AFM file but we don't have an AFM parser - Set names = new java.util.HashSet(); - names.add(pfm.getWindowsName()); //should be afm.getFamilyName()!! - returnFont.setFamilyNames(names); - returnFont.setCapHeight(pfm.getCapHeight()); - returnFont.setXHeight(pfm.getXHeight()); - returnFont.setAscender(pfm.getLowerCaseAscent()); - returnFont.setDescender(pfm.getLowerCaseDescent()); - returnFont.setFontBBox(pfm.getFontBBox()); - returnFont.setFirstChar(pfm.getFirstChar()); - returnFont.setLastChar(pfm.getLastChar()); - returnFont.setFlags(pfm.getFlags()); - returnFont.setStemV(pfm.getStemV()); - returnFont.setItalicAngle(pfm.getItalicAngle()); - returnFont.setMissingWidth(0); - for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { - singleFont.setWidth(i, pfm.getCharWidth(i)); - } - singleFont.setEmbedFileName(this.fontFileURI); - } -} +/* + * 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.fonts.type1; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Set; + +import org.apache.fop.fonts.FontLoader; +import org.apache.fop.fonts.FontResolver; +import org.apache.fop.fonts.FontType; +import org.apache.fop.fonts.SingleByteFont; + +/** + * Loads a Type 1 font into memory directly from the original font file. + */ +public class Type1FontLoader extends FontLoader { + + private PFMFile pfm; + private SingleByteFont singleFont; + + /** + * Constructs a new Type 1 font loader. + * @param fontFileURI the URI to the PFB file of a Type 1 font + * @param in the InputStream reading the PFM file of a Type 1 font + * @param resolver the font resolver used to resolve URIs + * @throws IOException In case of an I/O error + */ + public Type1FontLoader(String fontFileURI, InputStream in, FontResolver resolver) + throws IOException { + super(fontFileURI, in, resolver); + } + + /** + * {@inheritDoc} + */ + protected void read() throws IOException { + pfm = new PFMFile(); + pfm.load(in); + singleFont = new SingleByteFont(); + singleFont.setFontType(FontType.TYPE1); + if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { + singleFont.setEncoding(pfm.getCharSetName() + "Encoding"); + } else { + log.warn("The PFM reports an unsupported encoding (" + + pfm.getCharSetName() + "). The font may not work as expected."); + singleFont.setEncoding("WinAnsiEncoding"); //Try fallback, no guarantees! + } + singleFont.setResolver(this.resolver); + returnFont = singleFont; + returnFont.setFontName(pfm.getPostscriptName()); + String fullName = pfm.getPostscriptName(); + fullName = fullName.replace('-', ' '); //Hack! Try to emulate full name + returnFont.setFullName(fullName); //should be afm.getFullName()!! + //TODO not accurate: we need FullName from the AFM file but we don't have an AFM parser + Set names = new java.util.HashSet(); + names.add(pfm.getWindowsName()); //should be afm.getFamilyName()!! + returnFont.setFamilyNames(names); + returnFont.setCapHeight(pfm.getCapHeight()); + returnFont.setXHeight(pfm.getXHeight()); + returnFont.setAscender(pfm.getLowerCaseAscent()); + returnFont.setDescender(pfm.getLowerCaseDescent()); + returnFont.setFontBBox(pfm.getFontBBox()); + returnFont.setFirstChar(pfm.getFirstChar()); + returnFont.setLastChar(pfm.getLastChar()); + returnFont.setFlags(pfm.getFlags()); + returnFont.setStemV(pfm.getStemV()); + returnFont.setItalicAngle(pfm.getItalicAngle()); + returnFont.setMissingWidth(0); + for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { + singleFont.setWidth(i, pfm.getCharWidth(i)); + } + singleFont.setEmbedFileName(this.fontFileURI); + } +} diff --git a/src/java/org/apache/fop/image/EmfImage.java b/src/java/org/apache/fop/image/EmfImage.java index 1221b9b2b..73bbad232 100644 --- a/src/java/org/apache/fop/image/EmfImage.java +++ b/src/java/org/apache/fop/image/EmfImage.java @@ -1,51 +1,51 @@ -/* - * 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.image; - -/** - * Enhanced metafile image. - * This supports loading a EMF image. - * - * @see AbstractFopImage - * @see FopImage - */ -public class EmfImage extends AbstractFopImage { - - /** - * Create a bitmap image with the image data. - * - * @param imgInfo the image information - */ - public EmfImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * Load the original EMF data. - * This loads the original EMF data and reads the color space, - * and icc profile if any. - * - * @return true if loaded false for any error - */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } -} - +/* + * 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.image; + +/** + * Enhanced metafile image. + * This supports loading a EMF image. + * + * @see AbstractFopImage + * @see FopImage + */ +public class EmfImage extends AbstractFopImage { + + /** + * Create a bitmap image with the image data. + * + * @param imgInfo the image information + */ + public EmfImage(FopImage.ImageInfo imgInfo) { + super(imgInfo); + } + + /** + * Load the original EMF data. + * This loads the original EMF data and reads the color space, + * and icc profile if any. + * + * @return true if loaded false for any error + */ + protected boolean loadOriginalData() { + return loadDefaultOriginalData(); + } +} + diff --git a/src/java/org/apache/fop/image/analyser/EMFReader.java b/src/java/org/apache/fop/image/analyser/EMFReader.java index bdc4e97ff..d6e2f2975 100644 --- a/src/java/org/apache/fop/image/analyser/EMFReader.java +++ b/src/java/org/apache/fop/image/analyser/EMFReader.java @@ -1,162 +1,162 @@ -/* - * 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.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for EMF image type. - * - * @author Peter Herweg - */ -public class EMFReader implements ImageReader { - - /** Length of the EMF header */ - protected static final int EMF_SIG_LENGTH = 88; - - /** offset to signature */ - private static final int SIGNATURE_OFFSET = 40; - /** offset to width */ - private static final int WIDTH_OFFSET = 32; - /** offset to height */ - private static final int HEIGHT_OFFSET = 36; - /** offset to horizontal resolution in pixel */ - private static final int HRES_PIXEL_OFFSET = 72; - /** offset to vertical resolution in pixel */ - private static final int VRES_PIXEL_OFFSET = 76; - /** offset to horizontal resolution in mm */ - private static final int HRES_MM_OFFSET = 80; - /** offset to vertical resolution in mm */ - private static final int VRES_MM_OFFSET = 84; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported - = ( (header[SIGNATURE_OFFSET + 0] == (byte) 0x20) - && (header[SIGNATURE_OFFSET + 1] == (byte) 0x45) - && (header[SIGNATURE_OFFSET + 2] == (byte) 0x4D) - && (header[SIGNATURE_OFFSET + 3] == (byte) 0x46) ); - - if (supported) { - FopImage.ImageInfo info = getDimension(header); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/emf"; - } - - private FopImage.ImageInfo getDimension(byte[] header) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - long value = 0; - int byte1; - int byte2; - int byte3; - int byte4; - - // little endian notation - - //resolution - byte1 = header[HRES_MM_OFFSET] & 0xff; - byte2 = header[HRES_MM_OFFSET + 1] & 0xff; - byte3 = header[HRES_MM_OFFSET + 2] & 0xff; - byte4 = header[HRES_MM_OFFSET + 3] & 0xff; - long hresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[VRES_MM_OFFSET] & 0xff; - byte2 = header[VRES_MM_OFFSET + 1] & 0xff; - byte3 = header[VRES_MM_OFFSET + 2] & 0xff; - byte4 = header[VRES_MM_OFFSET + 3] & 0xff; - long vresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[HRES_PIXEL_OFFSET] & 0xff; - byte2 = header[HRES_PIXEL_OFFSET + 1] & 0xff; - byte3 = header[HRES_PIXEL_OFFSET + 2] & 0xff; - byte4 = header[HRES_PIXEL_OFFSET + 3] & 0xff; - long hresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[VRES_PIXEL_OFFSET] & 0xff; - byte2 = header[VRES_PIXEL_OFFSET + 1] & 0xff; - byte3 = header[VRES_PIXEL_OFFSET + 2] & 0xff; - byte4 = header[VRES_PIXEL_OFFSET + 3] & 0xff; - long vresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - info.dpiHorizontal = hresPixel / (hresMM / 25.4f); - info.dpiVertical = vresPixel / (vresMM / 25.4f); - - //width - byte1 = header[WIDTH_OFFSET] & 0xff; - byte2 = header[WIDTH_OFFSET + 1] & 0xff; - byte3 = header[WIDTH_OFFSET + 2] & 0xff; - byte4 = header[WIDTH_OFFSET + 3] & 0xff; - value = (long) ((byte4 << 24) | (byte3 << 16) - | (byte2 << 8) | byte1); - value = Math.round(value / 100f / 25.4f * info.dpiHorizontal); - info.width = (int) (value & 0xffffffff); - - //height - byte1 = header[HEIGHT_OFFSET] & 0xff; - byte2 = header[HEIGHT_OFFSET + 1] & 0xff; - byte3 = header[HEIGHT_OFFSET + 2] & 0xff; - byte4 = header[HEIGHT_OFFSET + 3] & 0xff; - value = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - value = Math.round(value / 100f / 25.4f * info.dpiVertical); - info.height = (int) (value & 0xffffffff); - - return info; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[EMF_SIG_LENGTH]; - try { - imageStream.mark(EMF_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } -} +/* + * 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.image.analyser; + +// Java +import java.io.InputStream; +import java.io.IOException; + +// FOP +import org.apache.fop.image.FopImage; +import org.apache.fop.apps.FOUserAgent; + +/** + * ImageReader object for EMF image type. + * + * @author Peter Herweg + */ +public class EMFReader implements ImageReader { + + /** Length of the EMF header */ + protected static final int EMF_SIG_LENGTH = 88; + + /** offset to signature */ + private static final int SIGNATURE_OFFSET = 40; + /** offset to width */ + private static final int WIDTH_OFFSET = 32; + /** offset to height */ + private static final int HEIGHT_OFFSET = 36; + /** offset to horizontal resolution in pixel */ + private static final int HRES_PIXEL_OFFSET = 72; + /** offset to vertical resolution in pixel */ + private static final int VRES_PIXEL_OFFSET = 76; + /** offset to horizontal resolution in mm */ + private static final int HRES_MM_OFFSET = 80; + /** offset to vertical resolution in mm */ + private static final int VRES_MM_OFFSET = 84; + + /** {@inheritDoc} */ + public FopImage.ImageInfo verifySignature(String uri, InputStream bis, + FOUserAgent ua) throws IOException { + byte[] header = getDefaultHeader(bis); + boolean supported + = ( (header[SIGNATURE_OFFSET + 0] == (byte) 0x20) + && (header[SIGNATURE_OFFSET + 1] == (byte) 0x45) + && (header[SIGNATURE_OFFSET + 2] == (byte) 0x4D) + && (header[SIGNATURE_OFFSET + 3] == (byte) 0x46) ); + + if (supported) { + FopImage.ImageInfo info = getDimension(header); + info.originalURI = uri; + info.mimeType = getMimeType(); + info.inputStream = bis; + return info; + } else { + return null; + } + } + + /** + * Returns the MIME type supported by this implementation. + * + * @return The MIME type + */ + public String getMimeType() { + return "image/emf"; + } + + private FopImage.ImageInfo getDimension(byte[] header) { + FopImage.ImageInfo info = new FopImage.ImageInfo(); + long value = 0; + int byte1; + int byte2; + int byte3; + int byte4; + + // little endian notation + + //resolution + byte1 = header[HRES_MM_OFFSET] & 0xff; + byte2 = header[HRES_MM_OFFSET + 1] & 0xff; + byte3 = header[HRES_MM_OFFSET + 2] & 0xff; + byte4 = header[HRES_MM_OFFSET + 3] & 0xff; + long hresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + + byte1 = header[VRES_MM_OFFSET] & 0xff; + byte2 = header[VRES_MM_OFFSET + 1] & 0xff; + byte3 = header[VRES_MM_OFFSET + 2] & 0xff; + byte4 = header[VRES_MM_OFFSET + 3] & 0xff; + long vresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + + byte1 = header[HRES_PIXEL_OFFSET] & 0xff; + byte2 = header[HRES_PIXEL_OFFSET + 1] & 0xff; + byte3 = header[HRES_PIXEL_OFFSET + 2] & 0xff; + byte4 = header[HRES_PIXEL_OFFSET + 3] & 0xff; + long hresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + + byte1 = header[VRES_PIXEL_OFFSET] & 0xff; + byte2 = header[VRES_PIXEL_OFFSET + 1] & 0xff; + byte3 = header[VRES_PIXEL_OFFSET + 2] & 0xff; + byte4 = header[VRES_PIXEL_OFFSET + 3] & 0xff; + long vresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + + info.dpiHorizontal = hresPixel / (hresMM / 25.4f); + info.dpiVertical = vresPixel / (vresMM / 25.4f); + + //width + byte1 = header[WIDTH_OFFSET] & 0xff; + byte2 = header[WIDTH_OFFSET + 1] & 0xff; + byte3 = header[WIDTH_OFFSET + 2] & 0xff; + byte4 = header[WIDTH_OFFSET + 3] & 0xff; + value = (long) ((byte4 << 24) | (byte3 << 16) + | (byte2 << 8) | byte1); + value = Math.round(value / 100f / 25.4f * info.dpiHorizontal); + info.width = (int) (value & 0xffffffff); + + //height + byte1 = header[HEIGHT_OFFSET] & 0xff; + byte2 = header[HEIGHT_OFFSET + 1] & 0xff; + byte3 = header[HEIGHT_OFFSET + 2] & 0xff; + byte4 = header[HEIGHT_OFFSET + 3] & 0xff; + value = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + value = Math.round(value / 100f / 25.4f * info.dpiVertical); + info.height = (int) (value & 0xffffffff); + + return info; + } + + private byte[] getDefaultHeader(InputStream imageStream) + throws IOException { + byte[] header = new byte[EMF_SIG_LENGTH]; + try { + imageStream.mark(EMF_SIG_LENGTH + 1); + imageStream.read(header); + imageStream.reset(); + } catch (IOException ex) { + try { + imageStream.reset(); + } catch (IOException exbis) { + // throw the original exception, not this one + } + throw ex; + } + return header; + } +} diff --git a/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java index 8d7375451..a28fdbfbc 100644 --- a/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java @@ -1,107 +1,107 @@ -/* - * 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.layoutmgr; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.traits.MinOptMax; - -/** - * This is a the breaking algorithm that is responsible for balancing columns in multi-column - * layout. - */ -public class BalancingColumnBreakingAlgorithm extends PageBreakingAlgorithm { - - private Log log = LogFactory.getLog(BalancingColumnBreakingAlgorithm.class); - - private int columnCount; - private int fullLen; - private int idealPartLen; - - public BalancingColumnBreakingAlgorithm(LayoutManager topLevelLM, - PageProvider pageProvider, - PageBreakingLayoutListener layoutListener, - int alignment, int alignmentLast, - MinOptMax footnoteSeparatorLength, - boolean partOverflowRecovery, - int columnCount) { - super(topLevelLM, pageProvider, layoutListener, - alignment, alignmentLast, - footnoteSeparatorLength, partOverflowRecovery, false, false); - this.columnCount = columnCount; - this.considerTooShort = true; //This is important! - } - - /** {@inheritDoc} */ - protected double computeDemerits(KnuthNode activeNode, - KnuthElement element, int fitnessClass, double r) { - double dem = super.computeDemerits(activeNode, element, fitnessClass, r); - if (log.isTraceEnabled()) { - log.trace("original demerit=" + dem + " " + totalWidth - + " line=" + activeNode.line + "/" + columnCount - + " pos=" + activeNode.position + "/" + (par.size() - 1)); - } - int remParts = columnCount - activeNode.line; - int curPos = par.indexOf(element); - if (fullLen == 0) { - fullLen = ElementListUtils.calcContentLength(par, activeNode.position, par.size() - 1); - this.idealPartLen = (fullLen / columnCount); - } - int partLen = ElementListUtils.calcContentLength(par, activeNode.position, curPos - 1); - int restLen = ElementListUtils.calcContentLength(par, curPos - 1, par.size() - 1); - int avgRestLen = 0; - if (remParts > 0) { - avgRestLen = restLen / remParts; - } - if (log.isTraceEnabled()) { - log.trace("remaining parts: " + remParts + " rest len: " + restLen - + " avg=" + avgRestLen); - } - double balance = (idealPartLen - partLen) / 1000f; - if (log.isTraceEnabled()) { - log.trace("balance=" + balance); - } - double absBalance = Math.abs(balance); - dem = absBalance; - //Step 1: This does the rough balancing - if (columnCount > 2) { - if (balance > 0) { - //shorter parts are less desired than longer ones - dem = dem * 1.2f; - } - } else { - if (balance < 0) { - //shorter parts are less desired than longer ones - dem = dem * 1.2f; - } - } - //Step 2: This helps keep the trailing parts shorter than the previous ones - dem += (avgRestLen) / 1000f; - - if (activeNode.line >= columnCount) { - //We don't want more columns than available - dem = Double.MAX_VALUE; - } - if (log.isTraceEnabled()) { - log.trace("effective dem=" + dem + " " + totalWidth); - } - return dem; - } -} +/* + * 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.layoutmgr; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.traits.MinOptMax; + +/** + * This is a the breaking algorithm that is responsible for balancing columns in multi-column + * layout. + */ +public class BalancingColumnBreakingAlgorithm extends PageBreakingAlgorithm { + + private Log log = LogFactory.getLog(BalancingColumnBreakingAlgorithm.class); + + private int columnCount; + private int fullLen; + private int idealPartLen; + + public BalancingColumnBreakingAlgorithm(LayoutManager topLevelLM, + PageProvider pageProvider, + PageBreakingLayoutListener layoutListener, + int alignment, int alignmentLast, + MinOptMax footnoteSeparatorLength, + boolean partOverflowRecovery, + int columnCount) { + super(topLevelLM, pageProvider, layoutListener, + alignment, alignmentLast, + footnoteSeparatorLength, partOverflowRecovery, false, false); + this.columnCount = columnCount; + this.considerTooShort = true; //This is important! + } + + /** {@inheritDoc} */ + protected double computeDemerits(KnuthNode activeNode, + KnuthElement element, int fitnessClass, double r) { + double dem = super.computeDemerits(activeNode, element, fitnessClass, r); + if (log.isTraceEnabled()) { + log.trace("original demerit=" + dem + " " + totalWidth + + " line=" + activeNode.line + "/" + columnCount + + " pos=" + activeNode.position + "/" + (par.size() - 1)); + } + int remParts = columnCount - activeNode.line; + int curPos = par.indexOf(element); + if (fullLen == 0) { + fullLen = ElementListUtils.calcContentLength(par, activeNode.position, par.size() - 1); + this.idealPartLen = (fullLen / columnCount); + } + int partLen = ElementListUtils.calcContentLength(par, activeNode.position, curPos - 1); + int restLen = ElementListUtils.calcContentLength(par, curPos - 1, par.size() - 1); + int avgRestLen = 0; + if (remParts > 0) { + avgRestLen = restLen / remParts; + } + if (log.isTraceEnabled()) { + log.trace("remaining parts: " + remParts + " rest len: " + restLen + + " avg=" + avgRestLen); + } + double balance = (idealPartLen - partLen) / 1000f; + if (log.isTraceEnabled()) { + log.trace("balance=" + balance); + } + double absBalance = Math.abs(balance); + dem = absBalance; + //Step 1: This does the rough balancing + if (columnCount > 2) { + if (balance > 0) { + //shorter parts are less desired than longer ones + dem = dem * 1.2f; + } + } else { + if (balance < 0) { + //shorter parts are less desired than longer ones + dem = dem * 1.2f; + } + } + //Step 2: This helps keep the trailing parts shorter than the previous ones + dem += (avgRestLen) / 1000f; + + if (activeNode.line >= columnCount) { + //We don't want more columns than available + dem = Double.MAX_VALUE; + } + if (log.isTraceEnabled()) { + log.trace("effective dem=" + dem + " " + totalWidth); + } + return dem; + } +} diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index 72dae25c3..09e22d481 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -1,81 +1,81 @@ -/* - * 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.layoutmgr.inline; - -import org.apache.fop.area.inline.InlineArea; -import org.apache.fop.fo.flow.Wrapper; -import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.TraitSetter; - -/** - * This is the layout manager for the fo:wrapper formatting object. - */ -public class WrapperLayoutManager extends LeafNodeLayoutManager { - - private Wrapper fobj; - - /** - * Creates a new LM for fo:wrapper. - * @param node the fo:wrapper - */ - public WrapperLayoutManager(Wrapper node) { - super(node); - fobj = node; - } - - /** {@inheritDoc} */ - public InlineArea get(LayoutContext context) { - // Create a zero-width, zero-height dummy area so this node can - // participate in the ID handling. Otherwise, addId() wouldn't - // be called. The area must also be added to the tree, because - // determination of the X,Y position is done in the renderer. - InlineArea area = new InlineArea(); - if (fobj.hasId()) { - TraitSetter.setProducerID(area, fobj.getId()); - } - return area; - } - - /** - * Add the area for this layout manager. - * This adds the dummy area to the parent, *if* it has an id - * - otherwise it serves no purpose. - * - * @param posIter the position iterator - * @param context the layout context for adding the area - */ - public void addAreas(PositionIterator posIter, LayoutContext context) { - if (fobj.hasId()) { - addId(); - InlineArea area = getEffectiveArea(); - parentLM.addChildArea(area); - } - while (posIter.hasNext()) { - posIter.next(); - } - } - - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - -} +/* + * 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.layoutmgr.inline; + +import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.fo.flow.Wrapper; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.TraitSetter; + +/** + * This is the layout manager for the fo:wrapper formatting object. + */ +public class WrapperLayoutManager extends LeafNodeLayoutManager { + + private Wrapper fobj; + + /** + * Creates a new LM for fo:wrapper. + * @param node the fo:wrapper + */ + public WrapperLayoutManager(Wrapper node) { + super(node); + fobj = node; + } + + /** {@inheritDoc} */ + public InlineArea get(LayoutContext context) { + // Create a zero-width, zero-height dummy area so this node can + // participate in the ID handling. Otherwise, addId() wouldn't + // be called. The area must also be added to the tree, because + // determination of the X,Y position is done in the renderer. + InlineArea area = new InlineArea(); + if (fobj.hasId()) { + TraitSetter.setProducerID(area, fobj.getId()); + } + return area; + } + + /** + * Add the area for this layout manager. + * This adds the dummy area to the parent, *if* it has an id + * - otherwise it serves no purpose. + * + * @param posIter the position iterator + * @param context the layout context for adding the area + */ + public void addAreas(PositionIterator posIter, LayoutContext context) { + if (fobj.hasId()) { + addId(); + InlineArea area = getEffectiveArea(); + parentLM.addChildArea(area); + } + while (posIter.hasNext()) { + posIter.next(); + } + } + + /** {@inheritDoc} */ + protected void addId() { + getPSLM().addIDToPage(fobj.getId()); + } + +} diff --git a/src/java/org/apache/fop/render/AbstractFOEventHandlerMaker.java b/src/java/org/apache/fop/render/AbstractFOEventHandlerMaker.java index ffa76dff4..b122db56f 100644 --- a/src/java/org/apache/fop/render/AbstractFOEventHandlerMaker.java +++ b/src/java/org/apache/fop/render/AbstractFOEventHandlerMaker.java @@ -1,69 +1,69 @@ -/* - * 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.render; - -import java.io.OutputStream; - -import org.apache.fop.apps.FOPException; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.fo.FOEventHandler; - -/** - * Base class for factory classes which instantiate FOEventHandlers and provide information - * about them. - */ -public abstract class AbstractFOEventHandlerMaker { - - /** - * Instantiates a new FOEventHandler. - * @param ua the user agent - * @param out OutputStream for the FOEventHandler to use - * @return the newly instantiated FOEventHandler - * @throws FOPException if a problem occurs while creating the event handler - */ - public abstract FOEventHandler makeFOEventHandler(FOUserAgent ua, OutputStream out) - throws FOPException; - - /** - * @return Indicates whether this renderer requires an OutputStream to work with. - */ - public abstract boolean needsOutputStream(); - - /** - * @return an array of MIME types the renderer supports. - */ - public abstract String[] getSupportedMimeTypes(); - - /** - * Indicates whether a specific MIME type is supported by this renderer. - * @param mimeType the MIME type (ex. "application/rtf") - * @return true if the MIME type is supported - */ - public boolean isMimeTypeSupported(String mimeType) { - String[] mimes = getSupportedMimeTypes(); - for (int i = 0; i < mimes.length; i++) { - if (mimes[i].equals(mimeType)) { - return true; - } - } - return false; - } - -} +/* + * 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.render; + +import java.io.OutputStream; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.fo.FOEventHandler; + +/** + * Base class for factory classes which instantiate FOEventHandlers and provide information + * about them. + */ +public abstract class AbstractFOEventHandlerMaker { + + /** + * Instantiates a new FOEventHandler. + * @param ua the user agent + * @param out OutputStream for the FOEventHandler to use + * @return the newly instantiated FOEventHandler + * @throws FOPException if a problem occurs while creating the event handler + */ + public abstract FOEventHandler makeFOEventHandler(FOUserAgent ua, OutputStream out) + throws FOPException; + + /** + * @return Indicates whether this renderer requires an OutputStream to work with. + */ + public abstract boolean needsOutputStream(); + + /** + * @return an array of MIME types the renderer supports. + */ + public abstract String[] getSupportedMimeTypes(); + + /** + * Indicates whether a specific MIME type is supported by this renderer. + * @param mimeType the MIME type (ex. "application/rtf") + * @return true if the MIME type is supported + */ + public boolean isMimeTypeSupported(String mimeType) { + String[] mimes = getSupportedMimeTypes(); + for (int i = 0; i < mimes.length; i++) { + if (mimes[i].equals(mimeType)) { + return true; + } + } + return false; + } + +} diff --git a/src/java/org/apache/fop/render/AbstractRendererConfigurator.java b/src/java/org/apache/fop/render/AbstractRendererConfigurator.java index 670881643..d6851c3c5 100644 --- a/src/java/org/apache/fop/render/AbstractRendererConfigurator.java +++ b/src/java/org/apache/fop/render/AbstractRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render; diff --git a/src/java/org/apache/fop/render/AbstractRendererMaker.java b/src/java/org/apache/fop/render/AbstractRendererMaker.java index ab1ddb338..381d2e134 100644 --- a/src/java/org/apache/fop/render/AbstractRendererMaker.java +++ b/src/java/org/apache/fop/render/AbstractRendererMaker.java @@ -1,71 +1,71 @@ -/* - * 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.render; - -import org.apache.fop.apps.FOUserAgent; - -/** - * Base class for factory classes which instantiate Renderers and provide information - * about them. - */ -public abstract class AbstractRendererMaker { - - /** - * Instantiates a new renderer. - * @param userAgent the user agent - * @return the newly instantiated renderer - */ - public abstract Renderer makeRenderer(FOUserAgent userAgent); - - /** - * @return Indicates whether this renderer requires an OutputStream to work with. - */ - public abstract boolean needsOutputStream(); - - /** - * @return an array of MIME types the renderer supports. - */ - public abstract String[] getSupportedMimeTypes(); - - /** - * Returns a renderer config object that can be used to - * configure the renderer. - * @param userAgent user agent - * @return a config object that can be used to configure the renderer - */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return null; - } - - /** - * Indicates whether a specific MIME type is supported by this renderer. - * @param mimeType the MIME type (ex. "application/pdf") - * @return true if the MIME type is supported - */ - public boolean isMimeTypeSupported(String mimeType) { - String[] mimes = getSupportedMimeTypes(); - for (int i = 0; i < mimes.length; i++) { - if (mimes[i].equals(mimeType)) { - return true; - } - } - return false; - } -} +/* + * 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.render; + +import org.apache.fop.apps.FOUserAgent; + +/** + * Base class for factory classes which instantiate Renderers and provide information + * about them. + */ +public abstract class AbstractRendererMaker { + + /** + * Instantiates a new renderer. + * @param userAgent the user agent + * @return the newly instantiated renderer + */ + public abstract Renderer makeRenderer(FOUserAgent userAgent); + + /** + * @return Indicates whether this renderer requires an OutputStream to work with. + */ + public abstract boolean needsOutputStream(); + + /** + * @return an array of MIME types the renderer supports. + */ + public abstract String[] getSupportedMimeTypes(); + + /** + * Returns a renderer config object that can be used to + * configure the renderer. + * @param userAgent user agent + * @return a config object that can be used to configure the renderer + */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return null; + } + + /** + * Indicates whether a specific MIME type is supported by this renderer. + * @param mimeType the MIME type (ex. "application/pdf") + * @return true if the MIME type is supported + */ + public boolean isMimeTypeSupported(String mimeType) { + String[] mimes = getSupportedMimeTypes(); + for (int i = 0; i < mimes.length; i++) { + if (mimes[i].equals(mimeType)) { + return true; + } + } + return false; + } +} diff --git a/src/java/org/apache/fop/render/Graphics2DAdapter.java b/src/java/org/apache/fop/render/Graphics2DAdapter.java index e9b00f103..0123e04a1 100644 --- a/src/java/org/apache/fop/render/Graphics2DAdapter.java +++ b/src/java/org/apache/fop/render/Graphics2DAdapter.java @@ -1,50 +1,50 @@ -/* - * 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.render; - -import java.io.IOException; - -/** - * This interface represents an optional feature that can be provided by - * a renderer. It is exposed by calling the getGraphics2DAdapter() method - * on the renderer. Renderers that support this feature allow painting - * of arbitrary images through a Graphics2D instance. - */ -public interface Graphics2DAdapter { - - /** - * Paints an arbitrary images on a given Graphics2D instance. The renderer - * providing this functionality must set up a Graphics2D instance so that - * the image with the given extents (in mpt) can be painted by the painter - * passed to this method. The Graphics2DImagePainter is then passed this - * Graphics2D instance so the image can be painted. - * @param painter the painter which will paint the actual image - * @param context the renderer context for the current renderer - * @param x X position of the image - * @param y Y position of the image - * @param width width of the image - * @param height height of the image - * @throws IOException In case of an I/O error while writing the output format - */ - void paintImage(org.apache.xmlgraphics.java2d.Graphics2DImagePainter painter, - RendererContext context, - int x, int y, int width, int height) throws IOException; - -} +/* + * 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.render; + +import java.io.IOException; + +/** + * This interface represents an optional feature that can be provided by + * a renderer. It is exposed by calling the getGraphics2DAdapter() method + * on the renderer. Renderers that support this feature allow painting + * of arbitrary images through a Graphics2D instance. + */ +public interface Graphics2DAdapter { + + /** + * Paints an arbitrary images on a given Graphics2D instance. The renderer + * providing this functionality must set up a Graphics2D instance so that + * the image with the given extents (in mpt) can be painted by the painter + * passed to this method. The Graphics2DImagePainter is then passed this + * Graphics2D instance so the image can be painted. + * @param painter the painter which will paint the actual image + * @param context the renderer context for the current renderer + * @param x X position of the image + * @param y Y position of the image + * @param width width of the image + * @param height height of the image + * @throws IOException In case of an I/O error while writing the output format + */ + void paintImage(org.apache.xmlgraphics.java2d.Graphics2DImagePainter painter, + RendererContext context, + int x, int y, int width, int height) throws IOException; + +} diff --git a/src/java/org/apache/fop/render/Graphics2DImagePainter.java b/src/java/org/apache/fop/render/Graphics2DImagePainter.java index 9301a6962..0167417fe 100644 --- a/src/java/org/apache/fop/render/Graphics2DImagePainter.java +++ b/src/java/org/apache/fop/render/Graphics2DImagePainter.java @@ -1,30 +1,30 @@ -/* - * 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.render; - -/** - * This interface is used by the Graphics2DAdapter. Components that can paint using - * a Graphics2D instance can implement this interface to paint themselves. - * @deprecated use {@link org.apache.xmlgraphics.java2d.Graphics2DImagePainter} directly! - */ -public interface Graphics2DImagePainter - extends org.apache.xmlgraphics.java2d.Graphics2DImagePainter { - +/* + * 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.render; + +/** + * This interface is used by the Graphics2DAdapter. Components that can paint using + * a Graphics2D instance can implement this interface to paint themselves. + * @deprecated use {@link org.apache.xmlgraphics.java2d.Graphics2DImagePainter} directly! + */ +public interface Graphics2DImagePainter + extends org.apache.xmlgraphics.java2d.Graphics2DImagePainter { + } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/ImageAdapter.java b/src/java/org/apache/fop/render/ImageAdapter.java index 93d6856d7..1984cfa96 100644 --- a/src/java/org/apache/fop/render/ImageAdapter.java +++ b/src/java/org/apache/fop/render/ImageAdapter.java @@ -1,47 +1,47 @@ -/* - * 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.render; - -import java.awt.image.RenderedImage; -import java.io.IOException; - -/** - * This interface represents an optional feature that can be provided by - * a renderer. It is exposed by calling the getImageAdapter() method - * on the renderer. Renderers that support this feature allow painting - * of images (RendererImage instances). - */ -public interface ImageAdapter { - - /** - * Paints an image at the given position. - * @param image the image which will be painted - * @param context the renderer context for the current renderer - * @param x X position of the image - * @param y Y position of the image - * @param width width of the image - * @param height height of the image - * @throws IOException In case of an I/O error while writing the output format - */ - void paintImage(RenderedImage image, - RendererContext context, - int x, int y, int width, int height) throws IOException; - -} +/* + * 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.render; + +import java.awt.image.RenderedImage; +import java.io.IOException; + +/** + * This interface represents an optional feature that can be provided by + * a renderer. It is exposed by calling the getImageAdapter() method + * on the renderer. Renderers that support this feature allow painting + * of images (RendererImage instances). + */ +public interface ImageAdapter { + + /** + * Paints an image at the given position. + * @param image the image which will be painted + * @param context the renderer context for the current renderer + * @param x X position of the image + * @param y Y position of the image + * @param width width of the image + * @param height height of the image + * @throws IOException In case of an I/O error while writing the output format + */ + void paintImage(RenderedImage image, + RendererContext context, + int x, int y, int width, int height) throws IOException; + +} diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index 0f53f2edc..0f0acd60d 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render; diff --git a/src/java/org/apache/fop/render/RendererConfigurator.java b/src/java/org/apache/fop/render/RendererConfigurator.java index 566daf07d..028a4863b 100644 --- a/src/java/org/apache/fop/render/RendererConfigurator.java +++ b/src/java/org/apache/fop/render/RendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render; diff --git a/src/java/org/apache/fop/render/XMLHandlerConfigurator.java b/src/java/org/apache/fop/render/XMLHandlerConfigurator.java index bf63329d7..78822e9c0 100644 --- a/src/java/org/apache/fop/render/XMLHandlerConfigurator.java +++ b/src/java/org/apache/fop/render/XMLHandlerConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render; diff --git a/src/java/org/apache/fop/render/XMLHandlerRegistry.java b/src/java/org/apache/fop/render/XMLHandlerRegistry.java index 0a105262f..533534c4c 100644 --- a/src/java/org/apache/fop/render/XMLHandlerRegistry.java +++ b/src/java/org/apache/fop/render/XMLHandlerRegistry.java @@ -1,166 +1,166 @@ -/* - * 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.render; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.xmlgraphics.util.Service; - -/** - * This class holds references to various XML handlers used by FOP. It also - * supports automatic discovery of additional XML handlers available through - * the class path. - */ -public class XMLHandlerRegistry { - - /** the logger */ - private static Log log = LogFactory.getLog(XMLHandlerRegistry.class); - - /** Map containing XML handlers for various document types */ - private Map handlers = new java.util.HashMap(); - - /** - * Default constructor. - */ - public XMLHandlerRegistry() { - discoverXMLHandlers(); - } - - /** - * Add a default XML handler which is able to handle any namespace. - * @param handler XMLHandler to use - */ - private void setDefaultXMLHandler(XMLHandler handler) { - addXMLHandler(XMLHandler.HANDLE_ALL, handler); - } - - /** - * Add an XML handler. The handler itself is inspected to find out what it supports. - * @param classname the fully qualified class name - */ - public void addXMLHandler(String classname) { - try { - XMLHandler handlerInstance = (XMLHandler)Class.forName(classname).newInstance(); - addXMLHandler(handlerInstance); - } catch (ClassNotFoundException e) { - throw new IllegalArgumentException("Could not find " - + classname); - } catch (InstantiationException e) { - throw new IllegalArgumentException("Could not instantiate " - + classname); - } catch (IllegalAccessException e) { - throw new IllegalArgumentException("Could not access " - + classname); - } catch (ClassCastException e) { - throw new IllegalArgumentException(classname - + " is not an " - + XMLHandler.class.getName()); - } - } - - /** - * Add an XML handler. The handler itself is inspected to find out what it supports. - * @param handler the XMLHandler instance - */ - public void addXMLHandler(XMLHandler handler) { - String ns = handler.getNamespace(); - if (ns == null) { - setDefaultXMLHandler(handler); - } else { - addXMLHandler(ns, handler); - } - } - - /** - * Add an XML handler for the given MIME type and XML namespace. - * @param ns Namespace URI - * @param handler XMLHandler to use - */ - private void addXMLHandler(String ns, - XMLHandler handler) { - List lst = (List)handlers.get(ns); - if (lst == null) { - lst = new java.util.ArrayList(); - handlers.put(ns, lst); - } - lst.add(handler); - } - - /** - * Returns an XMLHandler which handles an XML dialect of the given namespace and for - * a specified output format defined by its MIME type. - * @param renderer the Renderer for which to retrieve a Renderer - * @param ns the XML namespace associated with the XML to be rendered - * @return the XMLHandler responsible for handling the XML or null if none is available - */ - public XMLHandler getXMLHandler(Renderer renderer, String ns) { - XMLHandler handler; - - List lst = (List)handlers.get(ns); - handler = getXMLHandler(renderer, lst); - if (handler == null) { - lst = (List)handlers.get(XMLHandler.HANDLE_ALL); - handler = getXMLHandler(renderer, lst); - } - return handler; - } - - private XMLHandler getXMLHandler(Renderer renderer, List lst) { - XMLHandler handler; - if (lst != null) { - for (int i = 0, c = lst.size(); i < c; i++) { - //TODO Maybe add priorities later - handler = (XMLHandler)lst.get(i); - if (handler.supportsRenderer(renderer)) { - return handler; - } - } - } - return null; //No handler found - } - - /** - * Discovers XMLHandler implementations through the classpath and dynamically - * registers them. - */ - private void discoverXMLHandlers() { - // add mappings from available services - Iterator providers = Service.providers(XMLHandler.class); - if (providers != null) { - while (providers.hasNext()) { - XMLHandler handler = (XMLHandler)providers.next(); - try { - if (log.isDebugEnabled()) { - log.debug("Dynamically adding XMLHandler: " + handler.getClass().getName()); - } - addXMLHandler(handler); - } catch (IllegalArgumentException e) { - log.error("Error while adding XMLHandler", e); - } - - } - } - } -} +/* + * 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.render; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.util.Service; + +/** + * This class holds references to various XML handlers used by FOP. It also + * supports automatic discovery of additional XML handlers available through + * the class path. + */ +public class XMLHandlerRegistry { + + /** the logger */ + private static Log log = LogFactory.getLog(XMLHandlerRegistry.class); + + /** Map containing XML handlers for various document types */ + private Map handlers = new java.util.HashMap(); + + /** + * Default constructor. + */ + public XMLHandlerRegistry() { + discoverXMLHandlers(); + } + + /** + * Add a default XML handler which is able to handle any namespace. + * @param handler XMLHandler to use + */ + private void setDefaultXMLHandler(XMLHandler handler) { + addXMLHandler(XMLHandler.HANDLE_ALL, handler); + } + + /** + * Add an XML handler. The handler itself is inspected to find out what it supports. + * @param classname the fully qualified class name + */ + public void addXMLHandler(String classname) { + try { + XMLHandler handlerInstance = (XMLHandler)Class.forName(classname).newInstance(); + addXMLHandler(handlerInstance); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Could not find " + + classname); + } catch (InstantiationException e) { + throw new IllegalArgumentException("Could not instantiate " + + classname); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Could not access " + + classname); + } catch (ClassCastException e) { + throw new IllegalArgumentException(classname + + " is not an " + + XMLHandler.class.getName()); + } + } + + /** + * Add an XML handler. The handler itself is inspected to find out what it supports. + * @param handler the XMLHandler instance + */ + public void addXMLHandler(XMLHandler handler) { + String ns = handler.getNamespace(); + if (ns == null) { + setDefaultXMLHandler(handler); + } else { + addXMLHandler(ns, handler); + } + } + + /** + * Add an XML handler for the given MIME type and XML namespace. + * @param ns Namespace URI + * @param handler XMLHandler to use + */ + private void addXMLHandler(String ns, + XMLHandler handler) { + List lst = (List)handlers.get(ns); + if (lst == null) { + lst = new java.util.ArrayList(); + handlers.put(ns, lst); + } + lst.add(handler); + } + + /** + * Returns an XMLHandler which handles an XML dialect of the given namespace and for + * a specified output format defined by its MIME type. + * @param renderer the Renderer for which to retrieve a Renderer + * @param ns the XML namespace associated with the XML to be rendered + * @return the XMLHandler responsible for handling the XML or null if none is available + */ + public XMLHandler getXMLHandler(Renderer renderer, String ns) { + XMLHandler handler; + + List lst = (List)handlers.get(ns); + handler = getXMLHandler(renderer, lst); + if (handler == null) { + lst = (List)handlers.get(XMLHandler.HANDLE_ALL); + handler = getXMLHandler(renderer, lst); + } + return handler; + } + + private XMLHandler getXMLHandler(Renderer renderer, List lst) { + XMLHandler handler; + if (lst != null) { + for (int i = 0, c = lst.size(); i < c; i++) { + //TODO Maybe add priorities later + handler = (XMLHandler)lst.get(i); + if (handler.supportsRenderer(renderer)) { + return handler; + } + } + } + return null; //No handler found + } + + /** + * Discovers XMLHandler implementations through the classpath and dynamically + * registers them. + */ + private void discoverXMLHandlers() { + // add mappings from available services + Iterator providers = Service.providers(XMLHandler.class); + if (providers != null) { + while (providers.hasNext()) { + XMLHandler handler = (XMLHandler)providers.next(); + try { + if (log.isDebugEnabled()) { + log.debug("Dynamically adding XMLHandler: " + handler.getClass().getName()); + } + addXMLHandler(handler); + } catch (IllegalArgumentException e) { + log.error("Error while adding XMLHandler", e); + } + + } + } + } +} diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java index a64b77d35..3e477e224 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPGraphicsConfiguration.java b/src/java/org/apache/fop/render/afp/AFPGraphicsConfiguration.java index 086308975..1f40b7cfd 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphicsConfiguration.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphicsConfiguration.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPGraphicsDevice.java b/src/java/org/apache/fop/render/afp/AFPGraphicsDevice.java index dd31af9f1..d4c756a5a 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphicsDevice.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphicsDevice.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPInfo.java b/src/java/org/apache/fop/render/afp/AFPInfo.java index cd291da56..026ab4dfe 100644 --- a/src/java/org/apache/fop/render/afp/AFPInfo.java +++ b/src/java/org/apache/fop/render/afp/AFPInfo.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPPageFonts.java b/src/java/org/apache/fop/render/afp/AFPPageFonts.java index 1ca38a58f..e09167ff5 100644 --- a/src/java/org/apache/fop/render/afp/AFPPageFonts.java +++ b/src/java/org/apache/fop/render/afp/AFPPageFonts.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index c0f6a9c6f..9917eec70 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 1506acb4b..13fa62514 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPState.java b/src/java/org/apache/fop/render/afp/AFPState.java index a86d55cf9..7cb37e2f3 100644 --- a/src/java/org/apache/fop/render/afp/AFPState.java +++ b/src/java/org/apache/fop/render/afp/AFPState.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPTextElementBridge.java b/src/java/org/apache/fop/render/afp/AFPTextElementBridge.java index 150cbb236..fc26801ec 100644 --- a/src/java/org/apache/fop/render/afp/AFPTextElementBridge.java +++ b/src/java/org/apache/fop/render/afp/AFPTextElementBridge.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: PSTextElementBridge.java 426576 2006-07-28 15:44:37Z jeremias $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/AFPTextPainter.java b/src/java/org/apache/fop/render/afp/AFPTextPainter.java index 66183080f..850db550a 100644 --- a/src/java/org/apache/fop/render/afp/AFPTextPainter.java +++ b/src/java/org/apache/fop/render/afp/AFPTextPainter.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: PSTextPainter.java 542237 2007-05-28 14:31:24Z jeremias $ */ +/* $Id$ */ package org.apache.fop.render.afp; diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java index cc99295fb..7fdf7cd11 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java @@ -1,121 +1,121 @@ -/* - * 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.render.afp.extensions; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.util.ContentHandlerFactory; -import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -/** - * ContentHandler (parser) for restoring AFPExtension objects from XML. - */ -public class AFPExtensionHandler extends DefaultHandler - implements ContentHandlerFactory.ObjectSource { - - /** Logger instance */ - protected static Log log = LogFactory.getLog(AFPExtensionHandler.class); - - private StringBuffer content = new StringBuffer(); - private Attributes lastAttributes; - - private AFPPageSetup returnedObject; - private ObjectBuiltListener listener; - - /** {@inheritDoc} */ - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { - boolean handled = false; - if (AFPPageSetup.CATEGORY.equals(uri)) { - lastAttributes = attributes; - handled = true; - if (localName.equals(AFPElementMapping.NO_OPERATION) - || localName.equals(AFPElementMapping.TAG_LOGICAL_ELEMENT) - || localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) - || localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) - || localName.equals(AFPElementMapping.PAGE) - || localName.equals(AFPElementMapping.PAGE_GROUP)) { - //handled in endElement - } else { - handled = false; - } - } - if (!handled) { - if (AFPPageSetup.CATEGORY.equals(uri)) { - throw new SAXException("Unhandled element " + localName - + " in namespace: " + uri); - } else { - log.warn("Unhandled element " + localName - + " in namespace: " + uri); - } - } - } - - /** {@inheritDoc} */ - public void endElement(String uri, String localName, String qName) throws SAXException { - if (AFPPageSetup.CATEGORY.equals(uri)) { - this.returnedObject = new AFPPageSetup(localName); - String name = lastAttributes.getValue("name"); - if (name != null) { - returnedObject.setName(name); - } - String value = lastAttributes.getValue("value"); - if (value != null) { - returnedObject.setValue(value); - } - if (content.length() > 0) { - returnedObject.setContent(content.toString()); - content.setLength(0); //Reset text buffer (see characters()) - } - } - } - - /** {@inheritDoc} */ - public void characters(char[] ch, int start, int length) throws SAXException { - content.append(ch, start, length); - } - - /** - * {@inheritDoc} - */ - public void endDocument() throws SAXException { - if (listener != null) { - listener.notifyObjectBuilt(getObject()); - } - } - - /** - * {@inheritDoc} - */ - public Object getObject() { - return returnedObject; - } - - /** - * {@inheritDoc} - */ - public void setObjectBuiltListener(ObjectBuiltListener listen) { - this.listener = listen; - } - -} +/* + * 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.render.afp.extensions; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.util.ContentHandlerFactory; +import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * ContentHandler (parser) for restoring AFPExtension objects from XML. + */ +public class AFPExtensionHandler extends DefaultHandler + implements ContentHandlerFactory.ObjectSource { + + /** Logger instance */ + protected static Log log = LogFactory.getLog(AFPExtensionHandler.class); + + private StringBuffer content = new StringBuffer(); + private Attributes lastAttributes; + + private AFPPageSetup returnedObject; + private ObjectBuiltListener listener; + + /** {@inheritDoc} */ + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + boolean handled = false; + if (AFPPageSetup.CATEGORY.equals(uri)) { + lastAttributes = attributes; + handled = true; + if (localName.equals(AFPElementMapping.NO_OPERATION) + || localName.equals(AFPElementMapping.TAG_LOGICAL_ELEMENT) + || localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) + || localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) + || localName.equals(AFPElementMapping.PAGE) + || localName.equals(AFPElementMapping.PAGE_GROUP)) { + //handled in endElement + } else { + handled = false; + } + } + if (!handled) { + if (AFPPageSetup.CATEGORY.equals(uri)) { + throw new SAXException("Unhandled element " + localName + + " in namespace: " + uri); + } else { + log.warn("Unhandled element " + localName + + " in namespace: " + uri); + } + } + } + + /** {@inheritDoc} */ + public void endElement(String uri, String localName, String qName) throws SAXException { + if (AFPPageSetup.CATEGORY.equals(uri)) { + this.returnedObject = new AFPPageSetup(localName); + String name = lastAttributes.getValue("name"); + if (name != null) { + returnedObject.setName(name); + } + String value = lastAttributes.getValue("value"); + if (value != null) { + returnedObject.setValue(value); + } + if (content.length() > 0) { + returnedObject.setContent(content.toString()); + content.setLength(0); //Reset text buffer (see characters()) + } + } + } + + /** {@inheritDoc} */ + public void characters(char[] ch, int start, int length) throws SAXException { + content.append(ch, start, length); + } + + /** + * {@inheritDoc} + */ + public void endDocument() throws SAXException { + if (listener != null) { + listener.notifyObjectBuilt(getObject()); + } + } + + /** + * {@inheritDoc} + */ + public Object getObject() { + return returnedObject; + } + + /** + * {@inheritDoc} + */ + public void setObjectBuiltListener(ObjectBuiltListener listen) { + this.listener = listen; + } + +} diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandlerFactory.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandlerFactory.java index 4fe5eaab2..efd351c33 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandlerFactory.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandlerFactory.java @@ -1,41 +1,41 @@ -/* - * 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.render.afp.extensions; - -import org.apache.fop.util.ContentHandlerFactory; -import org.xml.sax.ContentHandler; - -/** - * Factory for the ContentHandler that handles serialized AFPPageSetup instances. - */ -public class AFPExtensionHandlerFactory implements ContentHandlerFactory { - - private static final String[] NAMESPACES = new String[] {AFPPageSetup.CATEGORY}; - - /** {@inheritDoc} */ - public String[] getSupportedNamespaces() { - return NAMESPACES; - } - - /** {@inheritDoc} */ - public ContentHandler createContentHandler() { - return new AFPExtensionHandler(); - } -} +/* + * 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.render.afp.extensions; + +import org.apache.fop.util.ContentHandlerFactory; +import org.xml.sax.ContentHandler; + +/** + * Factory for the ContentHandler that handles serialized AFPPageSetup instances. + */ +public class AFPExtensionHandlerFactory implements ContentHandlerFactory { + + private static final String[] NAMESPACES = new String[] {AFPPageSetup.CATEGORY}; + + /** {@inheritDoc} */ + public String[] getSupportedNamespaces() { + return NAMESPACES; + } + + /** {@inheritDoc} */ + public ContentHandler createContentHandler() { + return new AFPExtensionHandler(); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java index 363e5c6e4..cf5aad382 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca; diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java index f9348b81c..e061748ca 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca; diff --git a/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java index fdeb5c418..8fecc0e5b 100644 --- a/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca; diff --git a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java index 45c9f5751..065ca6626 100644 --- a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca; diff --git a/src/java/org/apache/fop/render/afp/modca/PreparedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/PreparedAFPObject.java index 8da724f36..c62577ca6 100644 --- a/src/java/org/apache/fop/render/afp/modca/PreparedAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PreparedAFPObject.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java b/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java index 27a80acc4..c0520fbf1 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java b/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java index 7378a5c07..8f6e55b23 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java index ed10e5456..b064896c7 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java index c96ca2973..88173d6d1 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java index ea4894e84..ba87dad9f 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java index 2c8f68857..4485370b9 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java index b660d5b9a..ccbb537f6 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java index ab30a3d93..1bac5b149 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java index b0dcf9c22..43f0d370d 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java index f7511e54f..e37b4b196 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java index 4cb59e51a..38b81ecd6 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java index e365e4444..40a518c4b 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java index 4bf396d0b..07127c387 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java index 6e1c7abf9..d39e1e167 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java index be244bd06..aeca3e9c5 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java index afa825a84..91597e8e3 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java index 99c2902c0..339902e2c 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java index 8e08d09e2..0cd077567 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java index 9a04139a2..23c0ac73c 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java index 47df7ba14..51153f065 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java index 1750c4348..7033ce92f 100644 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java +++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.afp.modca.goca; diff --git a/src/java/org/apache/fop/render/awt/AWTRendererMaker.java b/src/java/org/apache/fop/render/awt/AWTRendererMaker.java index 77bfd9166..bca4c0817 100644 --- a/src/java/org/apache/fop/render/awt/AWTRendererMaker.java +++ b/src/java/org/apache/fop/render/awt/AWTRendererMaker.java @@ -1,50 +1,50 @@ -/* - * 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.render.awt; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.Renderer; - -/** - * RendererMaker for the AWT Preview Renderer. - */ -public class AWTRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_FOP_AWT_PREVIEW}; - - - /** {@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent ua) { - return new AWTRenderer(); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return false; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.awt; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.Renderer; + +/** + * RendererMaker for the AWT Preview Renderer. + */ +public class AWTRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_FOP_AWT_PREVIEW}; + + + /** {@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent ua) { + return new AWTRenderer(); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return false; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/src/java/org/apache/fop/render/bitmap/MultiFileRenderingUtil.java b/src/java/org/apache/fop/render/bitmap/MultiFileRenderingUtil.java index ca757fccf..7c1c4ee31 100644 --- a/src/java/org/apache/fop/render/bitmap/MultiFileRenderingUtil.java +++ b/src/java/org/apache/fop/render/bitmap/MultiFileRenderingUtil.java @@ -1,75 +1,75 @@ -package org.apache.fop.render.bitmap; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * This utility class helps renderers who generate one file per page, - * like the PNG renderer. - */ -public class MultiFileRenderingUtil { - - /** The file syntax prefix, eg. "page" will output "page1.png" etc */ - private String filePrefix; - - private String fileExtension; - - /** The output directory where images are to be written */ - private File outputDir; - - /** - * Creates a new instance. - *

    - * The file name must not have an extension, or must have extension "png", - * and its last period must not be at the start (empty file prefix). - * @param ext the extension to be used - * @param outputFile the output file or null if there's no such information - */ - public MultiFileRenderingUtil(String ext, File outputFile) { - this.fileExtension = ext; - // the file provided on the command line - if (outputFile == null) { - //No filename information available. Only the first page will be rendered. - outputDir = null; - filePrefix = null; - } else { - outputDir = outputFile.getParentFile(); - - // extracting file name syntax - String s = outputFile.getName(); - int i = s.lastIndexOf("."); - if (i > 0) { - // Make sure that the file extension was "png" - String extension = s.substring(i + 1).toLowerCase(); - if (!ext.equals(extension)) { - throw new IllegalArgumentException("Invalid file extension ('" - + extension + "') specified"); - } - } else if (i == -1) { - i = s.length(); - } else { // i == 0 - throw new IllegalArgumentException("Invalid file name ('" - + s + "') specified"); - } - if (s.charAt(i - 1) == '1') { - i--; // getting rid of the "1" - } - filePrefix = s.substring(0, i); - } - } - - public OutputStream createOutputStream(int pageNumber) throws IOException { - if (filePrefix == null) { - return null; - } else { - File f = new File(outputDir, - filePrefix + (pageNumber + 1) + "." + fileExtension); - OutputStream os = new BufferedOutputStream(new FileOutputStream(f)); - return os; - } - } - -} +package org.apache.fop.render.bitmap; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * This utility class helps renderers who generate one file per page, + * like the PNG renderer. + */ +public class MultiFileRenderingUtil { + + /** The file syntax prefix, eg. "page" will output "page1.png" etc */ + private String filePrefix; + + private String fileExtension; + + /** The output directory where images are to be written */ + private File outputDir; + + /** + * Creates a new instance. + *

    + * The file name must not have an extension, or must have extension "png", + * and its last period must not be at the start (empty file prefix). + * @param ext the extension to be used + * @param outputFile the output file or null if there's no such information + */ + public MultiFileRenderingUtil(String ext, File outputFile) { + this.fileExtension = ext; + // the file provided on the command line + if (outputFile == null) { + //No filename information available. Only the first page will be rendered. + outputDir = null; + filePrefix = null; + } else { + outputDir = outputFile.getParentFile(); + + // extracting file name syntax + String s = outputFile.getName(); + int i = s.lastIndexOf("."); + if (i > 0) { + // Make sure that the file extension was "png" + String extension = s.substring(i + 1).toLowerCase(); + if (!ext.equals(extension)) { + throw new IllegalArgumentException("Invalid file extension ('" + + extension + "') specified"); + } + } else if (i == -1) { + i = s.length(); + } else { // i == 0 + throw new IllegalArgumentException("Invalid file name ('" + + s + "') specified"); + } + if (s.charAt(i - 1) == '1') { + i--; // getting rid of the "1" + } + filePrefix = s.substring(0, i); + } + } + + public OutputStream createOutputStream(int pageNumber) throws IOException { + if (filePrefix == null) { + return null; + } else { + File f = new File(outputDir, + filePrefix + (pageNumber + 1) + "." + fileExtension); + OutputStream os = new BufferedOutputStream(new FileOutputStream(f)); + return os; + } + } + +} diff --git a/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java b/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java index 63b901668..0f4c4c4fb 100644 --- a/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java +++ b/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java @@ -1,57 +1,57 @@ -/* - * 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.render.bitmap; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererConfigurator; -import org.apache.fop.render.java2d.Java2DRendererConfigurator; - -/** - * RendererMaker for the PNG Renderer. - */ -public class PNGRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_PNG}; - - - /** {@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent ua) { - return new PNGRenderer(); - } - - /** {@inheritDoc} */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return new Java2DRendererConfigurator(userAgent); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return true; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.bitmap; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererConfigurator; +import org.apache.fop.render.java2d.Java2DRendererConfigurator; + +/** + * RendererMaker for the PNG Renderer. + */ +public class PNGRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_PNG}; + + + /** {@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent ua) { + return new PNGRenderer(); + } + + /** {@inheritDoc} */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return new Java2DRendererConfigurator(userAgent); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return true; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java b/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java index 14e6734dd..71ad0b286 100644 --- a/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java +++ b/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.bitmap; diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java b/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java index 09af92b05..69463d127 100644 --- a/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java +++ b/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java @@ -1,55 +1,55 @@ -/* - * 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.render.bitmap; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererConfigurator; - -/** - * RendererMaker for the TIFF Renderer. - */ -public class TIFFRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_TIFF}; - - /** {@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent userAgent) { - return new TIFFRenderer(); - } - - /** {@inheritDoc} */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return new TIFFRendererConfigurator(userAgent); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return true; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.bitmap; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererConfigurator; + +/** + * RendererMaker for the TIFF Renderer. + */ +public class TIFFRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_TIFF}; + + /** {@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent userAgent) { + return new TIFFRenderer(); + } + + /** {@inheritDoc} */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return new TIFFRendererConfigurator(userAgent); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return true; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java index 1182fe42d..48feba135 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java @@ -1,82 +1,82 @@ -/* - * 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.render.java2d; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.io.IOException; - -import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; - -import org.apache.fop.render.Graphics2DAdapter; -import org.apache.fop.render.RendererContext; - -/** - * Graphics2DAdapter implementation for Java2D. - */ -public class Java2DGraphics2DAdapter implements Graphics2DAdapter { - - /** {@inheritDoc} */ - public void paintImage(Graphics2DImagePainter painter, - RendererContext context, - int x, int y, int width, int height) throws IOException { - - float fwidth = width / 1000f; - float fheight = height / 1000f; - float fx = x / 1000f; - float fy = y / 1000f; - - // get the 'width' and 'height' attributes of the SVG document - Dimension dim = painter.getImageSize(); - float imw = (float)dim.getWidth() / 1000f; - float imh = (float)dim.getHeight() / 1000f; - - float sx = fwidth / (float)imw; - float sy = fheight / (float)imh; - - Java2DRenderer renderer = (Java2DRenderer)context.getRenderer(); - Java2DGraphicsState state = renderer.state; - - //Create copy and paint on that - Graphics2D g2d = (Graphics2D)state.getGraph().create(); - g2d.setColor(Color.black); - g2d.setBackground(Color.black); - - //TODO Clip to the image area. - - // transform so that the coordinates (0,0) is from the top left - // and positive is down and to the right. (0,0) is where the - // viewBox puts it. - g2d.translate(fx, fy); - AffineTransform at = AffineTransform.getScaleInstance(sx, sy); - if (!at.isIdentity()) { - g2d.transform(at); - } - - Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); - painter.paint(g2d, area); - - g2d.dispose(); - } - -} +/* + * 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.render.java2d; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + +import org.apache.fop.render.Graphics2DAdapter; +import org.apache.fop.render.RendererContext; + +/** + * Graphics2DAdapter implementation for Java2D. + */ +public class Java2DGraphics2DAdapter implements Graphics2DAdapter { + + /** {@inheritDoc} */ + public void paintImage(Graphics2DImagePainter painter, + RendererContext context, + int x, int y, int width, int height) throws IOException { + + float fwidth = width / 1000f; + float fheight = height / 1000f; + float fx = x / 1000f; + float fy = y / 1000f; + + // get the 'width' and 'height' attributes of the SVG document + Dimension dim = painter.getImageSize(); + float imw = (float)dim.getWidth() / 1000f; + float imh = (float)dim.getHeight() / 1000f; + + float sx = fwidth / (float)imw; + float sy = fheight / (float)imh; + + Java2DRenderer renderer = (Java2DRenderer)context.getRenderer(); + Java2DGraphicsState state = renderer.state; + + //Create copy and paint on that + Graphics2D g2d = (Graphics2D)state.getGraph().create(); + g2d.setColor(Color.black); + g2d.setBackground(Color.black); + + //TODO Clip to the image area. + + // transform so that the coordinates (0,0) is from the top left + // and positive is down and to the right. (0,0) is where the + // viewBox puts it. + g2d.translate(fx, fy); + AffineTransform at = AffineTransform.getScaleInstance(sx, sy); + if (!at.isIdentity()) { + g2d.transform(at); + } + + Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); + painter.paint(g2d, area); + + g2d.dispose(); + } + +} diff --git a/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java b/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java index cc8d3d07f..a18f71cc0 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.java2d; diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java index 03b60f316..b9c772dcb 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.pcl; diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererMaker.java b/src/java/org/apache/fop/render/pcl/PCLRendererMaker.java index 025a1cb4b..f18446506 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererMaker.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererMaker.java @@ -1,57 +1,57 @@ -/* - * 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.render.pcl; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererConfigurator; - -/** - * RendererMaker for the PCL Renderer. - */ -public class PCLRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] { - MimeConstants.MIME_PCL, - MimeConstants.MIME_PCL_ALT - }; - - /**{@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent userAgent) { - return new PCLRenderer(); - } - - /** {@inheritDoc} */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return new PCLRendererConfigurator(userAgent); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return true; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } -} +/* + * 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.render.pcl; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererConfigurator; + +/** + * RendererMaker for the PCL Renderer. + */ +public class PCLRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] { + MimeConstants.MIME_PCL, + MimeConstants.MIME_PCL_ALT + }; + + /**{@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent userAgent) { + return new PCLRenderer(); + } + + /** {@inheritDoc} */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return new PCLRendererConfigurator(userAgent); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return true; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } +} diff --git a/src/java/org/apache/fop/render/pcl/extensions/PCLElementMapping.java b/src/java/org/apache/fop/render/pcl/extensions/PCLElementMapping.java index 863140688..1c540718b 100644 --- a/src/java/org/apache/fop/render/pcl/extensions/PCLElementMapping.java +++ b/src/java/org/apache/fop/render/pcl/extensions/PCLElementMapping.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: AFPElementMapping.java 397875 2006-04-28 11:58:33Z manuel $ */ +/* $Id$ */ package org.apache.fop.render.pcl.extensions; diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java index d1e0abd5c..1a121e294 100644 --- a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java @@ -1,130 +1,130 @@ -/* - * 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.render.pdf; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.io.IOException; - -import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; - -import org.apache.fop.render.AbstractGraphics2DAdapter; -import org.apache.fop.render.RendererContext; -import org.apache.fop.render.RendererContext.RendererContextWrapper; -import org.apache.fop.svg.PDFGraphics2D; - -/** - * Graphics2DAdapter implementation for PDF. - */ -public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter { - - private PDFRenderer renderer; - - /** - * Main constructor - * @param renderer the Renderer instance to which this instance belongs - */ - public PDFGraphics2DAdapter(PDFRenderer renderer) { - this.renderer = renderer; - } - - /** {@inheritDoc} */ - public void paintImage(Graphics2DImagePainter painter, - RendererContext context, - int x, int y, int width, int height) throws IOException { - - PDFSVGHandler.PDFInfo pdfInfo = PDFSVGHandler.getPDFInfo(context); - float fwidth = width / 1000f; - float fheight = height / 1000f; - float fx = x / 1000f; - float fy = y / 1000f; - - // get the 'width' and 'height' attributes of the SVG document - Dimension dim = painter.getImageSize(); - float imw = (float)dim.getWidth() / 1000f; - float imh = (float)dim.getHeight() / 1000f; - - float sx = fwidth / (float)imw; - float sy = fheight / (float)imh; - - renderer.saveGraphicsState(); - renderer.setColor(Color.black, false, null); - renderer.setColor(Color.black, true, null); - - //TODO Clip to the image area. - - // transform so that the coordinates (0,0) is from the top left - // and positive is down and to the right. (0,0) is where the - // viewBox puts it. - renderer.currentStream.add(sx + " 0 0 " + sy + " " + fx + " " - + fy + " cm\n"); - - - final boolean textAsShapes = false; - if (pdfInfo.pdfContext == null) { - pdfInfo.pdfContext = pdfInfo.pdfPage; - } - PDFGraphics2D graphics = new PDFGraphics2D(textAsShapes, - pdfInfo.fi, pdfInfo.pdfDoc, - pdfInfo.pdfContext, pdfInfo.pdfPage.referencePDF(), - renderer.currentFontName, - renderer.currentFontSize); - graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); - - AffineTransform transform = new AffineTransform(); - transform.translate(fx, fy); - pdfInfo.pdfState.concatenate(transform); - graphics.setPDFState(pdfInfo.pdfState); - graphics.setOutputStream(pdfInfo.outputStream); - - if (pdfInfo.paintAsBitmap) { - //Fallback solution: Paint to a BufferedImage - int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); - RendererContextWrapper ctx = RendererContext.wrapRendererContext(context); - BufferedImage bi = paintToBufferedImage(painter, ctx, resolution, false, false); - - float scale = PDFRenderer.NORMAL_PDF_RESOLUTION - / context.getUserAgent().getTargetResolution(); - graphics.drawImage(bi, new AffineTransform(scale, 0, 0, scale, 0, 0), null); - } else { - Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); - painter.paint(graphics, area); - } - - pdfInfo.currentStream.add(graphics.getString()); - renderer.restoreGraphicsState(); - pdfInfo.pdfState.pop(); - } - - /** {@inheritDoc} */ - protected void setRenderingHintsForBufferedImage(Graphics2D g2d) { - super.setRenderingHintsForBufferedImage(g2d); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - -} +/* + * 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.render.pdf; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.IOException; + +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + +import org.apache.fop.render.AbstractGraphics2DAdapter; +import org.apache.fop.render.RendererContext; +import org.apache.fop.render.RendererContext.RendererContextWrapper; +import org.apache.fop.svg.PDFGraphics2D; + +/** + * Graphics2DAdapter implementation for PDF. + */ +public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter { + + private PDFRenderer renderer; + + /** + * Main constructor + * @param renderer the Renderer instance to which this instance belongs + */ + public PDFGraphics2DAdapter(PDFRenderer renderer) { + this.renderer = renderer; + } + + /** {@inheritDoc} */ + public void paintImage(Graphics2DImagePainter painter, + RendererContext context, + int x, int y, int width, int height) throws IOException { + + PDFSVGHandler.PDFInfo pdfInfo = PDFSVGHandler.getPDFInfo(context); + float fwidth = width / 1000f; + float fheight = height / 1000f; + float fx = x / 1000f; + float fy = y / 1000f; + + // get the 'width' and 'height' attributes of the SVG document + Dimension dim = painter.getImageSize(); + float imw = (float)dim.getWidth() / 1000f; + float imh = (float)dim.getHeight() / 1000f; + + float sx = fwidth / (float)imw; + float sy = fheight / (float)imh; + + renderer.saveGraphicsState(); + renderer.setColor(Color.black, false, null); + renderer.setColor(Color.black, true, null); + + //TODO Clip to the image area. + + // transform so that the coordinates (0,0) is from the top left + // and positive is down and to the right. (0,0) is where the + // viewBox puts it. + renderer.currentStream.add(sx + " 0 0 " + sy + " " + fx + " " + + fy + " cm\n"); + + + final boolean textAsShapes = false; + if (pdfInfo.pdfContext == null) { + pdfInfo.pdfContext = pdfInfo.pdfPage; + } + PDFGraphics2D graphics = new PDFGraphics2D(textAsShapes, + pdfInfo.fi, pdfInfo.pdfDoc, + pdfInfo.pdfContext, pdfInfo.pdfPage.referencePDF(), + renderer.currentFontName, + renderer.currentFontSize); + graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); + + AffineTransform transform = new AffineTransform(); + transform.translate(fx, fy); + pdfInfo.pdfState.concatenate(transform); + graphics.setPDFState(pdfInfo.pdfState); + graphics.setOutputStream(pdfInfo.outputStream); + + if (pdfInfo.paintAsBitmap) { + //Fallback solution: Paint to a BufferedImage + int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); + RendererContextWrapper ctx = RendererContext.wrapRendererContext(context); + BufferedImage bi = paintToBufferedImage(painter, ctx, resolution, false, false); + + float scale = PDFRenderer.NORMAL_PDF_RESOLUTION + / context.getUserAgent().getTargetResolution(); + graphics.drawImage(bi, new AffineTransform(scale, 0, 0, scale, 0, 0), null); + } else { + Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); + painter.paint(graphics, area); + } + + pdfInfo.currentStream.add(graphics.getString()); + renderer.restoreGraphicsState(); + pdfInfo.pdfState.pop(); + } + + /** {@inheritDoc} */ + protected void setRenderingHintsForBufferedImage(Graphics2D g2d) { + super.setRenderingHintsForBufferedImage(g2d); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + } + +} diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererMaker.java b/src/java/org/apache/fop/render/pdf/PDFRendererMaker.java index 0e36e177b..98fd7b5db 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererMaker.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererMaker.java @@ -1,55 +1,55 @@ -/* - * 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.render.pdf; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererConfigurator; - -/** - * RendererMaker for the PDF Renderer. - */ -public class PDFRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_PDF}; - - /** {@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent userAgent) { - return new PDFRenderer(); - } - - /** {@inheritDoc} */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return new PDFRendererConfigurator(userAgent); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return true; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.pdf; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererConfigurator; + +/** + * RendererMaker for the PDF Renderer. + */ +public class PDFRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_PDF}; + + /** {@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent userAgent) { + return new PDFRenderer(); + } + + /** {@inheritDoc} */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return new PDFRendererConfigurator(userAgent); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return true; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/src/java/org/apache/fop/render/print/PrintRendererMaker.java b/src/java/org/apache/fop/render/print/PrintRendererMaker.java index 4b0523458..2390567ef 100644 --- a/src/java/org/apache/fop/render/print/PrintRendererMaker.java +++ b/src/java/org/apache/fop/render/print/PrintRendererMaker.java @@ -1,56 +1,56 @@ -/* - * 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.render.print; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.PrintRendererConfigurator; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererConfigurator; - -/** - * RendererMaker for the Print Renderer. - */ -public class PrintRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_FOP_PRINT}; - - /**{@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent userAgent) { - return new PrintRenderer(); - } - - /** {@inheritDoc} */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return new PrintRendererConfigurator(userAgent); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return false; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.print; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.PrintRendererConfigurator; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererConfigurator; + +/** + * RendererMaker for the Print Renderer. + */ +public class PrintRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_FOP_PRINT}; + + /**{@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent userAgent) { + return new PrintRenderer(); + } + + /** {@inheritDoc} */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return new PrintRendererConfigurator(userAgent); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return false; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/src/java/org/apache/fop/render/ps/PSDictionary.java b/src/java/org/apache/fop/render/ps/PSDictionary.java index dbf7173a5..5a8f1ea14 100644 --- a/src/java/org/apache/fop/render/ps/PSDictionary.java +++ b/src/java/org/apache/fop/render/ps/PSDictionary.java @@ -1,312 +1,312 @@ -/* - * 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.render.ps; - -import java.util.Iterator; -import java.util.List; -import java.util.StringTokenizer; - -/** - * This class is used to encapsulate postscript dictionary objects. - */ -public class PSDictionary extends java.util.HashMap { - - private static final long serialVersionUID = 815367222496219197L; - - /** - * This class is used to parse dictionary strings. - */ - private static class Maker { - - /** - * Simple token holding class - */ - private class Token { - /** - * start index in string - */ - private int startIndex = -1; - - /** - * end index in string - */ - private int endIndex = -1; - - /** - * token string value - */ - private String value; - } - - private static final String[][] BRACES = { - {"<<", ">>"}, - {"[", "]"}, - {"{", "}"} - }; - - private static final int OPENING = 0; - private static final int CLOSING = 1; - private static final int DICTIONARY = 0; - private static final int ARRAY = 1; - private static final int PROCEDURE = 2; - - /** - * Returns a Token containing the start, end index and value of the next token - * found in a given string - * - * @param str - * string to search - * @param fromIndex - * search from index - * @return Token containing the start, end index and value of the next token - */ - protected Token nextToken(String str, int fromIndex) { - Token t = null; - for (int i = fromIndex; i < str.length(); i++) { - boolean isWhitespace = Character.isWhitespace(str.charAt(i)); - // start index found - if (t == null && !isWhitespace) { - t = new Token(); - t.startIndex = i; - // end index found - } else if (t != null && isWhitespace) { - t.endIndex = i; - break; - } - } - // start index found - if (t != null) { - // end index not found so take end of string - if (t.endIndex == -1) { - t.endIndex = str.length(); - } - t.value = str.substring(t.startIndex, t.endIndex); - } - return t; - } - - /** - * Returns the closing brace index from a given string searches from a - * given index - * - * @param str - * string to search - * @param braces - * string array of opening and closing brace - * @param fromIndex - * searches from index - * @return matching brace index - * @throws org.apache.fop.render.ps.PSDictionaryFormatException - * thrown in the event that a parsing error occurred - */ - private int indexOfMatchingBrace(String str, String[] braces, - int fromIndex) throws PSDictionaryFormatException { - final int len = str.length(); - if (braces.length != 2) { - throw new PSDictionaryFormatException("Wrong number of braces"); - } - for (int openCnt = 0, closeCnt = 0; fromIndex < len; fromIndex++) { - if (str.startsWith(braces[OPENING], fromIndex)) { - openCnt++; - } else if (str.startsWith(braces[CLOSING], fromIndex)) { - closeCnt++; - if (openCnt > 0 && openCnt == closeCnt) { - return fromIndex; // found - } - } - } - return -1; // not found - } - - /** - * Strips braces from complex object string - * - * @param str - * String to parse - * @param braces - * String array containing opening and closing braces - * @return String with braces stripped - * @throws - * org.apache.fop.render.ps.PSDictionaryFormatException object format exception - */ - private String stripBraces(String str, String[] braces) throws PSDictionaryFormatException { - // find first opening brace - int firstIndex = str.indexOf(braces[OPENING]); - if (firstIndex == -1) { - throw new PSDictionaryFormatException( - "Failed to find opening parameter '" + braces[OPENING] - + ""); - } - - // find last matching brace - int lastIndex = indexOfMatchingBrace(str, braces, firstIndex); - if (lastIndex == -1) { - throw new PSDictionaryFormatException( - "Failed to find matching closing parameter '" - + braces[CLOSING] + "'"); - } - - // strip brace and trim - int braceLen = braces[OPENING].length(); - str = str.substring(firstIndex + braceLen, lastIndex).trim(); - return str; - } - - /** - * Parses a dictionary string and provides a dictionary object - * - * @param str a dictionary string - * @return A postscript dictionary object - * @throws - * PSDictionaryFormatException thrown if a dictionary format exception occurs - */ - public PSDictionary parseDictionary(String str) throws PSDictionaryFormatException { - PSDictionary dictionary = new PSDictionary(); - str = stripBraces(str.trim(), BRACES[DICTIONARY]); - // length of dictionary string - final int len = str.length(); - - Token keyToken; - for (int currIndex = 0; (keyToken = nextToken(str, currIndex)) != null - && currIndex <= len;) { - if (keyToken.value == null) { - throw new PSDictionaryFormatException("Failed to parse object key"); - } - Token valueToken = nextToken(str, keyToken.endIndex + 1); - String[] braces = null; - for (int i = 0; i < BRACES.length; i++) { - if (valueToken.value.startsWith(BRACES[i][OPENING])) { - braces = BRACES[i]; - break; - } - } - Object obj = null; - if (braces != null) { - // find closing brace - valueToken.endIndex = indexOfMatchingBrace(str, braces, - valueToken.startIndex) - + braces[OPENING].length(); - if (valueToken.endIndex < 0) { - throw new PSDictionaryFormatException("Closing value brace '" - + braces[CLOSING] + "' not found for key '" - + keyToken.value + "'"); - } - valueToken.value = str.substring(valueToken.startIndex, valueToken.endIndex); - } - if (braces == null || braces == BRACES[PROCEDURE]) { - obj = valueToken.value; - } else if (BRACES[ARRAY] == braces) { - List objList = new java.util.ArrayList(); - String objString = stripBraces(valueToken.value, braces); - StringTokenizer tokenizer = new StringTokenizer(objString, ","); - while (tokenizer.hasMoreTokens()) { - objList.add(tokenizer.nextToken()); - } - obj = objList; - } else if (BRACES[DICTIONARY] == braces) { - obj = parseDictionary(valueToken.value); - } - dictionary.put(keyToken.value, obj); - currIndex = valueToken.endIndex + 1; - } - return dictionary; - } - } - - /** - * Parses a given a dictionary string and returns an object - * - * @param str dictionary string - * @return dictionary object - * @throws PSDictionaryFormatException object format exception - */ - public static PSDictionary valueOf(String str) throws PSDictionaryFormatException { - return (new Maker()).parseDictionary(str); - } - - /** - * @param obj object to test equality against - * @return whether a given object is equal to this dictionary object - * @see java.lang.Object#equals(Object) - */ - public boolean equals(Object obj) { - if (!(obj instanceof PSPageDeviceDictionary)) { - return false; - } - PSDictionary dictionaryObj = (PSDictionary) obj; - if (dictionaryObj.size() != size()) { - return false; - } - for (Iterator it = keySet().iterator(); it.hasNext();) { - String key = (String) it.next(); - if (!dictionaryObj.containsKey(key)) { - return false; - } - if (!dictionaryObj.get(key).equals(get(key))) { - return false; - } - } - return true; - } - - /** - * @return a hash code value for this object. - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - int hashCode = 7; - for (Iterator it = values().iterator(); it.hasNext();) { - Object value = it.next(); - hashCode += value.hashCode(); - } - return hashCode; - } - - /** - * @return a string representation of this dictionary - * @see java.lang.String#toString() - */ - public String toString() { - if (isEmpty()) { - return ""; - } - StringBuffer sb = new StringBuffer("<<\n"); - for (Iterator it = super.keySet().iterator(); it.hasNext();) { - String key = (String) it.next(); - sb.append(" " + key + " "); - Object obj = super.get(key); - if (obj instanceof java.util.ArrayList) { - List array = (List)obj; - String str = "["; - for (int i = 0; i < array.size(); i++) { - Object element = array.get(i); - str += element + " "; - } - str = str.trim(); - str += "]"; - sb.append(str + "\n"); - } else { - sb.append(obj.toString() + "\n"); - } - } - sb.append(">>"); - return sb.toString(); - } -} +/* + * 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.render.ps; + +import java.util.Iterator; +import java.util.List; +import java.util.StringTokenizer; + +/** + * This class is used to encapsulate postscript dictionary objects. + */ +public class PSDictionary extends java.util.HashMap { + + private static final long serialVersionUID = 815367222496219197L; + + /** + * This class is used to parse dictionary strings. + */ + private static class Maker { + + /** + * Simple token holding class + */ + private class Token { + /** + * start index in string + */ + private int startIndex = -1; + + /** + * end index in string + */ + private int endIndex = -1; + + /** + * token string value + */ + private String value; + } + + private static final String[][] BRACES = { + {"<<", ">>"}, + {"[", "]"}, + {"{", "}"} + }; + + private static final int OPENING = 0; + private static final int CLOSING = 1; + private static final int DICTIONARY = 0; + private static final int ARRAY = 1; + private static final int PROCEDURE = 2; + + /** + * Returns a Token containing the start, end index and value of the next token + * found in a given string + * + * @param str + * string to search + * @param fromIndex + * search from index + * @return Token containing the start, end index and value of the next token + */ + protected Token nextToken(String str, int fromIndex) { + Token t = null; + for (int i = fromIndex; i < str.length(); i++) { + boolean isWhitespace = Character.isWhitespace(str.charAt(i)); + // start index found + if (t == null && !isWhitespace) { + t = new Token(); + t.startIndex = i; + // end index found + } else if (t != null && isWhitespace) { + t.endIndex = i; + break; + } + } + // start index found + if (t != null) { + // end index not found so take end of string + if (t.endIndex == -1) { + t.endIndex = str.length(); + } + t.value = str.substring(t.startIndex, t.endIndex); + } + return t; + } + + /** + * Returns the closing brace index from a given string searches from a + * given index + * + * @param str + * string to search + * @param braces + * string array of opening and closing brace + * @param fromIndex + * searches from index + * @return matching brace index + * @throws org.apache.fop.render.ps.PSDictionaryFormatException + * thrown in the event that a parsing error occurred + */ + private int indexOfMatchingBrace(String str, String[] braces, + int fromIndex) throws PSDictionaryFormatException { + final int len = str.length(); + if (braces.length != 2) { + throw new PSDictionaryFormatException("Wrong number of braces"); + } + for (int openCnt = 0, closeCnt = 0; fromIndex < len; fromIndex++) { + if (str.startsWith(braces[OPENING], fromIndex)) { + openCnt++; + } else if (str.startsWith(braces[CLOSING], fromIndex)) { + closeCnt++; + if (openCnt > 0 && openCnt == closeCnt) { + return fromIndex; // found + } + } + } + return -1; // not found + } + + /** + * Strips braces from complex object string + * + * @param str + * String to parse + * @param braces + * String array containing opening and closing braces + * @return String with braces stripped + * @throws + * org.apache.fop.render.ps.PSDictionaryFormatException object format exception + */ + private String stripBraces(String str, String[] braces) throws PSDictionaryFormatException { + // find first opening brace + int firstIndex = str.indexOf(braces[OPENING]); + if (firstIndex == -1) { + throw new PSDictionaryFormatException( + "Failed to find opening parameter '" + braces[OPENING] + + ""); + } + + // find last matching brace + int lastIndex = indexOfMatchingBrace(str, braces, firstIndex); + if (lastIndex == -1) { + throw new PSDictionaryFormatException( + "Failed to find matching closing parameter '" + + braces[CLOSING] + "'"); + } + + // strip brace and trim + int braceLen = braces[OPENING].length(); + str = str.substring(firstIndex + braceLen, lastIndex).trim(); + return str; + } + + /** + * Parses a dictionary string and provides a dictionary object + * + * @param str a dictionary string + * @return A postscript dictionary object + * @throws + * PSDictionaryFormatException thrown if a dictionary format exception occurs + */ + public PSDictionary parseDictionary(String str) throws PSDictionaryFormatException { + PSDictionary dictionary = new PSDictionary(); + str = stripBraces(str.trim(), BRACES[DICTIONARY]); + // length of dictionary string + final int len = str.length(); + + Token keyToken; + for (int currIndex = 0; (keyToken = nextToken(str, currIndex)) != null + && currIndex <= len;) { + if (keyToken.value == null) { + throw new PSDictionaryFormatException("Failed to parse object key"); + } + Token valueToken = nextToken(str, keyToken.endIndex + 1); + String[] braces = null; + for (int i = 0; i < BRACES.length; i++) { + if (valueToken.value.startsWith(BRACES[i][OPENING])) { + braces = BRACES[i]; + break; + } + } + Object obj = null; + if (braces != null) { + // find closing brace + valueToken.endIndex = indexOfMatchingBrace(str, braces, + valueToken.startIndex) + + braces[OPENING].length(); + if (valueToken.endIndex < 0) { + throw new PSDictionaryFormatException("Closing value brace '" + + braces[CLOSING] + "' not found for key '" + + keyToken.value + "'"); + } + valueToken.value = str.substring(valueToken.startIndex, valueToken.endIndex); + } + if (braces == null || braces == BRACES[PROCEDURE]) { + obj = valueToken.value; + } else if (BRACES[ARRAY] == braces) { + List objList = new java.util.ArrayList(); + String objString = stripBraces(valueToken.value, braces); + StringTokenizer tokenizer = new StringTokenizer(objString, ","); + while (tokenizer.hasMoreTokens()) { + objList.add(tokenizer.nextToken()); + } + obj = objList; + } else if (BRACES[DICTIONARY] == braces) { + obj = parseDictionary(valueToken.value); + } + dictionary.put(keyToken.value, obj); + currIndex = valueToken.endIndex + 1; + } + return dictionary; + } + } + + /** + * Parses a given a dictionary string and returns an object + * + * @param str dictionary string + * @return dictionary object + * @throws PSDictionaryFormatException object format exception + */ + public static PSDictionary valueOf(String str) throws PSDictionaryFormatException { + return (new Maker()).parseDictionary(str); + } + + /** + * @param obj object to test equality against + * @return whether a given object is equal to this dictionary object + * @see java.lang.Object#equals(Object) + */ + public boolean equals(Object obj) { + if (!(obj instanceof PSPageDeviceDictionary)) { + return false; + } + PSDictionary dictionaryObj = (PSDictionary) obj; + if (dictionaryObj.size() != size()) { + return false; + } + for (Iterator it = keySet().iterator(); it.hasNext();) { + String key = (String) it.next(); + if (!dictionaryObj.containsKey(key)) { + return false; + } + if (!dictionaryObj.get(key).equals(get(key))) { + return false; + } + } + return true; + } + + /** + * @return a hash code value for this object. + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + int hashCode = 7; + for (Iterator it = values().iterator(); it.hasNext();) { + Object value = it.next(); + hashCode += value.hashCode(); + } + return hashCode; + } + + /** + * @return a string representation of this dictionary + * @see java.lang.String#toString() + */ + public String toString() { + if (isEmpty()) { + return ""; + } + StringBuffer sb = new StringBuffer("<<\n"); + for (Iterator it = super.keySet().iterator(); it.hasNext();) { + String key = (String) it.next(); + sb.append(" " + key + " "); + Object obj = super.get(key); + if (obj instanceof java.util.ArrayList) { + List array = (List)obj; + String str = "["; + for (int i = 0; i < array.size(); i++) { + Object element = array.get(i); + str += element + " "; + } + str = str.trim(); + str += "]"; + sb.append(str + "\n"); + } else { + sb.append(obj.toString() + "\n"); + } + } + sb.append(">>"); + return sb.toString(); + } +} diff --git a/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java b/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java index 2153e8116..1a0171d68 100644 --- a/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java +++ b/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java @@ -1,37 +1,37 @@ -/* - * 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.render.ps; - -/** - * Thrown to indicate that a formatting error has occured when - * trying to parse a postscript dictionary object - */ -public class PSDictionaryFormatException extends Exception { - - private static final long serialVersionUID = 6492321557297860931L; - - /** - * Default constructor - * @param string error message - */ - public PSDictionaryFormatException(String string) { - super(string); - } -} +/* + * 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.render.ps; + +/** + * Thrown to indicate that a formatting error has occured when + * trying to parse a postscript dictionary object + */ +public class PSDictionaryFormatException extends Exception { + + private static final long serialVersionUID = 6492321557297860931L; + + /** + * Default constructor + * @param string error message + */ + public PSDictionaryFormatException(String string) { + super(string); + } +} diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java index 787af69a1..a592b4f44 100644 --- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java @@ -1,105 +1,105 @@ -/* - * 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.render.ps; - -import java.awt.Dimension; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.io.IOException; - -import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.ps.PSGenerator; - -import org.apache.fop.render.Graphics2DAdapter; -import org.apache.fop.render.RendererContext; - -/** - * Graphics2DAdapter implementation for PostScript. - */ -public class PSGraphics2DAdapter implements Graphics2DAdapter { - - private PSGenerator gen; - private boolean clip = true; - - /** - * Main constructor - * @param renderer the Renderer instance to which this instance belongs - */ - public PSGraphics2DAdapter(PSRenderer renderer) { - this(renderer.gen, true); - } - - /** - * Constructor for use without a PSRenderer instance. - * @param gen the PostScript generator - * @param clip true if the image should be clipped - */ - public PSGraphics2DAdapter(PSGenerator gen, boolean clip) { - this.gen = gen; - this.clip = clip; - } - - /** {@inheritDoc} */ - public void paintImage(Graphics2DImagePainter painter, - RendererContext context, - int x, int y, int width, int height) throws IOException { - float fwidth = width / 1000f; - float fheight = height / 1000f; - float fx = x / 1000f; - float fy = y / 1000f; - - // get the 'width' and 'height' attributes of the SVG document - Dimension dim = painter.getImageSize(); - float imw = (float)dim.getWidth() / 1000f; - float imh = (float)dim.getHeight() / 1000f; - - float sx = fwidth / (float)imw; - float sy = fheight / (float)imh; - - gen.commentln("%FOPBeginGraphics2D"); - gen.saveGraphicsState(); - if (clip) { - // Clip to the image area. - gen.writeln("newpath"); - gen.defineRect(fx, fy, fwidth, fheight); - gen.writeln("clip"); - } - - // transform so that the coordinates (0,0) is from the top left - // and positive is down and to the right. (0,0) is where the - // viewBox puts it. - gen.concatMatrix(sx, 0, 0, sy, fx, fy); - - final boolean textAsShapes = false; - PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen); - graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); - AffineTransform transform = new AffineTransform(); - // scale to viewbox - transform.translate(fx, fy); - gen.getCurrentState().concatMatrix(transform); - Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); - painter.paint(graphics, area); - - gen.restoreGraphicsState(); - gen.commentln("%FOPEndGraphics2D"); - } - -} +/* + * 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.render.ps; + +import java.awt.Dimension; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.ps.PSGenerator; + +import org.apache.fop.render.Graphics2DAdapter; +import org.apache.fop.render.RendererContext; + +/** + * Graphics2DAdapter implementation for PostScript. + */ +public class PSGraphics2DAdapter implements Graphics2DAdapter { + + private PSGenerator gen; + private boolean clip = true; + + /** + * Main constructor + * @param renderer the Renderer instance to which this instance belongs + */ + public PSGraphics2DAdapter(PSRenderer renderer) { + this(renderer.gen, true); + } + + /** + * Constructor for use without a PSRenderer instance. + * @param gen the PostScript generator + * @param clip true if the image should be clipped + */ + public PSGraphics2DAdapter(PSGenerator gen, boolean clip) { + this.gen = gen; + this.clip = clip; + } + + /** {@inheritDoc} */ + public void paintImage(Graphics2DImagePainter painter, + RendererContext context, + int x, int y, int width, int height) throws IOException { + float fwidth = width / 1000f; + float fheight = height / 1000f; + float fx = x / 1000f; + float fy = y / 1000f; + + // get the 'width' and 'height' attributes of the SVG document + Dimension dim = painter.getImageSize(); + float imw = (float)dim.getWidth() / 1000f; + float imh = (float)dim.getHeight() / 1000f; + + float sx = fwidth / (float)imw; + float sy = fheight / (float)imh; + + gen.commentln("%FOPBeginGraphics2D"); + gen.saveGraphicsState(); + if (clip) { + // Clip to the image area. + gen.writeln("newpath"); + gen.defineRect(fx, fy, fwidth, fheight); + gen.writeln("clip"); + } + + // transform so that the coordinates (0,0) is from the top left + // and positive is down and to the right. (0,0) is where the + // viewBox puts it. + gen.concatMatrix(sx, 0, 0, sy, fx, fy); + + final boolean textAsShapes = false; + PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen); + graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); + AffineTransform transform = new AffineTransform(); + // scale to viewbox + transform.translate(fx, fy); + gen.getCurrentState().concatMatrix(transform); + Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); + painter.paint(graphics, area); + + gen.restoreGraphicsState(); + gen.commentln("%FOPEndGraphics2D"); + } + +} diff --git a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java b/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java index c327423ef..88667c24d 100644 --- a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java +++ b/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java @@ -1,110 +1,110 @@ -/* - * 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.render.ps; - -/** - * Postscript page device dictionary object - * - * This object is used by the postscript renderer to hold postscript page device - * values. It can also be used to minimize the number of setpagedevice calls when - * DSC compliance is false. - */ -public class PSPageDeviceDictionary extends PSDictionary { - - private static final long serialVersionUID = 845943256485806509L; - - /** - * Whether or not the contents of the dictionary are flushed on retrieval - */ - private boolean flushOnRetrieval = false; - - /** - * Dictionary content that has not been output/written yet - */ - private PSDictionary unRetrievedContentDictionary; - - /** - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. - * @return the previous value associated with the key or null - * @see java.util.Map#put(Object, Object) - */ - public Object put(Object key, Object value) { - Object previousValue = super.put(key, value); - if (flushOnRetrieval) { - if (previousValue == null || !previousValue.equals(value)) { - unRetrievedContentDictionary.put(key, value); - } - } - return previousValue; - } - - /** - * @see java.util.Map#clear() - */ - public void clear() { - super.clear(); - if (unRetrievedContentDictionary != null) { - unRetrievedContentDictionary.clear(); - } - } - - /** - * Returns true if this map contains no key-value mappings. - * - * @return true if this map contains no key-value mappings. - */ - public boolean isEmpty() { - if (flushOnRetrieval) { - return unRetrievedContentDictionary.isEmpty(); - } - return super.isEmpty(); - } - - /** - * The contents of the dictionary are flushed when written - * @param flushOnRetrieval boolean value - */ - public void setFlushOnRetrieval(boolean flushOnRetrieval) { - this.flushOnRetrieval = flushOnRetrieval; - if (flushOnRetrieval) { - unRetrievedContentDictionary = new PSDictionary(); - } - } - - /** - * Returns a dictionary string with containing all unwritten content note: - * unnecessary writes are important as there is a device specific - * initgraphics call by the underlying postscript interpreter on every - * setpagedevice call which can result in blank pages etc. - * - * @return unwritten content dictionary string - */ - public String getContent() { - String content; - if (flushOnRetrieval) { - content = unRetrievedContentDictionary.toString(); - unRetrievedContentDictionary.clear(); - } else { - content = super.toString(); - } - return content; - } -} +/* + * 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.render.ps; + +/** + * Postscript page device dictionary object + * + * This object is used by the postscript renderer to hold postscript page device + * values. It can also be used to minimize the number of setpagedevice calls when + * DSC compliance is false. + */ +public class PSPageDeviceDictionary extends PSDictionary { + + private static final long serialVersionUID = 845943256485806509L; + + /** + * Whether or not the contents of the dictionary are flushed on retrieval + */ + private boolean flushOnRetrieval = false; + + /** + * Dictionary content that has not been output/written yet + */ + private PSDictionary unRetrievedContentDictionary; + + /** + * @param key key with which the specified value is to be associated. + * @param value value to be associated with the specified key. + * @return the previous value associated with the key or null + * @see java.util.Map#put(Object, Object) + */ + public Object put(Object key, Object value) { + Object previousValue = super.put(key, value); + if (flushOnRetrieval) { + if (previousValue == null || !previousValue.equals(value)) { + unRetrievedContentDictionary.put(key, value); + } + } + return previousValue; + } + + /** + * @see java.util.Map#clear() + */ + public void clear() { + super.clear(); + if (unRetrievedContentDictionary != null) { + unRetrievedContentDictionary.clear(); + } + } + + /** + * Returns true if this map contains no key-value mappings. + * + * @return true if this map contains no key-value mappings. + */ + public boolean isEmpty() { + if (flushOnRetrieval) { + return unRetrievedContentDictionary.isEmpty(); + } + return super.isEmpty(); + } + + /** + * The contents of the dictionary are flushed when written + * @param flushOnRetrieval boolean value + */ + public void setFlushOnRetrieval(boolean flushOnRetrieval) { + this.flushOnRetrieval = flushOnRetrieval; + if (flushOnRetrieval) { + unRetrievedContentDictionary = new PSDictionary(); + } + } + + /** + * Returns a dictionary string with containing all unwritten content note: + * unnecessary writes are important as there is a device specific + * initgraphics call by the underlying postscript interpreter on every + * setpagedevice call which can result in blank pages etc. + * + * @return unwritten content dictionary string + */ + public String getContent() { + String content; + if (flushOnRetrieval) { + content = unRetrievedContentDictionary.toString(); + unRetrievedContentDictionary.clear(); + } else { + content = super.toString(); + } + return content; + } +} diff --git a/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java b/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java index e94d873cb..3ce9751b5 100644 --- a/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java +++ b/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.ps; diff --git a/src/java/org/apache/fop/render/ps/PSRendererMaker.java b/src/java/org/apache/fop/render/ps/PSRendererMaker.java index d879c054c..657a65f70 100644 --- a/src/java/org/apache/fop/render/ps/PSRendererMaker.java +++ b/src/java/org/apache/fop/render/ps/PSRendererMaker.java @@ -1,54 +1,54 @@ -/* - * 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.render.ps; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererConfigurator; - -/** - * RendererMaker for the PostScript Renderer. - */ -public class PSRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_POSTSCRIPT}; - - /** {@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent userAgent) { - return new PSRenderer(); - } - - /** {@inheritDoc} */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return new PSRendererConfigurator(userAgent); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return true; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } -} +/* + * 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.render.ps; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererConfigurator; + +/** + * RendererMaker for the PostScript Renderer. + */ +public class PSRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_POSTSCRIPT}; + + /** {@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent userAgent) { + return new PSRenderer(); + } + + /** {@inheritDoc} */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return new PSRendererConfigurator(userAgent); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return true; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } +} diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java index f2a9c56d9..a10bb7518 100644 --- a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java @@ -1,133 +1,133 @@ -/* - * 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: AbstractPSExtensionObject.java 426576 2006-07-28 15:44:37Z jeremias $ */ - -package org.apache.fop.render.ps.extensions; - -// FOP -import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.extensions.ExtensionAttachment; - -import org.xml.sax.Locator; - -/** - * Base class for the PostScript-specific extension elements. - */ -public abstract class AbstractPSExtensionElement extends FONode { - - /** - * extension attachment - */ - protected PSExtensionAttachment attachment; - - /** - * Default constructor - * - * @param parent parent of this node - * @see org.apache.fop.fo.FONode#FONode(FONode) - */ - public AbstractPSExtensionElement(FONode parent) { - super(parent); - } - - /** - * Blocks XSL FO's from having non-FO parents. - * - * @param loc location in the FO source file - * @param nsURI namespace of incoming node - * @param localName (e.g. "table" for "fo:table") - * @throws ValidationException if incoming node not valid for parent - * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String) - */ - protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI)) { - invalidChildError(loc, nsURI, localName); - } - } - - /** - * Adds characters (does nothing here) - * @param data array of characters containing text to be added - * @param start starting array element to add - * @param length of data array to add - * @param pList currently applicable PropertyList - * @param locator location in fo source file. - * @see org.apache.fop.fo.FONode#addCharacters(char[], int, int, PropertyList, Locator) - */ - protected void addCharacters(char[] data, int start, int length, - PropertyList pList, Locator locator) { - PSExtensionAttachment a = (PSExtensionAttachment)getExtensionAttachment(); - if (a.getContent() != null) { - StringBuffer sb = new StringBuffer(a.getContent()); - sb.append(data, start, length - start); - a.setContent(sb.toString()); - } else { - a.setContent(new String(data, start, length - start)); - } - } - - /** - * @return a String representation of this object - * @see org.apache.fop.fo.FONode#getNamespaceURI() - */ - public String getNamespaceURI() { - return PSExtensionElementMapping.NAMESPACE; - } - - /** - * @return a String representation of this object - * @see org.apache.fop.fo.FONode#getNormalNamespacePrefix() - */ - public String getNormalNamespacePrefix() { - return "fox"; - } - - /** - * @see org.apache.fop.fo.FONode#endOfNode() - * @throws FOPException if there's a problem during processing - */ - protected void endOfNode() throws FOPException { - super.endOfNode(); - String s = ((PSExtensionAttachment)getExtensionAttachment()).getContent(); - if (s == null || s.length() == 0) { - missingChildElementError("#PCDATA"); - } - } - - /** - * @return the extension attachment if one is created by the extension element, null otherwise. - * @see org.apache.fop.fo.FONode#getExtensionAttachment() - */ - public ExtensionAttachment getExtensionAttachment() { - if (attachment == null) { - this.attachment = (PSExtensionAttachment)instantiateExtensionAttachment(); - } - return this.attachment; - } - - /** - * Instantiates extension attachment object - * @return extension attachment - */ - protected abstract ExtensionAttachment instantiateExtensionAttachment(); -} - +/* + * 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.render.ps.extensions; + +// FOP +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; + +import org.xml.sax.Locator; + +/** + * Base class for the PostScript-specific extension elements. + */ +public abstract class AbstractPSExtensionElement extends FONode { + + /** + * extension attachment + */ + protected PSExtensionAttachment attachment; + + /** + * Default constructor + * + * @param parent parent of this node + * @see org.apache.fop.fo.FONode#FONode(FONode) + */ + public AbstractPSExtensionElement(FONode parent) { + super(parent); + } + + /** + * Blocks XSL FO's from having non-FO parents. + * + * @param loc location in the FO source file + * @param nsURI namespace of incoming node + * @param localName (e.g. "table" for "fo:table") + * @throws ValidationException if incoming node not valid for parent + * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String) + */ + protected void validateChildNode(Locator loc, String nsURI, String localName) + throws ValidationException { + if (FO_URI.equals(nsURI)) { + invalidChildError(loc, nsURI, localName); + } + } + + /** + * Adds characters (does nothing here) + * @param data array of characters containing text to be added + * @param start starting array element to add + * @param length of data array to add + * @param pList currently applicable PropertyList + * @param locator location in fo source file. + * @see org.apache.fop.fo.FONode#addCharacters(char[], int, int, PropertyList, Locator) + */ + protected void addCharacters(char[] data, int start, int length, + PropertyList pList, Locator locator) { + PSExtensionAttachment a = (PSExtensionAttachment)getExtensionAttachment(); + if (a.getContent() != null) { + StringBuffer sb = new StringBuffer(a.getContent()); + sb.append(data, start, length - start); + a.setContent(sb.toString()); + } else { + a.setContent(new String(data, start, length - start)); + } + } + + /** + * @return a String representation of this object + * @see org.apache.fop.fo.FONode#getNamespaceURI() + */ + public String getNamespaceURI() { + return PSExtensionElementMapping.NAMESPACE; + } + + /** + * @return a String representation of this object + * @see org.apache.fop.fo.FONode#getNormalNamespacePrefix() + */ + public String getNormalNamespacePrefix() { + return "fox"; + } + + /** + * @see org.apache.fop.fo.FONode#endOfNode() + * @throws FOPException if there's a problem during processing + */ + protected void endOfNode() throws FOPException { + super.endOfNode(); + String s = ((PSExtensionAttachment)getExtensionAttachment()).getContent(); + if (s == null || s.length() == 0) { + missingChildElementError("#PCDATA"); + } + } + + /** + * @return the extension attachment if one is created by the extension element, null otherwise. + * @see org.apache.fop.fo.FONode#getExtensionAttachment() + */ + public ExtensionAttachment getExtensionAttachment() { + if (attachment == null) { + this.attachment = (PSExtensionAttachment)instantiateExtensionAttachment(); + } + return this.attachment; + } + + /** + * Instantiates extension attachment object + * @return extension attachment + */ + protected abstract ExtensionAttachment instantiateExtensionAttachment(); +} + diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java index 80a2aeee3..3fccf4f67 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java @@ -1,110 +1,110 @@ -/* - * 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.render.ps.extensions; - -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -import org.apache.xmlgraphics.util.XMLizable; - -import org.apache.fop.fo.extensions.ExtensionAttachment; - -/** - * This is the pass-through value object for the PostScript extension. - */ -public abstract class PSExtensionAttachment implements ExtensionAttachment, XMLizable { - - /** extension node content */ - protected String content; - - /** The category URI for this extension attachment. */ - public static final String CATEGORY = "apache:fop:extensions:postscript"; - - /** - * Default constructor. - * @param content the content of the setup code object - */ - public PSExtensionAttachment(String content) { - this.content = content; - } - - /** - * No-argument contructor. - */ - public PSExtensionAttachment() { - } - - /** - * @return the category URI - * @see org.apache.fop.fo.extensions.ExtensionAttachment#getCategory() - */ - public String getCategory() { - return CATEGORY; - } - - /** @return the content */ - public String getContent() { - return content; - } - - /** - * Sets the content for the setup code object. - * @param content The content to set. - */ - public void setContent(String content) { - this.content = content; - } - - /** - * Generates SAX events representing the object's state. - * - * @param handler ContentHandler instance to send the SAX events to - * @throws SAXException if there's a problem generating the SAX events - * @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler) - */ - public void toSAX(ContentHandler handler) throws SAXException { - AttributesImpl atts = new AttributesImpl(); - String element = getElement(); - handler.startElement(CATEGORY, element, element, atts); - if (content != null && content.length() > 0) { - char[] chars = content.toCharArray(); - handler.characters(chars, 0, chars.length); - } - handler.endElement(CATEGORY, element, element); - } - - /** @return type name */ - public String getType() { - String className = getClass().getName(); - return className.substring(className.lastIndexOf('.') + 3); - } - - /** - * @return a string representation of this object - * @see java.lang.Object#toString() - */ - public String toString() { - return getType() + ": content=" + content; - } - - /** @return element */ - protected abstract String getElement(); -} +/* + * 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.render.ps.extensions; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import org.apache.xmlgraphics.util.XMLizable; + +import org.apache.fop.fo.extensions.ExtensionAttachment; + +/** + * This is the pass-through value object for the PostScript extension. + */ +public abstract class PSExtensionAttachment implements ExtensionAttachment, XMLizable { + + /** extension node content */ + protected String content; + + /** The category URI for this extension attachment. */ + public static final String CATEGORY = "apache:fop:extensions:postscript"; + + /** + * Default constructor. + * @param content the content of the setup code object + */ + public PSExtensionAttachment(String content) { + this.content = content; + } + + /** + * No-argument contructor. + */ + public PSExtensionAttachment() { + } + + /** + * @return the category URI + * @see org.apache.fop.fo.extensions.ExtensionAttachment#getCategory() + */ + public String getCategory() { + return CATEGORY; + } + + /** @return the content */ + public String getContent() { + return content; + } + + /** + * Sets the content for the setup code object. + * @param content The content to set. + */ + public void setContent(String content) { + this.content = content; + } + + /** + * Generates SAX events representing the object's state. + * + * @param handler ContentHandler instance to send the SAX events to + * @throws SAXException if there's a problem generating the SAX events + * @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler) + */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + String element = getElement(); + handler.startElement(CATEGORY, element, element, atts); + if (content != null && content.length() > 0) { + char[] chars = content.toCharArray(); + handler.characters(chars, 0, chars.length); + } + handler.endElement(CATEGORY, element, element); + } + + /** @return type name */ + public String getType() { + String className = getClass().getName(); + return className.substring(className.lastIndexOf('.') + 3); + } + + /** + * @return a string representation of this object + * @see java.lang.Object#toString() + */ + public String toString() { + return getType() + ": content=" + content; + } + + /** @return element */ + protected abstract String getElement(); +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java index 72f665a0f..456d97430 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.ps.extensions; diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java index da84f97a2..28ea3c24c 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java @@ -1,114 +1,114 @@ -/* - * 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.render.ps.extensions; - -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -/** - * Element for postscript setpagedevice instruction - * This is a an extension which provides a pass-through value - * dictionary object for the postscript setpagedevice instruction. - */ -public class PSSetPageDevice extends PSExtensionAttachment { - /** element name */ - protected static final String ELEMENT = "ps-setpagedevice"; - - private static final String ATT_NAME = "name"; - - /** - * name attribute - */ - protected String name = null; - - /** - * default constructor - * @param content set page device dictionary - */ - public PSSetPageDevice(String content) { - super(content); - } - - /** - * constructor - * @param name name attribute of this setpagedevice content - * @param content set page device dictionary - */ - public PSSetPageDevice(String name, String content) { - this(content); - this.name = name; - } - - /** - * constructor - */ - public PSSetPageDevice() { - } - - /** @return the name */ - public String getName() { - return name; - } - - /** - * Sets the name of the setup code object. - * @param name The name to set. - */ - public void setName(String name) { - this.name = name; - } - - /** - * @return a string representation of this object - * @see java.lang.Object#toString() - */ - public String toString() { - return "PSSetPageDevice(name=" + getName() + ", content='" + getContent() + "')"; - } - - /** - * @return a string representation of this object - * @see org.apache.fop.render.ps.extensions.PSExtensionAttachment#getElement() - */ - protected String getElement() { - return ELEMENT; - } - - /** - * Generates SAX events representing the object's state. - * @param handler ContentHandler instance to send the SAX events to - * @throws SAXException if there's a problem generating the SAX events - * @see org.apache.xmlgraphics.util.XMLizable#toSAX(org.xml.sax.ContentHandler) - */ - public void toSAX(ContentHandler handler) throws SAXException { - AttributesImpl atts = new AttributesImpl(); - if (name != null && name.length() > 0) { - atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); - } - String element = getElement(); - handler.startElement(CATEGORY, element, element, atts); - if (content != null && content.length() > 0) { - char[] chars = content.toCharArray(); - handler.characters(chars, 0, chars.length); - } - handler.endElement(CATEGORY, element, element); - } -} +/* + * 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.render.ps.extensions; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Element for postscript setpagedevice instruction + * This is a an extension which provides a pass-through value + * dictionary object for the postscript setpagedevice instruction. + */ +public class PSSetPageDevice extends PSExtensionAttachment { + /** element name */ + protected static final String ELEMENT = "ps-setpagedevice"; + + private static final String ATT_NAME = "name"; + + /** + * name attribute + */ + protected String name = null; + + /** + * default constructor + * @param content set page device dictionary + */ + public PSSetPageDevice(String content) { + super(content); + } + + /** + * constructor + * @param name name attribute of this setpagedevice content + * @param content set page device dictionary + */ + public PSSetPageDevice(String name, String content) { + this(content); + this.name = name; + } + + /** + * constructor + */ + public PSSetPageDevice() { + } + + /** @return the name */ + public String getName() { + return name; + } + + /** + * Sets the name of the setup code object. + * @param name The name to set. + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return a string representation of this object + * @see java.lang.Object#toString() + */ + public String toString() { + return "PSSetPageDevice(name=" + getName() + ", content='" + getContent() + "')"; + } + + /** + * @return a string representation of this object + * @see org.apache.fop.render.ps.extensions.PSExtensionAttachment#getElement() + */ + protected String getElement() { + return ELEMENT; + } + + /** + * Generates SAX events representing the object's state. + * @param handler ContentHandler instance to send the SAX events to + * @throws SAXException if there's a problem generating the SAX events + * @see org.apache.xmlgraphics.util.XMLizable#toSAX(org.xml.sax.ContentHandler) + */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + if (name != null && name.length() > 0) { + atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); + } + String element = getElement(); + handler.startElement(CATEGORY, element, element, atts); + if (content != null && content.length() > 0) { + char[] chars = content.toCharArray(); + handler.characters(chars, 0, chars.length); + } + handler.endElement(CATEGORY, element, element); + } +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java index ff7e8f792..b512c6888 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java @@ -1,95 +1,95 @@ -/* - * 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.render.ps.extensions; - -import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.Constants; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; - -/** - * Extension element for ps:ps-setpagedevice. - */ -public class PSSetPageDeviceElement extends AbstractPSExtensionElement { - - protected static final String ELEMENT = "ps-setpagedevice"; - - /** - * Main constructor - * @param parent parent FO node - */ - protected PSSetPageDeviceElement(FONode parent) { - super(parent); - } - - /** - * Called after processNode() is called. Subclasses can do additional processing. - * @throws FOPException if there's a problem during processing - * @see org.apache.fop.fo.FONode#startOfNode() - */ - protected void startOfNode() throws FOPException { - super.startOfNode(); - if ( !((parent.getNameId() == Constants.FO_DECLARATIONS) - || (parent.getNameId() == Constants.FO_SIMPLE_PAGE_MASTER)) ) { - throw new ValidationException( getName() - + " must be a child of fo:declarations or fo:simple-page-master."); - } - } - - /** - * Initialize the node with its name, location information, and attributes - * The attributes must be used immediately as the sax attributes - * will be altered for the next element. - * @param elementName element name (e.g., "fo:block") - * @param locator Locator object (ignored by default) - * @param attlist Collection of attributes passed to us from the parser. - * @param propertyList property list - * @throws FOPException if there's a problem during processing - * @see org.apache.fop.fo.FONode#processNode - */ - public void processNode(String elementName, Locator locator, - Attributes attlist, PropertyList propertyList) - throws FOPException { - String name = attlist.getValue("name"); - if (name != null && name.length() > 0) { - ((PSSetPageDevice)getExtensionAttachment()).setName(name); - } - } - - /** - * @return local name - * @see org.apache.fop.fo.FONode#getLocalName() */ - public String getLocalName() { - return ELEMENT; - } - - /** - * @return a new PSSetPageDevice object - * @see org.apache.fop.render.ps.extensions.AbstractPSExtensionElement - * #instantiateExtensionAttachment() - */ - protected ExtensionAttachment instantiateExtensionAttachment() { - return new PSSetPageDevice(); - } -} +/* + * 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.render.ps.extensions; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +/** + * Extension element for ps:ps-setpagedevice. + */ +public class PSSetPageDeviceElement extends AbstractPSExtensionElement { + + protected static final String ELEMENT = "ps-setpagedevice"; + + /** + * Main constructor + * @param parent parent FO node + */ + protected PSSetPageDeviceElement(FONode parent) { + super(parent); + } + + /** + * Called after processNode() is called. Subclasses can do additional processing. + * @throws FOPException if there's a problem during processing + * @see org.apache.fop.fo.FONode#startOfNode() + */ + protected void startOfNode() throws FOPException { + super.startOfNode(); + if ( !((parent.getNameId() == Constants.FO_DECLARATIONS) + || (parent.getNameId() == Constants.FO_SIMPLE_PAGE_MASTER)) ) { + throw new ValidationException( getName() + + " must be a child of fo:declarations or fo:simple-page-master."); + } + } + + /** + * Initialize the node with its name, location information, and attributes + * The attributes must be used immediately as the sax attributes + * will be altered for the next element. + * @param elementName element name (e.g., "fo:block") + * @param locator Locator object (ignored by default) + * @param attlist Collection of attributes passed to us from the parser. + * @param propertyList property list + * @throws FOPException if there's a problem during processing + * @see org.apache.fop.fo.FONode#processNode + */ + public void processNode(String elementName, Locator locator, + Attributes attlist, PropertyList propertyList) + throws FOPException { + String name = attlist.getValue("name"); + if (name != null && name.length() > 0) { + ((PSSetPageDevice)getExtensionAttachment()).setName(name); + } + } + + /** + * @return local name + * @see org.apache.fop.fo.FONode#getLocalName() */ + public String getLocalName() { + return ELEMENT; + } + + /** + * @return a new PSSetPageDevice object + * @see org.apache.fop.render.ps.extensions.AbstractPSExtensionElement + * #instantiateExtensionAttachment() + */ + protected ExtensionAttachment instantiateExtensionAttachment() { + return new PSSetPageDevice(); + } +} diff --git a/src/java/org/apache/fop/render/rtf/RTFFOEventHandlerMaker.java b/src/java/org/apache/fop/render/rtf/RTFFOEventHandlerMaker.java index 40583253d..a15d206ee 100644 --- a/src/java/org/apache/fop/render/rtf/RTFFOEventHandlerMaker.java +++ b/src/java/org/apache/fop/render/rtf/RTFFOEventHandlerMaker.java @@ -1,66 +1,66 @@ -/* - * 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.render.rtf; - -import java.io.OutputStream; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.fo.FOEventHandler; -import org.apache.fop.render.AbstractFOEventHandlerMaker; - -/** - * Maker class for RTF support. - */ -public class RTFFOEventHandlerMaker extends AbstractFOEventHandlerMaker { - - private static final String[] MIMES = new String[] { - MimeConstants.MIME_RTF, - MimeConstants.MIME_RTF_ALT1, - MimeConstants.MIME_RTF_ALT2}; - - - /** - * {@inheritDoc} - * @param ua FOUserAgent - * @param out OutputStream - * @return created RTFHandler - */ - public FOEventHandler makeFOEventHandler(FOUserAgent ua, OutputStream out) { - return new RTFHandler(ua, out); - } - - /** - * {@inheritDoc} - * @return true, if an outputstream is needed - */ - public boolean needsOutputStream() { - return true; - } - - /** - * {@inheritDoc} - * @return array of MIME types - */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.rtf; + +import java.io.OutputStream; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.fo.FOEventHandler; +import org.apache.fop.render.AbstractFOEventHandlerMaker; + +/** + * Maker class for RTF support. + */ +public class RTFFOEventHandlerMaker extends AbstractFOEventHandlerMaker { + + private static final String[] MIMES = new String[] { + MimeConstants.MIME_RTF, + MimeConstants.MIME_RTF_ALT1, + MimeConstants.MIME_RTF_ALT2}; + + + /** + * {@inheritDoc} + * @param ua FOUserAgent + * @param out OutputStream + * @return created RTFHandler + */ + public FOEventHandler makeFOEventHandler(FOUserAgent ua, OutputStream out) { + return new RTFHandler(ua, out); + } + + /** + * {@inheritDoc} + * @return true, if an outputstream is needed + */ + public boolean needsOutputStream() { + return true; + } + + /** + * {@inheritDoc} + * @return array of MIME types + */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/IBorderAttributes.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/IBorderAttributes.java index 89cd45efc..0e9820994 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/IBorderAttributes.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/IBorderAttributes.java @@ -1,117 +1,117 @@ -/* - * 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.render.rtf.rtflib.rtfdoc; - -/* - * This file is part of the RTF library of the FOP project, which was originally - * created by Bertrand Delacretaz and by other - * contributors to the jfor project (www.jfor.org), who agreed to donate jfor to - * the FOP project. - */ - - - -/** Constants for RTF border attribute names. */ - -public interface IBorderAttributes { - - /** Constant for border left */ - String BORDER_LEFT = "brdrl"; - /** Constant for border right */ - String BORDER_RIGHT = "brdrr"; - /** Constant for border top */ - String BORDER_TOP = "brdrt"; - /** Constant for border bottom */ - String BORDER_BOTTOM = "brdrb"; - /** Constant for character border (border always appears on all sides) */ - String BORDER_CHARACTER = "chbrdr"; - /** Constant for a single-thick border */ - String BORDER_SINGLE_THICKNESS = "brdrs"; - /** Constant for a double-thick border */ - String BORDER_DOUBLE_THICKNESS = "brdrth"; - /** Constant for a shadowed border */ - String BORDER_SHADOWED = "brdrsh"; - /** Constant for a double border */ - String BORDER_DOUBLE = "brdrdb"; - /** Constant for a dotted border */ - String BORDER_DOTTED = "brdrdot"; - /** Constant for a dashed border */ - String BORDER_DASH = "brdrdash"; - /** Constant for a hairline border */ - String BORDER_HAIRLINE = "brdrhair"; - /** Constant for a small-dashed border */ - String BORDER_DASH_SMALL = "brdrdashsm"; - /** Constant for a dot-dashed border */ - String BORDER_DOT_DASH = "brdrdashd"; - /** Constant for a dot-dot-dashed border */ - String BORDER_DOT_DOT_DASH = "brdrdashdd"; - /** Constant for a triple border */ - String BORDER_TRIPLE = "brdrtriple"; - /** Constant for a think-thin-small border */ - String BORDER_THINK_THIN_SMALL = "brdrtnthsg"; - /** Constant for a thin-thick-small border */ - String BORDER_THIN_THICK_SMALL = "brdrthtnsg"; - /** Constant for a thin-thick-thin-small border */ - String BORDER_THIN_THICK_THIN_SMALL = "brdrthtnthsg"; - /** Constant for a think-thin-medium border */ - String BORDER_THINK_THIN_MEDIUM = "brdrtnthmg"; - /** Constant for a thin-thick-medium border */ - String BORDER_THIN_THICK_MEDIUM = "brdrthtnmg"; - /** Constant for a thin-thick-thin-medium border */ - String BORDER_THIN_THICK_THIN_MEDIUM = "brdrthtnthmg"; - /** Constant for a think-thin-large border */ - String BORDER_THINK_THIN_LARGE = "brdrtnthlg"; - /** Constant for a thin-thick-large border */ - String BORDER_THIN_THICK_LARGE = "brdrthtnlg"; - /** Constant for a thin-thick-thin-large border */ - String BORDER_THIN_THICK_THIN_LARGE = "brdrthtnthlg"; - /** Constant for a wavy border */ - String BORDER_WAVY = "brdrwavy"; - /** Constant for a double wavy border */ - String BORDER_WAVY_DOUBLE = "brdrwavydb"; - /** Constant for a striped border */ - String BORDER_STRIPED = "brdrdashdotstr"; - /** Constant for an embossed border */ - String BORDER_EMBOSS = "brdremboss"; - /** Constant for an engraved border */ - String BORDER_ENGRAVE = "brdrengrave"; - /** Constant for an nil border */ - String BORDER_NIL = "brdrnil"; - /** Constant for border color */ - String BORDER_COLOR = "brdrcf"; - /** Constant for border space */ - String BORDER_SPACE = "brsp"; - /** Constant for border width */ - String BORDER_WIDTH = "brdrw"; - - /** String array of border attributes */ - String [] BORDERS = new String[] { - BORDER_SINGLE_THICKNESS, BORDER_DOUBLE_THICKNESS, BORDER_SHADOWED, - BORDER_DOUBLE, BORDER_DOTTED, BORDER_DASH, - BORDER_HAIRLINE, BORDER_DASH_SMALL, BORDER_DOT_DASH, - BORDER_DOT_DOT_DASH, BORDER_TRIPLE, BORDER_THINK_THIN_SMALL, - BORDER_THIN_THICK_SMALL, BORDER_THIN_THICK_THIN_SMALL, BORDER_THINK_THIN_MEDIUM, - BORDER_THIN_THICK_MEDIUM, BORDER_THIN_THICK_THIN_MEDIUM, BORDER_THINK_THIN_LARGE, - BORDER_THIN_THICK_LARGE, BORDER_THIN_THICK_THIN_LARGE, BORDER_WAVY, - BORDER_WAVY_DOUBLE, BORDER_STRIPED, BORDER_EMBOSS, - BORDER_ENGRAVE, BORDER_COLOR, BORDER_SPACE, - BORDER_WIDTH - }; -} +/* + * 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.render.rtf.rtflib.rtfdoc; + +/* + * This file is part of the RTF library of the FOP project, which was originally + * created by Bertrand Delacretaz and by other + * contributors to the jfor project (www.jfor.org), who agreed to donate jfor to + * the FOP project. + */ + + + +/** Constants for RTF border attribute names. */ + +public interface IBorderAttributes { + + /** Constant for border left */ + String BORDER_LEFT = "brdrl"; + /** Constant for border right */ + String BORDER_RIGHT = "brdrr"; + /** Constant for border top */ + String BORDER_TOP = "brdrt"; + /** Constant for border bottom */ + String BORDER_BOTTOM = "brdrb"; + /** Constant for character border (border always appears on all sides) */ + String BORDER_CHARACTER = "chbrdr"; + /** Constant for a single-thick border */ + String BORDER_SINGLE_THICKNESS = "brdrs"; + /** Constant for a double-thick border */ + String BORDER_DOUBLE_THICKNESS = "brdrth"; + /** Constant for a shadowed border */ + String BORDER_SHADOWED = "brdrsh"; + /** Constant for a double border */ + String BORDER_DOUBLE = "brdrdb"; + /** Constant for a dotted border */ + String BORDER_DOTTED = "brdrdot"; + /** Constant for a dashed border */ + String BORDER_DASH = "brdrdash"; + /** Constant for a hairline border */ + String BORDER_HAIRLINE = "brdrhair"; + /** Constant for a small-dashed border */ + String BORDER_DASH_SMALL = "brdrdashsm"; + /** Constant for a dot-dashed border */ + String BORDER_DOT_DASH = "brdrdashd"; + /** Constant for a dot-dot-dashed border */ + String BORDER_DOT_DOT_DASH = "brdrdashdd"; + /** Constant for a triple border */ + String BORDER_TRIPLE = "brdrtriple"; + /** Constant for a think-thin-small border */ + String BORDER_THINK_THIN_SMALL = "brdrtnthsg"; + /** Constant for a thin-thick-small border */ + String BORDER_THIN_THICK_SMALL = "brdrthtnsg"; + /** Constant for a thin-thick-thin-small border */ + String BORDER_THIN_THICK_THIN_SMALL = "brdrthtnthsg"; + /** Constant for a think-thin-medium border */ + String BORDER_THINK_THIN_MEDIUM = "brdrtnthmg"; + /** Constant for a thin-thick-medium border */ + String BORDER_THIN_THICK_MEDIUM = "brdrthtnmg"; + /** Constant for a thin-thick-thin-medium border */ + String BORDER_THIN_THICK_THIN_MEDIUM = "brdrthtnthmg"; + /** Constant for a think-thin-large border */ + String BORDER_THINK_THIN_LARGE = "brdrtnthlg"; + /** Constant for a thin-thick-large border */ + String BORDER_THIN_THICK_LARGE = "brdrthtnlg"; + /** Constant for a thin-thick-thin-large border */ + String BORDER_THIN_THICK_THIN_LARGE = "brdrthtnthlg"; + /** Constant for a wavy border */ + String BORDER_WAVY = "brdrwavy"; + /** Constant for a double wavy border */ + String BORDER_WAVY_DOUBLE = "brdrwavydb"; + /** Constant for a striped border */ + String BORDER_STRIPED = "brdrdashdotstr"; + /** Constant for an embossed border */ + String BORDER_EMBOSS = "brdremboss"; + /** Constant for an engraved border */ + String BORDER_ENGRAVE = "brdrengrave"; + /** Constant for an nil border */ + String BORDER_NIL = "brdrnil"; + /** Constant for border color */ + String BORDER_COLOR = "brdrcf"; + /** Constant for border space */ + String BORDER_SPACE = "brsp"; + /** Constant for border width */ + String BORDER_WIDTH = "brdrw"; + + /** String array of border attributes */ + String [] BORDERS = new String[] { + BORDER_SINGLE_THICKNESS, BORDER_DOUBLE_THICKNESS, BORDER_SHADOWED, + BORDER_DOUBLE, BORDER_DOTTED, BORDER_DASH, + BORDER_HAIRLINE, BORDER_DASH_SMALL, BORDER_DOT_DASH, + BORDER_DOT_DOT_DASH, BORDER_TRIPLE, BORDER_THINK_THIN_SMALL, + BORDER_THIN_THICK_SMALL, BORDER_THIN_THICK_THIN_SMALL, BORDER_THINK_THIN_MEDIUM, + BORDER_THIN_THICK_MEDIUM, BORDER_THIN_THICK_THIN_MEDIUM, BORDER_THINK_THIN_LARGE, + BORDER_THIN_THICK_LARGE, BORDER_THIN_THICK_THIN_LARGE, BORDER_WAVY, + BORDER_WAVY_DOUBLE, BORDER_STRIPED, BORDER_EMBOSS, + BORDER_ENGRAVE, BORDER_COLOR, BORDER_SPACE, + BORDER_WIDTH + }; +} diff --git a/src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java b/src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java index ab655c92e..0ca509b66 100644 --- a/src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java +++ b/src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.txt; diff --git a/src/java/org/apache/fop/render/txt/TXTRendererMaker.java b/src/java/org/apache/fop/render/txt/TXTRendererMaker.java index b18c3faa0..24e24ea87 100644 --- a/src/java/org/apache/fop/render/txt/TXTRendererMaker.java +++ b/src/java/org/apache/fop/render/txt/TXTRendererMaker.java @@ -1,54 +1,54 @@ -/* - * 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.render.txt; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererConfigurator; - -/** - * RendererMaker for the Plain Text Renderer. - */ -public class TXTRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_PLAIN_TEXT}; - - /**{@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent userAgent) { - return new TXTRenderer(); - } - - /**{@inheritDoc} */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return new TXTRendererConfigurator(userAgent); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return true; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } -} +/* + * 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.render.txt; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererConfigurator; + +/** + * RendererMaker for the Plain Text Renderer. + */ +public class TXTRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_PLAIN_TEXT}; + + /**{@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent userAgent) { + return new TXTRenderer(); + } + + /**{@inheritDoc} */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return new TXTRendererConfigurator(userAgent); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return true; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } +} diff --git a/src/java/org/apache/fop/render/xml/XMLRendererMaker.java b/src/java/org/apache/fop/render/xml/XMLRendererMaker.java index 3ed62a6e1..5aa0deb2b 100644 --- a/src/java/org/apache/fop/render/xml/XMLRendererMaker.java +++ b/src/java/org/apache/fop/render/xml/XMLRendererMaker.java @@ -1,56 +1,56 @@ -/* - * 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.render.xml; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.PrintRendererConfigurator; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererConfigurator; - -/** - * RendererMaker for the Area Tree XML Renderer. - */ -public class XMLRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_FOP_AREA_TREE}; - - /**{@inheritDoc} */ - public Renderer makeRenderer(FOUserAgent userAgent) { - return new XMLRenderer(); - } - - /**{@inheritDoc} */ - public RendererConfigurator getConfigurator(FOUserAgent userAgent) { - return new PrintRendererConfigurator(userAgent); - } - - /** {@inheritDoc} */ - public boolean needsOutputStream() { - return true; - } - - /** {@inheritDoc} */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.xml; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.PrintRendererConfigurator; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererConfigurator; + +/** + * RendererMaker for the Area Tree XML Renderer. + */ +public class XMLRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_FOP_AREA_TREE}; + + /**{@inheritDoc} */ + public Renderer makeRenderer(FOUserAgent userAgent) { + return new XMLRenderer(); + } + + /**{@inheritDoc} */ + public RendererConfigurator getConfigurator(FOUserAgent userAgent) { + return new PrintRendererConfigurator(userAgent); + } + + /** {@inheritDoc} */ + public boolean needsOutputStream() { + return true; + } + + /** {@inheritDoc} */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/src/java/org/apache/fop/util/LogUtil.java b/src/java/org/apache/fop/util/LogUtil.java index 60eafb51a..e33397fcb 100644 --- a/src/java/org/apache/fop/util/LogUtil.java +++ b/src/java/org/apache/fop/util/LogUtil.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.util; diff --git a/src/java/org/apache/fop/util/QName.java b/src/java/org/apache/fop/util/QName.java index 0794d3088..390e29dd9 100644 --- a/src/java/org/apache/fop/util/QName.java +++ b/src/java/org/apache/fop/util/QName.java @@ -1,138 +1,138 @@ -/* - * 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.io.Serializable; - -/** - * Represents a qualified name of an XML element or an XML attribute. - *

    - * Note: This class allows to carry a namespace prefix but it is not used in the equals() and - * hashCode() methods. - */ -public class QName implements Serializable { - - private static final long serialVersionUID = -5225376740044770690L; - - private String namespaceURI; - private String localName; - private String prefix; - private int hashCode; - - /** - * Main constructor. - * @param namespaceURI the namespace URI - * @param prefix the namespace prefix, may be null - * @param localName the local name - */ - public QName(String namespaceURI, String prefix, String localName) { - if (localName == null) { - throw new NullPointerException("Parameter localName must not be null"); - } - if (localName.length() == 0) { - throw new IllegalArgumentException("Parameter localName must not be empty"); - } - this.namespaceURI = namespaceURI; - this.prefix = prefix; - this.localName = localName; - this.hashCode = toHashString().hashCode(); - } - - /** - * Main constructor. - * @param namespaceURI the namespace URI - * @param qName the qualified name - */ - public QName(String namespaceURI, String qName) { - if (qName == null) { - throw new NullPointerException("Parameter localName must not be null"); - } - if (qName.length() == 0) { - throw new IllegalArgumentException("Parameter localName must not be empty"); - } - this.namespaceURI = namespaceURI; - int p = qName.indexOf(':'); - if (p > 0) { - this.prefix = qName.substring(0, p); - this.localName = qName.substring(p + 1); - } else { - this.prefix = null; - this.localName = qName; - } - this.hashCode = toHashString().hashCode(); - } - - /** @return the namespace URI */ - public String getNamespaceURI() { - return this.namespaceURI; - } - - /** @return the namespace prefix */ - public String getPrefix() { - return this.prefix; - } - - /** @return the local name */ - public String getLocalName() { - return this.localName; - } - - /** @return the fully qualified name */ - public String getQName() { - return getPrefix() != null ? getPrefix() + ':' + getLocalName() : getLocalName(); - } - - /** {@inheritDoc} */ - public int hashCode() { - return this.hashCode; - } - - /** {@inheritDoc} */ - public boolean equals(Object obj) { - if (obj == null) { - return false; - } else if (obj == this) { - return true; - } else { - if (obj instanceof QName) { - QName other = (QName)obj; - if ((getNamespaceURI() == null && other.getNamespaceURI() == null) - || getNamespaceURI().equals(other.getNamespaceURI())) { - return getLocalName().equals(other.getLocalName()); - } - } - } - return false; - } - - /** {@inheritDoc} */ - public String toString() { - return prefix != null - ? (prefix + ":" + localName) - : toHashString(); - } - - private String toHashString() { - return (namespaceURI != null - ? ("{" + namespaceURI + "}" + localName) - : localName); - } - -} +/* + * 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.io.Serializable; + +/** + * Represents a qualified name of an XML element or an XML attribute. + *

    + * Note: This class allows to carry a namespace prefix but it is not used in the equals() and + * hashCode() methods. + */ +public class QName implements Serializable { + + private static final long serialVersionUID = -5225376740044770690L; + + private String namespaceURI; + private String localName; + private String prefix; + private int hashCode; + + /** + * Main constructor. + * @param namespaceURI the namespace URI + * @param prefix the namespace prefix, may be null + * @param localName the local name + */ + public QName(String namespaceURI, String prefix, String localName) { + if (localName == null) { + throw new NullPointerException("Parameter localName must not be null"); + } + if (localName.length() == 0) { + throw new IllegalArgumentException("Parameter localName must not be empty"); + } + this.namespaceURI = namespaceURI; + this.prefix = prefix; + this.localName = localName; + this.hashCode = toHashString().hashCode(); + } + + /** + * Main constructor. + * @param namespaceURI the namespace URI + * @param qName the qualified name + */ + public QName(String namespaceURI, String qName) { + if (qName == null) { + throw new NullPointerException("Parameter localName must not be null"); + } + if (qName.length() == 0) { + throw new IllegalArgumentException("Parameter localName must not be empty"); + } + this.namespaceURI = namespaceURI; + int p = qName.indexOf(':'); + if (p > 0) { + this.prefix = qName.substring(0, p); + this.localName = qName.substring(p + 1); + } else { + this.prefix = null; + this.localName = qName; + } + this.hashCode = toHashString().hashCode(); + } + + /** @return the namespace URI */ + public String getNamespaceURI() { + return this.namespaceURI; + } + + /** @return the namespace prefix */ + public String getPrefix() { + return this.prefix; + } + + /** @return the local name */ + public String getLocalName() { + return this.localName; + } + + /** @return the fully qualified name */ + public String getQName() { + return getPrefix() != null ? getPrefix() + ':' + getLocalName() : getLocalName(); + } + + /** {@inheritDoc} */ + public int hashCode() { + return this.hashCode; + } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + if (obj == null) { + return false; + } else if (obj == this) { + return true; + } else { + if (obj instanceof QName) { + QName other = (QName)obj; + if ((getNamespaceURI() == null && other.getNamespaceURI() == null) + || getNamespaceURI().equals(other.getNamespaceURI())) { + return getLocalName().equals(other.getLocalName()); + } + } + } + return false; + } + + /** {@inheritDoc} */ + public String toString() { + return prefix != null + ? (prefix + ":" + localName) + : toHashString(); + } + + private String toHashString() { + return (namespaceURI != null + ? ("{" + namespaceURI + "}" + localName) + : localName); + } + +} diff --git a/src/java/org/apache/fop/util/UnitConv.java b/src/java/org/apache/fop/util/UnitConv.java index 626321ff9..cd3276b9f 100644 --- a/src/java/org/apache/fop/util/UnitConv.java +++ b/src/java/org/apache/fop/util/UnitConv.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: FixedLength.java 279656 2005-09-08 22:06:48Z pietsch $ */ +/* $Id$ */ package org.apache.fop.util; diff --git a/src/sandbox/org/apache/fop/render/mif/MIFFOEventHandlerMaker.java b/src/sandbox/org/apache/fop/render/mif/MIFFOEventHandlerMaker.java index b841e61c5..edf6ffcf6 100644 --- a/src/sandbox/org/apache/fop/render/mif/MIFFOEventHandlerMaker.java +++ b/src/sandbox/org/apache/fop/render/mif/MIFFOEventHandlerMaker.java @@ -1,52 +1,52 @@ -/* - * 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.render.mif; - -import java.io.OutputStream; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.fo.FOEventHandler; -import org.apache.fop.render.AbstractFOEventHandlerMaker; - -/** - * Maker class for MIF support. - */ -public class MIFFOEventHandlerMaker extends AbstractFOEventHandlerMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_MIF}; - - - /** @see org.apache.fop.render.AbstractFOEventHandlerMaker */ - public FOEventHandler makeFOEventHandler(FOUserAgent ua, OutputStream out) { - return new MIFHandler(ua, out); - } - - /** @see org.apache.fop.render.AbstractFOEventHandlerMaker#needsOutputStream() */ - public boolean needsOutputStream() { - return true; - } - - /** @see org.apache.fop.render.AbstractFOEventHandlerMaker#getSupportedMimeTypes() */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.mif; + +import java.io.OutputStream; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.fo.FOEventHandler; +import org.apache.fop.render.AbstractFOEventHandlerMaker; + +/** + * Maker class for MIF support. + */ +public class MIFFOEventHandlerMaker extends AbstractFOEventHandlerMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_MIF}; + + + /** @see org.apache.fop.render.AbstractFOEventHandlerMaker */ + public FOEventHandler makeFOEventHandler(FOUserAgent ua, OutputStream out) { + return new MIFHandler(ua, out); + } + + /** @see org.apache.fop.render.AbstractFOEventHandlerMaker#needsOutputStream() */ + public boolean needsOutputStream() { + return true; + } + + /** @see org.apache.fop.render.AbstractFOEventHandlerMaker#getSupportedMimeTypes() */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java b/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java index 0aa5d185a..600c378d8 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java @@ -1,50 +1,50 @@ -/* - * 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.render.svg; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.AbstractRendererMaker; -import org.apache.fop.render.Renderer; - -/** - * RendererMaker for the SVG Renderer. - */ -public class SVGRendererMaker extends AbstractRendererMaker { - - private static final String[] MIMES = new String[] {MimeConstants.MIME_SVG}; - - - /**@see org.apache.fop.render.AbstractRendererMaker */ - public Renderer makeRenderer(FOUserAgent ua) { - return new SVGRenderer(); - } - - /** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */ - public boolean needsOutputStream() { - return true; - } - - /** @see org.apache.fop.render.AbstractRendererMaker#getSupportedMimeTypes() */ - public String[] getSupportedMimeTypes() { - return MIMES; - } - -} +/* + * 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.render.svg; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.AbstractRendererMaker; +import org.apache.fop.render.Renderer; + +/** + * RendererMaker for the SVG Renderer. + */ +public class SVGRendererMaker extends AbstractRendererMaker { + + private static final String[] MIMES = new String[] {MimeConstants.MIME_SVG}; + + + /**@see org.apache.fop.render.AbstractRendererMaker */ + public Renderer makeRenderer(FOUserAgent ua) { + return new SVGRenderer(); + } + + /** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */ + public boolean needsOutputStream() { + return true; + } + + /** @see org.apache.fop.render.AbstractRendererMaker#getSupportedMimeTypes() */ + public String[] getSupportedMimeTypes() { + return MIMES; + } + +} diff --git a/test/java/org/apache/fop/StandardTestSuite.java b/test/java/org/apache/fop/StandardTestSuite.java index 648f3d5d1..33e034de0 100644 --- a/test/java/org/apache/fop/StandardTestSuite.java +++ b/test/java/org/apache/fop/StandardTestSuite.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: BasicDriverTestSuite.java 231325 2005-08-10 21:05:39Z jeremias $ */ +/* $Id$ */ package org.apache.fop; diff --git a/test/java/org/apache/fop/config/BaseUserConfigTestCase.java b/test/java/org/apache/fop/config/BaseUserConfigTestCase.java index ae862664c..2de7ad673 100644 --- a/test/java/org/apache/fop/config/BaseUserConfigTestCase.java +++ b/test/java/org/apache/fop/config/BaseUserConfigTestCase.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.config; diff --git a/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java b/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java index bff9cf905..a7ea1a2db 100644 --- a/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java +++ b/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: PDFCMap.java 426576 2006-07-28 15:44:37Z jeremias $ */ +/* $Id$ */ package org.apache.fop.render.pdf; -- cgit v1.2.3 From 75a7d24627160b3358f7f22d82a3061e8771a8d4 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 13 Feb 2008 15:55:34 +0000 Subject: Replace useless javadoc comment. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627495 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/CIDFont.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java index 69f9704ff..c554d2165 100644 --- a/src/java/org/apache/fop/fonts/CIDFont.java +++ b/src/java/org/apache/fop/fonts/CIDFont.java @@ -83,15 +83,14 @@ public abstract class CIDFont extends CustomFont { return 0; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean isMultiByte() { return true; } /** - * Returns char[] array . + * Returns a char array containing all Unicode characters that have been accessed. + * @return a char array with all used Unicode characters */ public abstract char[] getCharsUsed(); } \ No newline at end of file -- cgit v1.2.3 From ea691f9d34c8b1757f36f2dcecf520b3ffe3e27e Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 13 Feb 2008 15:57:01 +0000 Subject: Easy way to force the discarding of the user's font cache file (especially after the recent changes). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627497 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontCache.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index efd7ea603..13afa5a65 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -31,6 +31,7 @@ import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; import org.apache.fop.util.LogUtil; @@ -39,8 +40,11 @@ import org.apache.fop.util.LogUtil; */ public final class FontCache implements Serializable { - /** Serialization Version UID */ - private static final long serialVersionUID = 605232520271754717L; + /** + * Serialization Version UID. Change this value if you want to make sure the user's cache + * file is purged after an update. + */ + private static final long serialVersionUID = 605232520271754718L; /** logging instance */ private static Log log = LogFactory.getLog(FontCache.class); -- cgit v1.2.3 From 71ecb950fba8d7134c912acda3a75845930099cb Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 13 Feb 2008 18:11:06 +0000 Subject: Added support for breaks before and after table cells git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627553 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/EffRow.java | 47 +- .../apache/fop/fo/flow/table/EmptyGridUnit.java | 2 +- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 42 + .../org/apache/fop/layoutmgr/table/ActiveCell.java | 20 +- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 14 +- .../org/apache/fop/layoutmgr/table/RowPainter.java | 15 +- .../layoutmgr/table/TableCellLayoutManager.java | 12 +- .../layoutmgr/table/TableContentLayoutManager.java | 15 +- .../apache/fop/layoutmgr/table/TableStepper.java | 36 +- src/java/org/apache/fop/util/BreakUtil.java | 65 ++ status.xml | 4 + .../standard-testcases/table-cell_break-after.xml | 1018 ++++++++++++++++++++ .../table-cell_break-after_last-row.xml | 688 +++++++++++++ .../standard-testcases/table-cell_break-before.xml | 1018 ++++++++++++++++++++ .../table-cell_break-before_first-row.xml | 688 +++++++++++++ .../table-cell_break-before_inside.xml | 6 +- .../table-cell_row-span_breaks.xml | 197 ++++ 17 files changed, 3824 insertions(+), 63 deletions(-) create mode 100644 src/java/org/apache/fop/util/BreakUtil.java create mode 100644 test/layoutengine/standard-testcases/table-cell_break-after.xml create mode 100644 test/layoutengine/standard-testcases/table-cell_break-after_last-row.xml create mode 100644 test/layoutengine/standard-testcases/table-cell_break-before.xml create mode 100644 test/layoutengine/standard-testcases/table-cell_break-before_first-row.xml create mode 100644 test/layoutengine/standard-testcases/table-cell_row-span_breaks.xml (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java index fb2162e55..ac99a1d37 100644 --- a/src/java/org/apache/fop/fo/flow/table/EffRow.java +++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java @@ -22,8 +22,10 @@ package org.apache.fop.fo.flow.table; import java.util.Iterator; import java.util.List; +import org.apache.fop.fo.Constants; import org.apache.fop.layoutmgr.table.TableRowIterator; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.BreakUtil; /** * This class represents an effective row in a table and holds a list of grid units occupying @@ -159,7 +161,50 @@ public class EffRow { throw new IllegalArgumentException("Illegal flag queried: " + which); } } - + + + /** + * Returns the break class for this row. This is a combination of break-before set on + * the first children of any cells starting on this row. + *

    Note: this works only after getNextKuthElements on the + * corresponding TableCellLM have been called!

    + * + * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link + * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE} + */ + public int getBreakBefore() { + int breakBefore = Constants.EN_AUTO; + for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + if (gu.isPrimary()) { + breakBefore = BreakUtil.compareBreakClasses(breakBefore, + gu.getPrimary().getBreakBefore()); + } + } + return breakBefore; + } + + /** + * Returns the break class for this row. This is a combination of break-after set on + * the last children of any cells ending on this row. + *

    Note: this works only after getNextKuthElements on the + * corresponding TableCellLM have been called!

    + * + * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link + * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE} + */ + public int getBreakAfter() { + int breakAfter = Constants.EN_AUTO; + for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + if (gu.isPrimary()) { + breakAfter = BreakUtil.compareBreakClasses(breakAfter, + gu.getPrimary().getBreakAfter()); + } + } + return breakAfter; + } + /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer("EffRow {"); diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java index ac793f889..583abcaa3 100644 --- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java @@ -52,7 +52,7 @@ public class EmptyGridUnit extends GridUnit { /** {@inheritDoc} */ public boolean isPrimary() { - return true; + return false; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index cff3c2ac1..c95f3f8c3 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -22,6 +22,7 @@ package org.apache.fop.fo.flow.table; import java.util.LinkedList; import java.util.List; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.table.TableCellLayoutManager; @@ -51,6 +52,9 @@ public class PrimaryGridUnit extends GridUnit { private boolean isSeparateBorderModel; private int halfBorderSeparationBPD; + private int breakBefore = Constants.EN_AUTO; + private int breakAfter = Constants.EN_AUTO; + /** * Creates a new primary grid unit. * @@ -320,4 +324,42 @@ public class PrimaryGridUnit extends GridUnit { cellLM = new TableCellLayoutManager(cell, this); } + /** + * Returns the class of the before break for the first child element of this cell. + * + * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link + * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE} + */ + public int getBreakBefore() { + return breakBefore; + } + + /** + * Don't use, reserved for TableCellLM. TODO + * + * @param breakBefore the breakBefore to set + */ + public void setBreakBefore(int breakBefore) { + this.breakBefore = breakBefore; + } + + /** + * Returns the class of the before after for the last child element of this cell. + * + * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link + * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE} + */ + public int getBreakAfter() { + return breakAfter; + } + + /** + * Don't use, reserved for TableCellLM. TODO + * + * @param breakAfter the breakAfter to set + */ + public void setBreakAfter(int breakAfter) { + this.breakAfter = breakAfter; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 485c63ea2..d89f43370 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -335,6 +335,7 @@ class ActiveCell { } else { nextStep.set(afterNextStep); nextStep.start = previousStep.end + 1; + afterNextStep.start = nextStep.start; if (afterNextStep.end < elementList.size() - 1) { gotoNextLegalBreak(); } @@ -405,17 +406,6 @@ class ActiveCell { } } - /** - * Returns true if some content of this cell is part of the chosen next step. - * - * @return true if this cell's next step is inferior or equal to the next minimal step - */ - boolean contributesContent() { - // return includedInLastStep() && the cell hasn't finished yet, otherwise there's - // nothing more to contribute - return includedInLastStep() && nextStep.end >= nextStep.start; - } - /** * Returns true if this cell would be finished after the given step. That is, it would * be included in the step and the end of its content would be reached. @@ -469,14 +459,6 @@ class ActiveCell { } } - boolean isLastForcedBreak() { - return ((KnuthElement)elementList.get(nextStep.end)).isForcedBreak(); - } - - int getLastBreakClass() { - return ((KnuthPenalty)elementList.get(nextStep.end)).getBreakClass(); - } - boolean keepWithNextSignal() { return keepWithNextSignal; } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 6d66da097..0127f4d81 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -40,6 +40,7 @@ import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.MinOptMaxUtil; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.BreakUtil; class RowGroupLayoutManager { @@ -66,11 +67,13 @@ class RowGroupLayoutManager { */ int getBreakBefore() { TableRow rowFO = rowGroup[0].getTableRow(); + int breakBefore; if (rowFO == null) { - return Constants.EN_AUTO; + breakBefore = Constants.EN_AUTO; } else { - return rowFO.getBreakBefore(); + breakBefore = rowFO.getBreakBefore(); } + return BreakUtil.compareBreakClasses(breakBefore, rowGroup[0].getBreakBefore()); } /** @@ -81,11 +84,14 @@ class RowGroupLayoutManager { */ int getBreakAfter() { TableRow rowFO = rowGroup[rowGroup.length - 1].getTableRow(); + int breakAfter; if (rowFO == null) { - return Constants.EN_AUTO; + breakAfter = Constants.EN_AUTO; } else { - return rowFO.getBreakAfter(); + breakAfter = rowFO.getBreakAfter(); } + return BreakUtil.compareBreakClasses(breakAfter, + rowGroup[rowGroup.length - 1].getBreakAfter()); } public LinkedList getNextKnuthElements(LayoutContext context, int alignment, int bodyType) { diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 26880faea..022ff0589 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -160,7 +160,17 @@ class RowPainter { for (int i = 0; i < colCount; i++) { GridUnit currentGU = currentRow.getGridUnit(i); if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 - && (lastInPart || currentGU.isLastGridUnitRowSpan())) { + && (lastInPart || currentGU.isLastGridUnitRowSpan()) + && firstCellParts[i] != null) { + // TODO + // The last test above is a workaround for the stepping algorithm's + // fundamental flaw making it unable to produce the right element list for + // multiple breaks inside a same row group. + // (see http://wiki.apache.org/xmlgraphics-fop/TableLayout/KnownProblems) + // In some extremely rare cases (forced breaks, very small page height), a + // TableContentPosition produced during row delaying may end up alone on a + // page. It will not contain the CellPart instances for the cells starting + // the next row, so firstCellParts[i] will still be null for those ones. int cellHeight = cellHeights[i]; cellHeight += lastCellParts[i].getConditionalAfterContentLength(); cellHeight += lastCellParts[i].getBorderPaddingAfter(lastInPart); @@ -177,7 +187,8 @@ class RowPainter { for (int i = 0; i < colCount; i++) { GridUnit currentGU = currentRow.getGridUnit(i); if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 - && (lastInPart || currentGU.isLastGridUnitRowSpan())) { + && (lastInPart || currentGU.isLastGridUnitRowSpan()) + && firstCellParts[i] != null) { assert firstCellParts[i].pgu == currentGU.getPrimary(); int borderBeforeWhich; if (firstCellParts[i].start == 0) { diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 9469a1121..fbc118723 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -210,7 +210,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager // with a SpaceResolver.SpaceHandlingBreakPosition element, having no // LM associated to it. Thus it will stop early instead of adding // areas for following Positions. The above test aims at preventing - // such a situation from occuring. add a null penalty to allow a break + // such a situation from occurring. add a null penalty to allow a break // between blocks contentList.add(new BreakElement( new Position(this), 0, context)); @@ -246,6 +246,16 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } //Space resolution SpaceResolver.resolveElementList(returnList); + if (((KnuthElement) returnList.getFirst()).isForcedBreak()) { + primaryGridUnit.setBreakBefore(((KnuthPenalty) returnList.getFirst()).getBreakClass()); + returnList.removeFirst(); + assert !returnList.isEmpty(); + } + if (((KnuthElement) returnList.getLast()).isForcedBreak()) { + KnuthPenalty p = (KnuthPenalty) returnList.getLast(); + primaryGridUnit.setBreakAfter(p.getBreakClass()); + p.setP(0); + } getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId()); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index baf1bd369..c09b9b076 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -48,6 +48,7 @@ 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. @@ -212,10 +213,14 @@ public class TableContentLayoutManager implements PercentBaseContext { while ((rowGroup = iter.getNextRowGroup()) != null) { RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, stepper); - if (breakBetween == Constants.EN_AUTO) { - // TODO improve - breakBetween = rowGroupLM.getBreakBefore(); - } + // TODO + // The RowGroupLM.getBreakBefore method will work correctly only after + // getNextKnuthElements is called. Indeed TableCellLM will set the values for + // breaks on PrimaryGridUnit once it has got the Knuth elements of its + // children. This can be changed once all the LMs adopt the same scheme of + // querying childrens LMs for breaks instead of producing penalty elements + List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); + breakBetween = BreakUtil.compareBreakClasses(breakBetween, rowGroupLM.getBreakBefore()); if (breakBetween != Constants.EN_AUTO) { if (returnList.size() > 0) { BreakElement breakPoss = (BreakElement) returnList.getLast(); @@ -226,7 +231,7 @@ public class TableContentLayoutManager implements PercentBaseContext { 0, -KnuthPenalty.INFINITE, breakBetween, context)); } } - returnList.addAll(rowGroupLM.getNextKnuthElements(context, alignment, bodyType)); + returnList.addAll(nextRowGroupElems); breakBetween = rowGroupLM.getBreakAfter(); } // Break after the table's last row diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 4eff1e931..0b494bf2d 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -37,6 +37,7 @@ 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. @@ -243,6 +244,12 @@ public class TableStepper { if (signalKeepWithNext || getTableLM().mustKeepTogether()) { p = KnuthPenalty.INFINITE; } + if (rowFinished && activeRowIndex < rowGroup.length - 1) { + 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) @@ -381,33 +388,8 @@ public class TableStepper { nextBreakClass = Constants.EN_AUTO; for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); - nextBreakClass = compareBreakClasses(nextBreakClass, activeCell.signalNextStep(step)); - } - } - - // TODO replace that with a proper 1.5 enumeration ASAP - // TODO this has nothing to do here - private static int getBreakClassPriority(int breakClass) { - switch (breakClass) { - case Constants.EN_AUTO: return 0; - case Constants.EN_COLUMN: return 1; - case Constants.EN_PAGE: return 2; - case Constants.EN_EVEN_PAGE: return 3; - case Constants.EN_ODD_PAGE: return 3; - default: throw new IllegalArgumentException(); - } - } - - // TODO even-page and odd-page can't be compared to each other and instead create a - // conflict situation. For now the first encountered break will win, but eventually - // some warning message should be sent to the user. - private static int compareBreakClasses(int b1, int b2) { - int p1 = getBreakClassPriority(b1); - int p2 = getBreakClassPriority(b2); - if (p1 < p2) { - return b2; - } else { - return b1; + nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass, + activeCell.signalNextStep(step)); } } diff --git a/src/java/org/apache/fop/util/BreakUtil.java b/src/java/org/apache/fop/util/BreakUtil.java new file mode 100644 index 000000000..c0528464d --- /dev/null +++ b/src/java/org/apache/fop/util/BreakUtil.java @@ -0,0 +1,65 @@ +/* + * 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 org.apache.fop.fo.Constants; + +/** + * A utility class for manipulating break classes (the break-before and break-after properties). + */ +public final class BreakUtil { + + private BreakUtil() { } + + // TODO replace that with a proper 1.5 enumeration ASAP + private static int getBreakClassPriority(int breakClass) { + switch (breakClass) { + case Constants.EN_AUTO: return 0; + case Constants.EN_COLUMN: return 1; + case Constants.EN_PAGE: return 2; + case Constants.EN_EVEN_PAGE: return 3; + case Constants.EN_ODD_PAGE: return 3; + default: throw new IllegalArgumentException(); + } + } + + /** + * Compares the given break classes and return the one that wins. even-page and + * odd-page win over page, which wins over column, which wins over auto. If even-page + * and odd-page are compared to each other, which one will be returned is undefined. + * + * @param break1 a break class, one of {@link Constants#EN_AUTO}, + * {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, + * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE} + * @param break2 another break class + * @return the break class that wins the comparison + */ + public static int compareBreakClasses(int break1, int break2) { + // TODO implement some warning mechanism if even-page and odd-page are being compared + int p1 = getBreakClassPriority(break1); + int p2 = getBreakClassPriority(break2); + if (p1 < p2) { + return break2; + } else { + return break1; + } + } + +} diff --git a/status.xml b/status.xml index 2eaf1a553..367bdf58d 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Added full support for breaks before and after table cells (that is, break-before/after set + on the first/last child of a cell). + Added full support for breaks inside the cells of a table. diff --git a/test/layoutengine/standard-testcases/table-cell_break-after.xml b/test/layoutengine/standard-testcases/table-cell_break-after.xml new file mode 100644 index 000000000..35d3f626a --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_break-after.xml @@ -0,0 +1,1018 @@ + + + + + +

    + This test checks that break-after set on blocks in table-cells works correctly in various + conditions: when headers/footers shall be repeated at page breaks or not, in the separate or + collapsing border model, etc. +

    +
    + + + + + + + + + + + + 1. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 2. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 3. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 4. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 5. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 6. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 7. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 8. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_break-after_last-row.xml b/test/layoutengine/standard-testcases/table-cell_break-after_last-row.xml new file mode 100644 index 000000000..290d8dea7 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_break-after_last-row.xml @@ -0,0 +1,688 @@ + + + + + +

    + This test checks that break-after set on blocks in table-cells works correctly in various + conditions: when headers/footers shall be repeated at page breaks or not, in the separate or + collapsing border model, etc. +

    +
    + + + + + + + + + + + + 1. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 2. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 3. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 4. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 5. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 6. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_break-before.xml b/test/layoutengine/standard-testcases/table-cell_break-before.xml new file mode 100644 index 000000000..8371afd97 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_break-before.xml @@ -0,0 +1,1018 @@ + + + + + +

    + This test checks that break-before set on blocks in table-cells works correctly in various + conditions: when headers/footers shall be repeated at page breaks or not, in the separate or + collapsing border model, etc. +

    +
    + + + + + + + + + + + + 1. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 2. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 3. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 4. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 5. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 6. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 7. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 8. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_break-before_first-row.xml b/test/layoutengine/standard-testcases/table-cell_break-before_first-row.xml new file mode 100644 index 000000000..c5e704aae --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_break-before_first-row.xml @@ -0,0 +1,688 @@ + + + + + +

    + This test checks that break-before set on blocks in table-cells works correctly in various + conditions: when headers/footers shall be repeated at page breaks or not, in the separate or + collapsing border model, etc. +

    +
    + + + + + + + + + + + + 1. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 2. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 3. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 4. Before the table + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 5. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + 6. Before the table + + + + + Header 1.1 + Header 1.2 + + + + + Footer 1.1 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.1 + Cell 2.1 + + + Cell 2.2 + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + Cell 3.2 + Cell 3.2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_break-before_inside.xml b/test/layoutengine/standard-testcases/table-cell_break-before_inside.xml index 780d60015..b79176be6 100644 --- a/test/layoutengine/standard-testcases/table-cell_break-before_inside.xml +++ b/test/layoutengine/standard-testcases/table-cell_break-before_inside.xml @@ -19,9 +19,9 @@

    - This test checks that break-before set on table-rows work correctly in various conditions: - when headers/footers shall be repeated at page breaks or not, in the separate or collapsing - border model, etc. + This test checks that break-before set on blocks in table-cells works correctly in various + conditions: when headers/footers shall be repeated at page breaks or not, in the separate or + collapsing border model, etc.

    diff --git a/test/layoutengine/standard-testcases/table-cell_row-span_breaks.xml b/test/layoutengine/standard-testcases/table-cell_row-span_breaks.xml new file mode 100644 index 000000000..f00d9894d --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_row-span_breaks.xml @@ -0,0 +1,197 @@ + + + + + +

    + This test checks that breaks on blocks inside cells work correctly when row spanning is in + progress. +

    +
    + + + + + + + + + + + + Before the table + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + Cell 1.1 Line 4 + + + Cell 1.2 Line 1 + Cell 1.2 Line 2 + + + + + Cell 2.2 Line 1 + Cell 2.2 Line 2 + + + + + After the table + + + + + + + + Before the table + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + + + Cell 1.2 Line 1 + Cell 1.2 Line 2 + Cell 1.2 Line 3 + Cell 1.2 Line 4 + + + + + Cell 2.1 Line 1 + Cell 2.1 Line 2 + + + + + After the table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -- cgit v1.2.3 From 40f03bc5a0233f5081acae13cc55f26e91714790 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 13 Feb 2008 20:10:01 +0000 Subject: Moved to the FO tree stage the check for break-before/after on table-row while spanning in progress, and fixed bug #44321 as well git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627576 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FONode.java | 2 +- .../fop/fo/flow/table/FixedColRowGroupBuilder.java | 20 +++++++++++++++++++- .../apache/fop/fo/flow/table/RowGroupBuilder.java | 19 +++++++++++++++---- .../fo/flow/table/VariableColRowGroupBuilder.java | 13 +++++++++++-- .../org/apache/fop/layoutmgr/table/TableStepper.java | 14 -------------- status.xml | 4 ++++ .../table-row_break-inside-span.xml | 8 ++++---- 7 files changed, 54 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index 7c517e418..f0422e414 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -360,7 +360,7 @@ public abstract class FONode implements Cloneable { * (e.g., currently unsupported properties) * @param problem text to display that indicates the problem */ - protected void attributeWarning(String problem) { + public void attributeWarning(String problem) { log.warn(warningText(locator) + getName() + ", " + problem); } diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index b0126dff0..62cf3e26d 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.List; import java.util.ListIterator; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.ValidationException; @@ -115,7 +116,24 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void endRow(TableCellContainer container) { + void endRow(TableRow row) { + if (currentRowIndex > 0 && row.getBreakBefore() != Constants.EN_AUTO) { + row.attributeWarning("break-before ignored because of row spanning " + + "in progress (See XSL 1.1, 7.20.2)"); + } + if (currentRowIndex < rows.size() - 1 && row.getBreakAfter() != Constants.EN_AUTO) { + row.attributeWarning("break-after ignored because of row spanning " + + "in progress (See XSL 1.1, 7.20.1)"); + } + handleRowEnd(row); + } + + /** {@inheritDoc} */ + void endRow(TableBody body) { + handleRowEnd(body); + } + + private void handleRowEnd(TableCellContainer container) { List currentRow = (List) rows.get(currentRowIndex); lastRow = currentRow; // Fill gaps with empty grid units diff --git a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java index f25886581..3f7549787 100644 --- a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java @@ -58,12 +58,23 @@ abstract class RowGroupBuilder { /** * Receives notification of the end of the current row. If the current row finishes * the row group, the {@link TableBody#addRowGroup(List)} method of the parent table - * part (i.e., the given container itself or its parent if this is a table-row) will - * be called + * part will be called. * - * @param container the parent element of the current row + * @param row the row being finished */ - abstract void endRow(TableCellContainer container); + abstract void endRow(TableRow row); + + /** + * Receives notification of the end of the current row, when the source contains no + * fo:table-row element. If the current row finishes the row group, the + * {@link TableBody#addRowGroup(List)} method of the given table part will be called. + * + *

    If the source does contain explicit fo:table-row elements, then the + * {@link #endRow(TableRow)} method will be called instead.

    + * + * @param part the part containing the current row + */ + abstract void endRow(TableBody part); /** * Receives notification of the start of a table-header/footer/body. diff --git a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java index 47c96dcca..801153ce9 100644 --- a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java @@ -73,10 +73,19 @@ class VariableColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void endRow(final TableCellContainer container) { + void endRow(final TableRow row) { events.add(new Event() { public void play(RowGroupBuilder rowGroupBuilder) { - rowGroupBuilder.endRow(container); + rowGroupBuilder.endRow(row); + } + }); + } + + /** {@inheritDoc} */ + void endRow(final TableBody part) { + events.add(new Event() { + public void play(RowGroupBuilder rowGroupBuilder) { + rowGroupBuilder.endRow(part); } }); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 0b494bf2d..2560b3aac 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -26,11 +26,9 @@ import java.util.List; 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; @@ -456,20 +454,8 @@ public class TableStepper { */ private void prepareNextRow() { if (activeRowIndex < rowGroup.length - 1) { - TableRow rowFO = rowGroup[activeRowIndex].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; activateCells(nextActiveCells, activeRowIndex + 1); - rowFO = rowGroup[activeRowIndex + 1].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)); - } if (log.isTraceEnabled()) { log.trace("Computing first step for row " + (activeRowIndex + 2)); } diff --git a/status.xml b/status.xml index 367bdf58d..7926fe379 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Moved to the FO tree stage the check for break-before/after on table-row while spanning in + progress. + Added full support for breaks before and after table cells (that is, break-before/after set on the first/last child of a cell). diff --git a/test/layoutengine/standard-testcases/table-row_break-inside-span.xml b/test/layoutengine/standard-testcases/table-row_break-inside-span.xml index 9918ec5ed..d55921e57 100644 --- a/test/layoutengine/standard-testcases/table-row_break-inside-span.xml +++ b/test/layoutengine/standard-testcases/table-row_break-inside-span.xml @@ -20,7 +20,7 @@

    This test checks breaks on tables. Breaks on table-row during row spanning are ignored - (XSL 1.0, 7.19.1 and 7.19.2). + (XSL 1.1, 7.20.1 and 7.20.2).

    @@ -33,10 +33,10 @@ - - + - + cell1 line 1 cell1 line 2 -- cgit v1.2.3 From c29ce0ae80329a756e17c263c1c4886d50708b3f Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 14 Feb 2008 08:12:34 +0000 Subject: Added support for Type 1 fonts which don't use the AdobeStandardEncoding for PDF and PS output. Details: Added an Type 1 AFM parser (only basic ltr script fonts are properly supported). Font loading changed slightly to allow loading an AFM in addition to a PFM. Added some mapping functionality to CodePointMapping. Now we also build custom CodePointMapping instances from AFM files and use it in SingleByteFonts. Changed more PDF object classes to make use of the generic PDFDictionary and PDFArray base classes. Type 1 Fonts with a special encoding now register their encoding in the Encoding value of the font dictionary so the mapping is correct. For PS this isn't necessary as the interpreter just uses the font's default encoding. Refactored CMap building code to it can also be used outside the PDF context. A CMap can now also be built from a single byte encoding. Update of XML Graphics Commons snapshot. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627679 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.3svn.jar | Bin 499250 -> 500806 bytes src/codegen/fonts/code-point-mapping.xsl | 44 +- src/codegen/fonts/encodings.xml | 18 +- src/java/org/apache/fop/fonts/CIDFontType.java | 4 +- src/java/org/apache/fop/fonts/CustomFont.java | 21 +- src/java/org/apache/fop/fonts/FontLoader.java | 59 +- src/java/org/apache/fop/fonts/FontType.java | 2 +- src/java/org/apache/fop/fonts/SingleByteFont.java | 111 ++-- .../apache/fop/fonts/truetype/TTFFontLoader.java | 32 +- .../org/apache/fop/fonts/type1/AFMCharMetrics.java | 131 +++++ src/java/org/apache/fop/fonts/type1/AFMFile.java | 378 +++++++++++++ src/java/org/apache/fop/fonts/type1/AFMParser.java | 594 +++++++++++++++++++++ .../fonts/type1/AFMWritingDirectionMetrics.java | 96 ++++ .../apache/fop/fonts/type1/Type1FontLoader.java | 213 +++++++- src/java/org/apache/fop/pdf/CMapBuilder.java | 157 ++++++ src/java/org/apache/fop/pdf/PDFArray.java | 5 +- .../org/apache/fop/pdf/PDFCIDFontDescriptor.java | 38 +- src/java/org/apache/fop/pdf/PDFCMap.java | 122 +---- src/java/org/apache/fop/pdf/PDFDictionary.java | 6 + src/java/org/apache/fop/pdf/PDFEncoding.java | 148 ++--- src/java/org/apache/fop/pdf/PDFFactory.java | 86 +-- src/java/org/apache/fop/pdf/PDFFont.java | 182 ++----- src/java/org/apache/fop/pdf/PDFFontDescriptor.java | 98 ++-- src/java/org/apache/fop/pdf/PDFFontNonBase14.java | 57 +- src/java/org/apache/fop/pdf/PDFFontTrueType.java | 4 +- src/java/org/apache/fop/pdf/PDFFontType0.java | 44 +- src/java/org/apache/fop/pdf/PDFFontType3.java | 58 +- src/java/org/apache/fop/pdf/PDFObject.java | 5 +- src/java/org/apache/fop/pdf/PDFRectangle.java | 30 +- src/java/org/apache/fop/pdf/PDFT1Stream.java | 5 +- src/java/org/apache/fop/pdf/PDFTTFStream.java | 4 +- src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java | 417 ++++++++------- .../org/apache/fop/render/pdf/PDFRenderer.java | 2 +- src/java/org/apache/fop/render/ps/PSFontUtils.java | 12 +- src/java/org/apache/fop/util/CharUtilities.java | 5 +- status.xml | 4 + .../org/apache/fop/render/pdf/PDFCMapTestCase.java | 14 +- 37 files changed, 2272 insertions(+), 934 deletions(-) create mode 100644 src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java create mode 100644 src/java/org/apache/fop/fonts/type1/AFMFile.java create mode 100644 src/java/org/apache/fop/fonts/type1/AFMParser.java create mode 100644 src/java/org/apache/fop/fonts/type1/AFMWritingDirectionMetrics.java create mode 100644 src/java/org/apache/fop/pdf/CMapBuilder.java (limited to 'src') diff --git a/lib/xmlgraphics-commons-1.3svn.jar b/lib/xmlgraphics-commons-1.3svn.jar index 0abad1c33..80927dd7e 100644 Binary files a/lib/xmlgraphics-commons-1.3svn.jar and b/lib/xmlgraphics-commons-1.3svn.jar differ diff --git a/src/codegen/fonts/code-point-mapping.xsl b/src/codegen/fonts/code-point-mapping.xsl index 53636505d..80b62dd17 100644 --- a/src/codegen/fonts/code-point-mapping.xsl +++ b/src/codegen/fonts/code-point-mapping.xsl @@ -40,23 +40,37 @@ package org.apache.fop.fonts; +import java.util.Arrays; import java.util.Map; import java.util.Collections; +import org.apache.fop.util.CharUtilities; + public class CodePointMapping { + + + + private String name; private char[] latin1Map; private char[] characters; private char[] codepoints; + private char[] unicodeMap; //code point to Unicode char - private CodePointMapping(int [] table) { + public CodePointMapping(String name, int[] table) { + this.name = name; int nonLatin1 = 0; latin1Map = new char[256]; + unicodeMap = new char[256]; + Arrays.fill(unicodeMap, CharUtilities.NOT_A_CHARACTER); for (int i = 0; i < table.length; i += 2) { if (table[i + 1] < 256) { latin1Map[table[i + 1]] = (char) table[i]; } else { ++nonLatin1; } + if (unicodeMap[table[i]] == CharUtilities.NOT_A_CHARACTER) { + unicodeMap[table[i]] = (char)table[i + 1]; + } } characters = new char[nonLatin1]; codepoints = new char[nonLatin1]; @@ -79,6 +93,10 @@ public class CodePointMapping { } } + public String getName() { + return this.name; + } + public final char mapChar(char c) { if (c < 256) { return latin1Map[c]; @@ -100,10 +118,26 @@ public class CodePointMapping { } } + public final char getUnicodeForIndex(int idx) { + return this.unicodeMap[idx]; + } + + public final char[] getUnicodeCharMap() { + char[] copy = new char[this.unicodeMap.length]; + System.arraycopy(this.unicodeMap, 0, copy, 0, this.unicodeMap.length); + return copy; + } + + /** {@inheritDoc} */ + public String toString() { + return getName(); + } + private static Map mappings; static { mappings = Collections.synchronizedMap(new java.util.HashMap()); } + public static CodePointMapping getMapping(String encoding) { CodePointMapping mapping = (CodePointMapping) mappings.get(encoding); if (mapping != null) { @@ -119,10 +153,12 @@ public class CodePointMapping { } + public static final String = ""; + - else if (encoding.equals("")) { - mapping = new CodePointMapping(enc); - mappings.put("", mapping); + else if (encoding.equals()) { + mapping = new CodePointMapping(, enc); + mappings.put(, mapping); return mapping; } diff --git a/src/codegen/fonts/encodings.xml b/src/codegen/fonts/encodings.xml index 1f8497ee3..d7855000e 100644 --- a/src/codegen/fonts/encodings.xml +++ b/src/codegen/fonts/encodings.xml @@ -19,12 +19,12 @@ - + ]> - + @@ -175,7 +175,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -594,7 +594,7 @@ - + @@ -803,7 +803,7 @@ - + @@ -1021,7 +1021,7 @@ - + @@ -1252,7 +1252,7 @@ - + @@ -1443,7 +1443,7 @@ - + diff --git a/src/java/org/apache/fop/fonts/CIDFontType.java b/src/java/org/apache/fop/fonts/CIDFontType.java index 4fa3597b2..51b4a73d1 100644 --- a/src/java/org/apache/fop/fonts/CIDFontType.java +++ b/src/java/org/apache/fop/fonts/CIDFontType.java @@ -27,12 +27,12 @@ import org.apache.avalon.framework.ValuedEnum; public class CIDFontType extends ValuedEnum { /** - * CID Font Type 0 + * CID Font Type 0 (based on Type 1 format) */ public static final CIDFontType CIDTYPE0 = new CIDFontType("CIDFontType0", 0); /** - * CID Font Type 2 + * CID Font Type 2 (based on TrueType format) */ public static final CIDFontType CIDTYPE2 = new CIDFontType("CIDFontType2", 1); diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index f165fbd67..0ac3b80bc 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/src/java/org/apache/fop/fonts/CustomFont.java @@ -230,9 +230,7 @@ public abstract class CustomFont extends Typeface * @return the index of the first character */ public int getFirstChar() { - return 0; - // return firstChar; - /**(todo) Why is this hardcoded??? This code was in SingleByteFont.java */ + return firstChar; } /** @@ -408,14 +406,25 @@ public abstract class CustomFont extends Typeface this.resolver = resolver; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void putKerningEntry(Integer key, Map value) { if (kerning == null) { kerning = new java.util.HashMap(); } this.kerning.put(key, value); } + + /** + * Replaces the existing kerning map with a new one. + * @param kerningMap the kerning map (Map, the integers are + * character codes) + */ + public void replaceKerningMap(Map kerningMap) { + if (kerningMap == null) { + this.kerning = Collections.EMPTY_MAP; + } else { + this.kerning = kerningMap; + } + } } diff --git a/src/java/org/apache/fop/fonts/FontLoader.java b/src/java/org/apache/fop/fonts/FontLoader.java index 8b682f1ae..1fa328a0a 100644 --- a/src/java/org/apache/fop/fonts/FontLoader.java +++ b/src/java/org/apache/fop/fonts/FontLoader.java @@ -28,9 +28,9 @@ import java.net.URL; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; -import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fonts.truetype.TTFFontLoader; import org.apache.fop.fonts.type1.Type1FontLoader; @@ -46,8 +46,6 @@ public abstract class FontLoader { /** URI representing the font file */ protected String fontFileURI = null; - /** the InputStream to load the font from */ - protected InputStream in = null; /** the FontResolver to use for font URI resolution */ protected FontResolver resolver = null; /** the loaded font */ @@ -59,12 +57,10 @@ public abstract class FontLoader { /** * Default constructor. * @param fontFileURI the URI to the PFB file of a Type 1 font - * @param in the InputStream reading the PFM file of a Type 1 font * @param resolver the font resolver used to resolve URIs */ - public FontLoader(String fontFileURI, InputStream in, FontResolver resolver) { + public FontLoader(String fontFileURI, FontResolver resolver) { this.fontFileURI = fontFileURI; - this.in = in; this.resolver = resolver; } @@ -107,58 +103,25 @@ public abstract class FontLoader { public static CustomFont loadFont(String fontFileURI, FontResolver resolver) throws IOException { fontFileURI = fontFileURI.trim(); - String effURI; boolean type1 = isType1(fontFileURI); + FontLoader loader; if (type1) { - String pfmExt = fontFileURI.substring( - fontFileURI.length() - 3, fontFileURI.length()); - pfmExt = pfmExt.substring(0, 2) + (Character.isUpperCase(pfmExt.charAt(2)) ? "M" : "m"); - effURI = fontFileURI.substring(0, fontFileURI.length() - 4) + "." + pfmExt; + loader = new Type1FontLoader(fontFileURI, resolver); } else { - effURI = fontFileURI; + loader = new TTFFontLoader(fontFileURI, resolver); } - if (log.isDebugEnabled()) { - log.debug("opening " + effURI); - } - InputStream in = openFontUri(resolver, effURI); - return loadFontFromInputStream(fontFileURI, resolver, type1, in); + return loader.getFont(); } /** - * Loads and returns a font given an input stream. - * @param fontFileURI font file uri - * @param resolver font resolver - * @param isType1 is it a type1 font? - * @param in input stream - * @return the loaded font. - * @throws IOException In case of an I/O error - */ - protected static CustomFont loadFontFromInputStream( - String fontFileURI, FontResolver resolver, boolean isType1, - InputStream in) - throws IOException { - FontLoader loader; - try { - if (isType1) { - loader = new Type1FontLoader(fontFileURI, in, resolver); - } else { - loader = new TTFFontLoader(fontFileURI, in, resolver); - } - return loader.getFont(); - } finally { - IOUtils.closeQuietly(in); - } - } - - /** - * Opens a font uri and returns an input stream. + * Opens a font URI and returns an input stream. * @param resolver the FontResolver to use for font URI resolution * @param uri the URI representing the font * @return the InputStream to read the font from. * @throws IOException In case of an I/O error * @throws MalformedURLException If an invalid URL is built */ - private static InputStream openFontUri(FontResolver resolver, String uri) + protected static InputStream openFontUri(FontResolver resolver, String uri) throws IOException, MalformedURLException { InputStream in = null; if (resolver != null) { @@ -191,7 +154,11 @@ public abstract class FontLoader { */ protected abstract void read() throws IOException; - /** @see FontLoader#getFont() */ + /** + * Returns the custom font that was read using this instance of FontLoader. + * @return the newly loaded font + * @throws IOException if an I/O error occurs + */ public CustomFont getFont() throws IOException { if (!loaded) { read(); diff --git a/src/java/org/apache/fop/fonts/FontType.java b/src/java/org/apache/fop/fonts/FontType.java index a00721ebf..50ca2c8a6 100644 --- a/src/java/org/apache/fop/fonts/FontType.java +++ b/src/java/org/apache/fop/fonts/FontType.java @@ -31,7 +31,7 @@ public class FontType extends ValuedEnum { */ public static final FontType OTHER = new FontType("Other", 0); /** - * Adobe Type 0 fonts + * Adobe Type 0 fonts (composite font) */ public static final FontType TYPE0 = new FontType("Type0", 1); /** diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index 1df44b3a2..b6f65edc8 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -19,6 +19,8 @@ package org.apache.fop.fonts; +import java.util.Set; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -32,92 +34,113 @@ public class SingleByteFont extends CustomFont { private CodePointMapping mapping; - private String encoding = "WinAnsiEncoding"; - private int[] width = null; + private Set warnedChars; + /** * Main constructor. */ public SingleByteFont() { - updateMapping(); + setEncoding(CodePointMapping.WIN_ANSI_ENCODING); } - /** - * Updates the mapping variable based on the encoding. - */ - protected void updateMapping() { - try { - mapping = CodePointMapping.getMapping(getEncoding()); - } catch (UnsupportedOperationException e) { - log.error("Font '" + super.getFontName() + "': " + e.getMessage()); - } - } - - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean isEmbeddable() { return (getEmbedFileName() == null && getEmbedResourceName() == null) ? false : true; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getEncoding() { - return encoding; + return this.mapping.getName(); } /** - * Sets the encoding of the font. - * @param encoding the encoding (ex. "WinAnsiEncoding" or "SymbolEncoding") + * Returns the code point mapping (encoding) of this font. + * @return the code point mapping */ - public void setEncoding(String encoding) { - this.encoding = encoding; - updateMapping(); + public CodePointMapping getCodePointMapping() { + return this.mapping; } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ public int getWidth(int i, int size) { - return size * width[i]; + int idx = i - getFirstChar(); + if (idx >= 0 && idx < width.length) { + return size * width[i - getFirstChar()]; + } else { + return 0; + } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int[] getWidths() { int[] arr = new int[width.length]; System.arraycopy(width, 0, arr, 0, width.length - 1); return arr; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public char mapChar(char c) { notifyMapOperation(); char d = mapping.mapChar(c); if (d != 0) { return d; } else { - log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) - + ") not available in font " + getFontName()); + Character ch = new Character(c); + if (warnedChars == null) { + warnedChars = new java.util.HashSet(); + } + if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { + warnedChars.add(ch); + if (warnedChars.size() == 8) { + log.warn("Many requested glyphs are not available in font " + getFontName()); + } else { + log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) + + ", " + Glyphs.charToGlyphName(c) + + ") not available in font " + getFontName()); + } + } return '#'; } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean hasChar(char c) { return (mapping.mapChar(c) > 0); } /* ---- single byte font specific setters --- */ + /** + * Updates the mapping variable based on the encoding. + * @param encoding the name of the encoding + */ + protected void updateMapping(String encoding) { + try { + this.mapping = CodePointMapping.getMapping(encoding); + } catch (UnsupportedOperationException e) { + log.error("Font '" + super.getFontName() + "': " + e.getMessage()); + } + } + + /** + * Sets the encoding of the font. + * @param encoding the encoding (ex. "WinAnsiEncoding" or "SymbolEncoding") + */ + public void setEncoding(String encoding) { + updateMapping(encoding); + } + + /** + * Sets the encoding of the font. + * @param encoding the encoding information + */ + public void setEncoding(CodePointMapping encoding) { + this.mapping = encoding; + } + /** * Sets a width for a character. * @param index index of the character @@ -125,9 +148,9 @@ public class SingleByteFont extends CustomFont { */ public void setWidth(int index, int width) { if (this.width == null) { - this.width = new int[256]; + this.width = new int[getLastChar() - getFirstChar() + 1]; } - this.width[index] = width; + this.width[index - getFirstChar()] = width; } } diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index 58267571e..5c9e51c81 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -25,6 +25,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.apache.commons.io.IOUtils; + import org.apache.fop.fonts.BFEntry; import org.apache.fop.fonts.CIDFontType; import org.apache.fop.fonts.FontLoader; @@ -41,23 +43,30 @@ public class TTFFontLoader extends FontLoader { /** * Default constructor * @param fontFileURI the URI representing the font file - * @param in the InputStream to load the font from * @param resolver the FontResolver for font URI resolution */ - public TTFFontLoader(String fontFileURI, InputStream in, FontResolver resolver) { - super(fontFileURI, in, resolver); + public TTFFontLoader(String fontFileURI, FontResolver resolver) { + super(fontFileURI, resolver); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void read() throws IOException { - TTFFile ttf = new TTFFile(); - FontFileReader reader = new FontFileReader(in); - boolean supported = ttf.readFont(reader, null); - if (!supported) { - throw new IOException("Could not load TrueType font: " + fontFileURI); + InputStream in = openFontUri(resolver, this.fontFileURI); + try { + TTFFile ttf = new TTFFile(); + FontFileReader reader = new FontFileReader(in); + boolean supported = ttf.readFont(reader, null); + if (!supported) { + throw new IOException("Could not load TrueType font: " + fontFileURI); + } + buildFont(ttf); + loaded = true; + } finally { + IOUtils.closeQuietly(in); } + } + + private void buildFont(TTFFile ttf) { if (ttf.isCFF()) { throw new UnsupportedOperationException( "OpenType fonts with CFF data are not supported, yet"); @@ -98,7 +107,6 @@ public class TTFFontLoader extends FontLoader { multiFont.setBFEntries(bfentries); copyKerning(ttf, true); multiFont.setEmbedFileName(this.fontFileURI); - loaded = true; } /** diff --git a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java new file mode 100644 index 000000000..918d9ee08 --- /dev/null +++ b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java @@ -0,0 +1,131 @@ +/* + * 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.fonts.type1; + + +/** + * Holds the metrics of a single character from an AFM file. + */ +public class AFMCharMetrics { + + private int charCode; + private String unicodeChars; + private String charName; + private double widthX; + private double widthY; + + /** + * Returns the character code. + * @return the charCode + */ + public int getCharCode() { + return charCode; + } + + /** + * Sets the character code. + * @param charCode the charCode to set + */ + public void setCharCode(int charCode) { + this.charCode = charCode; + } + + /** + * Returns the Unicode characters represented by this object. Some character names can be + * mapped to multiple Unicode code points, so expect to find more than one character in the + * String. + * @return the Unicode characters + */ + public String getUnicodeChars() { + return this.unicodeChars; + } + + /** + * Sets the Unicode characters represented by this object. + * @param unicodeChars the Unicode characters + */ + public void setUnicodeChars(String unicodeChars) { + this.unicodeChars = unicodeChars; + } + + /** + * Returns the PostScript character name. + * @return the charName + */ + public String getCharName() { + return charName; + } + + /** + * Sets the PostScript character name. + * @param charName the charName to set + */ + public void setCharName(String charName) { + this.charName = charName; + } + + /** + * Returns the progression dimension in x-direction. + * @return the widthX + */ + public double getWidthX() { + return widthX; + } + + /** + * Sets the progression dimension in x-direction + * @param widthX the widthX to set + */ + public void setWidthX(double widthX) { + this.widthX = widthX; + } + + /** + * Returns the progression dimension in y-direction. + * @return the widthY + */ + public double getWidthY() { + return widthY; + } + + /** + * Sets the progression dimension in y-direction + * @param widthY the widthY to set + */ + public void setWidthY(double widthY) { + this.widthY = widthY; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer("AFM Char: "); + sb.append(getCharCode()); + sb.append(" ("); + if (getUnicodeChars() != null) { + for (int i = 0, c = getUnicodeChars().length(); i < c; i++) { + sb.append("0x").append(Integer.toHexString(getUnicodeChars().charAt(i))); + sb.append(", "); + } + } + sb.append(getCharName()).append(')'); + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/fonts/type1/AFMFile.java b/src/java/org/apache/fop/fonts/type1/AFMFile.java new file mode 100644 index 000000000..af912975c --- /dev/null +++ b/src/java/org/apache/fop/fonts/type1/AFMFile.java @@ -0,0 +1,378 @@ +/* + * 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.fonts.type1; + +import java.awt.geom.RectangularShape; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.xmlgraphics.fonts.Glyphs; +import org.apache.xmlgraphics.java2d.Dimension2DDouble; + +/** + * Represents the contents of a Type 1 AFM font metrics file. + */ +public class AFMFile { + + private String fontName; + private String fullName; + private String familyName; + + private String weight; + private RectangularShape fontBBox; + + private String encodingScheme; + private String characterSet; + + private Number capHeight; + private Number xHeight; + private Number ascender; + private Number descender; + private Number stdHW; + private Number stdVW; + + private AFMWritingDirectionMetrics[] writingDirectionMetrics + = new AFMWritingDirectionMetrics[3]; + + private List charMetrics = new java.util.ArrayList(); + //List + private Map charNameToMetrics = new java.util.HashMap(); + //Map + + private Map kerningMap; + //Map> + + /** + * Default constructor. + */ + public AFMFile() { + //nop + } + + /** + * Returns the FontName value. + * @return the font name + */ + public String getFontName() { + return fontName; + } + + /** + * Sets the FontName value. + * @param fontName the font name to set + */ + public void setFontName(String fontName) { + this.fontName = fontName; + } + + /** + * Returns the FullName value. + * @return the full name of the font + */ + public String getFullName() { + return fullName; + } + + /** + * Sets the FullName value. + * @param fullName the full name to set + */ + public void setFullName(String fullName) { + this.fullName = fullName; + } + + /** + * Returns the FamilyName value. + * @return the family name of the font + */ + public String getFamilyName() { + return familyName; + } + + /** + * Sets the FamilyName value. + * @param familyName the family name to set + */ + public void setFamilyName(String familyName) { + this.familyName = familyName; + } + + /** + * Returns the Weight value. + * @return the weight + */ + public String getWeight() { + return weight; + } + + /** + * Sets the Weight value. + * @param weight the weight to set + */ + public void setWeight(String weight) { + this.weight = weight; + } + + /** + * Returns the FontBBox value. + * @return the font's bounding box + */ + public RectangularShape getFontBBox() { + return fontBBox; + } + + /** + * Returns the FontBBox value as integer array. + * @return the font's bounding box + */ + public int[] getFontBBoxAsIntArray() { + RectangularShape rect = getFontBBox(); + return new int[] { + (int)Math.floor(rect.getMinX()), (int)Math.floor(rect.getMinY()), + (int)Math.ceil(rect.getMaxX()), (int)Math.ceil(rect.getMaxY())}; + } + + /** + * Sets the FontBBox value. + * @param fontBBox the fontBBox to set + */ + public void setFontBBox(RectangularShape fontBBox) { + this.fontBBox = fontBBox; + } + + /** + * Returns the EncodingScheme value. + * @return the encoding scheme + */ + public String getEncodingScheme() { + return encodingScheme; + } + + /** + * Sets the EncodingScheme value + * @param encodingScheme the encodingScheme to set + */ + public void setEncodingScheme(String encodingScheme) { + this.encodingScheme = encodingScheme; + } + + /** + * Returns the CharacterSet value. + * @return the characterSet + */ + public String getCharacterSet() { + return characterSet; + } + + /** + * Sets the CharacterSet value. + * @param characterSet the characterSet to set + */ + public void setCharacterSet(String characterSet) { + this.characterSet = characterSet; + } + + /** + * Returns the CapHeight value. + * @return the capHeight + */ + public Number getCapHeight() { + return capHeight; + } + + /** + * Sets the CapHeight value. + * @param capHeight the capHeight to set + */ + public void setCapHeight(Number capHeight) { + this.capHeight = capHeight; + } + + /** + * Returns the XHeight value. + * @return the xHeight + */ + public Number getXHeight() { + return xHeight; + } + + /** + * Sets the XHeight value. + * @param height the xHeight to set + */ + public void setXHeight(Number height) { + xHeight = height; + } + + /** + * Returns the Ascender value. + * @return the ascender + */ + public Number getAscender() { + return ascender; + } + + /** + * Sets the Ascender value. + * @param ascender the ascender to set + */ + public void setAscender(Number ascender) { + this.ascender = ascender; + } + + /** + * Returns the Descender value. + * @return the descender + */ + public Number getDescender() { + return descender; + } + + /** + * Sets the Descender value. + * @param descender the descender to set + */ + public void setDescender(Number descender) { + this.descender = descender; + } + + /** + * Returns the StdHW value. + * @return the descender + */ + public Number getStdHW() { + return stdHW; + } + + /** + * Sets the StdHW value. + * @param stdHW the StdHW to set + */ + public void setStdHW(Number stdHW) { + this.stdHW = stdHW; + } + + /** + * Returns the StdVW value. + * @return the descender + */ + public Number getStdVW() { + return stdVW; + } + + /** + * Sets the StdVW value. + * @param stdVW the StdVW to set + */ + public void setStdVW(Number stdVW) { + this.stdVW = stdVW; + } + + /** + * Gets writing direction metrics. + * @param index the writing direction (0, 1 or 2) + * @return the writing direction metrics + */ + public AFMWritingDirectionMetrics getWritingDirectionMetrics(int index) { + return this.writingDirectionMetrics[index]; + } + + /** + * Sets writing direction metrics. + * @param index the writing direction (0, 1 or 2) + * @param metrics the writing direction metrics + */ + public void setWritingDirectionMetrics(int index, AFMWritingDirectionMetrics metrics) { + this.writingDirectionMetrics[index] = metrics; + } + + /** + * Adds new character metrics. + * @param metrics the character metrics + */ + public void addCharMetrics(AFMCharMetrics metrics) { + String name = metrics.getCharName(); + if (metrics.getUnicodeChars() == null) { + if (name != null) { + String u = Glyphs.getUnicodeCodePointsForGlyphName(metrics.getCharName()); + if (u != null) { + metrics.setUnicodeChars(u); + } + } else { + //Ignore as no Unicode assignment is possible + return; + } + } + this.charMetrics.add(metrics); + if (name != null) { + this.charNameToMetrics.put(name, metrics); + } + } + + /** + * Returns the number of character available for this font. + * @return the number of character + */ + public int getCharCount() { + return this.charMetrics.size(); + } + + /** + * Returns the character metrics associated with the character name. + * @param name the character name + * @return the character metrics or null if there's no such character + */ + public AFMCharMetrics getChar(String name) { + return (AFMCharMetrics)this.charNameToMetrics.get(name); + } + + /** + * Returns the list of AFMCharMetrics instances representing all the available characters. + * @return a List of AFMCharMetrics instances + */ + public List getCharMetrics() { + return Collections.unmodifiableList(this.charMetrics); + } + + /** + * Adds a X-kerning entry. + * @param name1 the name of the first character + * @param name2 the name of the second character + * @param kx kerning value in x-direction + */ + public void addXKerning(String name1, String name2, double kx) { + if (this.kerningMap == null) { + this.kerningMap = new java.util.HashMap(); + } + Map entries = (Map)this.kerningMap.get(name1); + if (entries == null) { + entries = new java.util.HashMap(); + this.kerningMap.put(name1, entries); + } + entries.put(name2, new Dimension2DDouble(kx, 0)); + } + + /** {@inheritDoc} */ + public String toString() { + return "AFM: " + getFullName(); + } + +} diff --git a/src/java/org/apache/fop/fonts/type1/AFMParser.java b/src/java/org/apache/fop/fonts/type1/AFMParser.java new file mode 100644 index 000000000..4d852058c --- /dev/null +++ b/src/java/org/apache/fop/fonts/type1/AFMParser.java @@ -0,0 +1,594 @@ +/* + * 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.fonts.type1; + +import java.awt.Rectangle; +import java.beans.Statement; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Map; +import java.util.Stack; + +import org.apache.commons.io.IOUtils; + +/** + * Parses the contents of a Type 1 AFM font metrics file into an object structure ({@link AFMFile}). + */ +public class AFMParser { + + private static final String START_FONT_METRICS = "StartFontMetrics"; + //private static final String END_FONT_METRICS = "EndFontMetrics"; + private static final String FONT_NAME = "FontName"; + private static final String FULL_NAME = "FullName"; + private static final String FAMILY_NAME = "FamilyName"; + private static final String WEIGHT = "Weight"; + private static final String FONT_BBOX = "FontBBox"; + private static final String ENCODING_SCHEME = "EncodingScheme"; + private static final String CHARACTER_SET = "CharacterSet"; + private static final String IS_BASE_FONT = "IsBaseFont"; + private static final String IS_CID_FONT = "IsCIDFont"; + private static final String CAP_HEIGHT = "CapHeight"; + private static final String X_HEIGHT = "XHeight"; + private static final String ASCENDER = "Ascender"; + private static final String DESCENDER = "Descender"; + private static final String STDHW = "StdHW"; + private static final String STDVW = "StdVW"; + private static final String UNDERLINE_POSITION = "UnderlinePosition"; + private static final String UNDERLINE_THICKNESS = "UnderlineThickness"; + private static final String ITALIC_ANGLE = "ItalicAngle"; + private static final String IS_FIXED_PITCH = "IsFixedPitch"; + private static final String START_DIRECTION = "StartDirection"; + private static final String END_DIRECTION = "EndDirection"; + private static final String START_CHAR_METRICS = "StartCharMetrics"; + private static final String END_CHAR_METRICS = "EndCharMetrics"; + private static final String C = "C"; + private static final String CH = "CH"; + private static final String WX = "WX"; + private static final String W0X = "W0X"; + private static final String W1X = "W1X"; + private static final String WY = "WY"; + private static final String W0Y = "W0Y"; + private static final String W1Y = "W1Y"; + private static final String W = "W"; + private static final String W0 = "W0"; + private static final String W1 = "W1"; + private static final String N = "N"; + private static final String START_TRACK_KERN = "StartTrackKern"; + private static final String END_TRACK_KERN = "EndTrackKern"; + //private static final String START_KERN_PAIRS = "StartKernPairs"; + //private static final String START_KERN_PAIRS0 = "StartKernPairs0"; + private static final String START_KERN_PAIRS1 = "StartKernPairs1"; + //private static final String END_KERN_PAIRS = "EndKernPairs"; + private static final String KP = "KP"; + private static final String KPH = "KPH"; + private static final String KPX = "KPX"; + private static final String KPY = "KPY"; + + private static final int PARSE_NORMAL = 0; + private static final int PARSE_CHAR_METRICS = 1; + + private static final Map VALUE_PARSERS; + private static final Map PARSE_MODE_CHANGES; + + static { + VALUE_PARSERS = new java.util.HashMap(); + VALUE_PARSERS.put(START_FONT_METRICS, new StartFontMetrics()); + VALUE_PARSERS.put(FONT_NAME, new StringSetter(FONT_NAME)); + VALUE_PARSERS.put(FULL_NAME, new StringSetter(FULL_NAME)); + VALUE_PARSERS.put(FAMILY_NAME, new StringSetter(FAMILY_NAME)); + VALUE_PARSERS.put(WEIGHT, new StringSetter(WEIGHT)); + VALUE_PARSERS.put(ENCODING_SCHEME, new StringSetter(ENCODING_SCHEME)); + VALUE_PARSERS.put(FONT_BBOX, new FontBBox()); + VALUE_PARSERS.put(CHARACTER_SET, new StringSetter(CHARACTER_SET)); + VALUE_PARSERS.put(IS_BASE_FONT, new IsBaseFont()); + VALUE_PARSERS.put(IS_CID_FONT, new IsCIDFont()); + VALUE_PARSERS.put(CAP_HEIGHT, new NumberSetter(CAP_HEIGHT)); + VALUE_PARSERS.put(X_HEIGHT, new NumberSetter(X_HEIGHT)); + VALUE_PARSERS.put(ASCENDER, new NumberSetter(ASCENDER)); + VALUE_PARSERS.put(DESCENDER, new NumberSetter(DESCENDER)); + VALUE_PARSERS.put(STDHW, new NumberSetter(STDHW)); + VALUE_PARSERS.put(STDVW, new NumberSetter(STDVW)); + VALUE_PARSERS.put(START_DIRECTION, new StartDirection()); + VALUE_PARSERS.put(END_DIRECTION, new EndDirection()); + VALUE_PARSERS.put(UNDERLINE_POSITION, new WritingDirNumberSetter(UNDERLINE_POSITION)); + VALUE_PARSERS.put(UNDERLINE_THICKNESS, new WritingDirNumberSetter(UNDERLINE_THICKNESS)); + VALUE_PARSERS.put(ITALIC_ANGLE, new WritingDirDoubleSetter(ITALIC_ANGLE)); + VALUE_PARSERS.put(IS_FIXED_PITCH, new WritingDirBooleanSetter(IS_FIXED_PITCH)); + VALUE_PARSERS.put(C, new IntegerSetter("CharCode")); + VALUE_PARSERS.put(CH, new NotImplementedYet(CH)); + VALUE_PARSERS.put(WX, new DoubleSetter("WidthX")); + VALUE_PARSERS.put(W0X, new DoubleSetter("WidthX")); + VALUE_PARSERS.put(W1X, new NotImplementedYet(W1X)); + VALUE_PARSERS.put(WY, new DoubleSetter("WidthY")); + VALUE_PARSERS.put(W0Y, new DoubleSetter("WidthY")); + VALUE_PARSERS.put(W1Y, new NotImplementedYet(W1Y)); + VALUE_PARSERS.put(W, new NotImplementedYet(W)); + VALUE_PARSERS.put(W0, new NotImplementedYet(W0)); + VALUE_PARSERS.put(W1, new NotImplementedYet(W1)); + VALUE_PARSERS.put(N, new StringSetter("CharName")); + VALUE_PARSERS.put(START_TRACK_KERN, new NotImplementedYet(START_TRACK_KERN)); + VALUE_PARSERS.put(END_TRACK_KERN, new NotImplementedYet(END_TRACK_KERN)); + VALUE_PARSERS.put(START_KERN_PAIRS1, new NotImplementedYet(START_KERN_PAIRS1)); + VALUE_PARSERS.put(KP, new NotImplementedYet(KP)); + VALUE_PARSERS.put(KPH, new NotImplementedYet(KPH)); + VALUE_PARSERS.put(KPX, new KPXHandler()); + VALUE_PARSERS.put(KPY, new NotImplementedYet(KPY)); + + PARSE_MODE_CHANGES = new java.util.HashMap(); + PARSE_MODE_CHANGES.put(START_CHAR_METRICS, new Integer(PARSE_CHAR_METRICS)); + PARSE_MODE_CHANGES.put(END_CHAR_METRICS, new Integer(PARSE_NORMAL)); + } + + /** + * Main constructor. + */ + public AFMParser() { + //nop + } + + /** + * Parses an AFM file from a local file. + * @param afmFile the AFM file + * @return the parsed AFM file + * @throws IOException if an I/O error occurs + */ + public AFMFile parse(File afmFile) throws IOException { + InputStream in = new java.io.FileInputStream(afmFile); + try { + return parse(in); + } finally { + IOUtils.closeQuietly(in); + } + } + + /** + * Parses an AFM file from a stream. + * @param in the stream to read from + * @return the parsed AFM file + * @throws IOException if an I/O error occurs + */ + public AFMFile parse(InputStream in) throws IOException { + Reader reader = new java.io.InputStreamReader(in, "US-ASCII"); + try { + return parse(new BufferedReader(reader)); + } finally { + IOUtils.closeQuietly(reader); + } + } + + /** + * Parses an AFM file from a BufferedReader. + * @param reader the BufferedReader instance to read from + * @return the parsed AFM file + * @throws IOException if an I/O error occurs + */ + public AFMFile parse(BufferedReader reader) throws IOException { + Stack stack = new Stack(); + int parseMode = PARSE_NORMAL; + while (true) { + String line = reader.readLine(); + if (line == null) { + break; + } + String key = null; + switch (parseMode) { + case PARSE_NORMAL: + key = parseLine(line, stack); + break; + case PARSE_CHAR_METRICS: + key = parseCharMetrics(line, stack); + break; + default: + throw new IllegalStateException("Invalid parse mode"); + } + Integer newParseMode = (Integer)PARSE_MODE_CHANGES.get(key); + if (newParseMode != null) { + parseMode = newParseMode.intValue(); + } + } + return (AFMFile)stack.pop(); + } + + private String parseLine(String line, Stack stack) throws IOException { + int startpos = 0; + //Find key + startpos = skipToNonWhiteSpace(line, startpos); + int endpos = skipToWhiteSpace(line, startpos); + String key = line.substring(startpos, endpos); + + //Parse value + startpos = skipToNonWhiteSpace(line, endpos); + ValueHandler vp = (ValueHandler)VALUE_PARSERS.get(key); + if (vp != null) { + vp.parse(line, startpos, stack); + } + return key; + } + + private String parseCharMetrics(String line, Stack stack) throws IOException { + int startpos = 0; + AFMCharMetrics chm = new AFMCharMetrics(); + stack.push(chm); + while (true) { + //Find key + startpos = skipToNonWhiteSpace(line, startpos); + int endpos = skipToWhiteSpace(line, startpos); + String key = line.substring(startpos, endpos); + if (END_CHAR_METRICS.equals(key)) { + stack.pop(); //Pop and forget unused AFMCharMetrics instance + return key; + } else if (key.length() == 0) { + //EOL: No more key so break + break; + } + + //Extract value + startpos = skipToNonWhiteSpace(line, endpos); + endpos = skipToSemicolon(line, startpos); + String value = line.substring(startpos, endpos).trim(); + startpos = endpos + 1; + + //Parse value + ValueHandler vp = (ValueHandler)VALUE_PARSERS.get(key); + if (vp != null) { + vp.parse(value, 0, stack); + } + if (false) { + break; + } + } + stack.pop(); + AFMFile afm = (AFMFile)stack.peek(); + afm.addCharMetrics(chm); + return null; + } + + private static int skipToNonWhiteSpace(String line, int startpos) { + int pos = startpos; + while (pos < line.length() && isWhitespace(line.charAt(pos))) { + pos++; + } + return pos; + } + + private static int skipToWhiteSpace(String line, int startpos) { + int pos = startpos; + while (pos < line.length() && !isWhitespace(line.charAt(pos))) { + pos++; + } + return pos; + } + + private static int skipToSemicolon(String line, int startpos) { + int pos = startpos; + while (pos < line.length() && ';' != line.charAt(pos)) { + pos++; + } + return pos; + } + + private static boolean isWhitespace(char ch) { + return ch == ' ' + || ch == '\t'; + } + + // ---------------- Value Handlers --------------------------- + + private interface ValueHandler { + void parse(String line, int startpos, Stack stack) throws IOException; + } + + private abstract static class AbstractValueHandler implements ValueHandler { + + protected int findValue(String line, int startpos) { + return skipToWhiteSpace(line, startpos); + } + + protected String getStringValue(String line, int startpos) { + return line.substring(startpos); + } + + protected Number getNumberValue(String line, int startpos) { + try { + return new Integer(getIntegerValue(line, startpos)); + } catch (NumberFormatException nfe) { + return new Double(getDoubleValue(line, startpos)); + } + } + + protected int getIntegerValue(String line, int startpos) { + int endpos = findValue(line, startpos); + return Integer.parseInt(line.substring(startpos, endpos)); + } + + protected double getDoubleValue(String line, int startpos) { + int endpos = findValue(line, startpos); + return Double.parseDouble(line.substring(startpos, endpos)); + } + + protected Boolean getBooleanValue(String line, int startpos) { + return Boolean.valueOf(getStringValue(line, startpos)); + } + + } + + private static class StartFontMetrics extends AbstractValueHandler { + public void parse(String line, int startpos, Stack stack) throws IOException { + int endpos = findValue(line, startpos); + double version = Double.parseDouble(line.substring(startpos, endpos)); + if (version < 2) { + throw new IOException( + "AFM version must be at least 2.0 but it is " + version + "!"); + } + AFMFile afm = new AFMFile(); + stack.push(afm); + } + } + + private abstract static class BeanSetter extends AbstractValueHandler { + private String method; + + public BeanSetter(String variable) { + this.method = "set" + variable; + } + + protected void setValue(Object target, Object value) { + //Uses Java Beans API + Statement statement = new Statement(target, method, new Object[] {value}); + try { + statement.execute(); + } catch (Exception e) { + //Should never happen + throw new RuntimeException("Bean error: " + e.getMessage()); + } + } + } + + private static class StringSetter extends BeanSetter { + + public StringSetter(String variable) { + super(variable); + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + String s = getStringValue(line, startpos); + Object obj = stack.peek(); + setValue(obj, s); + } + } + + private static class NumberSetter extends BeanSetter { + public NumberSetter(String variable) { + super(variable); + } + + protected Object getContextObject(Stack stack) { + return stack.peek(); + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + Number num = getNumberValue(line, startpos); + setValue(getContextObject(stack), num); + } + } + + private static class IntegerSetter extends NumberSetter { + public IntegerSetter(String variable) { + super(variable); + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + int value = getIntegerValue(line, startpos); + setValue(getContextObject(stack), new Integer(value)); + } + } + + private static class DoubleSetter extends NumberSetter { + public DoubleSetter(String variable) { + super(variable); + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + double value = getDoubleValue(line, startpos); + setValue(getContextObject(stack), new Double(value)); + } + } + + private static class WritingDirNumberSetter extends NumberSetter { + + public WritingDirNumberSetter(String variable) { + super(variable); + } + + protected Object getContextObject(Stack stack) { + if (stack.peek() instanceof AFMWritingDirectionMetrics) { + return (AFMWritingDirectionMetrics)stack.peek(); + } else { + AFMFile afm = (AFMFile)stack.peek(); + AFMWritingDirectionMetrics wdm = afm.getWritingDirectionMetrics(0); + if (wdm == null) { + wdm = new AFMWritingDirectionMetrics(); + afm.setWritingDirectionMetrics(0, wdm); + } + return wdm; + } + } + + } + + private static class WritingDirDoubleSetter extends WritingDirNumberSetter { + + public WritingDirDoubleSetter(String variable) { + super(variable); + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + double value = getDoubleValue(line, startpos); + setValue(getContextObject(stack), new Double(value)); + } + } + + private static class BooleanSetter extends AbstractValueHandler { + private String method; + + public BooleanSetter(String variable) { + this.method = "set" + variable.substring(2); //Cut "Is" in front + } + + protected Object getContextObject(Stack stack) { + return (AFMFile)stack.peek(); + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + Boolean b = getBooleanValue(line, startpos); + //Uses Java Beans API + Statement statement = new Statement(getContextObject(stack), + method, new Object[] {b}); + try { + statement.execute(); + } catch (Exception e) { + //Should never happen + throw new RuntimeException("Bean error: " + e.getMessage()); + } + } + } + + private static class WritingDirBooleanSetter extends BooleanSetter { + + public WritingDirBooleanSetter(String variable) { + super(variable); + } + + protected Object getContextObject(Stack stack) { + if (stack.peek() instanceof AFMWritingDirectionMetrics) { + return (AFMWritingDirectionMetrics)stack.peek(); + } else { + AFMFile afm = (AFMFile)stack.peek(); + AFMWritingDirectionMetrics wdm = afm.getWritingDirectionMetrics(0); + if (wdm == null) { + wdm = new AFMWritingDirectionMetrics(); + afm.setWritingDirectionMetrics(0, wdm); + } + return wdm; + } + } + + } + + private static class FontBBox extends AbstractValueHandler { + public void parse(String line, int startpos, Stack stack) throws IOException { + AFMFile afm = (AFMFile)stack.peek(); + Rectangle rect = new Rectangle(); + int endpos; + + endpos = findValue(line, startpos); + rect.x = Integer.parseInt(line.substring(startpos, endpos)); + startpos = skipToNonWhiteSpace(line, endpos); + + endpos = findValue(line, startpos); + rect.y = Integer.parseInt(line.substring(startpos, endpos)); + startpos = skipToNonWhiteSpace(line, endpos); + + endpos = findValue(line, startpos); + int v = Integer.parseInt(line.substring(startpos, endpos)); + rect.width = v - rect.x; + startpos = skipToNonWhiteSpace(line, endpos); + + endpos = findValue(line, startpos); + v = Integer.parseInt(line.substring(startpos, endpos)); + rect.height = v - rect.y; + startpos = skipToNonWhiteSpace(line, endpos); + + afm.setFontBBox(rect); + } + } + + private static class IsBaseFont extends AbstractValueHandler { + public void parse(String line, int startpos, Stack stack) throws IOException { + if (getBooleanValue(line, startpos).booleanValue()) { + throw new IOException("Only base fonts are currently supported!"); + } + } + } + + private static class IsCIDFont extends AbstractValueHandler { + public void parse(String line, int startpos, Stack stack) throws IOException { + if (getBooleanValue(line, startpos).booleanValue()) { + throw new IOException("CID fonts are currently not supported!"); + } + } + } + + private static class NotImplementedYet extends AbstractValueHandler { + private String key; + + public NotImplementedYet(String key) { + this.key = key; + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + throw new IOException("Support for '" + key + + "' has not been implemented, yet! Font is not supported."); + } + } + + private static class StartDirection extends AbstractValueHandler { + public void parse(String line, int startpos, Stack stack) throws IOException { + int index = getIntegerValue(line, startpos); + AFMWritingDirectionMetrics wdm = new AFMWritingDirectionMetrics(); + AFMFile afm = (AFMFile)stack.peek(); + afm.setWritingDirectionMetrics(index, wdm); + stack.push(wdm); + } + } + + private static class EndDirection extends AbstractValueHandler { + public void parse(String line, int startpos, Stack stack) throws IOException { + if (!(stack.pop() instanceof AFMWritingDirectionMetrics)) { + throw new IOException("AFM format error: nesting incorrect"); + } + } + } + + private static class KPXHandler extends AbstractValueHandler { + public void parse(String line, int startpos, Stack stack) throws IOException { + AFMFile afm = (AFMFile)stack.peek(); + int endpos; + + endpos = findValue(line, startpos); + String name1 = line.substring(startpos, endpos); + startpos = skipToNonWhiteSpace(line, endpos); + + endpos = findValue(line, startpos); + String name2 = line.substring(startpos, endpos); + startpos = skipToNonWhiteSpace(line, endpos); + + endpos = findValue(line, startpos); + double kx = Double.parseDouble(line.substring(startpos, endpos)); + startpos = skipToNonWhiteSpace(line, endpos); + + afm.addXKerning(name1, name2, kx); + } + } + +} diff --git a/src/java/org/apache/fop/fonts/type1/AFMWritingDirectionMetrics.java b/src/java/org/apache/fop/fonts/type1/AFMWritingDirectionMetrics.java new file mode 100644 index 000000000..5b6a9e43b --- /dev/null +++ b/src/java/org/apache/fop/fonts/type1/AFMWritingDirectionMetrics.java @@ -0,0 +1,96 @@ +/* + * 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.fonts.type1; + +/** + * Represents a writing direction metrics section from an AFM file. + */ +public class AFMWritingDirectionMetrics { + + private Number underlinePosition; + private Number underlineThickness; + private double italicAngle; + private boolean isFixedPitch; + + /** + * Returns the UnderlinePosition value. + * @return the underlinePosition + */ + public Number getUnderlinePosition() { + return underlinePosition; + } + + /** + * Sets the UnderlinePosition value. + * @param underlinePosition the underlinePosition to set + */ + public void setUnderlinePosition(Number underlinePosition) { + this.underlinePosition = underlinePosition; + } + + /** + * Returns the UnderlineThickness value. + * @return the underlineThickness + */ + public Number getUnderlineThickness() { + return underlineThickness; + } + + /** + * Sets the UnderlineThickness value. + * @param underlineThickness the underlineThickness to set + */ + public void setUnderlineThickness(Number underlineThickness) { + this.underlineThickness = underlineThickness; + } + + /** + * Returns the ItalicAngle value. + * @return the italicAngle + */ + public double getItalicAngle() { + return italicAngle; + } + + /** + * Sets the ItalicAngle value. + * @param italicAngle the italicAngle to set + */ + public void setItalicAngle(double italicAngle) { + this.italicAngle = italicAngle; + } + + /** + * Returns the IsFixedPitch value. + * @return the isFixedPitch + */ + public boolean isFixedPitch() { + return isFixedPitch; + } + + /** + * Set the IsFixedPitch value. + * @param value the isFixedPitch to set + */ + public void setFixedPitch(boolean value) { + this.isFixedPitch = value; + } + +} diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 1a1f691b2..f5b04442b 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -21,8 +21,13 @@ package org.apache.fop.fonts.type1; import java.io.IOException; import java.io.InputStream; +import java.util.Iterator; +import java.util.List; import java.util.Set; +import org.apache.commons.io.IOUtils; + +import org.apache.fop.fonts.CodePointMapping; import org.apache.fop.fonts.FontLoader; import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontType; @@ -33,27 +38,88 @@ import org.apache.fop.fonts.SingleByteFont; */ public class Type1FontLoader extends FontLoader { - private PFMFile pfm; private SingleByteFont singleFont; /** * Constructs a new Type 1 font loader. * @param fontFileURI the URI to the PFB file of a Type 1 font - * @param in the InputStream reading the PFM file of a Type 1 font * @param resolver the font resolver used to resolve URIs * @throws IOException In case of an I/O error */ - public Type1FontLoader(String fontFileURI, InputStream in, FontResolver resolver) + public Type1FontLoader(String fontFileURI, FontResolver resolver) throws IOException { - super(fontFileURI, in, resolver); + super(fontFileURI, resolver); } - /** - * {@inheritDoc} - */ + private String getPFMURI(String pfbURI) { + String pfbExt = pfbURI.substring(pfbURI.length() - 3, pfbURI.length()); + String pfmExt = pfbExt.substring(0, 2) + + (Character.isUpperCase(pfbExt.charAt(2)) ? "M" : "m"); + return pfbURI.substring(0, pfbURI.length() - 4) + "." + pfmExt; + } + + private static final String[] AFM_EXTENSIONS = new String[] {".AFM", ".afm", ".Afm"}; + + /** {@inheritDoc} */ protected void read() throws IOException { - pfm = new PFMFile(); - pfm.load(in); + AFMFile afm = null; + PFMFile pfm = null; + + InputStream afmIn = null; + for (int i = 0; i < AFM_EXTENSIONS.length; i++) { + try { + String afmUri = this.fontFileURI.substring(0, this.fontFileURI.length() - 4) + + AFM_EXTENSIONS[i]; + afmIn = openFontUri(resolver, afmUri); + if (afmIn != null) { + break; + } + } catch (IOException ioe) { + //Ignore, AFM probably not available under the URI + } + } + if (afmIn != null) { + try { + AFMParser afmParser = new AFMParser(); + afm = afmParser.parse(afmIn); + } finally { + IOUtils.closeQuietly(afmIn); + } + } + + String pfmUri = getPFMURI(this.fontFileURI); + InputStream pfmIn = null; + try { + pfmIn = openFontUri(resolver, pfmUri); + } catch (IOException ioe) { + //Ignore, PFM probably not available under the URI + } + if (pfmIn != null) { + try { + pfm = new PFMFile(); + pfm.load(pfmIn); + } finally { + IOUtils.closeQuietly(pfmIn); + } + } + + if (afm == null && pfm == null) { + throw new java.io.FileNotFoundException( + "Neither an AFM nor a PFM file was found for " + this.fontFileURI); + } + if (pfm == null) { + //Cannot do without for now + throw new java.io.FileNotFoundException( + "No PFM file was found for " + this.fontFileURI); + } + buildFont(afm, pfm); + this.loaded = true; + } + + private void buildFont(AFMFile afm, PFMFile pfm) { + if (afm == null && pfm == null) { + throw new IllegalArgumentException("Need at least an AFM or a PFM!"); + } singleFont = new SingleByteFont(); singleFont.setFontType(FontType.TYPE1); if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { @@ -65,28 +131,127 @@ public class Type1FontLoader extends FontLoader { } singleFont.setResolver(this.resolver); returnFont = singleFont; - returnFont.setFontName(pfm.getPostscriptName()); - String fullName = pfm.getPostscriptName(); - fullName = fullName.replace('-', ' '); //Hack! Try to emulate full name - returnFont.setFullName(fullName); //should be afm.getFullName()!! - //TODO not accurate: we need FullName from the AFM file but we don't have an AFM parser - Set names = new java.util.HashSet(); - names.add(pfm.getWindowsName()); //should be afm.getFamilyName()!! - returnFont.setFamilyNames(names); - returnFont.setCapHeight(pfm.getCapHeight()); - returnFont.setXHeight(pfm.getXHeight()); - returnFont.setAscender(pfm.getLowerCaseAscent()); - returnFont.setDescender(pfm.getLowerCaseDescent()); - returnFont.setFontBBox(pfm.getFontBBox()); + + //Font name + if (afm != null) { + returnFont.setFontName(afm.getFontName()); //PostScript font name + returnFont.setFullName(afm.getFullName()); + Set names = new java.util.HashSet(); + names.add(afm.getFamilyName()); + returnFont.setFamilyNames(names); + } else { + returnFont.setFontName(pfm.getPostscriptName()); + String fullName = pfm.getPostscriptName(); + fullName = fullName.replace('-', ' '); //Hack! Try to emulate full name + returnFont.setFullName(fullName); //emulate afm.getFullName() + Set names = new java.util.HashSet(); + names.add(pfm.getWindowsName()); //emulate afm.getFamilyName() + returnFont.setFamilyNames(names); + } + + //Encoding + if (afm != null) { + String encoding = afm.getEncodingScheme(); + if ("AdobeStandardEncoding".equals(encoding)) { + //Use WinAnsi in this case as it better fits the usual character set people need + singleFont.setEncoding(CodePointMapping.WIN_ANSI_ENCODING); + } else { + String effEncodingName; + if ("FontSpecific".equals(encoding)) { + effEncodingName = afm.getFontName() + "Encoding"; + } else { + effEncodingName = encoding; + } + if (log.isDebugEnabled()) { + log.debug("Unusual font encoding encountered: " + + encoding + " -> " + effEncodingName); + } + CodePointMapping mapping = buildCustomEncoding(effEncodingName, afm); + singleFont.setEncoding(mapping); + } + } + + //Basic metrics + if (afm != null) { + if (afm.getCapHeight() != null) { + returnFont.setCapHeight(afm.getCapHeight().intValue()); + } + if (afm.getXHeight() != null) { + returnFont.setXHeight(afm.getXHeight().intValue()); + } + if (afm.getAscender() != null) { + returnFont.setAscender(afm.getAscender().intValue()); + } + if (afm.getDescender() != null) { + returnFont.setDescender(afm.getDescender().intValue()); + } + returnFont.setFontBBox(afm.getFontBBoxAsIntArray()); + if (afm.getStdVW() != null) { + returnFont.setStemV(afm.getStdVW().intValue()); + } else { + returnFont.setStemV(80); //Arbitrary value + } + returnFont.setItalicAngle((int)afm.getWritingDirectionMetrics(0).getItalicAngle()); + } else { + returnFont.setFontBBox(pfm.getFontBBox()); + returnFont.setStemV(pfm.getStemV()); + returnFont.setItalicAngle(pfm.getItalicAngle()); + } + if (pfm != null) { + if (returnFont.getCapHeight() == 0) { + returnFont.setCapHeight(pfm.getCapHeight()); + } + if (returnFont.getXHeight(1) == 0) { + returnFont.setXHeight(pfm.getXHeight()); + } + if (returnFont.getAscender() == 0) { + returnFont.setAscender(pfm.getLowerCaseAscent()); + } + if (returnFont.getDescender() == 0) { + returnFont.setDescender(pfm.getLowerCaseDescent()); + } + } returnFont.setFirstChar(pfm.getFirstChar()); returnFont.setLastChar(pfm.getLastChar()); returnFont.setFlags(pfm.getFlags()); - returnFont.setStemV(pfm.getStemV()); - returnFont.setItalicAngle(pfm.getItalicAngle()); returnFont.setMissingWidth(0); for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { singleFont.setWidth(i, pfm.getCharWidth(i)); } + returnFont.replaceKerningMap(pfm.getKerning()); singleFont.setEmbedFileName(this.fontFileURI); } + + private CodePointMapping buildCustomEncoding(String encodingName, AFMFile afm) { + List chars = afm.getCharMetrics(); + int mappingCount = 0; + //Just count the first time... + Iterator iter = chars.iterator(); + while (iter.hasNext()) { + AFMCharMetrics charMetrics = (AFMCharMetrics)iter.next(); + if (charMetrics.getCharCode() >= 0) { + String u = charMetrics.getUnicodeChars(); + if (u != null) { + mappingCount += u.length(); + } + } + } + //...and now build the table. + int[] table = new int[mappingCount * 2]; + iter = chars.iterator(); + int idx = 0; + while (iter.hasNext()) { + AFMCharMetrics charMetrics = (AFMCharMetrics)iter.next(); + if (charMetrics.getCharCode() >= 0) { + String unicodes = charMetrics.getUnicodeChars(); + for (int i = 0, c = unicodes.length(); i < c; i++) { + table[idx] = charMetrics.getCharCode(); + idx++; + table[idx] = unicodes.charAt(i); + idx++; + } + } + } + return new CodePointMapping(encodingName, table); + } } diff --git a/src/java/org/apache/fop/pdf/CMapBuilder.java b/src/java/org/apache/fop/pdf/CMapBuilder.java new file mode 100644 index 000000000..f55c34fcf --- /dev/null +++ b/src/java/org/apache/fop/pdf/CMapBuilder.java @@ -0,0 +1,157 @@ +/* + * 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.pdf; + +import java.io.IOException; +import java.io.Writer; + +public class CMapBuilder { + + protected String name; + protected Writer writer; + + public CMapBuilder(Writer writer, String name) { + this.writer = writer; + this.name = name; + } + + /** + * Writes the CMap to a Writer. + * @throws IOException if an I/O error occurs + */ + public void writeCMap() throws IOException { + writePreStream(); + writeStreamComments(); + writeCIDInit(); + writeCIDSystemInfo(); + writeVersion("1"); + writeType("1"); + writeName(name); + writeCodeSpaceRange(); + writeCIDRange(); + writeBFEntries(); + writeWrapUp(); + writeStreamAfterComments(); + writeUseCMap(); + } + + protected void writePreStream() throws IOException { + // writer.write("/Type /CMap\n"); + // writer.write(sysInfo.toPDFString()); + // writer.write("/CMapName /" + name + EOL); + } + + protected void writeStreamComments() throws IOException { + writer.write("%!PS-Adobe-3.0 Resource-CMap\n"); + writer.write("%%DocumentNeededResources: ProcSet (CIDInit)\n"); + writer.write("%%IncludeResource: ProcSet (CIDInit)\n"); + writer.write("%%BeginResource: CMap (" + name + ")\n"); + writer.write("%%EndComments\n"); + } + + protected void writeCIDInit() throws IOException { + writer.write("/CIDInit /ProcSet findresource begin\n"); + writer.write("12 dict begin\n"); + writer.write("begincmap\n"); + } + + protected void writeCIDSystemInfo(String registry, String ordering, int supplement) + throws IOException { + writer.write("/CIDSystemInfo 3 dict dup begin\n"); + writer.write(" /Registry ("); + writer.write(registry); + writer.write(") def\n"); + writer.write(" /Ordering ("); + writer.write(ordering); + writer.write(") def\n"); + writer.write(" /Supplement "); + writer.write(Integer.toString(supplement)); + writer.write(" def\n"); + writer.write("end def\n"); + } + + protected void writeCIDSystemInfo() throws IOException { + writeCIDSystemInfo("Adobe", "Identity", 0); + } + + protected void writeVersion(String version) throws IOException { + writer.write("/CMapVersion "); + writer.write(version); + writer.write(" def\n"); + } + + protected void writeType(String type) throws IOException { + writer.write("/CMapType "); + writer.write(type); + writer.write(" def\n"); + } + + protected void writeName(String name) throws IOException { + writer.write("/CMapName /"); + writer.write(name); + writer.write(" def\n"); + } + + protected void writeCodeSpaceRange() throws IOException { + writer.write("1 begincodespacerange\n"); + writer.write("<0000> \n"); + writer.write("endcodespacerange\n"); + } + + protected void writeCIDRange() throws IOException { + writer.write("1 begincidrange\n"); + writer.write("<0000> 0\n"); + writer.write("endcidrange\n"); + } + + protected void writeBFEntries() throws IOException { + // writer.write("1 beginbfrange\n"); + // writer.write("<0020> <0100> <0000>\n"); + // writer.write("endbfrange\n"); + } + + protected void writeWrapUp() throws IOException { + writer.write("endcmap\n"); + writer.write("CMapName currentdict /CMap defineresource pop\n"); + writer.write("end\n"); + writer.write("end\n"); + } + + protected void writeStreamAfterComments() throws IOException { + writer.write("%%EndResource\n"); + writer.write("%%EOF\n"); + } + + protected void writeUseCMap() { + /* + * writer.write(" /Type /CMap"); + * writer.write("/CMapName /" + name + EOL); + * writer.write("/WMode " + wMode + EOL); + * if (base != null) { + * writer.write("/UseCMap "); + * if (base instanceof String) { + * writer.write("/"+base); + * } else {// base instanceof PDFStream + * writer.write(((PDFStream)base).referencePDF()); + * } + * } + */ + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/pdf/PDFArray.java b/src/java/org/apache/fop/pdf/PDFArray.java index 466ad7d6a..1fe55384c 100644 --- a/src/java/org/apache/fop/pdf/PDFArray.java +++ b/src/java/org/apache/fop/pdf/PDFArray.java @@ -147,7 +147,10 @@ public class PDFArray extends PDFObject { */ 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); } diff --git a/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java b/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java index 101709613..df552d96e 100644 --- a/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java +++ b/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java @@ -22,24 +22,14 @@ package org.apache.fop.pdf; // 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 @@ public class PDFCIDFontDescriptor extends PDFFontDescriptor { 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); } } diff --git a/src/java/org/apache/fop/pdf/PDFCMap.java b/src/java/org/apache/fop/pdf/PDFCMap.java index d62e45d85..bdf8108c2 100644 --- a/src/java/org/apache/fop/pdf/PDFCMap.java +++ b/src/java/org/apache/fop/pdf/PDFCMap.java @@ -21,6 +21,8 @@ package org.apache.fop.pdf; import java.io.IOException; import java.io.OutputStream; +import java.io.StringWriter; +import java.io.Writer; /** * Class representing the CMap encodings. @@ -394,15 +396,6 @@ public class PDFCMap extends PDFStream { this.wMode = mode; } - /** - * 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 * @@ -422,107 +415,20 @@ public class PDFCMap extends PDFStream { } /** - * Fill in the pdf string for this CMap. - * - * @param p the string buffer to add the pdf data to - */ - 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> \n"); - p.append("endcodespacerange\n"); - } - - protected void writeCIDRange(StringBuffer p) { - p.append("1 begincidrange\n"); - p.append("<0000> 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 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()); - * } - * } - */ + * 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 + */ + protected CMapBuilder createCMapBuilder(Writer writer) { + return new CMapBuilder(writer, this.name); } - + + /** {@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); } } diff --git a/src/java/org/apache/fop/pdf/PDFDictionary.java b/src/java/org/apache/fop/pdf/PDFDictionary.java index 49d48312c..34fe4c389 100644 --- a/src/java/org/apache/fop/pdf/PDFDictionary.java +++ b/src/java/org/apache/fop/pdf/PDFDictionary.java @@ -65,6 +65,12 @@ public class PDFDictionary extends PDFObject { * @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); } diff --git a/src/java/org/apache/fop/pdf/PDFEncoding.java b/src/java/org/apache/fop/pdf/PDFEncoding.java index b9064dc1f..b2fba6e53 100644 --- a/src/java/org/apache/fop/pdf/PDFEncoding.java +++ b/src/java/org/apache/fop/pdf/PDFEncoding.java @@ -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 @@ import java.util.Iterator; * * 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 diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index d0c48ee39..a50ef2545 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -40,15 +40,18 @@ import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.fonts.Glyphs; 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 +1185,7 @@ public class PDFFactory { } if (descriptor == null) { + //Usually Base 14 fonts PDFFont font = new PDFFont(fontname, FontType.TYPE1, basefont, encoding); getDocument().registerObject(font); return font; @@ -1190,30 +1194,11 @@ public class PDFFactory { 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 +1218,7 @@ public class PDFFactory { (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 +1226,57 @@ public class PDFFactory { ((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; + for (int i = 0; i < 256; i++) { + char wac = winansi.getUnicodeForIndex(i); + char c = mapping.getUnicodeForIndex(i); + if (wac != c) { + if (start != i) { + builder.addDifference(i); + start = i; + } + builder.addName(Glyphs.charToGlyphName(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; diff --git a/src/java/org/apache/fop/pdf/PDFFont.java b/src/java/org/apache/fop/pdf/PDFFont.java index 0730376db..497565e9c 100644 --- a/src/java/org/apache/fop/pdf/PDFFont.java +++ b/src/java/org/apache/fop/pdf/PDFFont.java @@ -30,38 +30,11 @@ import org.apache.fop.fonts.FontType; *

    * Fonts are specified on page 198 and onwards of the PDF 1.3 spec. */ -public class PDFFont extends PDFObject { - - /** - * the internal name for the font (eg "F1") - */ - protected String fontname; - - /** - * the font's subtype - * (as defined by the constants FontType: TYPE0, TYPE1, MMTYPE1, TYPE3, TRUETYPE) - */ - protected FontType subtype; - - /** - * the base font name (eg "Helvetica") - */ - protected String basefont; - - /** - * the character encoding scheme used by the font. - * It can be a String for standard encodings, or - * a PDFEncoding for a more complex scheme, or - * a PDFStream containing a CMap in a Type0 font. - * If null then not written out in the PDF. - */ - protected Object encoding; - - /** - * the Unicode mapping mechanism - */ - // protected PDFToUnicode mapping; +public class PDFFont extends PDFDictionary { + /** Internal F-number for each font (it is not written to the font dict) */ + private String fontname; + /** * create the /Font object * @@ -72,19 +45,45 @@ public class PDFFont extends PDFObject { */ public PDFFont(String fontname, FontType subtype, String basefont, - Object encoding /* , PDFToUnicode mapping */) { + Object encoding) { /* generic creation of PDF object */ super(); - /* set fields using paramaters */ this.fontname = fontname; - this.subtype = subtype; - this.basefont = basefont; - this.encoding = encoding; - // this.mapping = mapping; + put("Type", new PDFName("Font")); + put("Subtype", getPDFNameForFontType(subtype)); + //put("Name", new PDFName(fontname)); + put("BaseFont", new PDFName(basefont)); + if (encoding instanceof PDFEncoding) { + setEncoding((PDFEncoding)encoding); + } else if (encoding instanceof String) { + setEncoding((String)encoding); + } else { + throw new IllegalArgumentException("Illegal value for encoding"); + } } + /** + * Sets the Encoding value of the font. + * @param encoding the encoding + */ + public void setEncoding(String encoding) { + if (encoding != null) { + put("Encoding", new PDFName(encoding)); + } + } + + /** + * Sets the Encoding value of the font. + * @param encoding the encoding + */ + public void setEncoding(PDFEncoding encoding) { + if (encoding != null) { + put("Encoding", encoding); + } + } + /** * factory method with the basic parameters * @@ -111,80 +110,42 @@ public class PDFFont extends PDFObject { return new PDFFontTrueType(fontname, basefont, encoding); } else { - return null; // should not happend - } - } - - /** - * factory method with the extended parameters - * for Type1, MMType1 and TrueType - * - * @param fontname the internal name for the font - * @param subtype the font's subtype - * @param basefont the base font name - * @param encoding the character encoding schema used by the font - * @param firstChar the first character code in the font - * @param lastChar the last character code in the font - * @param widths an array of size (lastChar - firstChar +1) - * @param descriptor the descriptor for other font's metrics - * @return the generated PDFFont object - */ - public static PDFFont createFont(String fontname, - FontType subtype, String basefont, - Object encoding, int firstChar, - int lastChar, PDFArray widths, - PDFFontDescriptor descriptor) { - - PDFFontNonBase14 font; - if (subtype == FontType.TYPE0) { - font = new PDFFontType0(fontname, basefont, - encoding); - font.setDescriptor(descriptor); - return font; - } else if ((subtype == FontType.TYPE1) - || (subtype == FontType.MMTYPE1)) { - font = new PDFFontType1(fontname, basefont, - encoding); - font.setWidthMetrics(firstChar, lastChar, widths); - font.setDescriptor(descriptor); - return font; - } else if (subtype == FontType.TYPE3) { - return null; //NYI, should not happend - } else if (subtype == FontType.TRUETYPE) { - font = new PDFFontTrueType(fontname, basefont, - encoding); - font.setWidthMetrics(firstChar, lastChar, widths); - font.setDescriptor(descriptor); - return font; - } else { - return null; // should not happend + return null; // should not happen } } /** - * get the internal name used for this font + * Get the internal name used for this font. * @return the internal name */ public String getName() { return this.fontname; } + + /** + * Returns the name of the BaseFont. + * @return the BaseFont + */ + public PDFName getBaseFont() { + return (PDFName)get("BaseFont"); + } /** * Returns the PDF name for a certain font type. * @param fontType font type * @return String corresponding PDF name */ - protected String getPDFNameForFontType(FontType fontType) { + protected PDFName getPDFNameForFontType(FontType fontType) { if (fontType == FontType.TYPE0) { - return fontType.getName(); + return new PDFName(fontType.getName()); } else if (fontType == FontType.TYPE1) { - return fontType.getName(); + return new PDFName(fontType.getName()); } else if (fontType == FontType.MMTYPE1) { - return fontType.getName(); + return new PDFName(fontType.getName()); } else if (fontType == FontType.TYPE3) { - return fontType.getName(); + return new PDFName(fontType.getName()); } else if (fontType == FontType.TRUETYPE) { - return fontType.getName(); + return new PDFName(fontType.getName()); } else { throw new IllegalArgumentException("Unsupported font type: " + fontType.getName()); } @@ -198,46 +159,9 @@ public class PDFFont extends PDFObject { if (this.getClass() == PDFFont.class) { throw new PDFConformanceException("For " + getDocumentSafely().getProfile() + ", all fonts, even the base 14" - + " fonts, have to be embedded! Offending font: " + this.basefont); + + " fonts, have to be embedded! Offending font: " + getBaseFont()); } } } - /** - * {@inheritDoc} - */ - public String toPDFString() { - validate(); - StringBuffer p = new StringBuffer(128); - p.append(getObjectID()); - p.append("<< /Type /Font\n/Subtype /" - + getPDFNameForFontType(this.subtype) - + "\n/Name /" + this.fontname - + "\n/BaseFont /" + this.basefont); - if (encoding != null) { - p.append("\n/Encoding "); - if (encoding instanceof PDFEncoding) { - p.append(((PDFEncoding)this.encoding).referencePDF()); - } else if (encoding instanceof PDFStream) { - p.append(((PDFStream)this.encoding).referencePDF()); - } else { - p.append("/").append((String)encoding); - } - } - fillInPDF(p); - p.append(" >>\nendobj\n"); - return p.toString(); - } - - /** - * This method is called to receive the specifics for the font's subtype. - *

    - * The given buffer already contains the fields common to all font types. - * - * @param target the buffer to be completed with the type specific fields - */ - protected void fillInPDF(StringBuffer target) { - //nop - } - } diff --git a/src/java/org/apache/fop/pdf/PDFFontDescriptor.java b/src/java/org/apache/fop/pdf/PDFFontDescriptor.java index be460dcc2..aa40bc35b 100644 --- a/src/java/org/apache/fop/pdf/PDFFontDescriptor.java +++ b/src/java/org/apache/fop/pdf/PDFFontDescriptor.java @@ -26,29 +26,7 @@ import org.apache.fop.fonts.FontType; *

    * Font descriptors are specified on page 222 and onwards of the PDF 1.3 spec. */ -public class PDFFontDescriptor extends PDFObject { - - // Required fields - private int ascent; - private int capHeight; - private int descent; - private int flags; - private PDFRectangle fontBBox; - private String basefont; // PDF-spec: FontName - private int italicAngle; - private int stemV; - // Optional fields - private int stemH = 0; - private int xHeight = 0; - private int leading = 0; - private int avgWidth = 0; - private int maxWidth = 0; - private int missingWidth = 0; - private AbstractPDFStream fontfile; - private AbstractPDFStream cidSet; - // private String charSet = null; - - private FontType subtype; +public class PDFFontDescriptor extends PDFDictionary { /** * Create the /FontDescriptor object @@ -66,19 +44,17 @@ public class PDFFontDescriptor extends PDFObject { int descent, int capHeight, int flags, PDFRectangle fontBBox, int italicAngle, int stemV) { - - /* generic creation of PDF object */ super(); - /* set fields using paramaters */ - this.basefont = basefont; - this.ascent = ascent; - this.descent = descent; - this.capHeight = capHeight; - this.flags = flags; - this.fontBBox = fontBBox; - this.italicAngle = italicAngle; - this.stemV = stemV; + put("Type", new PDFName("FontDescriptor")); + put("FontName", new PDFName(basefont)); + put("FontBBox", fontBBox); + put("Flags", flags); + put("CapHeight", capHeight); + put("Ascent", ascent); + put("Descent", descent); + put("ItalicAngle", italicAngle); + put("StemV", stemV); } /** @@ -97,12 +73,24 @@ public class PDFFontDescriptor extends PDFObject { */ public void setMetrics(int avgWidth, int maxWidth, int missingWidth, int leading, int stemH, int xHeight) { - this.avgWidth = avgWidth; - this.maxWidth = maxWidth; - this.missingWidth = missingWidth; - this.leading = leading; - this.stemH = stemH; - this.xHeight = xHeight; + if (avgWidth != 0) { + put("AvgWidth", avgWidth); + } + if (maxWidth != 0) { + put("MaxWidth", maxWidth); + } + if (missingWidth != 0) { + put("MissingWidth", missingWidth); + } + if (leading != 0) { + put("Leading", leading); + } + if (stemH != 0) { + put("StemH", stemH); + } + if (xHeight != 0) { + put("XHeight", xHeight); + } } /** @@ -112,13 +100,24 @@ public class PDFFontDescriptor extends PDFObject { * @param fontfile the stream containing an embedded font */ public void setFontFile(FontType subtype, AbstractPDFStream fontfile) { - this.subtype = subtype; - this.fontfile = fontfile; + if (subtype == FontType.TYPE1) { + put("FontFile", fontfile); + } else { + put("FontFile2", fontfile); + } } /** @return the FontFile or null if the font is not embedded */ public AbstractPDFStream getFontFile() { - return this.fontfile; + AbstractPDFStream stream; + stream = (AbstractPDFStream)get("FontFile"); + if (stream == null) { + stream = (AbstractPDFStream)get("FontFile2"); + } + if (stream == null) { + stream = (AbstractPDFStream)get("FontFile3"); + } + return stream; } /** @@ -126,19 +125,18 @@ public class PDFFontDescriptor extends PDFObject { * @param cidSet the CIDSet stream */ public void setCIDSet(AbstractPDFStream cidSet) { - this.cidSet = cidSet; + put("CIDSet", cidSet); } /** @return the CIDSet stream or null if not applicable */ public AbstractPDFStream getCIDSet() { - return this.cidSet; + return (AbstractPDFStream)get("CIDSet"); } - // public void setCharSet(){}//for subset fonts - /** * {@inheritDoc} */ + /* public String toPDFString() { StringBuffer p = new StringBuffer(128); p.append(getObjectID() @@ -201,7 +199,7 @@ public class PDFFontDescriptor extends PDFObject { fillInPDF(p); p.append(" >>\nendobj\n"); return p.toString(); - } + }*/ /** * Fill in the specifics for the font's descriptor. @@ -209,9 +207,9 @@ public class PDFFontDescriptor extends PDFObject { * The given buffer already contains the fields common to all descriptors. * * @param begin the buffer to be completed with the specific fields - */ + *//* protected void fillInPDF(StringBuffer begin) { //nop - } + }*/ } diff --git a/src/java/org/apache/fop/pdf/PDFFontNonBase14.java b/src/java/org/apache/fop/pdf/PDFFontNonBase14.java index 0689cbbdb..b97d5deec 100644 --- a/src/java/org/apache/fop/pdf/PDFFontNonBase14.java +++ b/src/java/org/apache/fop/pdf/PDFFontNonBase14.java @@ -27,26 +27,6 @@ import org.apache.fop.fonts.FontType; */ public abstract class PDFFontNonBase14 extends PDFFont { - /** - * first character code in the font - */ - protected int firstChar; - - /** - * last character code in the font - */ - protected int lastChar; - - /** - * widths of characters from firstChar to lastChar - */ - protected PDFArray widths; - - /** - * descriptor of font metrics - */ - protected PDFFontDescriptor descriptor; - /** * Create the /Font object * @@ -61,8 +41,6 @@ public abstract class PDFFontNonBase14 extends PDFFont { /* generic creation of PDF object */ super(fontname, subtype, basefont, encoding); - - this.descriptor = null; } /** @@ -74,10 +52,9 @@ public abstract class PDFFontNonBase14 extends PDFFont { */ public void setWidthMetrics(int firstChar, int lastChar, PDFArray widths) { - /* set fields using paramaters */ - this.firstChar = firstChar; - this.lastChar = lastChar; - this.widths = widths; + put("FirstChar", new Integer(firstChar)); + put("LastChar", new Integer(lastChar)); + put("Widths", widths); } /** @@ -86,12 +63,20 @@ public abstract class PDFFontNonBase14 extends PDFFont { * @param descriptor the descriptor for other font's metrics */ public void setDescriptor(PDFFontDescriptor descriptor) { - this.descriptor = descriptor; + put("FontDescriptor", descriptor); } /** @return the FontDescriptor or null if there is none */ public PDFFontDescriptor getDescriptor() { - return this.descriptor; + return (PDFFontDescriptor)get("FontDescriptor"); + } + + /** + * Sets a ToUnicode CMap. + * @param cmap the ToUnicode character map + */ + public void setToUnicode(PDFCMap cmap) { + put("ToUnicode", cmap); } /** {@inheritDoc} */ @@ -104,20 +89,4 @@ public abstract class PDFFontNonBase14 extends PDFFont { } } - /** - * {@inheritDoc} - */ - protected void fillInPDF(StringBuffer target) { - target.append("\n/FirstChar "); - target.append(firstChar); - target.append("\n/LastChar "); - target.append(lastChar); - target.append("\n/Widths "); - target.append(this.widths.referencePDF()); - if (descriptor != null) { - target.append("\n/FontDescriptor "); - target.append(this.descriptor.referencePDF()); - } - } - } diff --git a/src/java/org/apache/fop/pdf/PDFFontTrueType.java b/src/java/org/apache/fop/pdf/PDFFontTrueType.java index eb3a94a27..a5636f951 100644 --- a/src/java/org/apache/fop/pdf/PDFFontTrueType.java +++ b/src/java/org/apache/fop/pdf/PDFFontTrueType.java @@ -39,9 +39,7 @@ public class PDFFontTrueType extends PDFFontNonBase14 { public PDFFontTrueType(String fontname, String basefont, Object encoding) { - - /* generic creation of PDF object */ - super(fontname, FontType.TRUETYPE, basefont, encoding /* , mapping */); + super(fontname, FontType.TRUETYPE, basefont, encoding); } } diff --git a/src/java/org/apache/fop/pdf/PDFFontType0.java b/src/java/org/apache/fop/pdf/PDFFontType0.java index e8a338ad4..29d6d1b4f 100644 --- a/src/java/org/apache/fop/pdf/PDFFontType0.java +++ b/src/java/org/apache/fop/pdf/PDFFontType0.java @@ -26,17 +26,7 @@ import org.apache.fop.fonts.FontType; *

    * Type0 fonts are specified on page 208 and onwards of the PDF 1.3 spec. */ -public class PDFFontType0 extends PDFFontNonBase14 { - - /** - * This should be an array of CIDFont but only the first one is used - */ - protected PDFCIDFont descendantFonts; - - /** - * The character map - */ - protected PDFCMap cmap; +public class PDFFontType0 extends PDFFont { /** * Create the /Font object @@ -48,13 +38,7 @@ public class PDFFontType0 extends PDFFontNonBase14 { public PDFFontType0(String fontname, String basefont, Object encoding) { - - /* generic creation of PDF object */ - super(fontname, FontType.TYPE0, basefont, encoding /* , mapping */); - - /* set fields using paramaters */ - this.descendantFonts = null; - cmap = null; + super(fontname, FontType.TYPE0, basefont, encoding); } /** @@ -69,12 +53,9 @@ public class PDFFontType0 extends PDFFontNonBase14 { String basefont, Object encoding, PDFCIDFont descendantFonts) { + super(fontname, FontType.TYPE0, basefont, encoding); - /* generic creation of PDF object */ - super(fontname, FontType.TYPE0, basefont, encoding /* , mapping */); - - /* set fields using paramaters */ - this.descendantFonts = descendantFonts; + setDescendantFonts(descendantFonts); } /** @@ -82,7 +63,7 @@ public class PDFFontType0 extends PDFFontNonBase14 { * @param descendantFonts the CIDFont upon which this font is based */ public void setDescendantFonts(PDFCIDFont descendantFonts) { - this.descendantFonts = descendantFonts; + put("DescendantFonts", new PDFArray(this, new PDFObject[] {descendantFonts})); } /** @@ -90,20 +71,7 @@ public class PDFFontType0 extends PDFFontNonBase14 { * @param cmap the character map */ public void setCMAP(PDFCMap cmap) { - this.cmap = cmap; - } - - /** - * {@inheritDoc} - */ - protected void fillInPDF(StringBuffer target) { - if (descendantFonts != null) { - target.append("\n/DescendantFonts [ " - + this.descendantFonts.referencePDF() + " ] "); - } - if (cmap != null) { - target.append("\n/ToUnicode " + cmap.referencePDF()); - } + put("ToUnicode", cmap); } } diff --git a/src/java/org/apache/fop/pdf/PDFFontType3.java b/src/java/org/apache/fop/pdf/PDFFontType3.java index 48df26fdf..96ecb6b5a 100644 --- a/src/java/org/apache/fop/pdf/PDFFontType3.java +++ b/src/java/org/apache/fop/pdf/PDFFontType3.java @@ -31,26 +31,6 @@ import org.apache.fop.fonts.FontType; */ public class PDFFontType3 extends PDFFontNonBase14 { - /** - * font's required /FontBBox bounding box - */ - protected PDFRectangle fontBBox; - - /** - * font's required /FontMatrix array - */ - protected PDFArray fontMatrix; - - /** - * font's required /CharProcs dictionary - */ - protected PDFCharProcs charProcs; - - /** - * font's optional /Resources object - */ - protected PDFResources resources; - /** * Create the /Font object * @@ -61,13 +41,7 @@ public class PDFFontType3 extends PDFFontNonBase14 { public PDFFontType3(String fontname, String basefont, Object encoding) { - - /* generic creation of PDF object */ - super(fontname, FontType.TYPE3, basefont, encoding /* , mapping */); - - this.fontBBox = null; - this.fontMatrix = null; - this.charProcs = null; + super(fontname, FontType.TYPE3, basefont, encoding); } /** @@ -89,9 +63,9 @@ public class PDFFontType3 extends PDFFontNonBase14 { /* generic creation of PDF object */ super(fontname, FontType.TYPE3, basefont, encoding /* , mapping */); - this.fontBBox = fontBBox; - this.fontMatrix = fontMatrix; - this.charProcs = charProcs; + setFontBBox(fontBBox); + setFontMatrix(fontMatrix); + setCharProcs(charProcs); } /** @@ -100,7 +74,7 @@ public class PDFFontType3 extends PDFFontNonBase14 { * @param bbox bounding box for the font */ public void setFontBBox(PDFRectangle bbox) { - this.fontBBox = bbox; + put("FontBBox", bbox); } /** @@ -109,7 +83,7 @@ public class PDFFontType3 extends PDFFontNonBase14 { * @param matrix the transformation matrix for the font */ public void setFontMatrix(PDFArray matrix) { - this.fontMatrix = matrix; + put("FontMatrix", matrix); } /** @@ -120,25 +94,7 @@ public class PDFFontType3 extends PDFFontNonBase14 { * @param chars the glyphs' dictionary */ public void setCharProcs(PDFCharProcs chars) { - this.charProcs = chars; - } - - /** - * {@inheritDoc} - */ - protected void fillInPDF(StringBuffer target) { - if (fontBBox != null) { - target.append("\n/FontBBox "); - target.append(fontBBox.toPDF()); - } - if (fontMatrix != null) { - target.append("\n/FontMatrix "); - target.append(fontMatrix.toPDF()); - } - if (charProcs != null) { - target.append("\n/CharProcs "); - target.append(charProcs.referencePDF()); - } + put("CharProcs", chars); } } diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java index d43ae71f1..8dc4d8794 100644 --- a/src/java/org/apache/fop/pdf/PDFObject.java +++ b/src/java/org/apache/fop/pdf/PDFObject.java @@ -103,7 +103,9 @@ public abstract class PDFObject implements PDFWritable { */ public void setObjectNumber(int objnum) { this.objnum = objnum; + PDFDocument doc = getDocument(); setParent(null); + setDocument(doc); //Restore reference to PDFDocument after setting parent to null if (log.isTraceEnabled()) { log.trace("Assigning " + this + " object number " + objnum); } @@ -141,7 +143,8 @@ public abstract class PDFObject implements PDFWritable { public final PDFDocument getDocumentSafely() { final PDFDocument doc = getDocument(); if (doc == null) { - throw new IllegalStateException("Parent PDFDocument is unavailable"); + throw new IllegalStateException("Parent PDFDocument is unavailable on " + + getClass().getName()); } return doc; } diff --git a/src/java/org/apache/fop/pdf/PDFRectangle.java b/src/java/org/apache/fop/pdf/PDFRectangle.java index e84227adf..ca97c2474 100644 --- a/src/java/org/apache/fop/pdf/PDFRectangle.java +++ b/src/java/org/apache/fop/pdf/PDFRectangle.java @@ -19,12 +19,16 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + /** * class representing a rectangle * * Rectangles are specified on page 183 of the PDF 1.3 spec. */ -public class PDFRectangle { +public class PDFRectangle implements PDFWritable { /** * lower left x coordinate @@ -73,23 +77,17 @@ public class PDFRectangle { this.ury = array[3]; } - /** - * produce the PDF representation for the object - * - * @return the PDF - */ - public byte[] toPDF() { - return PDFDocument.encode(toPDFString()); + private String format() { + return "[" + llx + " " + lly + " " + urx + " " + ury + "]"; } - /** - * Create a PDF string for this rectangle. - * - * @return the pdf string - */ - public String toPDFString() { - return new String(" [" + llx + " " + lly + " " + urx + " " + ury - + "] "); + /** {@inheritDoc} */ + public String toString() { + return "PDFRectangle" + format(); } + /** {@inheritDoc} */ + public void outputInline(OutputStream out, Writer writer) throws IOException { + writer.write(format()); + } } diff --git a/src/java/org/apache/fop/pdf/PDFT1Stream.java b/src/java/org/apache/fop/pdf/PDFT1Stream.java index 08a626009..d122743b0 100644 --- a/src/java/org/apache/fop/pdf/PDFT1Stream.java +++ b/src/java/org/apache/fop/pdf/PDFT1Stream.java @@ -23,7 +23,6 @@ package org.apache.fop.pdf; import java.io.IOException; import java.io.OutputStream; -// FOP import org.apache.fop.fonts.type1.PFBData; /** @@ -54,7 +53,9 @@ public class PDFT1Stream extends AbstractPDFStream { if (pfb == null) { throw new IllegalStateException("pfb must not be null at this point"); } - log.debug("Writing " + pfb.getLength() + " bytes of Type 1 font data"); + if (log.isDebugEnabled()) { + log.debug("Writing " + pfb.getLength() + " bytes of Type 1 font data"); + } int length = super.output(stream); log.debug("Embedded Type1 font"); diff --git a/src/java/org/apache/fop/pdf/PDFTTFStream.java b/src/java/org/apache/fop/pdf/PDFTTFStream.java index 9f4c543ad..b3488f6a1 100644 --- a/src/java/org/apache/fop/pdf/PDFTTFStream.java +++ b/src/java/org/apache/fop/pdf/PDFTTFStream.java @@ -44,7 +44,9 @@ public class PDFTTFStream extends PDFStream { */ protected int output(java.io.OutputStream stream) throws java.io.IOException { - log.debug("Writing " + origLength + " bytes of TTF font data"); + if (log.isDebugEnabled()) { + log.debug("Writing " + origLength + " bytes of TTF font data"); + } int length = super.output(stream); log.debug("Embedded TrueType/OpenType font"); diff --git a/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java b/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java index ab3295a46..3d25e28cb 100644 --- a/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java +++ b/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java @@ -19,7 +19,8 @@ package org.apache.fop.pdf; -import org.apache.fop.fonts.CIDFont; +import java.io.IOException; +import java.io.Writer; /** * Class representing ToUnicode CMaps. @@ -37,249 +38,251 @@ import org.apache.fop.fonts.CIDFont; public class PDFToUnicodeCMap extends PDFCMap { /** - * handle to read font + * The array of Unicode characters ordered by character code + * (maps from character code to Unicode code point). */ - protected CIDFont cidFont; + protected char[] unicodeCharMap; /** * Constructor. * - * @param cidMetrics the CID font for which this Unicode CMap is built + * @param unicodeCharMap An array of Unicode characters ordered by character code + * (maps from character code to Unicode code point) * @param name One of the registered names found in Table 5.14 in PDF * Reference, Second Edition. * @param sysInfo The attributes of the character collection of the CIDFont. */ - public PDFToUnicodeCMap(CIDFont cidMetrics, String name, PDFCIDSystemInfo sysInfo) { + public PDFToUnicodeCMap(char[] unicodeCharMap, String name, PDFCIDSystemInfo sysInfo) { super(name, sysInfo); - cidFont = cidMetrics; + this.unicodeCharMap = unicodeCharMap; } /** {@inheritDoc} */ - public void fillInPDF(StringBuffer p) { - writeCIDInit(p); - writeCIDSystemInfo(p); - writeVersionTypeName(p); - writeCodeSpaceRange(p); - writeBFEntries(p); - writeWrapUp(p); - add(p.toString()); + protected CMapBuilder createCMapBuilder(Writer writer) { + return new ToUnicodeCMapBuilder(writer); } - - /** {@inheritDoc} */ - protected void writeCIDSystemInfo(StringBuffer p) { - p.append("/CIDSystemInfo\n"); - p.append("<< /Registry (Adobe)\n"); - p.append("/Ordering (UCS)\n"); - p.append("/Supplement 0\n"); - p.append(">> def\n"); - } - - /** {@inheritDoc} */ - protected void writeVersionTypeName(StringBuffer p) { - p.append("/CMapName /Adobe-Identity-UCS def\n"); - p.append("/CMapType 2 def\n"); - } - - /** - * Writes the character mappings for this font. - * @param p StingBuffer to write to - */ - protected void writeBFEntries(StringBuffer p) { - if (cidFont == null) { - return; + + class ToUnicodeCMapBuilder extends CMapBuilder { + + public ToUnicodeCMapBuilder(Writer writer) { + super(writer, null); } - char[] charArray = cidFont.getCharsUsed(); - - if (charArray != null) { - writeBFCharEntries(p, charArray); - writeBFRangeEntries(p, charArray); + /** + * Writes the CMap to a Writer. + * @param writer the writer + * @throws IOException if an I/O error occurs + */ + public void writeCMap() throws IOException { + writeCIDInit(); + writeCIDSystemInfo("Adobe", "UCS", 0); + writeName("Adobe-Identity-UCS"); + writeType("2"); + writeCodeSpaceRange(); + writeBFEntries(); + writeWrapUp(); } - } - - /** - * Writes the entries for single characters of a base font (only characters which cannot be - * expressed as part of a character range). - * @param p StringBuffer to write to - * @param charArray all the characters to map - */ - protected void writeBFCharEntries(StringBuffer p, char[] charArray) { - int totalEntries = 0; - for (int i = 0; i < charArray.length; i++) { - if (!partOfRange(charArray, i)) { - totalEntries++; + + /** + * Writes the character mappings for this font. + * @param p StingBuffer to write to + */ + protected void writeBFEntries() throws IOException { + if (unicodeCharMap != null) { + writeBFCharEntries(unicodeCharMap); + writeBFRangeEntries(unicodeCharMap); } } - if (totalEntries < 1) { - return; - } - int remainingEntries = totalEntries; - int charIndex = 0; - do { - /* Limited to 100 entries in each section */ - int entriesThisSection = Math.min(remainingEntries, 100); - p.append(entriesThisSection + " beginbfchar\n"); - for (int i = 0; i < entriesThisSection; i++) { - /* Go to the next char not in a range */ - while (partOfRange(charArray, charIndex)) { - charIndex++; + + /** + * Writes the entries for single characters of a base font (only characters which cannot be + * expressed as part of a character range). + * @param p StringBuffer to write to + * @param charArray all the characters to map + * @throws IOException + */ + protected void writeBFCharEntries(char[] charArray) throws IOException { + int totalEntries = 0; + for (int i = 0; i < charArray.length; i++) { + if (!partOfRange(charArray, i)) { + totalEntries++; } - p.append("<" + padHexString(Integer.toHexString(charIndex), 4) + "> "); - p.append("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4) + ">\n"); - charIndex++; } - remainingEntries -= entriesThisSection; - p.append("endbfchar\n"); - } while (remainingEntries > 0); - } - - /** - * Writes the entries for character ranges for a base font. - * @param p StringBuffer to write to - * @param charArray all the characters to map - */ - protected void writeBFRangeEntries(StringBuffer p, char[] charArray) { - int totalEntries = 0; - for (int i = 0; i < charArray.length; i++) { - if (startOfRange(charArray, i)) { - totalEntries++; + if (totalEntries < 1) { + return; } - } - if (totalEntries < 1) { - return; - } - int remainingEntries = totalEntries; - int charIndex = 0; - do { - /* Limited to 100 entries in each section */ - int entriesThisSection = Math.min(remainingEntries, 100); - p.append(entriesThisSection + " beginbfrange\n"); - for (int i = 0; i < entriesThisSection; i++) { - /* Go to the next start of a range */ - while (!startOfRange(charArray, charIndex)) { + int remainingEntries = totalEntries; + int charIndex = 0; + do { + /* Limited to 100 entries in each section */ + int entriesThisSection = Math.min(remainingEntries, 100); + writer.write(entriesThisSection + " beginbfchar\n"); + for (int i = 0; i < entriesThisSection; i++) { + /* Go to the next char not in a range */ + while (partOfRange(charArray, charIndex)) { + charIndex++; + } + writer.write("<" + padHexString(Integer.toHexString(charIndex), 4) + "> "); + writer.write("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4) + + ">\n"); charIndex++; } - p.append("<" + padHexString(Integer.toHexString(charIndex), 4) + "> "); - p.append("<" - + padHexString(Integer.toHexString(endOfRange(charArray, charIndex)), 4) - + "> "); - p.append("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4) + ">\n"); - charIndex++; - } - remainingEntries -= entriesThisSection; - p.append("endbfrange\n"); - } while (remainingEntries > 0); - } - - /** - * Find the end of the current range. - * @param charArray The array which is being tested. - * @param startOfRange The index to the array element that is the start of - * the range. - * @return The index to the element that is the end of the range. - */ - private int endOfRange(char[] charArray, int startOfRange) { - int i = startOfRange; - while (i < charArray.length - 1 && sameRangeEntryAsNext(charArray, i)) { - i++; + remainingEntries -= entriesThisSection; + writer.write("endbfchar\n"); + } while (remainingEntries > 0); } - return i; - } - /** - * Determine whether this array element should be part of a bfchar entry or - * a bfrange entry. - * @param charArray The array to be tested. - * @param arrayIndex The index to the array element to be tested. - * @return True if this array element should be included in a range. - */ - private boolean partOfRange(char[] charArray, int arrayIndex) { - if (charArray.length < 2) { - return false; - } - if (arrayIndex == 0) { - return sameRangeEntryAsNext(charArray, 0); - } - if (arrayIndex == charArray.length - 1) { - return sameRangeEntryAsNext(charArray, arrayIndex - 1); - } - if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) { - return true; - } - if (sameRangeEntryAsNext(charArray, arrayIndex)) { - return true; + /** + * Writes the entries for character ranges for a base font. + * @param p StringBuffer to write to + * @param charArray all the characters to map + * @throws IOException + */ + protected void writeBFRangeEntries(char[] charArray) throws IOException { + int totalEntries = 0; + for (int i = 0; i < charArray.length; i++) { + if (startOfRange(charArray, i)) { + totalEntries++; + } + } + if (totalEntries < 1) { + return; + } + int remainingEntries = totalEntries; + int charIndex = 0; + do { + /* Limited to 100 entries in each section */ + int entriesThisSection = Math.min(remainingEntries, 100); + writer.write(entriesThisSection + " beginbfrange\n"); + for (int i = 0; i < entriesThisSection; i++) { + /* Go to the next start of a range */ + while (!startOfRange(charArray, charIndex)) { + charIndex++; + } + writer.write("<" + padHexString(Integer.toHexString(charIndex), 4) + "> "); + writer.write("<" + + padHexString(Integer.toHexString(endOfRange(charArray, charIndex)), 4) + + "> "); + writer.write("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4) + + ">\n"); + charIndex++; + } + remainingEntries -= entriesThisSection; + writer.write("endbfrange\n"); + } while (remainingEntries > 0); } - return false; - } - /** - * Determine whether two bytes can be written in the same bfrange entry. - * @param charArray The array to be tested. - * @param firstItem The first of the two items in the array to be tested. - * The second item is firstItem + 1. - * @return True if both 1) the next item in the array is sequential with - * this one, and 2) the first byte of the character in the first position - * is equal to the first byte of the character in the second position. - */ - private boolean sameRangeEntryAsNext(char[] charArray, int firstItem) { - if (charArray[firstItem] + 1 != charArray[firstItem + 1]) { - return false; - } - if (firstItem / 256 != (firstItem + 1) / 256) { - return false; + /** + * Find the end of the current range. + * @param charArray The array which is being tested. + * @param startOfRange The index to the array element that is the start of + * the range. + * @return The index to the element that is the end of the range. + */ + private int endOfRange(char[] charArray, int startOfRange) { + int i = startOfRange; + while (i < charArray.length - 1 && sameRangeEntryAsNext(charArray, i)) { + i++; + } + return i; } - return true; - } - /** - * Determine whether this array element should be the start of a bfrange - * entry. - * @param charArray The array to be tested. - * @param arrayIndex The index to the array element to be tested. - * @return True if this array element is the beginning of a range. - */ - private boolean startOfRange(char[] charArray, int arrayIndex) { - // Can't be the start of a range if not part of a range. - if (!partOfRange(charArray, arrayIndex)) { + /** + * Determine whether this array element should be part of a bfchar entry or + * a bfrange entry. + * @param charArray The array to be tested. + * @param arrayIndex The index to the array element to be tested. + * @return True if this array element should be included in a range. + */ + private boolean partOfRange(char[] charArray, int arrayIndex) { + if (charArray.length < 2) { + return false; + } + if (arrayIndex == 0) { + return sameRangeEntryAsNext(charArray, 0); + } + if (arrayIndex == charArray.length - 1) { + return sameRangeEntryAsNext(charArray, arrayIndex - 1); + } + if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) { + return true; + } + if (sameRangeEntryAsNext(charArray, arrayIndex)) { + return true; + } return false; } - // If first element in the array, must be start of a range - if (arrayIndex == 0) { + + /** + * Determine whether two bytes can be written in the same bfrange entry. + * @param charArray The array to be tested. + * @param firstItem The first of the two items in the array to be tested. + * The second item is firstItem + 1. + * @return True if both 1) the next item in the array is sequential with + * this one, and 2) the first byte of the character in the first position + * is equal to the first byte of the character in the second position. + */ + private boolean sameRangeEntryAsNext(char[] charArray, int firstItem) { + if (charArray[firstItem] + 1 != charArray[firstItem + 1]) { + return false; + } + if (firstItem / 256 != (firstItem + 1) / 256) { + return false; + } return true; } - // If last element in the array, cannot be start of a range - if (arrayIndex == charArray.length - 1) { - return false; - } - /* - * If part of same range as the previous element is, cannot be start - * of range. + + /** + * Determine whether this array element should be the start of a bfrange + * entry. + * @param charArray The array to be tested. + * @param arrayIndex The index to the array element to be tested. + * @return True if this array element is the beginning of a range. */ - if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) { - return false; + private boolean startOfRange(char[] charArray, int arrayIndex) { + // Can't be the start of a range if not part of a range. + if (!partOfRange(charArray, arrayIndex)) { + return false; + } + // If first element in the array, must be start of a range + if (arrayIndex == 0) { + return true; + } + // If last element in the array, cannot be start of a range + if (arrayIndex == charArray.length - 1) { + return false; + } + /* + * If part of same range as the previous element is, cannot be start + * of range. + */ + if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) { + return false; + } + // Otherwise, this is start of a range. + return true; } - // Otherwise, this is start of a range. - return true; - } - /** - * Prepends the input string with a sufficient number of "0" characters to - * get the returned string to be numChars length. - * @param input The input string. - * @param numChars The minimum characters in the output string. - * @return The padded string. - */ - public static String padHexString(String input, int numChars) { - int length = input.length(); - if (length >= numChars) { - return input; - } - StringBuffer returnString = new StringBuffer(); - for (int i = 1; i <= numChars - length; i++) { - returnString.append("0"); + /** + * Prepends the input string with a sufficient number of "0" characters to + * get the returned string to be numChars length. + * @param input The input string. + * @param numChars The minimum characters in the output string. + * @return The padded string. + */ + private String padHexString(String input, int numChars) { + int length = input.length(); + if (length >= numChars) { + return input; + } + StringBuffer returnString = new StringBuffer(); + for (int i = 1; i <= numChars - length; i++) { + returnString.append("0"); + } + returnString.append(input); + return returnString.toString(); } - returnString.append(input); - return returnString.toString(); - } + } + } diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 09c6fbed4..15ed6d98a 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -1565,7 +1565,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { startPending = false; } if (!useMultiByte) { - if (ch > 127) { + if (ch < 32 || ch > 127) { pdf.append("\\"); pdf.append(Integer.toOctalString((int) ch)); } else { diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java index 8fb29d302..bbc811b4e 100644 --- a/src/java/org/apache/fop/render/ps/PSFontUtils.java +++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java @@ -31,16 +31,18 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.ps.DSCConstants; +import org.apache.xmlgraphics.ps.PSGenerator; +import org.apache.xmlgraphics.ps.PSResource; +import org.apache.xmlgraphics.ps.dsc.ResourceTracker; + import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.Typeface; -import org.apache.xmlgraphics.ps.DSCConstants; -import org.apache.xmlgraphics.ps.PSGenerator; -import org.apache.xmlgraphics.ps.PSResource; -import org.apache.xmlgraphics.ps.dsc.ResourceTracker; /** * Utility code for font handling in PostScript. @@ -108,8 +110,10 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { } else if ("WinAnsiEncoding".equals(fm.getEncoding())) { redefineFontEncoding(gen, fm.getFontName(), fm.getEncoding()); } else { + /* Don't complain anymore, just use the font's default encoding. gen.commentln("%WARNING: Only WinAnsiEncoding is supported. Font '" + fm.getFontName() + "' asks for: " + fm.getEncoding()); + */ } } gen.commentln("%FOPEndFontReencode"); diff --git a/src/java/org/apache/fop/util/CharUtilities.java b/src/java/org/apache/fop/util/CharUtilities.java index bfcc90a64..4910a371c 100644 --- a/src/java/org/apache/fop/util/CharUtilities.java +++ b/src/java/org/apache/fop/util/CharUtilities.java @@ -68,7 +68,10 @@ public class CharUtilities { public static final char ZERO_WIDTH_NOBREAK_SPACE = '\uFEFF'; /** soft hyphen */ public static final char SOFT_HYPHEN = '\u00AD'; - + /** missing ideograph */ + public static final char MISSING_IDEOGRAPH = '\u25A1'; + /** Unicode value indicating the the character is "not a character". */ + public static final char NOT_A_CHARACTER = '\uFFFF'; /** * Utility class: Constructor prevents instantiating when subclassed. diff --git a/status.xml b/status.xml index 7926fe379..305fe8c7c 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Added support for unusual font encodings (like for Symbol or Cyrillic fonts) of Type 1 + fonts in PDF and PostScript output. + Moved to the FO tree stage the check for break-before/after on table-row while spanning in progress. diff --git a/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java b/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java index a7ea1a2db..eb34f70b8 100644 --- a/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java +++ b/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java @@ -19,14 +19,16 @@ package org.apache.fop.render.pdf; -import org.apache.fop.pdf.PDFCMap; +import java.io.StringWriter; import junit.framework.TestCase; +import org.apache.fop.pdf.CMapBuilder; + /** Simple sanity test of the PDFCmap class */ public class PDFCMapTestCase extends TestCase { - public void testPDFCMapFillInPDF() { + public void testPDFCMapFillInPDF() throws Exception { final String EOL = "\n"; final String expected = "%!PS-Adobe-3.0 Resource-CMap" + EOL @@ -59,10 +61,10 @@ public class PDFCMapTestCase extends TestCase { +"%%EOF" + EOL ; - final PDFCMap m = new PDFCMap("test", null); - final StringBuffer b = new StringBuffer(); - m.fillInPDF(b); - final String actual = b.toString(); + final StringWriter w = new StringWriter(); + final CMapBuilder builder = new CMapBuilder(w, "test"); + builder.writeCMap(); + final String actual = w.getBuffer().toString(); assertEquals("PDFCMap output matches expected PostScript code", expected, actual); } -- cgit v1.2.3 From 06e1fa6d243ec64dd675110e9344f34cabd566a3 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 14 Feb 2008 10:12:48 +0000 Subject: When I first saw this it surprised me, it seems to have been here for quite some time. The code block directly following this if/else condition was identical so I removed the copy/paste duplication and refactored it. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627698 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/AbstractRenderer.java | 37 ++++++---------------- 1 file changed, 9 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 86820066f..32c4b33c4 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -171,15 +171,7 @@ public abstract class AbstractRenderer return this.currentPageViewport; } - /** - * Prepare a page for rendering. This is called if the renderer supports - * out of order rendering. The renderer should prepare the page so that a - * page further on in the set of pages can be rendered. The body of the - * page should not be rendered. The page will be rendered at a later time - * by the call to render page. - * - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void preparePage(PageViewport page) { } /** @@ -562,31 +554,20 @@ public abstract class AbstractRenderer int saveIP = currentIPPosition; int saveBP = currentBPPosition; - if (block.getPositioning() == Block.ABSOLUTE) { - currentIPPosition += block.getXOffset(); - currentBPPosition += block.getYOffset(); - currentBPPosition += block.getSpaceBefore(); + currentIPPosition += block.getXOffset(); + currentBPPosition += block.getYOffset(); + currentBPPosition += block.getSpaceBefore(); - handleBlockTraits(block); + handleBlockTraits(block); - if (children != null) { - renderBlocks(block, children); - } + if (children != null) { + renderBlocks(block, children); + } + if (block.getPositioning() == Block.ABSOLUTE) { // absolute blocks do not effect the layout currentBPPosition = saveBP; } else { - // relative blocks are offset - currentIPPosition += block.getXOffset(); - currentBPPosition += block.getYOffset(); - currentBPPosition += block.getSpaceBefore(); - - handleBlockTraits(block); - - if (children != null) { - renderBlocks(block, children); - } - // stacked and relative blocks effect stacking currentIPPosition = saveIP; currentBPPosition = saveBP + block.getAllocBPD(); -- cgit v1.2.3 From e1c8b0065b1d5b8456546abbc9d7e040123c380a Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 14 Feb 2008 10:41:26 +0000 Subject: Fix problem with alternate Unicode code point overriding existing better ones in CodePointMapping (ex. a char code for NBSP was used in place of SPACE for non-standard encodings). Made PFM completely optional if an AFM is available. Widths and Kerning are now also read from the AFM. Fallbacks for missing values are in place. If both AFM and PFM are available, both are used to get the best possible result for certain metrics. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627702 13f79535-47bb-0310-9956-ffa450edef68 --- src/codegen/fonts/code-point-mapping.xsl | 19 +-- src/java/org/apache/fop/fo/FOPropertyMapping.java | 6 +- .../org/apache/fop/fonts/type1/AFMCharMetrics.java | 31 ++++- src/java/org/apache/fop/fonts/type1/AFMFile.java | 90 ++++++++++++- src/java/org/apache/fop/fonts/type1/AFMParser.java | 20 ++- .../apache/fop/fonts/type1/Type1FontLoader.java | 142 ++++++++++++++------- 6 files changed, 247 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/codegen/fonts/code-point-mapping.xsl b/src/codegen/fonts/code-point-mapping.xsl index 80b62dd17..c82ca0104 100644 --- a/src/codegen/fonts/code-point-mapping.xsl +++ b/src/codegen/fonts/code-point-mapping.xsl @@ -63,14 +63,17 @@ public class CodePointMapping { unicodeMap = new char[256]; Arrays.fill(unicodeMap, CharUtilities.NOT_A_CHARACTER); for (int i = 0; i < table.length; i += 2) { - if (table[i + 1] < 256) { - latin1Map[table[i + 1]] = (char) table[i]; - } else { - ++nonLatin1; - } - if (unicodeMap[table[i]] == CharUtilities.NOT_A_CHARACTER) { - unicodeMap[table[i]] = (char)table[i + 1]; - } + char unicode = (char)table[i + 1]; + if (unicode < 256) { + if (latin1Map[unicode] == 0) { + latin1Map[unicode] = (char) table[i]; + } + } else { + ++nonLatin1; + } + if (unicodeMap[table[i]] == CharUtilities.NOT_A_CHARACTER) { + unicodeMap[table[i]] = unicode; + } } characters = new char[nonLatin1]; codepoints = new char[nonLatin1]; diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index b78ec49c4..9910f1ce7 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1153,7 +1153,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericSpace); corr = new SpacePropertyMaker(m); corr.setCorresponding(PR_MARGIN_BOTTOM, PR_MARGIN_BOTTOM, PR_MARGIN_LEFT); - corr.setUseParent(true); + corr.setUseParent(false); corr.setRelative(true); addPropertyMaker("space-after", m); @@ -1163,7 +1163,7 @@ public final class FOPropertyMapping implements Constants { m.setDefault("0pt"); IndentPropertyMaker sCorr = new IndentPropertyMaker(m); sCorr.setCorresponding(PR_MARGIN_LEFT, PR_MARGIN_RIGHT, PR_MARGIN_TOP); - sCorr.setUseParent(true); + sCorr.setUseParent(false); sCorr.setRelative(true); sCorr.setPaddingCorresponding(new int[] { PR_PADDING_LEFT, PR_PADDING_RIGHT, PR_PADDING_TOP @@ -1179,7 +1179,7 @@ public final class FOPropertyMapping implements Constants { m.setDefault("0pt"); IndentPropertyMaker eCorr = new IndentPropertyMaker(m); eCorr.setCorresponding(PR_MARGIN_RIGHT, PR_MARGIN_LEFT, PR_MARGIN_BOTTOM); - eCorr.setUseParent(true); + eCorr.setUseParent(false); eCorr.setRelative(true); eCorr.setPaddingCorresponding(new int[] { PR_PADDING_RIGHT, PR_PADDING_LEFT, PR_PADDING_BOTTOM diff --git a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java index 918d9ee08..fbbff567e 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java +++ b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java @@ -19,26 +19,37 @@ package org.apache.fop.fonts.type1; +import java.awt.geom.RectangularShape; + /** * Holds the metrics of a single character from an AFM file. */ public class AFMCharMetrics { - private int charCode; + private int charCode = -1; private String unicodeChars; private String charName; private double widthX; private double widthY; + private RectangularShape bBox; /** * Returns the character code. - * @return the charCode + * @return the charCode (-1 if not part of the encoding) */ public int getCharCode() { return charCode; } + /** + * Indicates whether the character has a character code, i.e. is part of the default encoding. + * @return true if there is a character code. + */ + public boolean hasCharCode() { + return charCode >= 0; + } + /** * Sets the character code. * @param charCode the charCode to set @@ -113,6 +124,22 @@ public class AFMCharMetrics { this.widthY = widthY; } + /** + * Returns the character's bounding box. + * @return the bounding box (or null if it isn't available) + */ + public RectangularShape getBBox() { + return bBox; + } + + /** + * Sets the character's bounding box. + * @param box the bounding box + */ + public void setBBox(RectangularShape box) { + bBox = box; + } + /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer("AFM Char: "); diff --git a/src/java/org/apache/fop/fonts/type1/AFMFile.java b/src/java/org/apache/fop/fonts/type1/AFMFile.java index af912975c..0b7b8d3c2 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMFile.java +++ b/src/java/org/apache/fop/fonts/type1/AFMFile.java @@ -19,8 +19,11 @@ package org.apache.fop.fonts.type1; +import java.awt.geom.Dimension2D; import java.awt.geom.RectangularShape; +import java.util.Arrays; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -56,9 +59,11 @@ public class AFMFile { //List private Map charNameToMetrics = new java.util.HashMap(); //Map + private int firstChar = -1; + private int lastChar = -1; private Map kerningMap; - //Map> + //Map> /** * Default constructor. @@ -314,6 +319,13 @@ public class AFMFile { if (name != null) { String u = Glyphs.getUnicodeCodePointsForGlyphName(metrics.getCharName()); if (u != null) { + if (u.length() > 1) { + //Lower values (ex. space) are most probably more interesting than + //higher values (ex. non-break-space), so sort just to be sure: + char[] chars = u.toCharArray(); + Arrays.sort(chars); + u = String.valueOf(chars); + } metrics.setUnicodeChars(u); } } else { @@ -325,6 +337,15 @@ public class AFMFile { if (name != null) { this.charNameToMetrics.put(name, metrics); } + int idx = metrics.getCharCode(); + if (idx >= 0) { //Only if the character is part of the encoding + if (firstChar < 0 || idx < firstChar) { + firstChar = idx; + } + if (lastChar < 0 || idx > lastChar) { + lastChar = idx; + } + } } /** @@ -335,6 +356,22 @@ public class AFMFile { return this.charMetrics.size(); } + /** + * Returns the first character index in the encoding that has a glyph. + * @return the first character index with a glyph + */ + public int getFirstChar() { + return this.firstChar; + } + + /** + * Returns the last character index in the encoding that has a glyph. + * @return the last character index with a glyph + */ + public int getLastChar() { + return this.lastChar; + } + /** * Returns the character metrics associated with the character name. * @param name the character name @@ -370,6 +407,57 @@ public class AFMFile { entries.put(name2, new Dimension2DDouble(kx, 0)); } + /** + * Indicates whether the font has kerning information. + * @return true if there is kerning information + */ + public boolean hasKerning() { + return this.kerningMap != null; + } + + /** + * Creates and returns a kerning map for writing mode 0 (ltr) with character codes. + * @return the kerning map or null if there is no kerning information. + */ + public Map createXKerningMapEncoded() { + if (!hasKerning()) { + return null; + } + Map m = new java.util.HashMap(); + Iterator iterFrom = this.kerningMap.entrySet().iterator(); + while (iterFrom.hasNext()) { + Map.Entry entryFrom = (Map.Entry)iterFrom.next(); + String name1 = (String)entryFrom.getKey(); + AFMCharMetrics chm1 = getChar(name1); + if (!chm1.hasCharCode()) { + continue; + } + Map container = null; + Map entriesTo = (Map)entryFrom.getValue(); + Iterator iterTo = entriesTo.entrySet().iterator(); + while (iterTo.hasNext()) { + Map.Entry entryTo = (Map.Entry)iterTo.next(); + String name2 = (String)entryTo.getKey(); + AFMCharMetrics chm2 = getChar(name2); + if (!chm2.hasCharCode()) { + continue; + } + if (container == null) { + Integer k1 = new Integer(chm1.getCharCode()); + container = (Map)m.get(k1); + if (container == null) { + container = new java.util.HashMap(); + m.put(k1, container); + } + } + Dimension2D dim = (Dimension2D)entryTo.getValue(); + container.put(new Integer(chm2.getCharCode()), + new Integer((int)Math.round(dim.getWidth()))); + } + } + return m; + } + /** {@inheritDoc} */ public String toString() { return "AFM: " + getFullName(); diff --git a/src/java/org/apache/fop/fonts/type1/AFMParser.java b/src/java/org/apache/fop/fonts/type1/AFMParser.java index 4d852058c..bb7ea3d30 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMParser.java +++ b/src/java/org/apache/fop/fonts/type1/AFMParser.java @@ -73,6 +73,7 @@ public class AFMParser { private static final String W0 = "W0"; private static final String W1 = "W1"; private static final String N = "N"; + private static final String B = "B"; private static final String START_TRACK_KERN = "StartTrackKern"; private static final String END_TRACK_KERN = "EndTrackKern"; //private static final String START_KERN_PAIRS = "StartKernPairs"; @@ -126,6 +127,7 @@ public class AFMParser { VALUE_PARSERS.put(W0, new NotImplementedYet(W0)); VALUE_PARSERS.put(W1, new NotImplementedYet(W1)); VALUE_PARSERS.put(N, new StringSetter("CharName")); + VALUE_PARSERS.put(B, new CharBBox()); VALUE_PARSERS.put(START_TRACK_KERN, new NotImplementedYet(START_TRACK_KERN)); VALUE_PARSERS.put(END_TRACK_KERN, new NotImplementedYet(END_TRACK_KERN)); VALUE_PARSERS.put(START_KERN_PAIRS1, new NotImplementedYet(START_KERN_PAIRS1)); @@ -497,7 +499,13 @@ public class AFMParser { private static class FontBBox extends AbstractValueHandler { public void parse(String line, int startpos, Stack stack) throws IOException { + Rectangle rect = parseBBox(line, startpos); + AFMFile afm = (AFMFile)stack.peek(); + afm.setFontBBox(rect); + } + + protected Rectangle parseBBox(String line, int startpos) { Rectangle rect = new Rectangle(); int endpos; @@ -518,11 +526,19 @@ public class AFMParser { v = Integer.parseInt(line.substring(startpos, endpos)); rect.height = v - rect.y; startpos = skipToNonWhiteSpace(line, endpos); - - afm.setFontBBox(rect); + return rect; } } + private static class CharBBox extends FontBBox { + public void parse(String line, int startpos, Stack stack) throws IOException { + Rectangle rect = parseBBox(line, startpos); + + AFMCharMetrics metrics = (AFMCharMetrics)stack.peek(); + metrics.setBBox(rect); + } + } + private static class IsBaseFont extends AbstractValueHandler { public void parse(String line, int startpos, Stack stack) throws IOException { if (getBooleanValue(line, startpos).booleanValue()) { diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index f5b04442b..57383dc76 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts.type1; +import java.awt.geom.RectangularShape; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; @@ -107,11 +108,6 @@ public class Type1FontLoader extends FontLoader { throw new java.io.FileNotFoundException( "Neither an AFM nor a PFM file was found for " + this.fontFileURI); } - if (pfm == null) { - //Cannot do without for now - throw new java.io.FileNotFoundException( - "No PFM file was found for " + this.fontFileURI); - } buildFont(afm, pfm); this.loaded = true; } @@ -122,33 +118,10 @@ public class Type1FontLoader extends FontLoader { } singleFont = new SingleByteFont(); singleFont.setFontType(FontType.TYPE1); - if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { - singleFont.setEncoding(pfm.getCharSetName() + "Encoding"); - } else { - log.warn("The PFM reports an unsupported encoding (" - + pfm.getCharSetName() + "). The font may not work as expected."); - singleFont.setEncoding("WinAnsiEncoding"); //Try fallback, no guarantees! - } singleFont.setResolver(this.resolver); + singleFont.setEmbedFileName(this.fontFileURI); returnFont = singleFont; - //Font name - if (afm != null) { - returnFont.setFontName(afm.getFontName()); //PostScript font name - returnFont.setFullName(afm.getFullName()); - Set names = new java.util.HashSet(); - names.add(afm.getFamilyName()); - returnFont.setFamilyNames(names); - } else { - returnFont.setFontName(pfm.getPostscriptName()); - String fullName = pfm.getPostscriptName(); - fullName = fullName.replace('-', ' '); //Hack! Try to emulate full name - returnFont.setFullName(fullName); //emulate afm.getFullName() - Set names = new java.util.HashSet(); - names.add(pfm.getWindowsName()); //emulate afm.getFamilyName() - returnFont.setFamilyNames(names); - } - //Encoding if (afm != null) { String encoding = afm.getEncodingScheme(); @@ -169,6 +142,31 @@ public class Type1FontLoader extends FontLoader { CodePointMapping mapping = buildCustomEncoding(effEncodingName, afm); singleFont.setEncoding(mapping); } + } else { + if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { + singleFont.setEncoding(pfm.getCharSetName() + "Encoding"); + } else { + log.warn("The PFM reports an unsupported encoding (" + + pfm.getCharSetName() + "). The font may not work as expected."); + singleFont.setEncoding("WinAnsiEncoding"); //Try fallback, no guarantees! + } + } + + //Font name + if (afm != null) { + returnFont.setFontName(afm.getFontName()); //PostScript font name + returnFont.setFullName(afm.getFullName()); + Set names = new java.util.HashSet(); + names.add(afm.getFamilyName()); + returnFont.setFamilyNames(names); + } else { + returnFont.setFontName(pfm.getPostscriptName()); + String fullName = pfm.getPostscriptName(); + fullName = fullName.replace('-', ' '); //Hack! Try to emulate full name + returnFont.setFullName(fullName); //emulate afm.getFullName() + Set names = new java.util.HashSet(); + names.add(pfm.getWindowsName()); //emulate afm.getFamilyName() + returnFont.setFamilyNames(names); } //Basic metrics @@ -185,6 +183,7 @@ public class Type1FontLoader extends FontLoader { if (afm.getDescender() != null) { returnFont.setDescender(afm.getDescender().intValue()); } + returnFont.setFontBBox(afm.getFontBBoxAsIntArray()); if (afm.getStdVW() != null) { returnFont.setStemV(afm.getStdVW().intValue()); @@ -198,28 +197,81 @@ public class Type1FontLoader extends FontLoader { returnFont.setItalicAngle(pfm.getItalicAngle()); } if (pfm != null) { - if (returnFont.getCapHeight() == 0) { - returnFont.setCapHeight(pfm.getCapHeight()); + //Sometimes the PFM has these metrics while the AFM doesn't (ex. Symbol) + returnFont.setCapHeight(pfm.getCapHeight()); + returnFont.setXHeight(pfm.getXHeight()); + returnFont.setAscender(pfm.getLowerCaseAscent()); + returnFont.setDescender(pfm.getLowerCaseDescent()); + } + + //Fallbacks when some crucial font metrics aren't available + //(the following are all optional in AFM, but FontBBox is always available) + if (returnFont.getXHeight(1) == 0) { + int xHeight = 0; + AFMCharMetrics chm = afm.getChar("x"); + if (chm != null) { + RectangularShape rect = chm.getBBox(); + if (rect != null) { + xHeight = (int)Math.round(rect.getMinX()); + } } - if (returnFont.getXHeight(1) == 0) { - returnFont.setXHeight(pfm.getXHeight()); + if (xHeight == 0) { + xHeight = Math.round(returnFont.getFontBBox()[3] * 0.6f); } - if (returnFont.getAscender() == 0) { - returnFont.setAscender(pfm.getLowerCaseAscent()); + returnFont.setXHeight(xHeight); + } + if (returnFont.getAscender() == 0) { + int asc = 0; + AFMCharMetrics chm = afm.getChar("d"); + if (chm != null) { + RectangularShape rect = chm.getBBox(); + if (rect != null) { + asc = (int)Math.round(rect.getMinX()); + } } - if (returnFont.getDescender() == 0) { - returnFont.setDescender(pfm.getLowerCaseDescent()); + if (asc == 0) { + asc = Math.round(returnFont.getFontBBox()[3] * 0.9f); } + returnFont.setAscender(asc); } - returnFont.setFirstChar(pfm.getFirstChar()); - returnFont.setLastChar(pfm.getLastChar()); - returnFont.setFlags(pfm.getFlags()); - returnFont.setMissingWidth(0); - for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { - singleFont.setWidth(i, pfm.getCharWidth(i)); + if (returnFont.getDescender() == 0) { + int desc = 0; + AFMCharMetrics chm = afm.getChar("p"); + if (chm != null) { + RectangularShape rect = chm.getBBox(); + if (rect != null) { + desc = (int)Math.round(rect.getMinX()); + } + } + if (desc == 0) { + desc = returnFont.getFontBBox()[1]; + } + returnFont.setDescender(desc); + } + if (returnFont.getCapHeight() == 0) { + returnFont.setCapHeight(returnFont.getAscender()); + } + + if (afm != null) { + returnFont.setFirstChar(afm.getFirstChar()); + returnFont.setLastChar(afm.getLastChar()); + Iterator iter = afm.getCharMetrics().iterator(); + while (iter.hasNext()) { + AFMCharMetrics chm = (AFMCharMetrics)iter.next(); + if (chm.hasCharCode()) { + singleFont.setWidth(chm.getCharCode(), (int)Math.round(chm.getWidthX())); + } + } + returnFont.replaceKerningMap(afm.createXKerningMapEncoded()); + } else { + returnFont.setFirstChar(pfm.getFirstChar()); + returnFont.setLastChar(pfm.getLastChar()); + returnFont.setFlags(pfm.getFlags()); + for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { + singleFont.setWidth(i, pfm.getCharWidth(i)); + } + returnFont.replaceKerningMap(pfm.getKerning()); } - returnFont.replaceKerningMap(pfm.getKerning()); - singleFont.setEmbedFileName(this.fontFileURI); } private CodePointMapping buildCustomEncoding(String encodingName, AFMFile afm) { -- cgit v1.2.3 From 5aab37b2dece063adf9e7809e38fe3100862f8ca Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 14 Feb 2008 11:36:01 +0000 Subject: Simplified the detection of double as integer git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627712 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/properties/NumberProperty.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/NumberProperty.java b/src/java/org/apache/fop/fo/properties/NumberProperty.java index 087429dba..6f8d8a1d2 100644 --- a/src/java/org/apache/fop/fo/properties/NumberProperty.java +++ b/src/java/org/apache/fop/fo/properties/NumberProperty.java @@ -80,8 +80,7 @@ public final class NumberProperty extends Property implements Numeric { private NumberProperty(double num) { //Store the number as an int or a long, //if possible - if ((num >= 0 && num == Math.floor(num)) - || num == Math.ceil(num)) { + if (num == Math.floor(num)) { if (num < Integer.MAX_VALUE) { this.number = new Integer((int)num); } else { -- cgit v1.2.3 From e397444e624314c9b1d4ea3bd9e2a958d129e9f4 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Thu, 14 Feb 2008 11:57:05 +0000 Subject: Created Constants for unit descriptions git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627719 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/expr/NumericProperty.java | 3 +- .../org/apache/fop/fo/properties/FixedLength.java | 36 ++++++++++++++++------ .../apache/fop/render/afp/fonts/RasterFont.java | 7 +++-- .../apache/fop/render/rtf/FoUnitsConverter.java | 11 ++++--- src/java/org/apache/fop/render/rtf/RTFHandler.java | 7 +++-- .../fop/render/rtf/TableAttributesConverter.java | 3 +- 6 files changed, 45 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/NumericProperty.java b/src/java/org/apache/fop/fo/expr/NumericProperty.java index 9c0b9e2ba..54fe1f2f7 100644 --- a/src/java/org/apache/fop/fo/expr/NumericProperty.java +++ b/src/java/org/apache/fop/fo/expr/NumericProperty.java @@ -25,6 +25,7 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.datatypes.Numeric; +import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.fo.properties.Property; /** @@ -121,7 +122,7 @@ public class NumericProperty extends Property implements Numeric, Length { /** {@inheritDoc} */ public String toString() { if (dim == 1) { - return (int) value + "mpt"; + return (int) value + FixedLength.MPT; } else { return value + "^" + dim; } diff --git a/src/java/org/apache/fop/fo/properties/FixedLength.java b/src/java/org/apache/fop/fo/properties/FixedLength.java index 7c4344b53..6debdd145 100644 --- a/src/java/org/apache/fop/fo/properties/FixedLength.java +++ b/src/java/org/apache/fop/fo/properties/FixedLength.java @@ -26,11 +26,29 @@ import org.apache.fop.datatypes.PercentBaseContext; */ public final class FixedLength extends LengthProperty { + /** Describes the unit pica. */ + public static final String PICA = "pc"; + + /** Describes the unit point. */ + public static final String POINT = "pt"; + + /** Describes the unit millimeter. */ + public static final String MM = "mm"; + + /** Describes the unit centimeter. */ + public static final String CM = "cm"; + + /** Describes the unit inch. */ + public static final String INCH = "in"; + + /** Describes the unit millipoint. */ + public static final String MPT = "mpt"; + /** cache holding all canonical FixedLength instances */ private static final PropertyCache cache = new PropertyCache(); /** canonical zero-length instance */ - public static final FixedLength ZERO_FIXED_LENGTH = new FixedLength(0, "mpt", 1.0f); + public static final FixedLength ZERO_FIXED_LENGTH = new FixedLength(0, FixedLength.MPT, 1.0f); private int millipoints; @@ -96,7 +114,7 @@ public final class FixedLength extends LengthProperty { * to the given number of units and unit specifier */ public static FixedLength getInstance(double numUnits) { - return getInstance(numUnits, "mpt", 1.0f); + return getInstance(numUnits, FixedLength.MPT, 1.0f); } @@ -115,17 +133,17 @@ public final class FixedLength extends LengthProperty { //device-dependent units, take the resolution into account dvalue *= (res * 1000); } else { - if ("in".equals(unit)) { + if (FixedLength.INCH.equals(unit)) { dvalue *= 72000; - } else if ("cm".equals(unit)) { + } else if (FixedLength.CM.equals(unit)) { dvalue *= 28346.4567; - } else if ("mm".equals(unit)) { + } else if (FixedLength.MM.equals(unit)) { dvalue *= 2834.64567; - } else if ("pt".equals(unit)) { + } else if (FixedLength.POINT.equals(unit)) { dvalue *= 1000; - } else if ("pc".equals(unit)) { + } else if (FixedLength.PICA.equals(unit)) { dvalue *= 12000; - } else if (!"mpt".equals(unit)) { + } else if (!FixedLength.MPT.equals(unit)) { dvalue = 0; log.error("Unknown length unit '" + unit + "'"); } @@ -163,7 +181,7 @@ public final class FixedLength extends LengthProperty { /** {@inheritDoc} */ public String toString() { - return millipoints + "mpt"; + return millipoints + FixedLength.MPT; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java index d383660b9..a61f97ab5 100644 --- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.render.afp.exceptions.FontRuntimeException; /** @@ -75,7 +76,7 @@ public class RasterFont extends AFPFont { String pointsize = String.valueOf(size / 1000); CharacterSet csm = (CharacterSet) charSets.get(pointsize); if (csm == null) { - csm = (CharacterSet) charSets.get(size + "mpt"); + csm = (CharacterSet) charSets.get(size + FixedLength.MPT); } if (csm == null) { // Get char set with nearest font size @@ -83,7 +84,7 @@ public class RasterFont extends AFPFont { for (Iterator it = charSets.entrySet().iterator(); it.hasNext();) { Map.Entry me = (Map.Entry)it.next(); String key = (String)me.getKey(); - if (!key.endsWith("mpt")) { + if (!key.endsWith(FixedLength.MPT)) { int mpt = Integer.parseInt(key) * 1000; if (Math.abs(size - mpt) < distance) { distance = Math.abs(size - mpt); @@ -93,7 +94,7 @@ public class RasterFont extends AFPFont { } } if (csm != null) { - charSets.put(size + "mpt", csm); + charSets.put(size + FixedLength.MPT, csm); String msg = "No " + (size / 1000) + "pt font " + getFontName() + " found, substituted with " + pointsize + "pt font"; log.warn(msg); diff --git a/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java b/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java index 8a7e2612b..fa95b8502 100644 --- a/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java +++ b/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java @@ -24,6 +24,7 @@ import java.util.HashMap; //FOP import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.properties.FixedLength; /** Converts XSL-FO units to RTF units @@ -51,10 +52,10 @@ final class FoUnitsConverter { /** conversion factors keyed by xsl:fo units names */ private static final Map TWIP_FACTORS = new HashMap(); static { - TWIP_FACTORS.put("mm", new Float(MM_TO_TWIPS)); - TWIP_FACTORS.put("cm", new Float(CM_TO_TWIPS)); - TWIP_FACTORS.put("pt", new Float(POINT_TO_TWIPS)); - TWIP_FACTORS.put("in", new Float(IN_TO_TWIPS)); + TWIP_FACTORS.put(FixedLength.MM, new Float(MM_TO_TWIPS)); + TWIP_FACTORS.put(FixedLength.CM, new Float(CM_TO_TWIPS)); + TWIP_FACTORS.put(FixedLength.POINT, new Float(POINT_TO_TWIPS)); + TWIP_FACTORS.put(FixedLength.INCH, new Float(IN_TO_TWIPS)); } /** singleton pattern */ @@ -125,7 +126,7 @@ final class FoUnitsConverter { /** convert a font size given in points like "12pt" */ int convertFontSize(String size) throws FOPException { size = size.trim(); - final String sFONTSUFFIX = "pt"; + final String sFONTSUFFIX = FixedLength.POINT; if (!size.endsWith(sFONTSUFFIX)) { throw new FOPException("Invalid font size '" + size + "', must end with '" + sFONTSUFFIX + "'"); diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 333e4ab95..d2f2c4192 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -85,6 +85,7 @@ import org.apache.fop.fo.pagination.Region; import org.apache.fop.fo.pagination.SimplePageMaster; import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.fonts.FontSetup; import org.apache.fop.render.DefaultFontResolver; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer; @@ -578,7 +579,7 @@ public class RTFHandler extends FOEventHandler { Integer iWidth = new Integer(tc.getColumnWidth().getValue(context) / 1000); - String strWidth = iWidth.toString() + "pt"; + String strWidth = iWidth.toString() + FixedLength.POINT; Float width = new Float( FoUnitsConverter.getInstance().convertToTwips(strWidth)); builderContext.getTableContext().setNextColumnWidth(width); @@ -1277,11 +1278,11 @@ public class RTFHandler extends FOEventHandler { } //set width in rtf - //newGraphic.setWidth((long) (contentwidth / 1000f) + "pt"); + //newGraphic.setWidth((long) (contentwidth / 1000f) + FixedLength.POINT); rtfGraphic.setWidth((long) (contentwidth / 50f) + "twips"); //set height in rtf - //newGraphic.setHeight((long) (contentheight / 1000f) + "pt"); + //newGraphic.setHeight((long) (contentheight / 1000f) + FixedLength.POINT); rtfGraphic.setHeight((long) (contentheight / 50f) + "twips"); //TODO: make this configurable: diff --git a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java index 4c8865598..677832418 100644 --- a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java +++ b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java @@ -29,6 +29,7 @@ import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableHeader; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes; @@ -343,7 +344,7 @@ public final class TableAttributesConverter { LengthProperty lengthprop = (LengthProperty)p; Float f = new Float(lengthprop.getLength().getValue() / 1000f); - String sValue = f.toString() + "pt"; + String sValue = f.toString() + FixedLength.POINT; attrib.set(BorderAttributesConverter.BORDER_WIDTH, (int)FoUnitsConverter.getInstance().convertToTwips(sValue)); -- cgit v1.2.3 From 7594480319beef01b3c3d6b757b2c8aa53b6ae2e Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 14 Feb 2008 12:09:05 +0000 Subject: break-after set on the last child of a row-spanning cell must apply to the last row spanned by the cell git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627721 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/EffRow.java | 2 +- .../table-cell_row-span_breaks.xml | 91 ++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java index ac99a1d37..7989f3d9d 100644 --- a/src/java/org/apache/fop/fo/flow/table/EffRow.java +++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java @@ -197,7 +197,7 @@ public class EffRow { int breakAfter = Constants.EN_AUTO; for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); - if (gu.isPrimary()) { + if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) { breakAfter = BreakUtil.compareBreakClasses(breakAfter, gu.getPrimary().getBreakAfter()); } diff --git a/test/layoutengine/standard-testcases/table-cell_row-span_breaks.xml b/test/layoutengine/standard-testcases/table-cell_row-span_breaks.xml index f00d9894d..8f146ece5 100644 --- a/test/layoutengine/standard-testcases/table-cell_row-span_breaks.xml +++ b/test/layoutengine/standard-testcases/table-cell_row-span_breaks.xml @@ -97,6 +97,49 @@ + + + + + Before the table + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + Cell 1.1 Line 3 + + + Cell 1.2 Line 1 + Cell 1.2 Line 2 + + + + + Cell 2.2 Line 1 + Cell 2.2 Line 2 + + + + + Cell 3.1 Line 1 + Cell 3.1 Line 2 + + + Cell 3.2 Line 1 + Cell 3.2 Line 2 + + + + + After the table + + + @@ -193,5 +236,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 70d511b80f4099730738077cf15dc39a062df89a Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 15 Feb 2008 18:33:12 +0000 Subject: rowStarted doesn't need to be set in the signalNewRow method. If it is, it will prevent the startTablePart event from being triggered on RowGroupBuilder, in addChildNode. This will lead to a NPE being thrown in CollapsingBorderResolver because it would be improperly set up. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@628140 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/TableBody.java | 1 - test/fotree/unittests/table/RowGroupBuilder_no-row_simple.fo | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index 7df1ed0a7..c3642c260 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -286,7 +286,6 @@ public class TableBody extends TableCellContainer { getTable().getRowGroupBuilder().endRow(this); } } - rowsStarted = true; } } diff --git a/test/fotree/unittests/table/RowGroupBuilder_no-row_simple.fo b/test/fotree/unittests/table/RowGroupBuilder_no-row_simple.fo index d109797a4..3e798ab5f 100644 --- a/test/fotree/unittests/table/RowGroupBuilder_no-row_simple.fo +++ b/test/fotree/unittests/table/RowGroupBuilder_no-row_simple.fo @@ -32,7 +32,7 @@ + border-collapse="collapse" border="1pt solid black"> Cell 1 @@ -54,7 +54,7 @@ + border-collapse="collapse" border="1pt solid black"> Cell 1 @@ -88,7 +88,7 @@ + border-collapse="collapse" border="1pt solid black"> Header 1 @@ -116,7 +116,7 @@ + border-collapse="collapse" border="1pt solid black"> Header 1 @@ -160,7 +160,7 @@ + border-collapse="collapse" border="1pt solid black"> Header 1 -- cgit v1.2.3 From 57de10b2fdd6e6f0bbca3aac03bce84d82cfaba3 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Sat, 16 Feb 2008 12:28:48 +0000 Subject: Extracted most of the code in CodePointMapping (generated by XSLT) into a base class for easier maintenance and proper Javadocs. Deprecated FOP's copy of Glyphs.java. Took a different approach at handling mapping alternatives for single-byte fonts. The AFM now only lists the main character. Substitution is done through Glyphs.java later in CodePointMapping. Fixed a problem in Type1FontLoader where the PFM overrides asc/desc/cap/x even though the AFM provides the values. It showed itself because the URW Symbol font has wrong values in the PFM. Added a note to myself in Type1FontLoader to implement the "Flags" value. The whole thing still seems to work without that part. Added a glyph name list to the CodePointMapping so we can work with the original list from the AFM. Otherwise, various mapping operations to and from resulted in unwanted mappings (because the mappings are not necessarily 1:1) and in the end the PDF received an incorrect Encoding map. Now there's no such problem anymore. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@628280 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.3svn.jar | Bin 500806 -> 510302 bytes src/codegen/fonts/code-point-mapping.xsl | 170 +++++++------- .../apache/fop/fonts/AbstractCodePointMapping.java | 261 +++++++++++++++++++++ src/java/org/apache/fop/fonts/Glyphs.java | 1 + src/java/org/apache/fop/fonts/SingleByteFont.java | 2 + .../org/apache/fop/fonts/truetype/TTFFile.java | 4 +- .../org/apache/fop/fonts/type1/AFMCharMetrics.java | 25 +- src/java/org/apache/fop/fonts/type1/AFMFile.java | 14 +- src/java/org/apache/fop/fonts/type1/PFMFile.java | 2 +- .../apache/fop/fonts/type1/Type1FontLoader.java | 40 +++- src/java/org/apache/fop/pdf/PDFFactory.java | 11 +- 11 files changed, 397 insertions(+), 133 deletions(-) create mode 100644 src/java/org/apache/fop/fonts/AbstractCodePointMapping.java (limited to 'src') diff --git a/lib/xmlgraphics-commons-1.3svn.jar b/lib/xmlgraphics-commons-1.3svn.jar index 80927dd7e..55b9d9b2a 100644 Binary files a/lib/xmlgraphics-commons-1.3svn.jar and b/lib/xmlgraphics-commons-1.3svn.jar differ diff --git a/src/codegen/fonts/code-point-mapping.xsl b/src/codegen/fonts/code-point-mapping.xsl index c82ca0104..55b84c742 100644 --- a/src/codegen/fonts/code-point-mapping.xsl +++ b/src/codegen/fonts/code-point-mapping.xsl @@ -40,100 +40,19 @@ package org.apache.fop.fonts; -import java.util.Arrays; import java.util.Map; import java.util.Collections; -import org.apache.fop.util.CharUtilities; - -public class CodePointMapping { +public class CodePointMapping extends AbstractCodePointMapping { - private String name; - private char[] latin1Map; - private char[] characters; - private char[] codepoints; - private char[] unicodeMap; //code point to Unicode char - public CodePointMapping(String name, int[] table) { - this.name = name; - int nonLatin1 = 0; - latin1Map = new char[256]; - unicodeMap = new char[256]; - Arrays.fill(unicodeMap, CharUtilities.NOT_A_CHARACTER); - for (int i = 0; i < table.length; i += 2) { - char unicode = (char)table[i + 1]; - if (unicode < 256) { - if (latin1Map[unicode] == 0) { - latin1Map[unicode] = (char) table[i]; - } - } else { - ++nonLatin1; - } - if (unicodeMap[table[i]] == CharUtilities.NOT_A_CHARACTER) { - unicodeMap[table[i]] = unicode; - } - } - characters = new char[nonLatin1]; - codepoints = new char[nonLatin1]; - int top = 0; - for (int i = 0; i < table.length; i += 2) { - char c = (char) table[i + 1]; - if (c >= 256) { - ++top; - for (int j = top - 1; j >= 0; --j) { - if (j > 0 && characters[j - 1] >= c) { - characters[j] = characters[j - 1]; - codepoints[j] = codepoints[j - 1]; - } else { - characters[j] = c; - codepoints[j] = (char) table[i]; - break; - } - } - } - } - } - - public String getName() { - return this.name; - } - - public final char mapChar(char c) { - if (c < 256) { - return latin1Map[c]; - } else { - int bot = 0, top = characters.length - 1; - while (top >= bot) { - int mid = (bot + top) / 2; - char mc = characters[mid]; - - if (c == mc) { - return codepoints[mid]; - } else if (c < mc) { - top = mid - 1; - } else { - bot = mid + 1; - } - } - return 0; - } - } - - public final char getUnicodeForIndex(int idx) { - return this.unicodeMap[idx]; + super(name, table); } - public final char[] getUnicodeCharMap() { - char[] copy = new char[this.unicodeMap.length]; - System.arraycopy(this.unicodeMap, 0, copy, 0, this.unicodeMap.length); - return copy; - } - - /** {@inheritDoc} */ - public String toString() { - return getName(); + public CodePointMapping(String name, int[] table, String[] charNameMap) { + super(name, table, charNameMap); } private static Map mappings; @@ -146,13 +65,10 @@ public class CodePointMapping { if (mapping != null) { return mapping; } - //TODO: Implement support for Expert and ExpertSubset encoding - else if (encoding.startsWith("Expert")) { - throw new UnsupportedOperationException(encoding + " not implemented yet"); - } throw new UnsupportedOperationException("Unknown encoding: " + encoding); } + } @@ -160,7 +76,7 @@ public class CodePointMapping { else if (encoding.equals()) { - mapping = new CodePointMapping(, enc); + mapping = new CodePointMapping(, enc, names); mappings.put(, mapping); return mapping; } @@ -178,4 +94,78 @@ public class CodePointMapping { }; + + + private static final String[] names + = { + + + + }; + + + + + + + + + + + + + + + + + + /**/ + + + + + + + "" + + null + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java b/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java new file mode 100644 index 000000000..91d13da85 --- /dev/null +++ b/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java @@ -0,0 +1,261 @@ +/* + * 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.fonts; + +import java.util.Arrays; +import java.util.Map; + +import org.apache.xmlgraphics.fonts.Glyphs; + +import org.apache.fop.util.CharUtilities; + +/** + * Abstract base class for code point mapping classes (1-byte character encodings). + */ +public class AbstractCodePointMapping { + + private String name; + private char[] latin1Map; + private char[] characters; + private char[] codepoints; + private char[] unicodeMap; //code point to Unicode char + private String[] charNameMap; //all character names in the encoding + private Map fallbackMap; //Here we accumulate all mappings we have found through substitution + + /** + * Main constructor. + * @param name the name of the encoding + * @param table the table ([code point, unicode scalar value]+) with the mapping + */ + public AbstractCodePointMapping(String name, int[] table) { + this(name, table, null); + } + + /** + * Extended constructor. + * @param name the name of the encoding + * @param table the table ([code point, unicode scalar value]+) with the mapping + * @param charNameMap all character names in the encoding (a value of null will be converted + * to ".notdef") + */ + public AbstractCodePointMapping(String name, int[] table, String[] charNameMap) { + this.name = name; + buildFromTable(table); + if (charNameMap != null) { + this.charNameMap = new String[256]; + for (int i = 0; i < 256; i++) { + String charName = charNameMap[i]; + if (charName == null) { + this.charNameMap[i] = Glyphs.NOTDEF; + } else { + this.charNameMap[i] = charName; + } + } + } + } + + /** + * Builds the internal lookup structures based on a given table. + * @param table the table ([code point, unicode scalar value]+) with the mapping + */ + protected void buildFromTable(int[] table) { + int nonLatin1 = 0; + latin1Map = new char[256]; + unicodeMap = new char[256]; + Arrays.fill(unicodeMap, CharUtilities.NOT_A_CHARACTER); + for (int i = 0; i < table.length; i += 2) { + char unicode = (char)table[i + 1]; + if (unicode < 256) { + if (latin1Map[unicode] == 0) { + latin1Map[unicode] = (char) table[i]; + } + } else { + ++nonLatin1; + } + if (unicodeMap[table[i]] == CharUtilities.NOT_A_CHARACTER) { + unicodeMap[table[i]] = unicode; + } + } + characters = new char[nonLatin1]; + codepoints = new char[nonLatin1]; + int top = 0; + for (int i = 0; i < table.length; i += 2) { + char c = (char) table[i + 1]; + if (c >= 256) { + ++top; + for (int j = top - 1; j >= 0; --j) { + if (j > 0 && characters[j - 1] >= c) { + characters[j] = characters[j - 1]; + codepoints[j] = codepoints[j - 1]; + } else { + characters[j] = c; + codepoints[j] = (char) table[i]; + break; + } + } + } + } + } + + /** + * Returns the encoding's name. + * @return the name of the encoding + */ + public String getName() { + return this.name; + } + + /** + * Maps a Unicode character to a code point in the encoding. + * @param c the Unicode character to map + * @return the coid point in the encoding or 0 (=.notdef) if not found + */ + public final char mapChar(char c) { + if (c < 256) { + char latin1 = latin1Map[c]; + if (latin1 > 0) { + return latin1; + } + } + int bot = 0, top = characters.length - 1; + while (top >= bot) { + int mid = (bot + top) / 2; + char mc = characters[mid]; + + if (c == mc) { + return codepoints[mid]; + } else if (c < mc) { + top = mid - 1; + } else { + bot = mid + 1; + } + } + + //Fallback: using cache + synchronized (this) { + if (fallbackMap != null) { + Character fallback = (Character)fallbackMap.get(new Character(c)); + if (fallback != null) { + return fallback.charValue(); + } + } + } + //Fallback: find alternatives (slow!) + String glyphName = Glyphs.charToGlyphName(c); + if (glyphName.length() > 0) { + String[] alternatives = Glyphs.getCharNameAlternativesFor(glyphName); + if (alternatives != null) { + for (int i = 0, ic = alternatives.length; i < ic; i++) { + int idx = getCodePointForGlyph(alternatives[i]); + if (idx >= 0) { + putFallbackCharacter(c, (char)idx); + return (char)idx; + } + } + } + } + + putFallbackCharacter(c, '\0'); + return 0; + } + + private void putFallbackCharacter(char c, char mapTo) { + synchronized (this) { + if (this.fallbackMap == null) { + this.fallbackMap = new java.util.HashMap(); + } + this.fallbackMap.put(new Character(c), new Character(mapTo)); + } + } + + /** + * Returns the main Unicode value that is associated with the given code point in the encoding. + * Note that multiple Unicode values can theoretically be mapped to one code point in the + * encoding. + * @param idx the code point in the encoding + * @return the Unicode value (or \uFFFF (NOT A CHARACTER) if no Unicode value is at that point) + */ + public final char getUnicodeForIndex(int idx) { + return this.unicodeMap[idx]; + } + + /** + * Returns a character array with Unicode scalar values which can be used to map encoding + * code points to Unicode values. Note that this does not return all possible Unicode values + * that the encoding maps. + * @return a character array with Unicode scalar values + */ + public final char[] getUnicodeCharMap() { + char[] copy = new char[this.unicodeMap.length]; + System.arraycopy(this.unicodeMap, 0, copy, 0, this.unicodeMap.length); + return copy; + } + + /** + * Returns the index of a character/glyph with the given name. Note that this + * method is relatively slow and should only be used for fallback operations. + * @param charName the character name + * @return the index of the character in the encoding or -1 if it doesn't exist + */ + public short getCodePointForGlyph(String charName) { + String[] names = this.charNameMap; + if (names == null) { + names = getCharNameMap(); + } + for (short i = 0, c = (short)names.length; i < c; i++) { + if (names[i].equals(charName)) { + return i; + } + } + return -1; + } + + /** + * Returns the array of character names for this encoding. + * @return the array of character names + * (unmapped code points are represented by a ".notdef" value) + */ + public String[] getCharNameMap() { + if (this.charNameMap != null) { + String[] copy = new String[this.charNameMap.length]; + System.arraycopy(this.charNameMap, 0, copy, 0, this.charNameMap.length); + return copy; + } else { + //Note: this is suboptimal but will probably never be used. + String[] derived = new String[256]; + Arrays.fill(derived, Glyphs.NOTDEF); + for (int i = 0; i < 256; i++) { + char c = getUnicodeForIndex(i); + if (c != CharUtilities.NOT_A_CHARACTER) { + String charName = Glyphs.charToGlyphName(c); + if (charName.length() > 0) { + derived[i] = charName; + } + } + } + return derived; + } + } + + /** {@inheritDoc} */ + public String toString() { + return getName(); + } +} diff --git a/src/java/org/apache/fop/fonts/Glyphs.java b/src/java/org/apache/fop/fonts/Glyphs.java index e75a6bf54..4fb6c4e5c 100644 --- a/src/java/org/apache/fop/fonts/Glyphs.java +++ b/src/java/org/apache/fop/fonts/Glyphs.java @@ -21,6 +21,7 @@ package org.apache.fop.fonts; /** * This class provides a number of constants for glyph management. + * @deprecated Use the Glyphs class from XML Graphics Commons instead! */ public class Glyphs { diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index b6f65edc8..814d05a2c 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -24,6 +24,8 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.fonts.Glyphs; + /** * Generic SingleByte font */ diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index e46029709..fe40c4b33 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -27,8 +27,10 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.fonts.Glyphs; + import org.apache.fop.fonts.FontUtil; -import org.apache.fop.fonts.Glyphs; /** * Reads a TrueType file or a TrueType Collection. diff --git a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java index fbbff567e..1b7f814b8 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java +++ b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java @@ -28,7 +28,7 @@ import java.awt.geom.RectangularShape; public class AFMCharMetrics { private int charCode = -1; - private String unicodeChars; + private String unicodeSequence; private String charName; private double widthX; private double widthY; @@ -59,21 +59,20 @@ public class AFMCharMetrics { } /** - * Returns the Unicode characters represented by this object. Some character names can be - * mapped to multiple Unicode code points, so expect to find more than one character in the - * String. + * Returns the Unicode sequence for this character. * @return the Unicode characters + * (or null if no such Unicode sequence exists for this character) */ - public String getUnicodeChars() { - return this.unicodeChars; + public String getUnicodeSequence() { + return this.unicodeSequence; } /** - * Sets the Unicode characters represented by this object. - * @param unicodeChars the Unicode characters + * Sets the Unicode sequence for this character. + * @param unicodeSequence the Unicode sequence */ - public void setUnicodeChars(String unicodeChars) { - this.unicodeChars = unicodeChars; + public void setUnicodeSequence(String unicodeSequence) { + this.unicodeSequence = unicodeSequence; } /** @@ -145,9 +144,9 @@ public class AFMCharMetrics { StringBuffer sb = new StringBuffer("AFM Char: "); sb.append(getCharCode()); sb.append(" ("); - if (getUnicodeChars() != null) { - for (int i = 0, c = getUnicodeChars().length(); i < c; i++) { - sb.append("0x").append(Integer.toHexString(getUnicodeChars().charAt(i))); + if (getUnicodeSequence() != null) { + for (int i = 0, c = getUnicodeSequence().length(); i < c; i++) { + sb.append("0x").append(Integer.toHexString(getUnicodeSequence().charAt(i))); sb.append(", "); } } diff --git a/src/java/org/apache/fop/fonts/type1/AFMFile.java b/src/java/org/apache/fop/fonts/type1/AFMFile.java index 0b7b8d3c2..b51485485 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMFile.java +++ b/src/java/org/apache/fop/fonts/type1/AFMFile.java @@ -21,7 +21,6 @@ package org.apache.fop.fonts.type1; import java.awt.geom.Dimension2D; import java.awt.geom.RectangularShape; -import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -315,18 +314,11 @@ public class AFMFile { */ public void addCharMetrics(AFMCharMetrics metrics) { String name = metrics.getCharName(); - if (metrics.getUnicodeChars() == null) { + if (metrics.getUnicodeSequence() == null) { if (name != null) { - String u = Glyphs.getUnicodeCodePointsForGlyphName(metrics.getCharName()); + String u = Glyphs.getUnicodeSequenceForGlyphName(metrics.getCharName()); if (u != null) { - if (u.length() > 1) { - //Lower values (ex. space) are most probably more interesting than - //higher values (ex. non-break-space), so sort just to be sure: - char[] chars = u.toCharArray(); - Arrays.sort(chars); - u = String.valueOf(chars); - } - metrics.setUnicodeChars(u); + metrics.setUnicodeSequence(u); } } else { //Ignore as no Unicode assignment is possible diff --git a/src/java/org/apache/fop/fonts/type1/PFMFile.java b/src/java/org/apache/fop/fonts/type1/PFMFile.java index a1e560746..69f8e836f 100644 --- a/src/java/org/apache/fop/fonts/type1/PFMFile.java +++ b/src/java/org/apache/fop/fonts/type1/PFMFile.java @@ -29,7 +29,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.fonts.Glyphs; +import org.apache.xmlgraphics.fonts.Glyphs; /** * This class represents a PFM file (or parts of it) as a Java object. diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 57383dc76..009a446f9 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -198,10 +198,18 @@ public class Type1FontLoader extends FontLoader { } if (pfm != null) { //Sometimes the PFM has these metrics while the AFM doesn't (ex. Symbol) - returnFont.setCapHeight(pfm.getCapHeight()); - returnFont.setXHeight(pfm.getXHeight()); - returnFont.setAscender(pfm.getLowerCaseAscent()); - returnFont.setDescender(pfm.getLowerCaseDescent()); + if (returnFont.getCapHeight() == 0) { + returnFont.setCapHeight(pfm.getCapHeight()); + } + if (returnFont.getXHeight(1) == 0) { + returnFont.setXHeight(pfm.getXHeight()); + } + if (returnFont.getAscender() == 0) { + returnFont.setAscender(pfm.getLowerCaseAscent()); + } + if (returnFont.getDescender() == 0) { + returnFont.setDescender(pfm.getLowerCaseDescent()); + } } //Fallbacks when some crucial font metrics aren't available @@ -253,6 +261,7 @@ public class Type1FontLoader extends FontLoader { } if (afm != null) { + //TODO returnFont.setFlags(flags); returnFont.setFirstChar(afm.getFirstChar()); returnFont.setLastChar(afm.getLastChar()); Iterator iter = afm.getCharMetrics().iterator(); @@ -264,9 +273,9 @@ public class Type1FontLoader extends FontLoader { } returnFont.replaceKerningMap(afm.createXKerningMapEncoded()); } else { + returnFont.setFlags(pfm.getFlags()); returnFont.setFirstChar(pfm.getFirstChar()); returnFont.setLastChar(pfm.getLastChar()); - returnFont.setFlags(pfm.getFlags()); for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { singleFont.setWidth(i, pfm.getCharWidth(i)); } @@ -282,28 +291,35 @@ public class Type1FontLoader extends FontLoader { while (iter.hasNext()) { AFMCharMetrics charMetrics = (AFMCharMetrics)iter.next(); if (charMetrics.getCharCode() >= 0) { - String u = charMetrics.getUnicodeChars(); - if (u != null) { - mappingCount += u.length(); + String u = charMetrics.getUnicodeSequence(); + if (u != null && u.length() == 1) { + mappingCount++; } } } //...and now build the table. int[] table = new int[mappingCount * 2]; + String[] charNameMap = new String[256]; iter = chars.iterator(); int idx = 0; while (iter.hasNext()) { AFMCharMetrics charMetrics = (AFMCharMetrics)iter.next(); if (charMetrics.getCharCode() >= 0) { - String unicodes = charMetrics.getUnicodeChars(); - for (int i = 0, c = unicodes.length(); i < c; i++) { + charNameMap[charMetrics.getCharCode()] = charMetrics.getCharName(); + String unicodes = charMetrics.getUnicodeSequence(); + if (unicodes == null) { + log.info("No Unicode mapping for glyph: " + charMetrics); + } else if (unicodes.length() == 1) { table[idx] = charMetrics.getCharCode(); idx++; - table[idx] = unicodes.charAt(i); + table[idx] = unicodes.charAt(0); idx++; + } else { + log.warn("Multi-character representation of glyph not currently supported: " + + charMetrics); } } } - return new CodePointMapping(encodingName, table); + return new CodePointMapping(encodingName, table, charNameMap); } } diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index a50ef2545..687b32016 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -40,7 +40,6 @@ import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.xmlgraphics.fonts.Glyphs; import org.apache.xmlgraphics.xmp.Metadata; import org.apache.fop.fonts.CIDFont; @@ -1252,15 +1251,17 @@ public class PDFFactory { PDFEncoding.DifferencesBuilder builder = pdfEncoding.createDifferencesBuilder(); int start = -1; + String[] winansiNames = winansi.getCharNameMap(); + String[] charNameMap = mapping.getCharNameMap(); for (int i = 0; i < 256; i++) { - char wac = winansi.getUnicodeForIndex(i); - char c = mapping.getUnicodeForIndex(i); - if (wac != c) { + String wac = winansiNames[i]; + String c = charNameMap[i]; + if (!wac.equals(c)) { if (start != i) { builder.addDifference(i); start = i; } - builder.addName(Glyphs.charToGlyphName(c)); + builder.addName(c); start++; } } -- cgit v1.2.3 From a5c33430c6e04172ab219455fdecf86eb9f63aae Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 18 Feb 2008 09:00:08 +0000 Subject: No stack traces with missing images. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@628652 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/ExternalGraphic.java | 3 +++ src/java/org/apache/fop/render/java2d/Java2DRenderer.java | 3 +++ src/java/org/apache/fop/render/pdf/PDFRenderer.java | 3 +++ 3 files changed, 9 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java index 03229e4c2..fdddf3918 100644 --- a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java +++ b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java @@ -19,6 +19,7 @@ package org.apache.fop.fo.flow; +import java.io.FileNotFoundException; import java.io.IOException; import org.xml.sax.Locator; @@ -78,6 +79,8 @@ public class ExternalGraphic extends AbstractGraphics { info = manager.getImageInfo(url, userAgent.getImageSessionContext()); } catch (ImageException e) { log.error("Image not available: " + e.getMessage()); + } catch (FileNotFoundException fnfe) { + log.error(fnfe.getMessage()); } catch (IOException ioe) { log.error("I/O error while loading image: " + ioe.getMessage()); } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 63d5ad04c..8442af229 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -35,6 +35,7 @@ import java.awt.image.BufferedImage; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; @@ -929,6 +930,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } catch (ImageException ie) { log.error("Error while processing image: " + (info != null ? info.toString() : uri), ie); + } catch (FileNotFoundException fnfe) { + log.error(fnfe.getMessage()); } catch (IOException ioe) { log.error("I/O error while processing image: " + (info != null ? info.toString() : uri), ioe); diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 15ed6d98a..5b7dd840e 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -27,6 +27,7 @@ import java.awt.color.ICC_Profile; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -1754,6 +1755,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } catch (ImageException ie) { log.error("Error while processing image: " + (info != null ? info.toString() : uri), ie); + } catch (FileNotFoundException fnfe) { + log.error(fnfe.getMessage()); } catch (IOException ioe) { log.error("I/O error while processing image: " + (info != null ? info.toString() : uri), ioe); -- cgit v1.2.3 From 263b70846b06d2a119d5d253633e5678a9f908bb Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 18 Feb 2008 09:41:03 +0000 Subject: Extract original exception in BasePDFTestCase.java. They are normally embedded in a TransformerException and sometimes additionally in a SAXException (depending on the JAXP implementation). Restore validation for Base14 font check when PDF/A is active. Got lost when I refactored to generic structures in the PDF library. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@628668 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFFont.java | 9 ++++++ .../org/apache/fop/render/pdf/BasePDFTestCase.java | 34 +++++++++++++++++----- 2 files changed, 36 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFFont.java b/src/java/org/apache/fop/pdf/PDFFont.java index 497565e9c..14f1a657c 100644 --- a/src/java/org/apache/fop/pdf/PDFFont.java +++ b/src/java/org/apache/fop/pdf/PDFFont.java @@ -19,6 +19,9 @@ package org.apache.fop.pdf; +import java.io.IOException; +import java.io.OutputStream; + import org.apache.fop.fonts.FontType; /** @@ -163,5 +166,11 @@ public class PDFFont extends PDFDictionary { } } } + + /** {@inheritDoc} */ + protected int output(OutputStream stream) throws IOException { + validate(); + return super.output(stream); + } } diff --git a/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java b/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java index 3b4e03118..7c66a0ceb 100644 --- a/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java +++ b/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java @@ -23,12 +23,16 @@ import java.io.File; import javax.xml.transform.Source; import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamSource; +import org.xml.sax.SAXException; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.output.ByteArrayOutputStream; + import org.apache.fop.AbstractFOPTestCase; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; @@ -78,21 +82,37 @@ public class BasePDFTestCase extends AbstractFOPTestCase { * @throws Exception if the conversion fails */ protected byte[] convertFO(File foFile, FOUserAgent ua, boolean dumpPdfFile) - throws Exception { + throws Exception { ByteArrayOutputStream baout = new ByteArrayOutputStream(); Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, ua, baout); Transformer transformer = tFactory.newTransformer(); Source src = new StreamSource(foFile); SAXResult res = new SAXResult(fop.getDefaultHandler()); - transformer.transform(src, res); - final byte[] result = baout.toByteArray(); - if (dumpPdfFile) { - final File outFile = new File(foFile.getParentFile(), foFile.getName() + ".pdf"); - FileUtils.writeByteArrayToFile(outFile, result); + try { + transformer.transform(src, res); + final byte[] result = baout.toByteArray(); + if (dumpPdfFile) { + final File outFile = new File(foFile.getParentFile(), foFile.getName() + ".pdf"); + FileUtils.writeByteArrayToFile(outFile, result); + } + return result; + } catch (TransformerException e) { + throw extractOriginalException(e); } - return result; } + private static Exception extractOriginalException(Exception e) { + if (e.getCause() != null) { + return extractOriginalException((Exception)e.getCause()); + } else if (e instanceof SAXException) { + SAXException se = (SAXException)e; + if (se.getException() != null) { + return extractOriginalException(se.getException()); + } + } + return e; + } + /** * get FOP config File * @return user config file to be used for testing -- cgit v1.2.3 From 76ebc1fa40782c2e6e8e91e51a5440cbc15198f2 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 18 Feb 2008 15:02:39 +0000 Subject: fop-rgb-icc() function did not make the round-trip which caused an error in the color_1.xml test case (intermediate format tests). Added a unit test to test the parsing and round-trip. Documented the cmyk() function. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@628775 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/extensions.xml | 18 +++ .../org/apache/fop/fo/expr/ICCColorFunction.java | 22 ++- src/java/org/apache/fop/util/ColorUtil.java | 28 ++-- test/java/org/apache/fop/UtilityCodeTestSuite.java | 4 +- .../org/apache/fop/traits/TraitColorTestCase.java | 79 ---------- .../org/apache/fop/util/ColorUtilTestCase.java | 173 +++++++++++++++++++++ test/layoutengine/standard-testcases/color_1.xml | 7 +- 7 files changed, 233 insertions(+), 98 deletions(-) delete mode 100644 test/java/org/apache/fop/traits/TraitColorTestCase.java create mode 100644 test/java/org/apache/fop/util/ColorUtilTestCase.java (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/extensions.xml b/src/documentation/content/xdocs/trunk/extensions.xml index fb3db86fe..483866e61 100644 --- a/src/documentation/content/xdocs/trunk/extensions.xml +++ b/src/documentation/content/xdocs/trunk/extensions.xml @@ -210,6 +210,24 @@ to following pages. Here is an example of FO code creating such a table-header:< supported for PDF, PS and Java2D-based renderers.

    +
    + Color functions +

    + XSL-FO supports specifying color using the rgb(), rgb-icc() and system-color() functions. + Apache FOP provides additional color functions for special use cases. Please note that + using these functions compromises the interoperability of an FO document. +

    +
    + cmyk() +

    color cmyk(numeric, numeric, numeric, numeric)

    +

    + This function will construct a color in device-specific CMYK color space. The numbers + must be between 0.0 and 1.0. For output formats that don't support device-specific + color space the CMYK value is converted to an sRGB value. +

    +
    +
    +
    diff --git a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java index 5bd9d145d..9444639a5 100644 --- a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java @@ -71,19 +71,31 @@ class ICCColorFunction extends FunctionBase { } String src = cp.getSrc(); + float red = 0, green = 0, blue = 0; + red = args[0].getNumber().floatValue(); + green = args[1].getNumber().floatValue(); + blue = args[2].getNumber().floatValue(); + /* Verify rgb replacement arguments */ + if ((red < 0 || red > 255) + || (green < 0 || green > 255) + || (blue < 0 || blue > 255)) { + throw new PropertyException("Color values out of range. " + + "Arguments to rgb-icc() must be [0..255] or [0%..100%]"); + } + // rgb-icc is replaced with fop-rgb-icc which has an extra fifth argument containing the // color profile src attribute as it is defined in the color-profile declarations element. StringBuffer sb = new StringBuffer(); sb.append("fop-rgb-icc("); - for (int ix = 0; ix < args.length; ix++) { + sb.append(red / 255f); + sb.append(',').append(green / 255f); + sb.append(',').append(blue / 255f); + for (int ix = 3; ix < args.length; ix++) { if (ix == 3) { sb.append(',').append(colorProfileName); sb.append(',').append(src); } else { - if (ix > 0) { - sb.append(','); - } - sb.append(args[ix]); + sb.append(',').append(args[ix]); } } sb.append(")"); diff --git a/src/java/org/apache/fop/util/ColorUtil.java b/src/java/org/apache/fop/util/ColorUtil.java index bb014b2af..fbfc68c36 100644 --- a/src/java/org/apache/fop/util/ColorUtil.java +++ b/src/java/org/apache/fop/util/ColorUtil.java @@ -26,6 +26,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.expr.PropertyException; @@ -73,8 +74,8 @@ public final class ColorUtil { *
  • system-color(colorname)
  • *
  • transparent
  • *
  • colorname
  • - *
  • fop-rgb-icc
  • - *
  • cmyk
  • + *
  • fop-rgb-icc(r,g,b,cs,cs-src,[num]+) (r/g/b: 0..1, num: 0..1)
  • + *
  • cmyk(c,m,y,k) (0..1)
  • * * * @param foUserAgent FOUserAgent object @@ -278,7 +279,7 @@ public final class ColorUtil { //multiply by 0x11 = 17 = 255/15 red = Integer.parseInt(value.substring(1, 2), 16) * 0x11; green = Integer.parseInt(value.substring(2, 3), 16) * 0x11; - blue = Integer.parseInt(value.substring(3, 4), 16) *0X11; + blue = Integer.parseInt(value.substring(3, 4), 16) * 0X11; } else if ((len == 7) || (len == 9)) { red = Integer.parseInt(value.substring(1, 3), 16); green = Integer.parseInt(value.substring(3, 5), 16); @@ -323,6 +324,12 @@ public final class ColorUtil { if (iccProfileSrc == null || "".equals(iccProfileSrc)) { throw new PropertyException("ICC profile source missing"); } + if (iccProfileSrc.startsWith("\"") || iccProfileSrc.startsWith("'")) { + iccProfileSrc = iccProfileSrc.substring(1); + } + if (iccProfileSrc.endsWith("\"") || iccProfileSrc.endsWith("'")) { + iccProfileSrc = iccProfileSrc.substring(0, iccProfileSrc.length() - 1); + } /* ICC profile arguments */ float[] iccComponents = new float[args.length - 5]; for (int ix = 4; ++ix < args.length;) { @@ -336,25 +343,26 @@ public final class ColorUtil { float red = 0, green = 0, blue = 0; red = Float.parseFloat(args[0].trim()); green = Float.parseFloat(args[1].trim()); - blue = Float.parseFloat(args[2].trim());; + blue = Float.parseFloat(args[2].trim()); /* Verify rgb replacement arguments */ - if ((red < 0 || red > 255) - || (green < 0 || green > 255) - || (blue < 0 || blue > 255)) { + if ((red < 0 || red > 1) + || (green < 0 || green > 1) + || (blue < 0 || blue > 1)) { throw new PropertyException("Color values out of range. " - + "Arguments to rgb-icc() must be [0..255] or [0%..100%]"); + + "Fallback RGB arguments to fop-rgb-icc() must be [0..1]"); } if (colorSpace != null) { // ColorSpace available - create ColorExt (keeps track of replacement rgb // values for possible later colorTOsRGBString call - parsedColor = ColorExt.createFromFoRgbIcc(red/255, green/255, blue/255, + parsedColor = ColorExt.createFromFoRgbIcc(red, green, blue, iccProfileName, iccProfileSrc, colorSpace, iccComponents); } else { // ICC profile could not be loaded - use rgb replacement values */ log.warn("Color profile '" + iccProfileSrc + "' not found. Using rgb replacement values."); - parsedColor = new Color((int)red, (int)green, (int)blue); + parsedColor = new Color(Math.round(red * 255), + Math.round(green * 255), Math.round(blue * 255)); } } catch (PropertyException pe) { //simply re-throw diff --git a/test/java/org/apache/fop/UtilityCodeTestSuite.java b/test/java/org/apache/fop/UtilityCodeTestSuite.java index 19d7d0266..86a3469ce 100644 --- a/test/java/org/apache/fop/UtilityCodeTestSuite.java +++ b/test/java/org/apache/fop/UtilityCodeTestSuite.java @@ -24,10 +24,10 @@ import junit.framework.TestSuite; import org.apache.fop.pdf.PDFObjectTestCase; import org.apache.fop.traits.BorderPropsTestCase; -import org.apache.fop.traits.TraitColorTestCase; import org.apache.fop.util.DataURIResolverTestCase; import org.apache.fop.util.ElementListUtilsTestCase; import org.apache.fop.util.PDFNumberTestCase; +import org.apache.fop.util.ColorUtilTestCase; import org.apache.fop.util.UnitConvTestCase; /** @@ -46,7 +46,7 @@ public class UtilityCodeTestSuite { suite.addTest(new TestSuite(PDFNumberTestCase.class)); suite.addTest(new TestSuite(PDFObjectTestCase.class)); suite.addTest(new TestSuite(UnitConvTestCase.class)); - suite.addTest(new TestSuite(TraitColorTestCase.class)); + suite.addTest(new TestSuite(ColorUtilTestCase.class)); suite.addTest(new TestSuite(BorderPropsTestCase.class)); suite.addTest(new TestSuite(ElementListUtilsTestCase.class)); suite.addTest(new TestSuite(DataURIResolverTestCase.class)); diff --git a/test/java/org/apache/fop/traits/TraitColorTestCase.java b/test/java/org/apache/fop/traits/TraitColorTestCase.java deleted file mode 100644 index 90f73dcc3..000000000 --- a/test/java/org/apache/fop/traits/TraitColorTestCase.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.traits; - -import java.awt.Color; - -import junit.framework.TestCase; - -import org.apache.fop.util.ColorUtil; - -/** - * Tests the Trait.Color class. - * TODO: This actually tests the ColorUtil class now. - */ -public class TraitColorTestCase extends TestCase { - - /** - * Test serialization to String. - * @throws Exception if an error occurs - */ - public void testSerialization() throws Exception { - Color col = new Color(1.0f, 1.0f, 0.5f, 1.0f); - String s = ColorUtil.colorToString(col); - - //This is what the old color spit out. Now it is 80 due to rounding - //assertEquals("#ffff7f", s); - assertEquals("#ffff80", s); - - col = new Color(1.0f, 0.0f, 0.0f, 0.8f); - s = ColorUtil.colorToString(col); - assertEquals("#ff0000cc", s); - } - - /** - * Test deserialization from String. - * @throws Exception if an error occurs - */ - public void testDeserialization() throws Exception { - Color col = ColorUtil.parseColorString(null, "#ffff7f"); - assertEquals(255, col.getRed()); - assertEquals(255, col.getGreen()); - assertEquals(127, col.getBlue()); - assertEquals(255, col.getAlpha()); - - col = ColorUtil.parseColorString(null, "#ff0000cc"); - assertEquals(255, col.getRed()); - assertEquals(0, col.getGreen()); - assertEquals(0, col.getBlue()); - assertEquals(204, col.getAlpha()); - } - - /** - * Test equals(). - * @throws Exception if an error occurs - */ - public void testEquals() throws Exception { - Color col1 = ColorUtil.parseColorString(null, "#ff0000cc"); - Color col2 = ColorUtil.parseColorString(null, "#ff0000cc"); - assertEquals(col1, col2); - } - -} diff --git a/test/java/org/apache/fop/util/ColorUtilTestCase.java b/test/java/org/apache/fop/util/ColorUtilTestCase.java new file mode 100644 index 000000000..bdeca4379 --- /dev/null +++ b/test/java/org/apache/fop/util/ColorUtilTestCase.java @@ -0,0 +1,173 @@ +/* + * 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.awt.Color; +import java.awt.color.ColorSpace; + +import junit.framework.TestCase; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.FopFactory; + +/** + * Tests the ColorUtil class. + */ +public class ColorUtilTestCase extends TestCase { + + /** + * Test serialization to String. + * @throws Exception if an error occurs + */ + public void testSerialization() throws Exception { + Color col = new Color(1.0f, 1.0f, 0.5f, 1.0f); + String s = ColorUtil.colorToString(col); + + //This is what the old color spit out. Now it is 80 due to rounding + //assertEquals("#ffff7f", s); + assertEquals("#ffff80", s); + + col = new Color(1.0f, 0.0f, 0.0f, 0.8f); + s = ColorUtil.colorToString(col); + assertEquals("#ff0000cc", s); + } + + /** + * Test deserialization from String. + * @throws Exception if an error occurs + */ + public void testDeserialization() throws Exception { + Color col = ColorUtil.parseColorString(null, "#ffff7f"); + assertEquals(255, col.getRed()); + assertEquals(255, col.getGreen()); + assertEquals(127, col.getBlue()); + assertEquals(255, col.getAlpha()); + + col = ColorUtil.parseColorString(null, "#ff0000cc"); + assertEquals(255, col.getRed()); + assertEquals(0, col.getGreen()); + assertEquals(0, col.getBlue()); + assertEquals(204, col.getAlpha()); + } + + /** + * Test equals(). + * @throws Exception if an error occurs + */ + public void testEquals() throws Exception { + Color col1 = ColorUtil.parseColorString(null, "#ff0000cc"); + Color col2 = ColorUtil.parseColorString(null, "#ff0000cc"); + assertEquals(col1, col2); + } + + /** + * Tests the rgb() function. + * @throws Exception if an error occurs + */ + public void testRGB() throws Exception { + FopFactory fopFactory = FopFactory.newInstance(); + FOUserAgent ua = fopFactory.newFOUserAgent(); + Color colActual; + + colActual = ColorUtil.parseColorString(ua, "rgb(255, 40, 0)"); + assertEquals(255, colActual.getRed()); + assertEquals(40, colActual.getGreen()); + assertEquals(0, colActual.getBlue()); + assertEquals(255, colActual.getAlpha()); + assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colActual.getColorSpace()); + } + + /** + * Tests the fop-rgb-icc() function. + * @throws Exception if an error occurs + */ + public void testRGBICC() throws Exception { + FopFactory fopFactory = FopFactory.newInstance(); + ColorSpace cs = fopFactory.getColorSpace(null, + "src/java/org/apache/fop/pdf/sRGB Color Space Profile.icm"); + assertNotNull(cs); + + + FOUserAgent ua = fopFactory.newFOUserAgent(); + ColorExt colActual; + + //fop-rgb-icc() is used instead of rgb-icc() inside FOP! + String colSpec = "fop-rgb-icc(1.0,0.0,0.0,sRGBAlt," + + "\"src/java/org/apache/fop/pdf/sRGB Color Space Profile.icm\",1.0,0.0,0.0)"; + colActual = (ColorExt)ColorUtil.parseColorString(ua, colSpec); + //assertEquals(255, colActual.getRed()); //253 is returned + //assertEquals(24, colActual.getGreen()); //24 is returned + //I don't understand the difference. Maybe Java's sRGB and HP's sRGB are somehow not + //equivalent. This is only going to be a problem if anyone actually makes use of the + //RGB fallback in any renderer. + //TODO Anyone know what's going on here? + assertEquals(0, colActual.getBlue()); + assertEquals(cs, colActual.getColorSpace()); + float[] comps = colActual.getOriginalColorComponents(); + assertEquals(3, comps.length); + assertEquals(1f, comps[0], 0); + assertEquals(0f, comps[1], 0); + assertEquals(0f, comps[2], 0); + + assertEquals(colSpec, ColorUtil.colorToString(colActual)); + + colSpec = "fop-rgb-icc(1.0,0.5,0.0,blah," + + "\"invalid.icm\",1.0,0.5,0.0,0.15)"; + Color colFallback = ColorUtil.parseColorString(ua, colSpec); + assertEquals(new Color(1.0f, 0.5f, 0.0f), colFallback); + } + + /** + * Tests the cmyk() function. + * @throws Exception if an error occurs + */ + public void testCMYK() throws Exception { + ColorExt colActual; + String colSpec; + + colSpec = "cmyk(0.0, 0.0, 1.0, 0.0)"; + colActual = (ColorExt)ColorUtil.parseColorString(null, colSpec); + assertEquals(255, colActual.getRed()); + assertEquals(255, colActual.getGreen()); + assertEquals(0, colActual.getBlue()); + assertEquals(CMYKColorSpace.getInstance(), colActual.getColorSpace()); + float[] comps = colActual.getOriginalColorComponents(); + assertEquals(4, comps.length); + assertEquals(0f, comps[0], 0); + assertEquals(0f, comps[1], 0); + assertEquals(1f, comps[2], 0); + assertEquals(0f, comps[3], 0); + assertEquals("cmyk(0.0,0.0,1.0,0.0)", ColorUtil.colorToString(colActual)); + + colSpec = "cmyk(0.0274, 0.2196, 0.3216, 0.0)"; + colActual = (ColorExt)ColorUtil.parseColorString(null, colSpec); + assertEquals(248, colActual.getRed()); + assertEquals(199, colActual.getGreen()); + assertEquals(172, colActual.getBlue()); + assertEquals(CMYKColorSpace.getInstance(), colActual.getColorSpace()); + comps = colActual.getOriginalColorComponents(); + assertEquals(0.0274f, comps[0], 0.001); + assertEquals(0.2196f, comps[1], 0.001); + assertEquals(0.3216f, comps[2], 0.001); + assertEquals(0f, comps[3], 0); + assertEquals("cmyk(0.0274,0.2196,0.3216,0.0)", ColorUtil.colorToString(colActual)); + } + +} diff --git a/test/layoutengine/standard-testcases/color_1.xml b/test/layoutengine/standard-testcases/color_1.xml index 55ab47b01..0eb08f8b1 100644 --- a/test/layoutengine/standard-testcases/color_1.xml +++ b/test/layoutengine/standard-testcases/color_1.xml @@ -26,7 +26,7 @@ - + @@ -41,6 +41,9 @@ color "rgb-icc(100%,50%,0%, sRGB, 1, 0.5, 0)" color "rgb-icc(0%,100%,0%, unknown, 1, 0.5, 0)" color "cmyk(0%,0%,20%,40%)" (Khaki) + @@ -49,7 +52,7 @@ - + -- cgit v1.2.3 From 4189170667e5712e3bf1caf2c7560bccd876d5f2 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 18 Feb 2008 16:45:18 +0000 Subject: Reducing noise. Better messages. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@628804 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/truetype/TTFFile.java | 13 ++++++++----- src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index fe40c4b33..86a1d75e2 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -222,7 +222,9 @@ public class TTFFile { int cmapEID = in.readTTFUShort(); long cmapOffset = in.readTTFULong(); - log.debug("Platform ID: " + cmapPID + " Encoding: " + cmapEID); + if (log.isDebugEnabled()) { + log.debug("Platform ID: " + cmapPID + " Encoding: " + cmapEID); + } if (cmapPID == 3 && cmapEID == 1) { cmapUniOffset = cmapOffset; @@ -230,8 +232,7 @@ public class TTFFile { } if (cmapUniOffset <= 0) { - log.fatal("Unicode cmap table not present"); - log.fatal("Unsupported format: Aborting"); + log.fatal("Unsupported TrueType font: Unicode cmap table not present. Aborting"); return false; } @@ -1333,9 +1334,11 @@ public class TTFFile { if (iObj == null) { // happens for many fonts (Ubuntu font set), // stray entries in the kerning table?? - log.warn("Unicode index (1) not found for glyph " + i); + log.debug("Ignoring kerning pair because no Unicode index was" + + " found for the first glyph " + i); } else if (u2 == null) { - log.warn("Unicode index (2) not found for glyph " + i); + log.debug("Ignoring kerning pair because Unicode index was" + + " found for the second glyph " + i); } else { Map adjTab = (Map)kerningTab.get(iObj); if (adjTab == null) { diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index 5c9e51c81..b29aff808 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -57,7 +57,7 @@ public class TTFFontLoader extends FontLoader { FontFileReader reader = new FontFileReader(in); boolean supported = ttf.readFont(reader, null); if (!supported) { - throw new IOException("Could not load TrueType font: " + fontFileURI); + throw new IOException("TrueType font is not supported: " + fontFileURI); } buildFont(ttf); loaded = true; -- cgit v1.2.3 From dbd7b4a8245dd84e9a745eb921291c3d91e6245c Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 18 Feb 2008 17:24:23 +0000 Subject: Made the necessary changes to remove the long-standing deprecations in the apps package as discussed. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@628826 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/apps/FOUserAgent.java | 38 +--------------- src/java/org/apache/fop/apps/Fop.java | 64 ++------------------------- src/java/org/apache/fop/apps/FopFactory.java | 36 +++++++-------- 3 files changed, 22 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index 966e227fe..a7405b466 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -37,11 +37,9 @@ import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext; import org.apache.fop.Version; import org.apache.fop.fo.FOEventHandler; -import org.apache.fop.pdf.PDFEncryptionParams; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererFactory; import org.apache.fop.render.XMLHandlerRegistry; -import org.apache.fop.render.pdf.PDFRenderer; /** * This is the user agent for FOP. @@ -66,7 +64,8 @@ import org.apache.fop.render.pdf.PDFRenderer; public class FOUserAgent { /** Defines the default target resolution (72dpi) for FOP */ - public static final float DEFAULT_TARGET_RESOLUTION = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION; + public static final float DEFAULT_TARGET_RESOLUTION + = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION; private static Log log = LogFactory.getLog("FOP"); @@ -129,16 +128,6 @@ public class FOUserAgent { }; - /** - * Default constructor - * @see org.apache.fop.apps.FopFactory - * @deprecated Provided for compatibility only. Please use the methods from - * FopFactory to construct FOUserAgent instances! - */ - public FOUserAgent() throws FOPException { - this(FopFactory.newInstance()); - } - /** * Main constructor. This constructor should not be called directly. Please use the * methods from FopFactory to construct FOUserAgent instances! @@ -341,29 +330,6 @@ public class FOUserAgent { return this.uriResolver; } - /** - * Returns the parameters for PDF encryption. - * @return the PDF encryption parameters, null if not applicable - * @deprecated Use (PDFEncryptionParams)getRendererOptions().get("encryption-params") - * instead. - */ - public PDFEncryptionParams getPDFEncryptionParams() { - return (PDFEncryptionParams)getRendererOptions().get(PDFRenderer.ENCRYPTION_PARAMS); - } - - /** - * Sets the parameters for PDF encryption. - * @param pdfEncryptionParams the PDF encryption parameters, null to - * disable PDF encryption - * @deprecated Use getRendererOptions().put("encryption-params", - * new PDFEncryptionParams(..)) instead or set every parameter separately: - * getRendererOptions().put("noprint", Boolean.TRUE). - */ - public void setPDFEncryptionParams(PDFEncryptionParams pdfEncryptionParams) { - getRendererOptions().put(PDFRenderer.ENCRYPTION_PARAMS, pdfEncryptionParams); - } - - /** * Attempts to resolve the given URI. * Will use the configured resolver and if not successful fall back diff --git a/src/java/org/apache/fop/apps/Fop.java b/src/java/org/apache/fop/apps/Fop.java index a7602a981..d1a56789f 100644 --- a/src/java/org/apache/fop/apps/Fop.java +++ b/src/java/org/apache/fop/apps/Fop.java @@ -22,10 +22,8 @@ package org.apache.fop.apps; // Java import java.io.OutputStream; -// XML import org.xml.sax.helpers.DefaultHandler; -// FOP import org.apache.fop.fo.FOTreeBuilder; /** @@ -66,10 +64,8 @@ public class Fop { * @param ua FOUserAgent object * @param stream the output stream * @throws FOPException if setting up the DefaultHandler fails - * @deprecated End-users should use {@link FopFactory#newFop(String, FOUserAgent, OutputStream)} - * instead! This constructor will become invisible with FOP 1.0. */ - public Fop(String outputFormat, FOUserAgent ua, OutputStream stream) throws FOPException { + Fop(String outputFormat, FOUserAgent ua, OutputStream stream) throws FOPException { this.outputFormat = outputFormat; foUserAgent = ua; @@ -83,56 +79,13 @@ public class Fop { } /** - * Constructor for use with already-created FOUserAgents. It uses MIME types to select the - * output format (ex. "application/pdf" for PDF). - * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). - * @param ua FOUserAgent object - * @throws FOPException if setting up the DefaultHandler fails - * @deprecated End-users should use {@link FopFactory#newFop(String, FOUserAgent)} instead! - * This constructor will become invisible with FOP 1.0. - */ - public Fop(String outputFormat, FOUserAgent ua) throws FOPException { - this.outputFormat = outputFormat; - - foUserAgent = ua; - if (foUserAgent == null) { - foUserAgent = FopFactory.newInstance().newFOUserAgent(); - } - - createDefaultHandler(); - } - - /** - * Constructor for FOP with a default FOUserAgent. It uses MIME types to select the - * output format (ex. "application/pdf" for PDF). - * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). - * @deprecated End-users should use {@link FopFactory#newFop(String)} instead! - * This constructor will become invisible with FOP 1.0. - */ - public Fop(String outputFormat) { - this.outputFormat = outputFormat; - foUserAgent = FopFactory.newInstance().newFOUserAgent(); - } - - /** - * Get the FOUserAgent instance for this process + * Get the FOUserAgent instance associated with the rendering run represented by this instance. * @return the user agent */ public FOUserAgent getUserAgent() { return foUserAgent; } - /** - * Set the OutputStream to use to output the result of the Render - * (if applicable) - * @param stream the stream to output the result of rendering to - * @deprecated Use one of the factory methods on {@link FopFactory} with an OutputStream - * parameter instead. This method will be removed with FOP 1.0. - */ - public void setOutputStream(OutputStream stream) { - this.stream = stream; - } - /** * Creates a DefaultHandler object used to generate the document. * Note this object implements the ContentHandler interface. @@ -148,8 +101,8 @@ public class Fop { } /** - * Returns the DefaultHandler object used to generate the document. - * Checking for null and the exception is only for the deprecated constructor. + * Returns the DefaultHandler object that will receive the SAX stream containing the + * FO document to be rendered. * @return the SAX DefaultHandler for handling the SAX events. * @throws FOPException if setting up the DefaultHandler fails */ @@ -178,13 +131,4 @@ public class Fop { } } - /** - * Get the version of FOP - * @return the version string - * @deprecated Use {@link org.apache.fop.Version#getVersion()} instead! - * This method will be removed with FOP 1.0. - */ - public static String getVersion() { - return org.apache.fop.Version.getVersion(); - } } diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index de4c43626..e6ac70d67 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -24,7 +24,6 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.MalformedURLException; -import java.net.URISyntaxException; import java.net.URL; import java.util.Collection; import java.util.Collections; @@ -195,7 +194,7 @@ public class FopFactory implements ImageContext { * @throws FOPException when the constructor fails */ public Fop newFop(String outputFormat) throws FOPException { - return new Fop(outputFormat, newFOUserAgent()); + return newFop(outputFormat, newFOUserAgent()); } /** @@ -212,10 +211,7 @@ public class FopFactory implements ImageContext { * @throws FOPException when the constructor fails */ public Fop newFop(String outputFormat, FOUserAgent userAgent) throws FOPException { - if (userAgent == null) { - throw new NullPointerException("The userAgent parameter must not be null!"); - } - return new Fop(outputFormat, userAgent); + return newFop(outputFormat, userAgent, null); } /** @@ -230,7 +226,7 @@ public class FopFactory implements ImageContext { * @throws FOPException when the constructor fails */ public Fop newFop(String outputFormat, OutputStream stream) throws FOPException { - return new Fop(outputFormat, newFOUserAgent(), stream); + return newFop(outputFormat, newFOUserAgent(), stream); } /** @@ -333,11 +329,10 @@ public class FopFactory implements ImageContext { } /** - * cleans the base url - * @param base - * @return - * @throws MalformedURLException - * @throws URISyntaxException + * Checks if the given base URL is acceptable. It also normalizes the URL. + * @param base the base URL to check + * @return the normalized URL + * @throws MalformedURLException if there's a problem with a file URL */ private String checkBaseURL(String base) throws MalformedURLException { if (!base.endsWith("/")) { @@ -364,8 +359,7 @@ public class FopFactory implements ImageContext { /** * Sets the base URL. * @param base base URL - * @throws MalformedURLException - * @throws URISyntaxException + * @throws MalformedURLException if there's a problem with a file URL */ public void setBaseURL(String base) throws MalformedURLException { this.base = checkBaseURL(base); @@ -382,8 +376,7 @@ public class FopFactory implements ImageContext { /** * Sets the font base URL. * @param fontBase font base URL - * @throws MalformedURLException - * @throws URISyntaxException + * @throws MalformedURLException if there's a problem with a file URL */ public void setFontBaseURL(String fontBase) throws MalformedURLException { this.fontBase = checkBaseURL(fontBase); @@ -402,8 +395,7 @@ public class FopFactory implements ImageContext { /** * Sets the hyphen base URL. * @param hyphenBase hythen base URL - * @throws MalformedURLException - * @throws URISyntaxException + * @throws MalformedURLException if there's a problem with a file URL * */ public void setHyphenBaseURL(final String hyphenBase) throws MalformedURLException { if (hyphenBase != null) { @@ -440,8 +432,8 @@ public class FopFactory implements ImageContext { } /** - * sets the HyphenationTreeResolver - * @param hyphResolver + * Sets the HyphenationTreeResolver to be used for resolving user-supplied hyphenation files. + * @param hyphResolver the HyphenationTreeResolver instance */ public void setHyphenationTreeResolver(HyphenationTreeResolver hyphResolver) { this.hyphResolver = hyphResolver; @@ -724,6 +716,10 @@ public class FopFactory implements ImageContext { return (this.fontCache != null); } + /** + * Returns the font cache instance used by this factory. + * @return the font cache + */ public FontCache getFontCache() { return this.fontCache; } -- cgit v1.2.3 From ff6ac460f195633039ec5697519a1fa1228a038a Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 19 Feb 2008 13:08:39 +0000 Subject: Bugzilla #44451: The patch fixes two problems: - If distinct fonts declare the same font family name, the resulting font mapping is currently arbitrary; now, a name-similarity heuristic is used to prioritize the font mappings. - "Medium" and "demi" fonts are now recognized as "bold", solving several real-world problems (although this solution may be an oversimplification). Submitted by: Justus Piater Patch modified by jeremias: - Style fixes (tab chars) - Refined font weight identification: medium -> 500, semi/demi -> 600 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@629093 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontInfo.java | 42 ++++++++++++++++++++++ src/java/org/apache/fop/fonts/FontResolver.java | 2 +- src/java/org/apache/fop/fonts/FontTriplet.java | 20 ++++++++++- src/java/org/apache/fop/fonts/FontUtil.java | 25 +++++++++++-- .../fop/fonts/autodetect/FontInfoFinder.java | 25 +++++++------ src/java/org/apache/fop/render/PrintRenderer.java | 2 +- status.xml | 4 +++ 7 files changed, 104 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index af0fba579..ab11eb768 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -52,6 +52,10 @@ public class FontInfo { /** look up a font-triplet to find a font-name */ private Map triplets; //Map (String = font key) + /** look up a font-triplet to find its priority + * (only used inside addFontProperties()) */ + private Map tripletPriorities; //Map + /** look up a font-name to get a font (that implements FontMetrics at least) */ private Map fonts; //Map (String = font key) @@ -68,6 +72,7 @@ public class FontInfo { */ public FontInfo() { this.triplets = new java.util.HashMap(); + this.tripletPriorities = new java.util.HashMap(); this.fonts = new java.util.HashMap(); this.usedFonts = new java.util.HashMap(); } @@ -78,6 +83,8 @@ public class FontInfo { * @return True if valid */ public boolean isSetupValid() { + //We're only called when font setup is done: + tripletPriorities = null; // candidate for garbage collection return triplets.containsKey(Font.DEFAULT_FONT); } @@ -105,7 +112,42 @@ public class FontInfo { if (log.isDebugEnabled()) { log.debug("Registering: " + triplet + " under " + name); } + String oldName = (String)triplets.get(triplet); + int newPriority = triplet.getPriority(); + if (oldName != null) { + int oldPriority = ((Integer)tripletPriorities.get(triplet)).intValue(); + if (oldPriority < newPriority) { + logDuplicateFont(triplet, false, oldName, oldPriority, + name, newPriority); + return; + } else { + logDuplicateFont(triplet, true, oldName, oldPriority, + name, newPriority); + } + } this.triplets.put(triplet, name); + this.tripletPriorities.put(triplet, new Integer(newPriority)); + } + + /** Log warning about duplicate font triplets. + * @param triplet the duplicate font triplet + * @param replacing true iff the new font will replace the old one + * @param oldKey the old internal font name + * @param oldPriority the priority of the existing font mapping + * @param newKey the new internal font name + * @param newPriority the priority of the duplicate font mapping + */ + private void logDuplicateFont(FontTriplet triplet, boolean replacing, + String oldKey, int oldPriority, + String newKey, int newPriority) { + if (log.isDebugEnabled()) { + log.debug(triplet + + (replacing ? ": Replacing " : ": Not replacing ") + + ((FontMetrics)fonts.get(triplets.get(triplet))).getFullName() + + " (" + oldPriority + ") by " + + ((FontMetrics)fonts.get(newKey)).getFullName() + + " (" + newPriority + ")"); + } } /** diff --git a/src/java/org/apache/fop/fonts/FontResolver.java b/src/java/org/apache/fop/fonts/FontResolver.java index cd8e965fb..b054b054a 100644 --- a/src/java/org/apache/fop/fonts/FontResolver.java +++ b/src/java/org/apache/fop/fonts/FontResolver.java @@ -28,7 +28,7 @@ public interface FontResolver { /** * Called to resolve an URI to a Source instance. The base URI needed by the URIResolver's - * resolve() method is defined to be implicitely available in this case. If the URI cannot + * resolve() method is defined to be implicitly available in this case. If the URI cannot * be resolved, null is returned and it is assumed that the FontResolver implementation * already warned the user about the problem. * @param href An href attribute, which may be relative or absolute. diff --git a/src/java/org/apache/fop/fonts/FontTriplet.java b/src/java/org/apache/fop/fonts/FontTriplet.java index 66be36bc7..a7890ecbd 100644 --- a/src/java/org/apache/fop/fonts/FontTriplet.java +++ b/src/java/org/apache/fop/fonts/FontTriplet.java @@ -32,10 +32,11 @@ public class FontTriplet implements Comparable, Serializable { private String name; private String style; private int weight; + private int priority; // priority of this triplet/font mapping //This is only a cache private transient String key; - + /** * Creates a new font triplet. * @param name font name @@ -43,9 +44,21 @@ public class FontTriplet implements Comparable, Serializable { * @param weight font weight (100, 200, 300...800, 900) */ public FontTriplet(String name, String style, int weight) { + this(name, style, weight, 0); + } + + /** + * Creates a new font triplet. + * @param name font name + * @param style font style (normal, italic etc.) + * @param weight font weight (100, 200, 300...800, 900) + * @param priority priority of this triplet/font mapping + */ + public FontTriplet(String name, String style, int weight, int priority) { this.name = name; this.style = style; this.weight = weight; + this.priority = priority; } /** @return the font name */ @@ -63,6 +76,11 @@ public class FontTriplet implements Comparable, Serializable { return weight; } + /** @return the priority of this triplet/font mapping */ + public int getPriority() { + return priority; + } + private String getKey() { if (this.key == null) { //This caches the combined key diff --git a/src/java/org/apache/fop/fonts/FontUtil.java b/src/java/org/apache/fop/fonts/FontUtil.java index b9e891c9c..89ea132c0 100644 --- a/src/java/org/apache/fop/fonts/FontUtil.java +++ b/src/java/org/apache/fop/fonts/FontUtil.java @@ -77,14 +77,18 @@ public class FontUtil { } /** font constituent names which identify a font as being of "italic" style */ - private static final String[] ITALIC_WORDS = {"italic", "oblique"}; + private static final String[] ITALIC_WORDS = {"italic", "oblique", "inclined"}; /** font constituent names which identify a font as being of "light" weight */ private static final String[] LIGHT_WORDS = {"light"}; + /** font constituent names which identify a font as being of "medium" weight */ + private static final String[] MEDIUM_WORDS = {"medium"}; + /** font constituent names which identify a font as being of "demi/semi" weight */ + private static final String[] DEMI_WORDS = {"demi", "semi"}; /** font constituent names which identify a font as being of "bold" weight */ private static final String[] BOLD_WORDS = {"bold"}; - /** font constituent names which identify a font as being of "bold" weight */ - private static final String[] EXTRA_BOLD_WORDS = {"extrabold", "black", + /** font constituent names which identify a font as being of "extra bold" weight */ + private static final String[] EXTRA_BOLD_WORDS = {"extrabold", "extra bold", "black", "heavy", "ultra", "super"}; /** @@ -109,12 +113,27 @@ public class FontUtil { public static int guessWeight(String fontName) { // weight int weight = Font.WEIGHT_NORMAL; + for (int i = 0; i < BOLD_WORDS.length; i++) { if (fontName.indexOf(BOLD_WORDS[i]) != -1) { weight = Font.WEIGHT_BOLD; break; } } + for (int i = 0; i < MEDIUM_WORDS.length; i++) { + if (fontName.indexOf(MEDIUM_WORDS[i]) != -1) { + weight = Font.WEIGHT_NORMAL + 100; //500 + break; + } + } + //Search for "semi/demi" before "light", but after "bold" + //(normally semi/demi-bold is meant, but it can also be semi/demi-light) + for (int i = 0; i < DEMI_WORDS.length; i++) { + if (fontName.indexOf(DEMI_WORDS[i]) != -1) { + weight = Font.WEIGHT_BOLD - 100; //600 + break; + } + } for (int i = 0; i < EXTRA_BOLD_WORDS.length; i++) { if (fontName.indexOf(EXTRA_BOLD_WORDS[i]) != -1) { weight = Font.WEIGHT_EXTRA_BOLD; diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index aaefc789b..1ec8a5528 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -31,6 +31,7 @@ import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fonts.CachedFontInfo; import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.EmbedFontInfo; @@ -66,28 +67,32 @@ public class FontInfoFinder { // default style and weight triplet vales (fallback) String strippedName = stripQuotes(customFont.getStrippedFontName()); - String subName = customFont.getFontSubName(); - String searchName = strippedName.toLowerCase(); - if (subName != null) { - searchName += subName.toLowerCase(); - } - + //String subName = customFont.getFontSubName(); + String fullName = stripQuotes(customFont.getFullName()); + String searchName = fullName.toLowerCase(); + String style = guessStyle(customFont, searchName); int weight = FontUtil.guessWeight(searchName); //Full Name usually includes style/weight info so don't use these traits //If we still want to use these traits, we have to make FontInfo.fontLookup() smarter - String fullName = stripQuotes(customFont.getFullName()); - triplets.add(new FontTriplet(fullName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)); + triplets.add(new FontTriplet(fullName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, 0)); if (!fullName.equals(strippedName)) { - triplets.add(new FontTriplet(strippedName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)); + triplets.add(new FontTriplet(strippedName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, 0)); } Set familyNames = customFont.getFamilyNames(); Iterator iter = familyNames.iterator(); while (iter.hasNext()) { String familyName = stripQuotes((String)iter.next()); if (!fullName.equals(familyName)) { - triplets.add(new FontTriplet(familyName, style, weight)); + /* Heuristic: + * The more similar the family name to the full font name, + * the higher the priority of its triplet. + * (Lower values indicate higher priorities.) */ + int priority = fullName.startsWith(familyName) + ? fullName.length() - familyName.length() + : fullName.length(); + triplets.add(new FontTriplet(familyName, style, weight, priority)); } } } diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index f725bd711..6f1bfeea6 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -78,7 +78,7 @@ public abstract class PrintRenderer extends AbstractRenderer { } /** - * Returns the internal font key fot a font triplet coming from the area tree + * Returns the internal font key for a font triplet coming from the area tree * @param area the area from which to retrieve the font triplet information * @return the internal font key (F1, F2 etc.) or null if not found */ diff --git a/status.xml b/status.xml index d6693d2cd..6236a7c56 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Improved the font auto-detection so fonts accessed using the font-family name are + selected with higher accuracy. + Removed deprecated methods in the "apps" package that were left-overs from the API discussions. -- cgit v1.2.3 From 5b06b2c75f10e0be591f878b1d7a533a9b826f7c Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 19 Feb 2008 14:16:08 +0000 Subject: Bugfix: a specified font-weight of 100 could result into a resolved font-weight of 400 even when a font with weight 200 is registered. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@629103 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontInfo.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index ab11eb768..218734f15 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -383,11 +383,17 @@ public class FontInfo { String f = null; int newWeight = weight; if (newWeight < 400) { - while (f == null && newWeight > 0) { + while (f == null && newWeight > 100) { newWeight -= 100; key = createFontKey(family, style, newWeight); f = getInternalFontKey(key); } + newWeight = weight; + while (f == null && newWeight < 400) { + newWeight += 100; + key = createFontKey(family, style, newWeight); + f = getInternalFontKey(key); + } } else if (newWeight == 500) { key = createFontKey(family, style, 400); f = getInternalFontKey(key); -- cgit v1.2.3 From e4cc262c1fac77fc38286b412b6293f1f1767ec8 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 19 Feb 2008 15:43:31 +0000 Subject: Fixed NPE when no AFM is available and the PFM didn't provide a xHeight. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@629129 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fonts/type1/Type1FontLoader.java | 36 +++++++++++++--------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 009a446f9..910ee82cc 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -216,11 +216,13 @@ public class Type1FontLoader extends FontLoader { //(the following are all optional in AFM, but FontBBox is always available) if (returnFont.getXHeight(1) == 0) { int xHeight = 0; - AFMCharMetrics chm = afm.getChar("x"); - if (chm != null) { - RectangularShape rect = chm.getBBox(); - if (rect != null) { - xHeight = (int)Math.round(rect.getMinX()); + if (afm != null) { + AFMCharMetrics chm = afm.getChar("x"); + if (chm != null) { + RectangularShape rect = chm.getBBox(); + if (rect != null) { + xHeight = (int)Math.round(rect.getMinX()); + } } } if (xHeight == 0) { @@ -230,11 +232,13 @@ public class Type1FontLoader extends FontLoader { } if (returnFont.getAscender() == 0) { int asc = 0; - AFMCharMetrics chm = afm.getChar("d"); - if (chm != null) { - RectangularShape rect = chm.getBBox(); - if (rect != null) { - asc = (int)Math.round(rect.getMinX()); + if (afm != null) { + AFMCharMetrics chm = afm.getChar("d"); + if (chm != null) { + RectangularShape rect = chm.getBBox(); + if (rect != null) { + asc = (int)Math.round(rect.getMinX()); + } } } if (asc == 0) { @@ -244,11 +248,13 @@ public class Type1FontLoader extends FontLoader { } if (returnFont.getDescender() == 0) { int desc = 0; - AFMCharMetrics chm = afm.getChar("p"); - if (chm != null) { - RectangularShape rect = chm.getBBox(); - if (rect != null) { - desc = (int)Math.round(rect.getMinX()); + if (afm != null) { + AFMCharMetrics chm = afm.getChar("p"); + if (chm != null) { + RectangularShape rect = chm.getBBox(); + if (rect != null) { + desc = (int)Math.round(rect.getMinX()); + } } } if (desc == 0) { -- cgit v1.2.3 From 56387de039f142b731d6ced52db6c79cb422824b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 19 Feb 2008 15:47:48 +0000 Subject: Added support for reading the OS/2 table's usWeightClass value which supports the same font weight values as we use in XSL-FO. However, in my tests these values proved to be unreliable (like ExtraBlack fonts returning 400). I just hooked the whole thing in so this work isn't lost if anyone has an idea to make it work. The FontInfoFinder will continue to only use guessed font weights for now. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@629131 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/CustomFont.java | 21 +++++++++++++++++++++ .../apache/fop/fonts/autodetect/FontInfoFinder.java | 6 +++++- src/java/org/apache/fop/fonts/truetype/TTFFile.java | 12 +++++++++++- .../apache/fop/fonts/truetype/TTFFontLoader.java | 1 + 4 files changed, 38 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index 0ac3b80bc..f6bb52cb3 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/src/java/org/apache/fop/fonts/CustomFont.java @@ -46,6 +46,7 @@ public abstract class CustomFont extends Typeface private int descender = 0; private int[] fontBBox = {0, 0, 0, 0}; private int flags = 4; + private int weight = 0; //0 means unknown weight private int stemV = 0; private int italicAngle = 0; private int missingWidth = 0; @@ -196,6 +197,15 @@ public abstract class CustomFont extends Typeface return flags; } + /** + * Returns the font weight (100, 200...800, 900). This value may be different from the + * one that was actually used to register the font. + * @return the font weight (or 0 if the font weight is unknown) + */ + public int getWeight() { + return this.weight; + } + /** * {@inheritDoc} */ @@ -349,6 +359,17 @@ public abstract class CustomFont extends Typeface this.flags = flags; } + /** + * Sets the font weight. Valid values are 100, 200...800, 900. + * @param weight the font weight + */ + public void setWeight(int weight) { + weight = (weight / 100) * 100; + weight = Math.max(100, weight); + weight = Math.min(900, weight); + this.weight = weight; + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index 1ec8a5528..5fc0525c3 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -72,7 +72,11 @@ public class FontInfoFinder { String searchName = fullName.toLowerCase(); String style = guessStyle(customFont, searchName); - int weight = FontUtil.guessWeight(searchName); + int weight; //= customFont.getWeight(); + int guessedWeight = FontUtil.guessWeight(searchName); + //We always take the guessed weight for now since it yield much better results. + //OpenType's OS/2 usWeightClass value proves to be unreliable. + weight = guessedWeight; //Full Name usually includes style/weight info so don't use these traits //If we still want to use these traits, we have to make FontInfo.fontLookup() smarter diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index 86a1d75e2..e60722331 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -105,6 +105,7 @@ public class TTFFile { //Ascender/descender from OS/2 table private int os2Ascender = 0; private int os2Descender = 0; + private int usWeightClass = 0; private short lastChar = 0; @@ -620,6 +621,13 @@ public class TTFFile { return flags; } + /** + * Returns the weight class of this font. Valid values are 100, 200....,800, 900. + * @return the weight class value (or 0 if there was no OS/2 table in the font) + */ + public int getWeightClass() { + return this.usWeightClass; + } /** * Returns the StemV attribute of the font. @@ -978,7 +986,9 @@ public class TTFFile { private final void readOS2(FontFileReader in) throws IOException { // Check if font is embeddable if (dirTabs.get("OS/2") != null) { - seekTab(in, "OS/2", 2 * 4); + seekTab(in, "OS/2", 2 * 2); + this.usWeightClass = in.readTTFUShort(); + in.skip(2); int fsType = in.readTTFUShort(); if (fsType == 2) { isEmbeddable = false; diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index b29aff808..60a6948fc 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -90,6 +90,7 @@ public class TTFFontLoader extends FontLoader { returnFont.setStemV(Integer.parseInt(ttf.getStemV())); //not used for TTF returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle())); returnFont.setMissingWidth(0); + returnFont.setWeight(ttf.getWeightClass()); multiFont.setCIDType(CIDFontType.CIDTYPE2); int[] wx = ttf.getWidths(); -- cgit v1.2.3 From d2ab1d818a06caa65580ccc7d28b773b01b1f2f9 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 19 Feb 2008 17:32:18 +0000 Subject: Fixed a bug leading to the content of row-spanning cells being duplicated at page breaks, when it's small enough to fit on the previous row git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@629169 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 12 ++-- .../standard-testcases/table_row-delay.xml | 72 ++++++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index d89f43370..c4bff5112 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -290,12 +290,14 @@ class ActiveCell { * @see #signalRowLastStep(int) */ private void increaseCurrentStep(int limit) { - while (afterNextStep.totalLength <= limit && nextStep.breakClass == Constants.EN_AUTO) { - nextStep.set(afterNextStep); - if (afterNextStep.end >= elementList.size() - 1) { - break; + if (nextStep.end < elementList.size() - 1) { + while (afterNextStep.totalLength <= limit && nextStep.breakClass == Constants.EN_AUTO) { + nextStep.set(afterNextStep); + if (afterNextStep.end >= elementList.size() - 1) { + break; + } + gotoNextLegalBreak(); } - gotoNextLegalBreak(); } } diff --git a/test/layoutengine/standard-testcases/table_row-delay.xml b/test/layoutengine/standard-testcases/table_row-delay.xml index a5d88cf46..b3b962da9 100644 --- a/test/layoutengine/standard-testcases/table_row-delay.xml +++ b/test/layoutengine/standard-testcases/table_row-delay.xml @@ -231,6 +231,40 @@ + + + + 5. Before the table. + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + + + Cell 1.2 Line 1 + Cell 1.2 Line 2 + + + + + Cell 2.1 Line 1 + Cell 2.1 Line 2 + + + + + + + + @@ -433,5 +467,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 0c0480eb79ef67c1ef94e276d1ae72766ee9501d Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Thu, 21 Feb 2008 12:52:33 +0000 Subject: Moved me to commiters :) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@629769 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/team.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index 63d943702..23cb87708 100644 --- a/src/documentation/content/xdocs/team.xml +++ b/src/documentation/content/xdocs/team.xml @@ -79,16 +79,16 @@ page for some of his private projects.
  • Jörg Pietschmann (JP)
  • Oleg Tkachenko (OT)
  • +
  • Max Berger (MB) is currently a + PostDoc pursuing an academic career in computer science. His main interest in FOP is to + improve the DocBook to PDF tool-chain to produce high quality output, while still + conforming to given style-guides. See his home + page for more information.
  • Active Contributors
    diff --git a/src/documentation/content/xdocs/site.xml b/src/documentation/content/xdocs/site.xml index 7914d5ef2..8a30d0078 100644 --- a/src/documentation/content/xdocs/site.xml +++ b/src/documentation/content/xdocs/site.xml @@ -22,6 +22,7 @@ + @@ -34,7 +35,6 @@ --> - @@ -57,12 +57,12 @@ --> - + - - + + @@ -89,16 +89,16 @@ - + - - + + @@ -125,9 +125,9 @@ - + diff --git a/src/documentation/content/xdocs/tabs.xml b/src/documentation/content/xdocs/tabs.xml index bb2fd7e72..3db01d4fa 100644 --- a/src/documentation/content/xdocs/tabs.xml +++ b/src/documentation/content/xdocs/tabs.xml @@ -21,14 +21,8 @@ - + - - -- cgit v1.2.3 From 92922510c0af312dfc51732456545f27a666b36f Mon Sep 17 00:00:00 2001 From: Clay Leeds Date: Sun, 2 Mar 2008 06:42:02 +0000 Subject: Adding Quick Start Guide. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@632716 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/quickstartguide.xml | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/documentation/content/xdocs/quickstartguide.xml (limited to 'src') diff --git a/src/documentation/content/xdocs/quickstartguide.xml b/src/documentation/content/xdocs/quickstartguide.xml new file mode 100644 index 000000000..469698730 --- /dev/null +++ b/src/documentation/content/xdocs/quickstartguide.xml @@ -0,0 +1,57 @@ + + + + + +
    + FOP: Quick Start Guide + Everything you need to start using and appreciating Apache FOP quickly. + $Revision: 627324 $ +
    + +

    The goal of his Quick Start Guide is to help novice users get Apache FOP up and running quickly. Typically, you'll need to:

    +
      +
    1. Download FOP
    2. +
    3. Build FOP
    4. +
    5. Configure FOP
    6. +
    7. Run FOP
    8. +
    +

    Here are some links to help you find out what FOP can do, as well as how and where to get help:

    + +

    The following links will help you understand what FOP supports out of the box, and how to extend FOP using your own Fonts and Hyphenation files, as well as how to extend FOP with Extensions.

    + + +
    -- cgit v1.2.3 From a1939c7e0c470f7d44bf1320dc5c122e3c3eef5f Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Sun, 2 Mar 2008 16:53:24 +0000 Subject: Further preparations for the 0.95 release. This was tested with the latest Forrest Trunk (which uses FOP 0.94 for the PDFs). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@632784 13f79535-47bb-0310-9956-ffa450edef68 --- forrest.properties | 3 +- src/documentation/content/xdocs/0.95/anttask.xml | 197 +++++ src/documentation/content/xdocs/0.95/compiling.xml | 141 ++++ .../content/xdocs/0.95/configuration.xml | 394 ++++++++++ src/documentation/content/xdocs/0.95/embedding.xml | 689 +++++++++++++++++ .../content/xdocs/0.95/extensions.xml | 234 ++++++ src/documentation/content/xdocs/0.95/fonts.xml | 348 +++++++++ .../xdocs/0.95/fotree/disabled-testcases.xml | 26 + src/documentation/content/xdocs/0.95/graphics.xml | 551 +++++++++++++ .../content/xdocs/0.95/hyphenation.xml | 237 ++++++ src/documentation/content/xdocs/0.95/index.xml | 54 ++ .../content/xdocs/0.95/intermediate.xml | 146 ++++ .../content/xdocs/0.95/known-issues.xml | 74 ++ .../content/xdocs/0.95/knownissues_overview.xml | 70 ++ .../xdocs/0.95/layoutengine/disabled-testcases.xml | 308 ++++++++ src/documentation/content/xdocs/0.95/output.xml | 859 +++++++++++++++++++++ src/documentation/content/xdocs/0.95/pdfa.xml | 159 ++++ .../content/xdocs/0.95/pdfencryption.xml | 230 ++++++ src/documentation/content/xdocs/0.95/pdfx.xml | 136 ++++ src/documentation/content/xdocs/0.95/running.xml | 350 +++++++++ src/documentation/content/xdocs/0.95/servlets.xml | 325 ++++++++ src/documentation/content/xdocs/0.95/upgrading.xml | 126 +++ src/documentation/content/xdocs/site.xml | 1 + src/documentation/sitemap.xmap | 22 +- src/documentation/skinconf.xml | 10 +- 25 files changed, 5673 insertions(+), 17 deletions(-) create mode 100644 src/documentation/content/xdocs/0.95/anttask.xml create mode 100644 src/documentation/content/xdocs/0.95/compiling.xml create mode 100644 src/documentation/content/xdocs/0.95/configuration.xml create mode 100644 src/documentation/content/xdocs/0.95/embedding.xml create mode 100644 src/documentation/content/xdocs/0.95/extensions.xml create mode 100644 src/documentation/content/xdocs/0.95/fonts.xml create mode 100644 src/documentation/content/xdocs/0.95/fotree/disabled-testcases.xml create mode 100644 src/documentation/content/xdocs/0.95/graphics.xml create mode 100644 src/documentation/content/xdocs/0.95/hyphenation.xml create mode 100644 src/documentation/content/xdocs/0.95/index.xml create mode 100644 src/documentation/content/xdocs/0.95/intermediate.xml create mode 100644 src/documentation/content/xdocs/0.95/known-issues.xml create mode 100644 src/documentation/content/xdocs/0.95/knownissues_overview.xml create mode 100644 src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml create mode 100644 src/documentation/content/xdocs/0.95/output.xml create mode 100644 src/documentation/content/xdocs/0.95/pdfa.xml create mode 100644 src/documentation/content/xdocs/0.95/pdfencryption.xml create mode 100644 src/documentation/content/xdocs/0.95/pdfx.xml create mode 100644 src/documentation/content/xdocs/0.95/running.xml create mode 100644 src/documentation/content/xdocs/0.95/servlets.xml create mode 100644 src/documentation/content/xdocs/0.95/upgrading.xml (limited to 'src') diff --git a/forrest.properties b/forrest.properties index dc8219d7a..40e6cf06c 100644 --- a/forrest.properties +++ b/forrest.properties @@ -97,7 +97,8 @@ forrest.validate.skins.stylesheets=${forrest.validate.skins} # server, set to -Djava.awt.headless=true #forrest.jvmargs= # The bugtracking URL - the issue number will be appended -#project.bugtracking-url=http://issues.apache.org/bugzilla/show_bug.cgi?id= +project.bugtracking-url=http://issues.apache.org/bugzilla/show_bug.cgi?id= +bugtracking-url=http://issues.apache.org/bugzilla/show_bug.cgi?id= #project.bugtracking-url=http://issues.apache.org/jira/browse/ # The issues list as rss #project.issues-rss-url= diff --git a/src/documentation/content/xdocs/0.95/anttask.xml b/src/documentation/content/xdocs/0.95/anttask.xml new file mode 100644 index 000000000..44550c3d7 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/anttask.xml @@ -0,0 +1,197 @@ + + + + + +
    + Ant task + $Revision$ +
    + +

    + Apache FOP provides an Ant task for automating the document build process. +

    +
    + Description +

    + The FOP Ant task will convert XSL-FO documents to PDF, PS, PCL etc. output + (see Output formats for available formats). +

    +

    + To call FOP tasks within Ant, first add a FOP task definition to your Ant build file. + One method of defining the task is as follows: +

    + + + + + + + + + + + + + + ]]> +

    + Then create FOP tasks within your Ant build file, using the FOP task parameters listed below.

    +
    + +
    Parameters for FOP Ant task + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Parameters specified as attributes
    AttributeDescriptionRequired
    fofileXSL-FO file to be renderedYes, if no fileset nested element is used
    outfileOutput filenameYes, when fofile is used. (This attribute is not valid for filesets.)
    formatPossible output formats:
    + application/X-fop-awt-preview
    + application/X-fop-print
    + application/X-fop-areatree
    + application/pdf
    + application/postscript
    + application/mif
    + application/rtf, + text/richtext, + text/rtf
    + application/x-pcl, + application/vnd.hp-PCL
    + application/x-afp, + application/vnd.ibm.modcap
    + text/plain
    + image/svg+xml
    + image/gif
    + image/png
    + image/tiff
    +
    No, defaults to application/pdf
    outdirOutput directoryRequired if a fileset is used to specify the files to render; optional for fofile. (Can alternatively specify the full path in the fofile value.)
    forceRecreate target files, even if they are newer than their corresponding + source files. Note: This attribute is available in post-0.20.5 + versions (0.20.x nightly build and 1.0dev) only; target files are + always generated (i.e., force=true) in 0.20.5 release. + No, default is false
    basedirBase directory to resolve relative references (e.g., graphics files) within the + FO document. + No, for single FO File entry, default is to use the location + of that FO file. +
    relativebaseFor fileset usage only. A value of true specifies using the location + of each .fo file as the base directory for resolving relative file references located + within that .fo file. A value of false specifies using the value of + basedir for all files within the fileset, or just the current working directory + if basedir is not specified. + No, default is false. +
    userconfigUser configuration file (same as the FOP "-c" command line option).No
    messagelevelLogging level
    + Possible values: error, warn, info, verbose, debug. Currently doesn't work in FOP Trunk!!!
    No, defaults to verbose
    logFilesControls whether the names of the files that are processed are logged + (true) or not (false). Currently doesn't work in FOP Trunk!!!No, default is true
    +

    + + + + + + + + + + + +
    Parameters specified as nested elements
    AttributeDescriptionRequired
    filesetFileSets + are used to specify multiple XSL-FO files to be rendered.Yes, if no fofile attribute is supplied
    +

    +
    + Examples +

    + The following example converts a single XSL-FO file to a PDF document: +

    + + + + + ]]> +

    + This example converts all XSL-FO files within an entire directory to PostScript: +

    + + + + + + + + ]]> +
    + +
    + diff --git a/src/documentation/content/xdocs/0.95/compiling.xml b/src/documentation/content/xdocs/0.95/compiling.xml new file mode 100644 index 000000000..c6c17a3c0 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/compiling.xml @@ -0,0 +1,141 @@ + + + + + +
    + Apache FOP: Building from Source Code + $Revision$ +
    + +
    + Do You Need To Build? +

    + FOP distributions are either pre-compiled binary or source. + If you are using a binary distribution, it is already built and there is no need to build it again. + See the Download Instructions for information about whether a + binary or source distribution is best for your needs. +

    +

    + If you got the source code from a repository snapshot or via Subversion you will need to build FOP + in any case. +

    +
    +
    + Set Up Your Environment +
    + JDK +

    + Building FOP requires a minimum Java Development Kit (JDK/SDK) of 1.3 + (A Java Runtime Environment is not sufficient). +

    +
    +
    + CLASSPATH +

    + There is generally no need to setup a classpath. All libraries needed to compile FOP are included + in the source distribution and are referenced by the build script. + You will only need to adjust the classpath if you build FOP in some other way. See the build + script build.xml for details. +

    +
    +
    + JAVA_HOME +

    + The build script uses Apache Ant, a popular + Java-based build tool, which usually requires that the environment variable JAVA_HOME point to + your local JDK root directory. This is true even if you use JDK 1.3 or above, which normally + does not need this setting. +

    +
    +
    + Apache Ant +

    + Apache Ant must be installed in order to + build FOP. Following best practices we don't include Ant with FOP anymore. You can find the + instructions to install Ant in the Ant manual on the web. +

    +
    +
    +
    + Run the Build Script +

    + Change to the FOP root directory and build FOP by executing the build script (build.xml) + using the "ant" command. +

    + + The "ant" command is only available on your system if you've properly + installed Apache Ant and added Ant's location to the PATH + environment variable. + +

    + The file build.xml in the FOP root directory is the blueprint that Ant uses for the build. It + contains information for numerous build targets, many of which are building blocks to more + useful target, and others which are primarily used by the FOP developers. + You may benefit from looking through this file to learn more about the various build targets. + To obtain a complete list of useful build targets: +

    + ant -projecthelp +

    The most useful targets are:

    +
      +
    • + package: Generates the JAR files (default). This is the normal build that + produces a jar file usable for running FOP. +
    • +
    • + clean : Cleans the build directory. This is useful for making sure that + any build errors are cleaned up before starting a new build. It should not ordinarily be + needed, but may be helpful if you are having problems with the build process itself. +
    • +
    • + javadocs: Creates the FOP API documentation. + A minimum JDK version of 1.4.2 is required for generating the javadocs. +
    • +
    +

    To run the build:

    + ant [target ...] +

    For example to do a normal build for the "all" target (which is the default):

    + ant +

    OR

    + ant all +

    To clean the build directory first:

    + ant clean all + + If you want to shorten the build time you can just call the "package" target which + doesn't perform any automated tests during the build. + +
    +
    + Troubleshooting +

    If you have problems building FOP, please try the following:

    +
      +
    • Run the build with the target of "clean", then rerun the build.
    • +
    • Delete the build directory completely, then rerun the build.
    • +
    • + Make sure you do not have a non-FOP version of xerces.jar, xalan.jar, batik.jar, + or another dependency product somewhere in your CLASSPATH. +
    • +
    • + If the build still fails, see the Getting Help + page for further help. +
    • +
    +
    + +
    + diff --git a/src/documentation/content/xdocs/0.95/configuration.xml b/src/documentation/content/xdocs/0.95/configuration.xml new file mode 100644 index 000000000..e82a6e862 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/configuration.xml @@ -0,0 +1,394 @@ + + + + + +
    + Apache FOP: Configuration + $Revision$ +
    + + +
    + Configuration File Basics +

    + The FOP configuration file is an XML file containing a variety of settings that are useful + for controlling FOP's behavior, and for helping it find resources that you wish it to use. +

    +

    + The easiest way to get started using a FOP configuration file is to copy the sample found + at {fop-dir}/conf/fop.xconf to a location of your choice, and then to + edit it according to your needs. + It contains templates for the various configuration options, most of which are commented + out. Remove the comments and change the settings for entries that you wish to use. + Be sure to follow any instructions, including comments which specify the value range. + Also, since the configuration file is XML, be sure to keep it well-formed. +

    +
    + Making Configuration Available to FOP +

    After creating your configuration file, you must tell FOP how to find it:

    + +

    + See Setting the Configuration Programmatically + for instructions on how to do so in an embedded environment. +

    +
    +
    +
    + Summary of the General Configuration Options + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ElementData Type (for the value)DescriptionDefault Value
    baseURL or directorySpecifies the base URL based on which relative URL will be resolved.current directory
    font-baseURL or directorySpecifies the base URL based on which relative font URLs will be resolved. + base URL/directory (above)
    hyphenation-baseURL or directorySpecifies the base URL based on which relative URLs to hyphenation pattern + files will be resolved. If not specified, support for user-supplied hyphenation + patterns remains disabled. + disabled
    source-resolutionInteger, dpi + Resolution in dpi (dots per inch) which is used internally to determine the pixel + size for SVG images and bitmap images without resolution information. + 72 dpi
    target-resolutionInteger, dpi + Resolution in dpi (dots per inch) used to specify the output resolution for bitmap + images generated by bitmap renderers (such as the TIFF renderer) and by bitmaps + generated by Apache Batik for filter effects and such. + 72 dpi
    strict-configurationBoolean (true, false) + Setting this option to 'true' will cause FOP to strictly verify the contents of the + FOP configuration file to ensure that defined resources (such as fonts and base + URLs/directories) are valid and available to FOP. Any errors found will cause FOP to + immediately raise an exception.false
    strict-validationBoolean (true, false) + Setting this option to 'false' causes FOP to be more forgiving about XSL-FO validity, + for example, you're allowed to specify a border on a region-body which is supported + by some FO implementations but is non-standard. Note that such a border would + currently have no effect in Apache FOP.true
    break-indent-inheritanceBoolean (true, false) + Setting this option to 'true' causes FOP to use an alternative rule set to determine + text indents specified through margins, start-indent and end-indent. Many commercial + FO implementations have chosen to break the XSL specification in this aspect. This + option tries to mimic their behaviour. Please note that Apache FOP may still not + behave exactly like those implementations either because FOP has not fully matched + the desired behaviour and because the behaviour among the commercial implementations + varies. The default for this option (i.e. false) is to behave exactly like the + specification describes.false
    default-page-settingsn/a + Specifies the default width and height of a page if "auto" is specified + for either or both values. Use "height" and "width" attributes on the + default-page-settings element to specify the two values."height" 11 inches, "width" 8.26 inches
    use-cacheboolean (true, false)All fonts information that has been gathered as a result of "directory" + or "auto-detect" font configurations will be cached for future rendering runs. + This setting should improve performance on systems where + fonts have been configured using the "directory" or "auto-detect" tag mechanisms. + By default this option is switched on.true
    cache-fileStringThis options specifies the file/directory path of the fop cache file. + This option can also be specified on the command-line using the -cache option. + This file is currently only used to cache font triplet information for future reference.${base}/conf/fop.cache
    renderers(see text below)Contains the configuration for each renderer. See below.N/A
    +

    + This is an excerpt from the example configuration file coming with FOP: +

    + + + + true + + + true + + + ./ + + + ./ + + + 72 + + 72 + + + + + +]]> +
    +
    + Renderer configuration +

    + Each Renderer has its own configuration section which is identified by the + MIME type the Renderer is written for, ex. "application/pdf" for the PDF Renderer. +

    +

    + The configuration for the PDF Renderer could look like this: +

    + + + + + flate + + + + + + + + + + + + + + + ]]> +

    + The details on the font configuration can be found on the separate Fonts page. + Note especially the section entitled Register Fonts with FOP. +

    +
    + Special Settings for the PDF Renderer +

    + The configuration element for the PDF renderer contains two elements. One is for the font configuration + (please follow the link above) and one is for the "filter list". The filter list controls how the + individual objects in a PDF file are encoded. By default, all objects get "flate" encoded (i.e. simply + compressed with the same algorithm that is also used in ZIP files). Most users don't need to change that + setting. For debugging purposes, it may be desired not to compress the internal objects at all so the + generated PDF commands can be read. In that case, you can simply use the following filter list. The + second filter list (type="image") ensures that all images still get compressed but also ASCII-85 encoded + so the produced PDF file is still easily readable in a text editor. +

    + + + null + + + flate + ascii-85 + + + ]]> +

    + Another (optional) setting specific to the PDF Renderer is an output color profile, an ICC + color profile which indicates the target color space the PDF file is generated for. This + setting is mainly used in conjunction with the PDF/X feature. + An example: +

    + + C:\FOP\Color\EuropeISOCoatedFOGRA27.icc + + ]]> +

    + Some people don't have high requirements on color fidelity but instead want the smallest + PDF file sizes possible. In this case it's possible to disable the default sRGB color space + which XSL-FO requires. This will cause RGB colors to be generated as device-specific RGB. + Please note that this option is unavailable (and will cause an error) if you enable + PDF/A or PDF/X functionality or if you specify an output profile. This setting will make the + PDF about 4KB smaller. To disable the sRGB color space add the following setting: +

    + + true + + ]]> +
    +
    + Special Settings for the PostScript Renderer +

    + Besides the normal font configuration (the same "fonts" element as for the PDF renderer) the PostScript + renderer has an additional setting to force landscape pages to be rotated to fit on a page inserted into + the printer in portrait mode. Set the value to "true" to activate this feature. The default is "false". + Example: +

    + + true + + + + + + + + + + + + ]]> +
    +
    + Special Settings for the PCL Renderer +

    + Non-standard fonts for the PCL renderer are made available through the Java2D subsystem which means that + you don't have to do any custom font configuration in this case but you have to use the font names + offered by Java. +

    +

    + Additionally, there are certain settings that control how the renderer handles various elements. +

    + + quality + bitmap +]]> +

    + The default value for the "rendering" setting is "speed" which causes borders + to be painted as plain rectangles. In this mode, no special borders (dotted, + dashed etc.) are available. If you want support for all border modes, set the + value to "quality" as indicated above. This will cause the borders to be painted + as bitmaps. +

    +

    + The default value for the "text-rendering" setting is "auto" which paints the + base fonts using PCL fonts. Non-base fonts are painted as bitmaps through Java2D. + If the mix of painting methods results in unwelcome output, you can set this + to "bitmap" which causes all text to be rendered as bitmaps. +

    +
    +
    + +
    + When it does not work + +

    FOP searches the configuration file for the information it +expects, at the position it expects. When that information is not +present, FOP will not complain, it will just continue. When there is +other information in the file, FOP will not complain, it will just +ignore it. That means that when your configuration information is in +the file but in a different XML element, or in a different XML path, +than FOP expects, it will be silently ignored.

    + +

    Check the following possibilities:

    + +
      +
    • The format of the configuration file has changed +considerably between FOP 0.20.5 and FOP 1.0 and its beta versions. Did +you convert your file to the new format?
    • + +
    • The FOP distribution contains a schema for configuration +files, at src/foschema/fop-configuration.xsd. Did you validate your +configuration file against it? Add the following schema location to +the schema element: + +]]> + + +and run the configuration file through a validating schema +parser. Note that the schema cannot detect all errors, and that it is +stricter about the order of some elements than FOP itself is.
    • + +
    • Run FOP in debug mode (command line option +-d). This makes FOP report which configuration +information it finds. Check if FOP finds what you expect.
    • + +
    + +
    + +
    + diff --git a/src/documentation/content/xdocs/0.95/embedding.xml b/src/documentation/content/xdocs/0.95/embedding.xml new file mode 100644 index 000000000..b2c802db7 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/embedding.xml @@ -0,0 +1,689 @@ + + + + + + +
    + Apache FOP: Embedding + How to Embed FOP in a Java application + $Revision$ +
    + + +
    + Overview +

    + Review Running FOP for important information that applies + to embedded applications as well as command-line use, such as options and performance. +

    +

    + To embed Apache FOP in your application, first create a new + org.apache.fop.apps.FopFactory instance. This object can be used to launch multiple + rendering runs. For each run, create a new org.apache.fop.apps.Fop instance through + one of the factory methods of FopFactory. In the method call you specify which output + format (i.e. Renderer) to use and, if the selected renderer requires an OutputStream, + which OutputStream to use for the results of the rendering. You can customize FOP's + behaviour in a rendering run by supplying your own FOUserAgent instance. The + FOUserAgent can, for example, be used to set your own Renderer instance (details + below). Finally, you retrieve a SAX DefaultHandler instance from the Fop object and + use that as the SAXResult of your transformation. +

    + + We recently changed FOP's outer API to what we consider the final API. This might require + some changes in your application. The main reasons for these changes were performance + improvements due to better reuse of reusable objects and reduced use of static variables + for added flexibility in complex environments. + +
    +
    + Basic Usage Pattern +

    + Apache FOP relies heavily on JAXP. It uses SAX events exclusively to receive the XSL-FO + input document. It is therefore a good idea that you know a few things about JAXP (which + is a good skill anyway). Let's look at the basic usage pattern for FOP... +

    +

    Here is the basic pattern to render an XSL-FO file to PDF: +

    + +

    + Let's discuss these 5 steps in detail: +

    +
      +
    • + Step 1: You create a new FopFactory instance. The FopFactory instance holds + references to configuration information and cached data. It's important to reuse this + instance if you plan to render multiple documents during a JVM's lifetime. +
    • +
    • + Step 2: You set up an OutputStream that the generated document + will be written to. It's a good idea to buffer the OutputStream as demonstrated + to improve performance. +
    • +
    • + Step 3: You create a new Fop instance through one of the factory + methods on the FopFactory. You tell the FopFactory what your desired output format + is. This is done by using the MIME type of the desired output format (ex. "application/pdf"). + You can use one of the MimeConstants.* constants. The second parameter is the + OutputStream you've setup up in step 2. +
    • +
    • + Step 4 We recommend that you use JAXP Transformers even + if you don't do XSLT transformations to generate the XSL-FO file. This way + you can always use the same basic pattern. The example here sets up an + "identity transformer" which just passes the input (Source) unchanged to the + output (Result). You don't have to work with a SAXParser if you don't do any + XSLT transformations. +
    • +
    • + Step 5: Here you set up the input and output for the XSLT + transformation. The Source object is set up to load the "myfile.fo" file. + The Result is set up so the output of the XSLT transformation is sent to FOP. + The FO file is sent to FOP in the form of SAX events which is the most efficient + way. Please always avoid saving intermediate results to a file or a memory buffer + because that affects performance negatively. +
    • +
    • + Step 6: Finally, we start the XSLT transformation by starting + the JAXP Transformer. As soon as the JAXP Transformer starts to send its output + to FOP, FOP itself starts its processing in the background. When the + transform() method returns FOP will also have finished converting + the FO file to a PDF file and you can close the OutputStream. + + It's a good idea to enclose the whole conversion in a try..finally statement. If + you close the OutputStream in the finally section, this will make sure that the + OutputStream is properly closed even if an exception occurs during the conversion. + +
    • +
    +

    + If you're not totally familiar with JAXP Transformers, please have a look at the + Embedding examples below. The section contains examples + for all sorts of use cases. If you look at all of them in turn you should be able + to see the patterns in use and the flexibility this approach offers without adding + too much complexity. +

    +

    + This may look complicated at first, but it's really just the combination of an + XSL transformation and a FOP run. It's also easy to comment out the FOP part + for debugging purposes, for example when you're tracking down a bug in your + stylesheet. You can easily write the XSL-FO output from the XSL transformation + to a file to check if that part generates the expected output. An example for that + can be found in the Embedding examples (See "ExampleXML2FO"). +

    +
    + Logging +

    + Logging is now a little different than it was in FOP 0.20.5. We've switched from + Avalon Logging to Jakarta Commons Logging. + While with Avalon Logging the loggers were directly given to FOP, FOP now retrieves + its logger(s) through a statically available LogFactory. This is similar to the + general pattern that you use when you work with Apache Log4J directly, for example. + We call this "static logging" (Commons Logging, Log4J) as opposed to "instance logging" + (Avalon Logging). This has a consequence: You can't give FOP a logger for each + processing run anymore. The log output of multiple, simultaneously running FOP instances + is sent to the same logger. +

    + + We know this may be an issue in multi-threaded server environments if you'd like to + know what's going on in every single FOP processing run. We're planning to add an + additional feedback facility to FOP which can be used to obtain all sorts of specific + feedback (validation messages, layout problems etc.). "Static logging" is mainly + interesting for a developer working on FOP and for advanced users who are debugging + FOP. We don't consider the logging output to be useful to normal FOP users. Please + have some patience until we can add this feature or jump in and help us build it. We've + set up a Wiki page + which documents what we're going to build. + +

    + By default, Jakarta Commons Logging uses + JDK logging (available in JDKs 1.4 or higher) as its backend. You can configure Commons + Logging to use an alternative backend, for example Log4J. Please consult the + documentation for Jakarta Commons Logging on + how to configure alternative backends. +

    +
    + +
    + Processing XSL-FO +

    + Once the Fop instance is set up, call getDefaultHandler() to obtain a SAX + DefaultHandler instance to which you can send the SAX events making up the XSL-FO + document you'd like to render. FOP processing starts as soon as the DefaultHandler's + startDocument() method is called. Processing stops again when the + DefaultHandler's endDocument() method is called. Please refer to the basic + usage pattern shown above to render a simple XSL-FO document. +

    +
    + +
    + Processing XSL-FO generated from XML+XSLT +

    + If you want to process XSL-FO generated from XML using XSLT we recommend + again using standard JAXP to do the XSLT part and piping the generated SAX + events directly through to FOP. The only thing you'd change to do that + on the basic usage pattern above is to set up the Transformer differently: +

    + +
    +
    +
    + Input Sources +

    + The input XSL-FO document is always received by FOP as a SAX stream (see the + Parsing Design Document for the rationale). +

    +

    + However, you may not always have your input document available as a SAX stream. + But with JAXP it's easy to convert different input sources to a SAX stream so you + can pipe it into FOP. That sounds more difficult than it is. You simply have + to set up the right Source instance as input for the JAXP transformation. + A few examples: +

    +
      +
    • + URL: Source src = new StreamSource("http://localhost:8080/testfile.xml"); +
    • +
    • + File: Source src = new StreamSource(new File("C:/Temp/myinputfile.xml")); +
    • +
    • + String: Source src = new StreamSource(new StringReader(myString)); // myString is a String +
    • +
    • + InputStream: Source src = new StreamSource(new MyInputStream(something)); +
    • +
    • + Byte Array: Source src = new StreamSource(new ByteArrayInputStream(myBuffer)); // myBuffer is a byte[] here +
    • +
    • + DOM: Source src = new DOMSource(myDocument); // myDocument is a Document or a Node +
    • +
    • + Java Objects: Please have a look at the Embedding examples which contain an example for this. +
    • +
    +

    + There are a variety of upstream data manipulations possible. + For example, you may have a DOM and an XSL stylesheet; or you may want to + set variables in the stylesheet. Interface documentation and some cookbook + solutions to these situations are provided in + Xalan Basic Usage Patterns. +

    +
    +
    + Configuring Apache FOP Programmatically +

    + Apache FOP provides two levels on which you can customize FOP's + behaviour: the FopFactory and the user agent. +

    +
    + Customizing the FopFactory +

    + The FopFactory holds configuration data and references to objects which are reusable over + multiple rendering runs. It's important to instantiate it only once (except in special + environments) and reuse it every time to create new FOUserAgent and Fop instances. +

    +

    + You can set all sorts of things on the FopFactory: +

    +
      +
    • +

      + The font base URL to use when resolving relative URLs for fonts. Example: +

      + fopFactory.setFontBaseURL("file:///C:/Temp/fonts"); +
    • +
    • +

      + The hyphenation base URL to use when resolving relative URLs for + hyphenation patterns. Example: +

      + fopFactory.setHyphenBaseURL("file:///C:/Temp/hyph"); +
    • +
    • +

      + Disable strict validation. When disabled FOP is less strict about the rules + established by the XSL-FO specification. Example: +

      + fopFactory.setStrictValidation(false); +
    • +
    • +

      + Enable an alternative set of rules for text indents that tries to mimic the behaviour of many commercial + FO implementations, that chose to break the specification in this respect. The default of this option is + 'false', which causes Apache FOP to behave exactly as described in the specification. To enable the + alternative behaviour, call: +

      + fopFactory.setBreakIndentInheritanceOnReferenceAreaBoundary(true); +
    • +
    • +

      + Set the source resolution for the document. This is used internally to determine the pixel + size for SVG images and bitmap images without resolution information. Default: 72 dpi. Example: +

      + fopFactory.setSourceResolution(96); // =96dpi (dots/pixels per Inch) +
    • +
    • +

      + Manually add an ElementMapping instance. If you want to supply a special FOP extension + you can give the instance to the FOUserAgent. Normally, the FOP extensions can be automatically detected + (see the documentation on extension for more info). Example: +

      + fopFactory.addElementMapping(myElementMapping); // myElementMapping is a org.apache.fop.fo.ElementMapping +
    • +
    • +

      + Set a URIResolver for custom URI resolution. By supplying a JAXP URIResolver you can add + custom URI resolution functionality to FOP. For example, you can use + Apache XML Commons Resolver to make use of XCatalogs. Example: +

      + fopFactory.setURIResolver(myResolver); // myResolver is a javax.xml.transform.URIResolver + + Both the FopFactory and the FOUserAgent have a method to set a URIResolver. The URIResolver on the FopFactory + is primarily used to resolve URIs on factory-level (hyphenation patterns, for example) and it is always used + if no other URIResolver (for example on the FOUserAgent) resolved the URI first. + +
    • +
    +
    +
    + Customizing the User Agent +

    + The user agent is the entity that allows you to interact with a single rendering run, i.e. the processing of a single + document. If you wish to customize the user agent's behaviour, the first step is to create your own instance + of FOUserAgent using the appropriate factory method on FopFactory and pass that + to the factory method that will create a new Fop instance: +

    + +

    + You can do all sorts of things on the user agent: +

    +
      +
    • +

      + The base URL to use when resolving relative URLs. Example: +

      + userAgent.setBaseURL("file:///C:/Temp/"); +
    • +
    • +

      + Set the producer of the document. This is metadata information that can be used for certain output formats such as PDF. The default producer is "Apache FOP". Example: +

      + userAgent.setProducer("MyKillerApplication"); +
    • +
    • +

      + Set the creating user of the document. This is metadata information that can be used for certain output formats such as PDF. Example: +

      + userAgent.setCreator("John Doe"); +
    • +
    • +

      + Set the author of the document. This is metadata information that can be used for certain output formats such as PDF. Example: +

      + userAgent.setAuthor("John Doe"); +
    • +
    • +

      + Override the creation date and time of the document. This is metadata information that can be used for certain output formats such as PDF. Example: +

      + userAgent.setCreationDate(new Date()); +
    • +
    • +

      + Set the title of the document. This is metadata information that can be used for certain output formats such as PDF. Example: +

      + userAgent.setTitle("Invoice No 138716847"); +
    • +
    • +

      + Set the keywords of the document. This is metadata information that can be used for certain output formats such as PDF. Example: +

      + userAgent.setKeywords("XML XSL-FO"); +
    • +
    • +

      + Set the target resolution for the document. This is used to + specify the output resolution for bitmap images generated by bitmap renderers + (such as the TIFF renderer) and by bitmaps generated by Apache Batik for filter + effects and such. Default: 72 dpi. Example: +

      + userAgent.setTargetResolution(300); // =300dpi (dots/pixels per Inch) +
    • +
    • +

      + Set your own Renderer instance. If you want to supply your own renderer or + configure a Renderer in a special way you can give the instance to the FOUserAgent. Normally, + the Renderer instance is created by FOP. Example: +

      + userAgent.setRendererOverride(myRenderer); // myRenderer is an org.apache.fop.render.Renderer +
    • +
    • +

      + Set your own FOEventHandler instance. If you want to supply your own FOEventHandler or + configure an FOEventHandler subclass in a special way you can give the instance to the FOUserAgent. Normally, + the FOEventHandler instance is created by FOP. Example: +

      + userAgent.setFOEventHandlerOverride(myFOEventHandler); // myFOEventHandler is an org.apache.fop.fo.FOEventHandler +
    • +
    • +

      + Set a URIResolver for custom URI resolution. By supplying a JAXP URIResolver you can add + custom URI resolution functionality to FOP. For example, you can use + Apache XML Commons Resolver to make use of XCatalogs. Example: +

      + userAgent.setURIResolver(myResolver); // myResolver is a javax.xml.transform.URIResolver + + Both the FopFactory and the FOUserAgent have a method to set a URIResolver. The URIResolver on the FOUserAgent is + used for resolving URIs which are document-related. If it's not set or cannot resolve a URI, the URIResolver + from the FopFactory is used. + +
    • +
    + + You should not reuse an FOUserAgent instance between FOP rendering runs although you can. Especially + in multi-threaded environment, this is a bad idea. + +
    +
    +
    + Using a Configuration File +

    + Instead of setting the parameters manually in code as shown above you can also set + many values from an XML configuration file: +

    + +

    + The layout of the configuration file is described on the Configuration page. +

    +
    +
    + Hints +
    + Object reuse +

    + Fop instances shouldn't (and can't) be reused. Please recreate + Fop and FOUserAgent instances for each rendering run using the FopFactory. + This is a cheap operation as all reusable information is held in the + FopFactory. That's why it's so important to reuse the FopFactory instance. +

    +
    +
    + AWT issues +

    + If your XSL-FO files contain SVG then Apache Batik will be used. When Batik is + initialised it uses certain classes in java.awt that + intialise the Java AWT classes. This means that a daemon thread + is created by the JVM and on Unix it will need to connect to a + DISPLAY. +

    +

    + The thread means that the Java application may not automatically quit + when finished, you will need to call System.exit(). These + issues should be fixed in the JDK 1.4. +

    +

    + If you run into trouble running FOP on a head-less server, please see the + notes on Batik. +

    +
    +
    + Getting information on the rendering process +

    + To get the number of pages that were rendered by FOP you can call + Fop.getResults(). This returns a FormattingResults object + where you can look up the number of pages produced. It also gives you the + page-sequences that were produced along with their id attribute and their + numbers of pages. This is particularly useful if you render multiple + documents (each enclosed by a page-sequence) and have to know the number of + pages of each document. +

    +
    +
    +
    + Improving performance +

    + There are several options to consider: +

    +
      +
    • + Whenever possible, try to use SAX to couple the individual components involved + (parser, XSL transformer, SQL datasource etc.). +
    • +
    • + Depending on the target OutputStream (in case of a FileOutputStream, but not + for a ByteArrayOutputStream, for example) it may improve performance considerably + if you buffer the OutputStream using a BufferedOutputStream: + out = new java.io.BufferedOutputStream(out); +
      + Make sure you properly close the OutputStream when FOP is finished. +
    • +
    • + Cache the stylesheet. If you use the same stylesheet multiple times + you can set up a JAXP Templates object and reuse it each time you do + the XSL transformation. (More information can be found + here.) +
    • +
    • + Use an XSLT compiler like XSLTC + that comes with Xalan-J. +
    • +
    • + Fine-tune your stylesheet to make the XSLT process more efficient and to create XSL-FO that can + be processed by FOP more efficiently. Less is more: Try to make use of property inheritance where possible. +
    • +
    +
    +
    + Multithreading FOP +

    + Apache FOP may currently not be completely thread safe. + The code has not been fully tested for multi-threading issues, yet. + If you encounter any suspicious behaviour, please notify us. +

    +

    + There is also a known issue with fonts being jumbled between threads when using + the Java2D/AWT renderer (which is used by the -awt and -print output options). + In general, you cannot safely run multiple threads through the AWT renderer. +

    +
    +
    + Examples +

    + The directory "{fop-dir}/examples/embedding" contains several working examples. +

    +
    + ExampleFO2PDF.java +

    This + + example +demonstrates the basic usage pattern to transform an XSL-FO +file to PDF using FOP. +

    +
    +
    +
    + ExampleXML2FO.java +

    This + + example +has nothing to do with FOP. It is there to show you how an XML +file can be converted to XSL-FO using XSLT. The JAXP API is used to do the +transformation. Make sure you've got a JAXP-compliant XSLT processor in your +classpath (ex. Xalan). +

    +
    +
    +
    + ExampleXML2PDF.java +

    This + + example +demonstrates how you can convert an arbitrary XML file to PDF +using XSLT and XSL-FO/FOP. It is a combination of the first two examples +above. The example uses JAXP to transform the XML file to XSL-FO and FOP to +transform the XSL-FO to PDF. +

    +
    +

    +The output (XSL-FO) from the XSL transformation is piped through to FOP using +SAX events. This is the most efficient way to do this because the +intermediate result doesn't have to be saved somewhere. Often, novice users +save the intermediate result in a file, a byte array or a DOM tree. We +strongly discourage you to do this if it isn't absolutely necessary. The +performance is significantly higher with SAX. +

    +
    +
    + ExampleObj2XML.java +

    This + + example +is a preparatory example for the next one. It's an example that +shows how an arbitrary Java object can be converted to XML. It's an often +needed task to do this. Often people create a DOM tree from a Java object and +use that. This is pretty straightforward. The example here, however, shows how +to do this using SAX, which will probably be faster and not even more +complicated once you know how this works. +

    +
    +

    +For this example we've created two classes: ProjectTeam and ProjectMember +(found in xml-fop/examples/embedding/java/embedding/model). They represent +the same data structure found in +xml-fop/examples/embedding/xml/xml/projectteam.xml. We want to serialize to XML a +project team with several members which exist as Java objects. +Therefore we created the two classes: ProjectTeamInputSource and +ProjectTeamXMLReader (in the same place as ProjectTeam above). +

    +

    +The XMLReader implementation (regard it as a special kind of XML parser) is +responsible for creating SAX events from the Java object. The InputSource +class is only used to hold the ProjectTeam object to be used. +

    +

    +Have a look at the source of ExampleObj2XML.java to find out how this is +used. For more detailed information see other resources on JAXP (ex. +An older JAXP tutorial). +

    +
    +
    + ExampleObj2PDF.java +

    This + + example +combines the previous and the third to demonstrate +how you can transform a Java object to a PDF directly in one smooth run +by generating SAX events from the Java object that get fed to an XSL +transformation. The result of the transformation is then converted to PDF +using FOP as before. +

    +
    +
    +
    + ExampleDOM2PDF.java +

    This + + example +has FOP use a DOMSource instead of a StreamSource in order to +use a DOM tree as input for an XSL transformation. +

    +
    +
    + ExampleSVG2PDF.java (PDF Transcoder example) +

    This + + example +shows the usage of the PDF Transcoder, a sub-application within FOP. +It is used to generate a PDF document from an SVG file. +

    +
    +
    + Final notes +

    +These examples should give you an idea of what's possible. It should be easy +to adjust these examples to your needs. Also, if you have other examples that you +think should be added here, please let us know via either the fop-users or fop-dev +mailing lists. Finally, for more help please send your questions to the fop-users +mailing list. +

    +
    +
    + +
    + diff --git a/src/documentation/content/xdocs/0.95/extensions.xml b/src/documentation/content/xdocs/0.95/extensions.xml new file mode 100644 index 000000000..483866e61 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/extensions.xml @@ -0,0 +1,234 @@ + + + + + +
    + Standard FOP Extensions + $Revision$ +
    + +

    + By "extension", we mean any data that can be placed in the input XML document that + is not addressed by the XSL-FO standard. + By having a mechanism for supporting extensions, FOP is able to add features that + are not covered in the specification. +

    +

    + The extensions documented here are included with FOP, and are automatically available + to you. If you wish to add an extension of your own to FOP, please see the + Developers' Extension Page. +

    + All extensions require the correct use of an appropriate namespace in your input document. +
    + SVG +

    + Please see the SVG documentation for more details. +

    +
    +
    + FO Extensions +
    + Namespace +

    + By convention, FO extensions in FOP use the "fox" namespace prefix. + To use any of the FO extensions, add a namespace entry for + http://xml.apache.org/fop/extensions to the root element: +

    + ]]> +
    +
    + PDF Bookmarks +

    + In previous versions of Apache FOP there was a fox:outline element + which was used to create outlines in PDF files. The redesigned code makes use + of the new bookmark feature defined in the latest XSL 1.1 working draft. +

    +
    +
    + Anchors or Named Destinations +

    Use the fox:destination element to define "named destinations" inside a PDF document. +These are useful as fragment identifiers, e.g. "http://server/document.pdf#anchor-name". +fox:destination elements can be placed almost anywhere in the fo document, including a child of +root, a block-level element, or an inline-level element. +For the destination to actually work, it must correspond to an "id" attribute on some fo element +within the document. In other words, the "id" attribute actually creates the "view" within the +PDF document. The fox:destination simply gives that view an independent name. +

    + +... +Table of Contents]]> + It is possible that in some future release of FOP, all elements with +"id" attributes will generate named-destinations, which will eliminate the need for +fox:destination. +
    +
    + Table Continuation Label +

    This extension element hasn't been reimplemented for the redesigned code, yet.

    + +
    +
    + fox:orphan-content-limit and fox:widow-content-limit +

    + 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. +

    +
    +
    + fox:external-document + + This feature is incomplete. Support for multi-page documents will be added shortly. + At the moment, only single-page images will work. And this will not work with RTF output. + +

    + This is a proprietary extension element which allows to add whole images as pages to + an FO document. For example, if you have a scanned document or a fax as multi-page TIFF + file, you can append or insert this document using the fox:external-document + element. Each page of the external document will create one full page in the target + format. +

    +

    + The fox:external-document element is structurally a peer to + fo:page-sequence, so wherever you can put an fo:page-sequence + you could also place a fox:external-document. + Therefore, the specified contents for fo:root change to: +

    +

    + + (layout-master-set, declarations?, bookmark-tree?, (page-sequence|page-sequence-wrapper|fox:external-document|fox:destination)+) + +

    +
    + Specification +

    + The fox:external-document extension formatting object is used to specify + how to create a (sub-)sequence of pages within a document. The content of these pages + comes from the individual subimages/pages of an image or paged document (for example: + multi-page TIFF in the form of faxes or scanned documents, or PDF files). The + formatting object creates the necessary areas to display one image per page. +

    +

    + In terms of page numbers, the behaviour is the same as for + fo:page-sequence. The placement of the image inside the page is similar + to that of fo:external-graphic or fo:instream-foreign-object, + i.e. the viewport (and therefore the page size) is defined by either the intrinsic + size of the image or by the size properties that apply to this formatting object. +

    +

    Content: EMPTY

    +

    The following properties apply to this formatting object:

    +
      +
    • (Common Accessibility Properties) (not implemented, yet)
    • +
    • (Common Aural Properties) (not implemented, yet)
    • +
    • block-progression-dimension
    • +
    • content-height
    • +
    • content-type
    • +
    • content-width
    • +
    • display-align
    • +
    • height
    • +
    • id
    • +
    • inline-progression-dimension
    • +
    • overflow
    • +
    • pages: <page-set> (see below) (not implemented, yet)
    • +
    • reference-orientation
    • +
    • scaling
    • +
    • scaling-method
    • +
    • src
    • +
    • text-align
    • +
    • width
    • +
    +

    + Datatype "page-set": Value: auto | <integer-range>, + Default: "auto" which means all pages/subimages of the document. + <integer-range> allows values such as "7" or "1-3" +

    + + fox:external-document is not suitable for concatenating FO documents. + For this, XInclude is recommended. + +
    +
    +
    + Free-form Transformation for fo:block-container +

    + For fo:block-container elements whose absolute-position set to + "absolute" or "fixed" you can use the extension attribute fox:transform + to apply a free-form transformation to the whole block-container. The content of the + fox:transform attribute is the same as for + SVG's transform attribute. + The transformation specified here is performed in addition to other implicit + transformations of the block-container (resulting from top, left and other properties) + and after them. +

    +

    + Examples: fox:transform="rotate(45)" would rotate the block-container + by 45 degrees clock-wise around its upper-left corner. + fox:transform="translate(10000,0)" would move the block-container to the + right by 10 points (=10000 millipoints, FOP uses millipoints internally!). +

    + + This extension attribute doesn't work for all output formats! It's currently only + supported for PDF, PS and Java2D-based renderers. + +
    +
    + Color functions +

    + XSL-FO supports specifying color using the rgb(), rgb-icc() and system-color() functions. + Apache FOP provides additional color functions for special use cases. Please note that + using these functions compromises the interoperability of an FO document. +

    +
    + cmyk() +

    color cmyk(numeric, numeric, numeric, numeric)

    +

    + This function will construct a color in device-specific CMYK color space. The numbers + must be between 0.0 and 1.0. For output formats that don't support device-specific + color space the CMYK value is converted to an sRGB value. +

    +
    +
    + +
    + +
    + diff --git a/src/documentation/content/xdocs/0.95/fonts.xml b/src/documentation/content/xdocs/0.95/fonts.xml new file mode 100644 index 000000000..e12527fe3 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/fonts.xml @@ -0,0 +1,348 @@ + + + + + +
    + Apache FOP: Fonts + $Revision$ + + + + + + +
    + +
    + Summary + The FOP Font subsystem is currently undergoing a significant change. + The details provided here especially related to the generation of FOP Font + Metrics files and the FOP Font configuration are likely to change substantially + in the future. + +

    The following table summarizes the font capabilities of the various FOP renderers:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    RendererBase-14AWT/OSCustomCustom Embedding
    PDFyesnoyesyes
    PostScriptyesnoyesyes
    TXTyes (used for layout but not for output)noyes (used for layout but not for output)no
    AWTif available from OSyesyesn/a (display only)
    Printif available from OSyesyescontrolled by OS printer driver
    RTFn/a (font metrics not needed)n/an/an/a
    MIFn/a (font metrics not needed)n/an/an/a
    SVGif available from OSyesnono
    XMLyesnoyesn/a
    +
    +
    + Base-14 Fonts +

    + The Adobe PDF Specification specifies a set of 14 fonts that must be + available to every PDF reader: + Helvetica (normal, bold, italic, bold italic), + Times (normal, bold, italic, bold italic), + Courier (normal, bold, italic, bold italic), + Symbol and ZapfDingbats. +

    +

    + Please note that recent versions of Adobe Acrobat Reader replace + "Helvetica" with "Arial" and "Times" with "Times New Roman" internally. + GhostScript replaces "Helvetica" with "Nimbus Sans L" and "Times" with + "Nimbus Roman No9 L". Other document viewers may do similar font + substitutions. If you need to make sure that there are no such + substitutions, you need to specify an explicit font and embed it in + the target document. +

    +
    +
    + Missing Fonts +

    + When FOP does not have a specific font at its disposal (because it's + not installed in the operating system or set up in FOP's configuration), + the font is replaced with "any". "any" is internally mapped to the + Base-14 font "Times" (see above). +

    +
    +
    + AWT/Operating System Fonts +

    The AWT family of renderers (AWT, Print, SVG), use the Java AWT libraries for font metric information. Through operating system registration, the AWT libraries know what fonts are available on the system, and the font metrics for each one.

    +
    +
    + Custom Fonts +

    Support for custom fonts is added by creating font metric files (written in XML) from the actual font files, and registering them with FOP. Currently only Type 1 and TrueType fonts can be added. +More information about fonts can be found at:

    + +
    + Type 1 Font Metrics +

    FOP includes PFMReader, which reads the PFM file that normally comes with a Type 1 font, and generates an appropriate font metrics file for it. +To use it, run the class org.apache.fop.fonts.apps.PFMReader:

    +

    Windows (on JDK 1.4 and later):

    + java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file +

    Windows (on JDK 1.3.x):

    + java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar;lib\xml-apis.jar; + lib\xercesImpl.jar;lib\xalan.jar;lib\serializer.jar + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file +

    Unix (on JDK 1.4 and later):

    + java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file +

    Unix (on JDK 1.3.1):

    + java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar:lib/xml-apis.jar: + lib/xercesImpl.jar:lib/xalan.jar:lib/serializer.jar + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file +

    PFMReader [options]:

    +
      +
    • -fn <fontname> By default, FOP uses the fontname from the +.pfm file when embedding the font. Use the "-fn" option to override this name with one you have +chosen. This may be useful in some cases to ensure that applications using the output document +(Acrobat Reader for example) use the embedded font instead of a local font with the same +name.
    • +
    + The classpath in the above example has been simplified for readability. +You will have to adjust the classpath to the names of the actual JAR files in the lib directory. +xml-apis.jar, xercesImpl.jar, xalan.jar and serializer.jar are not necessary for JDK version 1.4 or later. + The tool will construct some values (FontBBox, StemV and ItalicAngle) based on assumptions and calculations which are only an approximation to the real values. +FontBBox and Italic Angle can be found in the human-readable part of the PFB file or in the AFM file. +The PFMReader tool does not yet interpret PFB or AFM files, so if you want to be correct, you may have to adjust the values in the XML file manually. +The constructed values however appear to have no visible influence. +
    +
    + TrueType Font Metrics +

    FOP includes TTFReader, which reads the TTF file and generates an appropriate font metrics file for it. +Use it in a similar manner to PFMReader. +For example, to create such a metrics file in Windows from the TrueType font at c:\myfonts\cmr10.ttf:

    + java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar + org.apache.fop.fonts.apps.TTFReader [options] + C:\myfonts\cmr10.ttf ttfcm.xml +

    TTFReader [options]:

    +
      +
    • -d <DEBUG | INFO > Sets the debug level (default is +INFO).
    • +
    • -fn <fontname> Same as for PFMReader.
    • +
    • -ttcname <fontname> If you're reading data from a +TrueType Collection (.ttc file) you must specify which font from the collection you will read +metrics from. +If you read from a .ttc file without this option, the fontnames will be listed for you.
    • +
    • -enc ansi Creates a WinAnsi-encoded font metrics file. +Without this option, a CID-keyed font metrics file is created. +The table below summarizes the differences between these two encoding options as currently +used within FOP. +Please note that this information only applies to TrueType fonts and TrueType collections:
    • +
    + + + + + + + + + + + + + + + + +
    IssueWinAnsiCID-keyed
    Usable Character SetLimited to WinAnsi character set, which is roughly equivalent to iso-8889-1.Limited only by the characters in the font itself.
    Embedding the FontOptional.Mandatory. Not embedding the font produces invalid PDF documents.
    + + You may experience failures with certain TrueType fonts, especially if they don't contain + the so-called Unicode "cmap" table. TTFReader can currently not deal with font like this. + +
    +
    + TrueType Collections Font Metrics +

    TrueType collections (.ttc files) contain more than one font. +To create metrics files for these fonts, you must specify which font in the collection should be generated, by using the "-ttcname" option with the TTFReader.

    +

    To get a list of the fonts in a collection, just start the TTFReader as if it were a normal TrueType file (without the -ttcname option). +It will display all of the font names and exit with an Exception.

    +

    Here is an example of generating a metrics file for a .ttc file:

    + java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar + org.apache.fop.fonts.apps.TTFReader -ttcname "MS Mincho" + msmincho.ttc msminch.xml +
    +
    + Register Fonts with FOP +

    You must tell FOP how to find and use the font metrics files by registering them in the FOP Configuration. Add entries for your custom fonts, regardless of font type, to the configuration file in a manner similar to the following:

    + + + + + + + + C:\MyFonts1 + + + C:\MyFonts2 + + + +]]> + Review the documentation for FOP Configuration for instructions on making the FOP configuration available to FOP when it runs. Otherwise, FOP has no way of finding your custom font information. +
      +
    • + URLs are used to access the font metric and font files. + Relative URLs are resolved relative to the font-base property (or base) if available. + See FOP: Configuration for more information. +
    • +
    • Either an "embed-url" or a "metrics-url" must be specified for font tag configurations.
    • +
    • The font "kerning" attribute is optional.
    • +
    • If embedding is off, the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.
    • +
    • When setting the "embed-url" attribute for Type 1 fonts, be sure to specify the PFB (actual font data), not PFM (font metrics) file that you used to generate the XML font metrics file.
    • +
    • The fonts "directory" tag can be used to register fonts contained within a single or list of directory paths. The "recursive" attribute can be specified to recursively add fonts from all sub directories.
    • +
    • The fonts "auto-detect" tag can be used to automatically register fonts that are found to be installed on the native operating system.
    • +
    • Fonts registered with "font" tag configurations override fonts found by means of "directory" tag definitions.
    • +
    • Fonts found as a result of a "directory" tag configuration override fonts found as a result of the "auto-detect" tag being specified.
    • +
    • + If relative URLs are specified, they are evaluated relative to the value of the + "font-base" setting. If there is no "font-base" setting, the fonts are evaluated + relative to the base directory. +
    • +
    + +
    +
    + Auto-Detect and auto-embedd feature +

    When the "auto-detect" flag is set in the configuration, FOP will automatically search for fonts in the default paths for your operating system.

    +

    FOP will also auto-detect fonts which are available in the classpath, if they are described as "application/x-font" in the MANIFEST.MF file. For example, if your .jar file contains font/myfont.ttf:

    + Manifest-Version: 1.0 + +Name: font/myfont.ttf +Content-Type: application/x-font +

    This feature allows you to create JAR files containing fonts. The JAR files can be added to fop by providem them in the classpath, e.g. copying them into the lib/ directory.

    +
    +
    + Embedding + The PostScript renderer does not yet support TrueType fonts, but can embed Type 1 fonts. + The font is simply embedded into the PDF file, it is not converted. +

    Font embedding is enabled in the userconfig.xml file and controlled by the embed-url attribute. +If you don't specify the embed-url attribute the font will not be embedded, but will only be referenced.

    + + Omitting the embed-url attribute for CID-encoded TrueType fonts will currently produce invalid + PDF files! If you create the XML font metric file using the "-enc ansi" option, you can omit + the embed-url attribute for TrueType fonts but you're restricted to the WinAnsi character set. + +

    When FOP embeds a font, it adds a prefix to the fontname to ensure that the name will not match the fontname of an installed font. +This is helpful with older versions of Acrobat Reader that preferred installed fonts over embedded fonts.

    +

    When embedding PostScript fonts, the entire font is always embedded.

    +

    When embedding TrueType fonts (ttf) or TrueType Collections (ttc), a subset of the + original font, containing only the glyphs used, is embedded in the output document.

    +
    +
    + Explicitly embedding the base 14 fonts +

    + There are cases where you might want to force the embedding of one or more of the base 14 fonts that + can normally be considered available on the target platform (viewer, printer). One of these cases is + PDF/A which mandates the embedding of even the base 14 fonts. Embedding a font such as Helvetica or + Courier is straight-forward. The "Symbol" and "ZapfDingbats" fonts, however, currently present a + problem because FOP cannot correctly determine the encoding of these two single-byte fonts through + the PFM file. FOP now correctly interprets the "encoding" value in the XML font metrics file, but the + PFMReader application writes "UnknownEncoding" to the generated XML file. In order to embed "Symbol" + and "ZapfDingbats" you have to manually change the XML font metrics file and specify "SymbolEncoding" + or "ZapfdingbatsEncoding" encoding respectively as the value for the "encoding" element. +

    +

    Example:

    + + + Symbol + + SymbolEncoding + 673 + 766 + [..]]]> +
    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/fotree/disabled-testcases.xml b/src/documentation/content/xdocs/0.95/fotree/disabled-testcases.xml new file mode 100644 index 000000000..f6f78dcf7 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/fotree/disabled-testcases.xml @@ -0,0 +1,26 @@ + + + + + + Markers and core function evaluation + from-table-column_marker.fo + The code currently evaluates this function according to the column in which the + marker appears in the source document, rather than the column it is retrieved in. + + diff --git a/src/documentation/content/xdocs/0.95/graphics.xml b/src/documentation/content/xdocs/0.95/graphics.xml new file mode 100644 index 000000000..31e54d8fd --- /dev/null +++ b/src/documentation/content/xdocs/0.95/graphics.xml @@ -0,0 +1,551 @@ + + + + + +
    + Apache FOP: Graphics Formats + $Revision$ +
    + +
    + Introduction +

    + After the Apache FOP 0.94 release, the image handling subsystem has been rewritten in + order to improve the range of supported images and image subtypes, to lower the + overall memory consumption when handling images, to produce smaller output files and to + increase the performance in certain areas. Of course, this causes a few changes most of + which the user will probably not notice. The most important changes are: +

    +
      +
    • + The image libraries Jimi and JAI are no longer supported. Instead, Apache FOP uses the + Image I/O API that was introduced with Java 1.4 for all bitmap codecs. +
    • +
    • + Some bitmap images are no longer converted to a standardized 24 bit RGB image but are + instead handled in their native format. +
    • +
    • + A plug-in mechanism offers a possibility to add support for new formats without changing + the FOP's source code. +
    • +
    +

    + The actual image loading framework + no longer resides in Apache FOP, but was instead placed in + XML Graphics Commons. +

    +
    +
    + Overview of Graphics Support +

    + The table below summarizes the theoretical support for graphical formats + within FOP. In other words, within the constraints of the limitations listed here, + these formats should work. However, many of them have not been tested, + and there may be limitations that have not yet been discovered or documented. + The packages needed to support some formats are not included in the FOP distribution + and must be installed separately. Follow the links in the "Support Through" columns + for more details. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FormatTypeSupport Through
    Apache FOP (native)Apache BatikImage I/O
    BMP (Microsoft Windows Bitmap)bitmapX [1]
    EMF (Windows Enhanced Metafile)vector (with embedded bitmaps)(X)
    EPS (Encapsulated PostScript)metafile (both bitmap and vector), most frequently used for vector drawings(X)
    GIF (Graphics Interchange Format)bitmapX
    JPEG (Joint Photographic Experts Group)bitmap(X)X
    PNG (Portable Network Graphic)bitmapX
    SVG (Scalable Vector Graphics)vector (with embedded bitmaps)X
    TIFF (Tag Image Format File)bitmap(X)X [1]
    WMF (Windows Metafile)vector (with embedded bitmaps)(X)
    +

    + Legend: +

    +
      +
    • "(X)" means restricted support. Please see the details below.
    • +
    • + [1]: Requires the presence of JAI Image I/O Tools + (or an equivalent Image I/O compatible codec) in the classpath. JAI Image I/O Tools also + adds support for JPEG 2000, WBMP, RAW and PNM. Other Image I/O codecs may provide + support for additional formats. +
    • +
    + + JAI Image I/O Tools is not the same as the + JAI library! The + former simply exposes JAI's codecs using the Image I/O API but does not include all + the image manipulation functionality. + +
    + Map of supported image formats by output format +

    + Not all image formats are supported for all output formats! For example, while you can + use EPS (Encapsulated PostScript) files when you generate PostScript output, this format + will not be supported by any other output format. Here's an overview of which image + formats are supported by which output format: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Image FormatPDFPostScriptJava2D, PNG, TIFF, AWTPCLAFPRTF
    BMP (Microsoft Windows Bitmap)XXXXXX
    EMF (Windows Enhanced Metafile)X [1]
    EPS (Encapsulated PostScript)X [1]
    GIF (Graphics Interchange Format)XXXXXX
    JPEG (Joint Photographic Experts Group)X [1]X [1]XXX [1]X
    PNG (Portable Network Graphic)XXXXXX
    SVG (Scalable Vector Graphics)XXXXXX
    TIFF (Tag Image Format File)X [2]X [2]XXX [2]X
    WMF (Windows Metafile)XXXXXX
    +

    + Legend: +

    +
      +
    • + [1]: Supported without the need to decode the image. +
    • +
    • + [2]: Supported without the need to decode the image, but only for certain subtypes. +
    • +
    +
    +
    +
    + Graphics Packages +
    + XML Graphics Commons Native +

    + XML Graphics Commons supports a number + of graphic file formats natively as basic functionality: all bitmap formats for which + there are Image I/O codecs available (JPEG, PNG, GIF, TIFF, etc.), EPS and EMF. +

    +
    +
    + FOP Native +

    + FOP has no native image plug-ins for the image loading framework of its own but currently + hosts the Batik-dependent SVG and WMF plug-ins until they can be moved to + Apache Batik. +

    +
    +
    + Apache Batik +

    + Apache Batik will later receive the + SVG and WMF plug-ins for the image loading framework that are currently hosted inside + FOP. +

    +

    + Current FOP distributions include a distribution of the + Apache Batik. + Because Batik's API changes frequently, it is highly recommended that you use the + version that ships with FOP, at least when running FOP. +

    + Batik must be run in a graphical environment. +

    + Batik must be run in a graphical environment. + It uses AWT classes for rendering SVG, which in turn require an X server on Unixish + systems. If you run a server without X, or if you can't connect to the X server due to + security restrictions or policies (a so-called "headless" environment), SVG rendering + will fail. +

    +

    Here are some workarounds:

    +
      +
    • + Start Java with the -Djava.awt.headless=true command line option. +
    • +
    • + Install an X server which provides an in-memory framebuffer without actually using a + screen device or any display hardware. One example is Xvfb. +
    • +
    • + Install a toolkit which emulates AWT without the need for an underlying X server. One + example is the PJA toolkit, which is free + and comes with detailed installation instructions. +
    • +
    +
    +
    +
    + Details on image formats +
    + BMP +

    + BMP images are supported through an Image I/O codec. There may be limitations of the + codec which are outside the control of Apache FOP. +

    +
    +
    + EMF +

    + Windows Enhanced Metafiles (EMF) are only supported in RTF output where they are + embedded without decoding. +

    +
    +
    + EPS +

    Apache FOP allows to use EPS files when generating PostScript output only.

    +

    + Other output targets can't be supported at the moment because + FOP lacks a PostScript interpreter. Furthermore, FOP is currently not able + to parse the preview bitmaps sometimes contained in EPS files. +

    +
    +
    + GIF +

    + GIF images are supported through an Image I/O codec. Transparency is supported but + not guaranteed to work with every output format. +

    +
    +
    + JPEG +

    + FOP native support (i.e. the handling of undecoded images) of JPEG does not include all + variants, especially those containing unusual color lookup tables and color profiles. + If you have trouble with a JPEG image in FOP, try opening it with an image processing + program (such as Photoshop or Gimp) and then saving it. Specifying 24-bit color output + may also help. For the PDF and PostScript renderers most JPEG images can be passed + through without decompression. User reports indicate that grayscale, RGB, and + CMYK color spaces are all rendered properly. However, for other output formats, the + JPEG images have to be decompressed. Tests have shown that there are some limitation + in some Image I/O codecs concerning images in the CMYK color space. Work-arounds are + in place but may not always work as expected. +

    +
    +
    + PNG +

    + PNG images are supported through an Image I/O codec. Transparency is supported but + not guaranteed to work with every output format. +

    +
    +
    + SVG +
    + Introduction +

    FOP uses Apache Batik for SVG support. + This format can be handled as an fo:instream-foreign-object or in a separate + file referenced with fo:external-graphic.

    + + Batik's SVG Rasterizer utility may also be used to convert standalone SVG + documents into PDF. For more information please see the + SVG Rasterizer documentation + on the Batik site. + +
    +
    + Placing SVG Graphics into PDF +

    + The SVG is rendered into PDF by using PDF commands to draw and fill + lines and curves. This means that the graphical objects created with + this remain as vector graphics. The same applies to PostScript output. + For other output formats the SVG graphic may be converted to a bitmap + image. +

    +

    + There are a number of SVG things that cannot be converted directly into + PDF. Parts of the graphic such as effects, patterns and images are inserted + into the PDF as a raster graphic. The resolution of these raster images can + be controlled through the "target resolution" setting in the + configuration.

    +

    + Currently transparency is limited in PDF so many SVG images that + contain effects or graphics with transparent areas may not be displayed + correctly. +

    +
    +
    + Placing SVG Text into PDF and PostScript +

    If possible, Batik will use normal PDF or PostScript text when inserting text. It does + this by checking if the text can be drawn normally and the font is + supported. This example svg text.svg / + text.pdf + shows how various types and effects with text are handled. + Note that tspan and outlined text are not yet implemented.

    +

    + Otherwise, text is converted and drawn as a set of shapes by Batik, using the + stroking text painter. This means that a typical character will + have about 10 curves (each curve consists of at least 20 characters). + This can make the output files large and when it is viewed the + viewer may not normally draw those fine curves very well (In Adobe Acrobat, turning on + "Smooth Line Art" in the preferences will fix this). Copy/paste functionality + will not be supported in this case. + If the text is inserted into the output file using the inbuilt text commands + it will use a single character. +

    +

    + Note that because SVG text can be rendered as either text or a vector graphic, you + may need to consider settings in your viewer for both. The Acrobat viewer has both + "smooth line art" and "smooth text" settings that may need to be set for SVG images + to be displayed nicely on your screen (see Edit / Preferences / Display). + This setting will not affect the printing of your document, which should be OK in + any case, but will only affect the quality of the screen display.

    +
    +
    + Scaling +

    + Currently, SVG images are rendered with the dimensions specified in the SVG + file, within the viewport specified in the fo:external-graphic element. + For everything to work properly, the two should be equal. The SVG standard leaves + this issue as an implementation detail. Additional scaling options are available + through XSL-FO means. +

    +

    + If you use pixels to specify the size of an SVG graphic the "source resolution" setting + in the configuration will be used to determine the + size of a pixel. The use of pixels to specify sizes is discouraged as they may + be interpreted differently in different environments. +

    +
    +
    + Known Problems +
      +
    • + Soft mask transparency is combined with white so that it looks better + on PDF 1.3 viewers but this causes the soft mask to be slightly lighter + or darker on PDF 1.4 viewers. +
    • +
    • + There is some problem with a gradient inside a pattern which may cause a PDF + error when viewed in Acrobat 5. +
    • +
    • + Text is not always handled correctly, it may select the wrong font + especially if characters have multiple fonts in the font list. +
    • +
    • + Uniform transparency for images and other SVG elements that are converted + into a raster graphic are not drawn properly in PDF. The image is opaque. +
    • +
    +
    +
    +
    + TIFF +

    + FOP can embed TIFF images without decompression into PDF, PostScript and AFP if they + have either CCITT T.4, CCITT T.6, or JPEG compression. Otherwise, a TIFF-capable + Image I/O codec is necessary for decoding the image. +

    +

    + There may be some limitation concerning images in the CMYK color space. +

    +
    +
    + WMF +

    + Windows Metafiles (WMF) are supported through classes in + Apache Batik. At the moment, support + for this format is experimental and may not always work as expected. +

    +
    +
    +
    + Graphics Resolution +

    + Some bitmapped image file formats store a dots-per-inch (dpi) or other resolution + values. FOP tries to use this resolution information whenever possible to determine + the image's intrinsic size. This size is used during the layout process when it is not + superseded by an explicit size on fo:external-graphic (content-width and content-height + properties). +

    +

    + Please note that not all images contain resolution information. If it's not available + the source resolution set on the FopFactory (or through the user configuration XML) is used. + The default here is 72 dpi. +

    +

    + Bitmap images are generally embedded into the output format at their original resolution + (as is). No resampling of the image is performed. Explicit resampling is on our wishlist, + but hasn't been implemented, yet. Bitmaps included in SVG graphics may be resampled to + the resolution specified in the "target resolution" setting in the + configuration if SVG filters are applied. This can be + used as a work-around to resample images in FO documents. +

    +
    +
    + Page selection for multi-page formats +

    + Some image formats such as TIFF support multiple pages/sub-images per file. You can + select a particular page using a special URI fragment in the form: + <uri>#page=<nr> + (for example: http://localhost/images/myimage.tiff#page=3) +

    +
    +
    + Image caching +

    + FOP caches images between runs. There is one cache per FopFactory instance. The URI is + used as a key to identify images which means that when a particular URI appears again, + the image is taken from the cache. If you have a servlet that generates a different + image each time it is called with the same URI you need to use a constantly + changing dummy parameter on the URI to avoid caching. +

    +

    + The image cache has been improved considerably in the redesigned code. Therefore, a + resetCache() method like in earlier versions of FOP has become unnecessary. If you + still experience OutOfMemoryErrors, please notify us. +

    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/hyphenation.xml b/src/documentation/content/xdocs/0.95/hyphenation.xml new file mode 100644 index 000000000..ed97c6868 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/hyphenation.xml @@ -0,0 +1,237 @@ + + + + + +
    + Apache FOP: Hyphenation + $Revision$ +
    + +
    + Hyphenation Support +
    + Introduction +

    FOP uses Liang's hyphenation algorithm, well known from TeX. It needs + language specific pattern and other data for operation.

    +

    Because of licensing issues (and for + convenience), all hyphenation patterns for FOP are made available through + the Objects For + Formatting Objects project.

    + If you have made improvements to an existing FOP hyphenation pattern, + or if you have created one from scratch, please consider contributing these + to OFFO so that they can benefit other FOP users as well. + Please inquire on the FOP User + mailing list. +
    +
    + License Issues +

    Many of the hyphenation files distributed with TeX and its offspring are + licenced under the LaTeX + Project Public License (LPPL), which prevents them from being + distributed with Apache software. The LPPL puts restrictions on file names + in redistributed derived works which we feel can't guarantee. Some + hyphenation pattern files have other or additional restrictions, for + example against use for commercial purposes.

    +

    Although Apache FOP cannot redistribute hyphenation pattern files that do + not conform with its license scheme, that does not necessarily prevent users + from using such hyphenation patterns with FOP. However, it does place on + the user the responsibility for determining whether the user can rightly use + such hyphenation patterns under the hyphenation pattern license.

    + The user is responsible to settle license issues for hyphenation + pattern files that are obtained from non-Apache sources. +
    +
    + Sources of Custom Hyphenation Pattern Files +

    The most important source of hyphenation pattern files is the + CTAN TeX + Archive.

    +
    +
    + Installing Custom Hyphenation Patterns +

    To install a custom hyphenation pattern for use with FOP:

    +
      +
    1. Convert the TeX hyphenation pattern file to the FOP format. The FOP + format is an xml file conforming to the DTD found at + {fop-dir}/hyph/hyphenation.dtd.
    2. +
    3. Name this new file following this schema: + languageCode_countryCode.xml. The country code is + optional, and should be used only if needed. For example: +
        +
      • en_US.xml would be the file name for American + English hyphenation patterns.
      • +
      • it.xml would be the file name for Italian + hyphenation patterns.
      • +
      + The language and country codes must match the XSL-FO input, which + follows ISO + 639 (languages) and ISO + 3166 (countries). NOTE: The ISO 639/ISO 3166 convention is that + language names are written in lower case, while country codes are written + in upper case. FOP does not check whether the language and country specified + in the FO source are actually from the current standard, but it relies + on it being two letter strings in a few places. So you can make up your + own codes for custom hyphenation patterns, but they should be two + letter strings too (patches for proper handling extensions are welcome)
    4. +
    5. There are basically three ways to make the FOP-compatible hyphenation pattern + file(s) accessible to FOP: +
        +
      • Download the precompiled JAR from OFFO + and place it either in the {fop-dir}/lib directory, or + in a directory of your choice (and append the full path to the JAR to + the environment variable FOP_HYPHENATION_PATH).
      • +
      • Download the desired FOP-compatible hyphenation pattern file(s) from + OFFO, + and/or take your self created hyphenation pattern file(s), +
          +
        • place them in the directory {fop-dir}/hyph,
        • +
        • or place them in a directory of your choice and set the Ant variable + user.hyph.dir to point to that directory (in + build-local.properties),
        • +
        + and run Ant with build target + jar-hyphenation. This will create a JAR containing the + compiled patterns in {fop-dir}/build that will be added to the + classpath on the next run. + (When FOP is built from scratch, and there are pattern source file(s) + present in the directory pointed to by the + user.hyph.dir variable, this JAR will automatically + be created from the supplied pattern(s)).
      • +
      • Put the pattern source file(s) into a directory of your choice and + configure FOP to look for custom patterns in this directory, by setting the + <hyphenation-base> + configuration option.
      • +
      +
    6. +
    + + Either of these three options will ensure hyphenation is working when using + FOP from the command-line. If FOP is being embedded, remember to add the location(s) + of the hyphenation JAR(s) to the CLASSPATH (option 1 and 2) or to set the + <hyphenation-dir> + configuration option programmatically (option 3). + +
    +
    +
    + Hyphenation Patterns +

    If you would like to build your own hyphenation pattern files, or modify + existing ones, this section will help you understand how to do so. Even + when creating a pattern file from scratch, it may be beneficial to start + with an existing file and modify it. See + OFFO's Hyphenation page for examples. + Here is a brief explanation of the contents of FOP's hyphenation patterns:

    + The remaining content of this section should be considered "draft" + quality. It was drafted from theoretical literature, and has not been + tested against actual FOP behavior. It may contain errors or omissions. + Do not rely on these instructions without testing everything stated here. + If you use these instructions, please provide feedback on the + FOP User mailing list, either + confirming their accuracy, or raising specific problems that we can + address. +
      +
    • The root of the pattern file is the <hyphenation-info> element.
    • +
    • <hyphen-char>: its attribute "value" contains the character signalling + a hyphen in the <exceptions> section. It has nothing to do with the + hyphenation character used in FOP, use the XSLFO hyphenation-character + property for defining the hyphenation character there. At some points + a dash U+002D is hardwired in the code, so you'd better use this too + (patches to rectify the situation are welcome). There is no default, + if you declare exceptions with hyphenations, you must declare the + hyphen-char too.
    • +
    • <hyphen-min> contains two attributes: +
        +
      • before: the minimum number of characters in a word allowed to exist + on a line immediately preceding a hyphenated word-break.
      • +
      • after: the minimum number of characters in a word allowed to exist + on a line immediately after a hyphenated word-break.
      • +
      + This element is unused and not even read. It should be considered a + documentation for parameters used during pattern generation. +
    • +
    • <classes> contains whitespace-separated character sets. The members + of each set should be treated as equivalent for purposes of hyphenation, + usually upper and lower case of the same character. The first character + of the set is the canonical character, the patterns and exceptions + should only contain these canonical representation characters (except + digits for weight, the period (.) as word delimiter in the patterns and + the hyphen char in exceptions, of course).
    • +
    • <exceptions> contains whitespace-separated words, each of which + has either explicit hyphen characters to denote acceptable breakage + points, or no hyphen characters, to indicate that this word should + never be hyphenated, or contain explicit <hyp> elements for specifying + changes of spelling due to hyphenation (like backen -> bak-ken or + Stoffarbe -> Stoff-farbe in the old german spelling). Exceptions override + the patterns described below. Explicit <hyp> declarations don't work + yet (patches welcome). Exceptions are generally a bit brittle, test + carefully.
    • +
    • <patterns> includes whitespace-separated patterns, which are what + drive most hyphenation decisions. The characters in these patterns are + explained as follows: +
        +
      • non-numeric characters represent characters in a sub-word to be + evaluated
      • +
      • the period character (.) represents a word boundary, i.e. either + the beginning or ending of a word
      • +
      • numeric characters represent a scoring system for indicating the + acceptability of a hyphen in this location. Odd numbers represent an + acceptable location for a hyphen, with higher values overriding lower + inhibiting values. Even numbers indicate an unacceptable location, with + higher values overriding lower values indicating an acceptable position. + A value of zero (inhibiting) is implied when there is no number present. + Generally patterns are constructed so that valuse greater than 4 are rare. + Due to a bug currently patterns with values of 8 and greater don't + have an effect, so don't wonder.
      • +
      + Here are some examples from the English patterns file: +
        +
      • Knuth (The TeXBook, Appendix H) uses the example hach4, which indicates that it is extremely undesirable to place a hyphen after the substring "hach", for example in the word "toothach-es".
      • +
      • .leg5e indicates that "leg-e", when it occurs at the beginning of a word, is a very good place to place a hyphen, if one is needed. Words like "leg-end" and "leg-er-de-main" fit this pattern.
      • +
      + Note that the algorithm that uses this data searches for each of the word's substrings in the patterns, and chooses the highest value found for letter combination. +
    • +
    +

    If you want to convert a TeX hyphenation pattern file, you have to undo + the TeX encoding for non-ASCII text. FOP uses Unicode, and the patterns + must be proper Unicode too. You should be aware of the XML encoding issues, + preferably use a good Unicode editor.

    +

    Note that FOP does not do Unicode character normalization. If you use + combining chars for accents and other character decorations, you must + declare character classes for them, and use the same sequence of base character + and combining marks in the XSLFO source, otherwise the pattern wouldn't match. + Fortunately, Unicode provides precomposed characters for all important cases + in common languages, until now nobody run seriously into this issue. Some dead + languages and dialects, especially ancient ones, may pose a real problem + though.

    +

    If you want to generate your own patterns, an open-source utility called + patgen is available on many Unix/Linux distributions and every TeX + distribution which can be used to assist in + creating pattern files from dictionaries. Pattern creation for languages like + english or german is an art. If you can, read Frank Liang's original paper + "Word Hy-phen-a-tion by Com-pu-ter" (yes, with hyphens). It is not available + online. The original patgen.web source, included in the TeX source distributions, + contains valuable comments, unfortunately technical details obscure often the + high level issues. Another important source is + The + TeX Book, appendix H (either read the TeX source, or run it through + TeX to typeset it). Secondary articles, for example the works by Petr Sojka, + may also give some much needed insight into problems arising in automated + hyphenation.

    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/index.xml b/src/documentation/content/xdocs/0.95/index.xml new file mode 100644 index 000000000..3bc718b34 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/index.xml @@ -0,0 +1,54 @@ + + + + + +
    + Apache FOP Version 0.95 + $Revision$ +
    + +
    + Introduction +

    + The Apache FOP team is proud to present to you this production quality release. + We're still in the process of adding new features. We welcome any feedback you + might have and even more, any other form of help to get the project forward. +

    +

    + This sixth release contains many bug fix release and new features compared + to 0.94. To see what has changed since the last release, please visit the + Changes Page and the + Release Notes. +

    +
    +
    + Upgrading from an earlier version +

    + If you're upgrading to this version from an earlier version of FOP, please read the + information contained on the Upgrading page! +

    +
    +
    + Download +

    + To download this version, please visit the download page. +

    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/intermediate.xml b/src/documentation/content/xdocs/0.95/intermediate.xml new file mode 100644 index 000000000..4744185aa --- /dev/null +++ b/src/documentation/content/xdocs/0.95/intermediate.xml @@ -0,0 +1,146 @@ + + + + + +
    + Intermediate Format + $Revision$ +
    + + + Please note that the intermediate format is an advanced feature and can be ignored by most + users of Apache FOP. + +
    + Introduction +

    + The intermediate format (IF) is a proprietary XML format that represents the area tree + generated by the layout engine. The area tree is conceptually defined in the + XSL-FO specification in chapter 1.1.2. + The IF can be generated through the area tree XML Renderer (the XMLRenderer). +

    +

    + The intermediate format can be used to generate intermediate documents that are modified + before they are finally rendered to their ultimate output format. Modifications include + adjusting and changing trait values, adding or modifying area objects, inserting prefabricated + pages, overlays, imposition (n-up, rotation, scaling etc.). Multiple IF files can be combined + to a single output file. +

    +
    +
    + Usage of the Intermediate Format +

    + As already mentioned, the IF is generated by using the XMLRenderer (MIME type: + application/X-fop-areatree). So, you basically set the right MIME type for + the output format and process your FO files as if you would create a PDF file. However, there + is an important detail to consider: The various Renderers don't all use the same font sources. + To be able to create the right area tree for the ultimate output file, you need to create + the IF file using the right font setup. This is achieved by telling the XMLRenderer to mimic + another renderer. This is done by calling the XMLRenderer's mimicRenderer() method with an + instance of the ultimate target renderer as the single parameter. This has a consequence: An + IF file rendered with the Java2DRenderer may not look as expected when it was actually generated + for the PDF renderer. For renderers that use the same font setup, this restriction does not + apply (PDF and PS, for example). Generating the intermediate format file is the first step. +

    +

    + The second step is to reparse the IF file using the AreaTreeParser which is + found in the org.apache.fop.area package. The pages retrieved from the IF file are added to an + AreaTreeModel instance from where they are normally rendered using one of the available Renderer + implementations. You can find examples for the IF processing in the + examples/embedding + directory in the FOP distribution +

    +

    + The basic pattern to parse the IF format looks like this: +

    + +

    + This example simply reads an IF file and renders it to a PDF file. Please note, that in normal + FOP operation you're shielded from having to instantiate the FontInfo object yourself. This + is normally a task of the AreaTreeHandler which is not present in this scenario. The same + applies to the AreaTreeModel instance, in this case an instance of a subclass called + RenderPagesModel. RenderPagesModel is ideal in this case as it has very little overhead + processing the individual pages. An important line in the example is the call to + endDocument() on the AreaTreeModel. This lets the Renderer know that the processing + is now finished. +

    +

    + The intermediate format can also be used from the command-line + by using the "-atin" parameter for specifying the area tree XML as input file. You can also + specify a "mimic renderer" by inserting a MIME type between "-at" and the output file. +

    +
    + Concatenating Documents +

    + This initial example is obviously not very useful. It would be faster to create the PDF file + directly. As the ExampleConcat.java + example shows you can easily parse multiple IF files in a row and add the parsed pages to the + same AreaTreeModel instance which essentially concatenates all the input document to one single + output document. +

    +
    +
    + Modifying Documents +

    + One of the most important use cases for the intermediate format is obviously modifying the area + tree XML before finally rendering it to the target format. You can easily use XSLT to process + the IF file according to your needs. Please note, that we will currently not formally describe + the intermediate format. You need to have a good understanding its structure so you don't + create any non-parseable files. We may add an XML Schema and more detailed documentation at a + later time. You're invited to help us with that. +

    +
    +
    + Advanced Use +

    + The generation of the intermediate format as well as it parsing process has been designed to allow + for maximum flexibility and optimization. Please note that you can call setTransformerHandler() on + XMLRenderer to give the XMLRenderer your own TransformerHandler instance in case you would like to + do custom serialization (to a W3C DOM, for example) and/or to directly modify the area tree using + XSLT. The AreaTreeParser on the other side allows you to retrieve a ContentHandler instance where + you can manually send SAX events to to start the parsing process (see getContentHandler()). +

    +
    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/known-issues.xml b/src/documentation/content/xdocs/0.95/known-issues.xml new file mode 100644 index 000000000..568fec8d9 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/known-issues.xml @@ -0,0 +1,74 @@ + + + + + + MIF and SVG output support have not been restored, yet. + + + Auto table layout is not implemented, yet. + + + Footnotes may overlap with text of the region-body in multi-column + documents. + + + Space resolution does not work between footnote regions. + + + There's a problem involving nested block-containers and + reference-orientation 180/-180 (Bugzilla #36391) + + + block-containers with no height currently don't create a fence for + spaces as they should (they behave like a normal block). + + + Preserved linefeeds in fo:character are not handled correctly. + + + An empty block currently produces a fence for stacking constraints + which it shouldn't. + + + There are several small problems around white space handling. + + + leaders with leader-pattern="use-content" may not work as expected. + + + If two consecutive pages don't have the same available width, the + content currently isn't properly fit into the available space on + the new page. + + + background-images on page-number-citations are not placed correctly. + + + Not all FO elements can be referenced by their "id", most notably: + table-body, table-header, table-footer and table-row. + + + The backgrounds of table-body, table-header, table-footer and + table-column are not painted, yet. + + + Column balancing in multi-column documents may not work as expected + (Bugzilla #36356) + + diff --git a/src/documentation/content/xdocs/0.95/knownissues_overview.xml b/src/documentation/content/xdocs/0.95/knownissues_overview.xml new file mode 100644 index 000000000..7247e6b79 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/knownissues_overview.xml @@ -0,0 +1,70 @@ + + + + + +
    + Apache FOP: Known Issues + $Revision$ +
    + +
    + Known issues +

    + This page lists currently known issues in the current release. +

    + +

    + For additional information on known issues in Apache FOP, please have a look at the following pages, too: +

    + +
    +

    + Apache FOP has an extensive automated testing infrastructure. Parts of this infrastructure are several + sets of test cases. When a test case is listed in disabled-testcases.xml it is disabled in the JUnit + tests during the normal build process. This indicates a problem in the current codebase. When a bug is + fixed or a missing feature is added the entry for the relevant test case(s) are removed. +

    +
    + FO Tree +

    + This section lists disabled test cases in the test suite for the FO tree tests, at the time + of the release. +

    + +
    +
    + Layout Engine +

    + This section lists disabled test cases in the test suite for the layout engine tests, at the + time of the release. +

    + +
    +
    + Other known issues +

    This section lists other known issues.

    + +
    +
    + +
    + diff --git a/src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml b/src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml new file mode 100644 index 000000000..15ac8aa48 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml @@ -0,0 +1,308 @@ + + + + + + + + External link around an SVG not properly sized + basic-link_external-destination_2.xml + The bpd trait of the inlineparent area for the basic-link + is not sized correctly if it wraps an image that is higher than the + nominal line. + + + Auto-height block-containers produce fences + block-container_space-before_space-after_3.xml + Block-containers with no height currently don't + create a fence for spaces as they should (they behave like a + normal block). + + + font-stretch NYI + block_font-stretch.xml + Font-stretch is not implemented, yet. + + + Hyphenation with preserved linefeeds + block_hyphenation_linefeed_preserve.xml + When hyphenation is enabled and linefeeds are preserved, + the text is output multiple times. + + + linefeed-treatment + block_linefeed-treatment.xml + Preserved linefeeds in a fo:character are not handled + correctly. + + + white-space-treatment + block_white-space-treatment_3.xml + White space handling incorrectly stops at fo:inline + boundaries when it comes to formatter generated line breaks. + + + Empty blocks produce fences + block_space-before_space-after_8.xml + An empty block currently produces a fence for + stacking constraints which it shouldn't. + + + block white-space nbsp 2 + block_white-space_nbsp_2.xml + The nbsp given as an fo:character is not adjustable and therefore + the justification does not work in this case. + + + block word-spacing + block_word-spacing.xml + Word-spacing may not work as expected. + + + block word-spacing text-align justify + block_word-spacing_text-align_justify.xml + Word-spacing may not work as expected. + + + external-graphic don't shrink + external-graphic_oversized.xml + Images currently don't shrink so they fit on a page + when they are too big and shrinking is allowed to + happen (min/opt/max). + + + Test case with HTTP URL + external-graphic_src_uri.xml + Doesn't work behind a proxy which requires + authorization. + + + Space Resolution in foot note area + footnote_space-resolution.xml + Space resolution does not work between footnote + regions. + + + Footnotes swallowed in lists + footnote_in_list.xml + Element lists for lists are created by combining the + element lists from list-item-label and list-item-body. The + footnotes contained in the KnuthBlockBoxes are not propagated to + the combined element list. + http://issues.apache.org/bugzilla/show_bug.cgi?id=37579 + + + Footnotes swallowed in tables + footnote_in_table.xml + Element lists for tables are created by combining the + element lists from the individual table-cells. The footnotes + contained in the KnuthBlockBoxes are not propagated to the combined + element list. + http://issues.apache.org/bugzilla/show_bug.cgi?id=37579 + + + NPE for table inside an inline + inline_block_nested_3.xml + Placing a table as a child of an fo:inline produces a + NullPointerException. + + + inline-container is not implemented, yet. + inline-container_block_nested.xml + inline-container is not implemented, yet. Content of an + inline-container will get swallowed. The test case contains no checks. + + + inline-container is not implemented, yet. + inline-container_border_padding.xml + inline-container is not implemented, yet. Content of an + inline-container will get swallowed. + + + inline letter-spacing + inline_letter-spacing.xml + Letter-spacing may not work as + expected within fo:inline. + + + inline word-spacing + inline_word-spacing.xml + Word-spacing may not work as expected within + fo:inline. + + + inline word-spacing text-align justify + inline_word-spacing_text-align_justify.xml + + + + leader-alignment NYI + leader-alignment.xml + Leader-alignment is not yet + implemented. + + + leader-pattern="use-content": Problem with line height + leader_leader-pattern_use-content_bug.xml + Line height is not correctly calculated for + use-content leaders whose height is larger than the rest of the + line. + http://www.nabble.com/leaders-with-leader-pattern%3D%22use-content%22-t546244.html + + + keep-with-previous doesn't work in lists + list-block_keep-with-previous.xml + Keep-with-previous doesn't work inside tables and + lists, yet. + + + keep-with-previous doesn't work in lists + list-item_block_keep-with-previous.xml + Keep-with-previous doesn't work inside tables and + lists, yet. + + + Page breaking doesn't deal with IPD changes + page-breaking_4.xml + Page breaking currently doesn't support changing available IPD + between pages of a single page-sequence. Element list generation has to be reset to + redetermine line breaks in this case. + + + Overflow handing is incomplete + page-breaking_6.xml + Line breaking is not 100% correct when there's too little space. + Overflows are not detected and warned. + + + Indefinite page height handling is imcomplete + page-height_indefinite_simple.xml + A RuntimeException is thrown for a page of indefinite height. Lots of warnings. + + + page-number-citation: Problem with background-image + page-number-citation_background-image.xml + Background-images on page-number-citations are not + placed correctly. + + + page-number-citation-last: FOs spanning multiple pages are not properly handled. + page-number-citation-last_basic.xml + Resolution of forward references does not wait until an FO is fully finished when an FO spans multiple pages. + + + IDs are not working on all FO elements + page-number-citation_complex_1.xml + The "id" attributes are not properly handled for all block-level FO elements. + + + IDs are not working on all FO elements + page-number-citation_complex_2.xml + The "id" attributes are not properly handled for all inline-level FO elements. + + + Footnotes in multi-column documents + region-body_column-count_footnote.xml + Footnotes may overlap with text of the region-body in + multi-column documents. + + + Column Balancing problems + region-body_column-count_balance_4col.xml + Situation in a 4-column document where the column balancing doesn't work and even causes some + content to disappear. + + + Column Balancing problems + region-body_column-count_bug36356.xml + Column balancing doesn't work as expected. + + + No background-images on table-body + table-body_background-image.xml + The backgrounds of table-body, table-header, + table-footer and table-column are not painted, yet. + + + Collapsing Border Model NYI + table_border-collapse_collapse_1.xml + Border-collapse="collapse" is not yet + implemented. + + + Collapsing Border Model NYI + table_border-collapse_collapse_2.xml + Border-collapse="collapse" is not yet + implemented. + + + Problems with border and padding on tables + table_border_padding.xml + The element list seems to not be fully correct, yet, causing + the layout to look odd. + + + keep-with-previous doesn't work inside tables + table-cell_block_keep-with-previous.xml + Keep-with-previous doesn't work inside tables and + lists, yet. + + + Border and padding conditionality is NYI on table-cells + table-cell_border_padding_conditionality.xml + Border and padding conditionality are not supported + on table-cells, yet. + + + No background-images on table-header + table-header_background-image.xml + The backgrounds of table-body, table-header, + table-footer and table-column are not painted, yet. + + + keep-with-previous doesn't work on table-rows + table-row_keep-with-previous.xml + Keep-with-previous doesn't work inside tables and + lists, yet. + + + table-cell empty area with marker.xml + table-cell_empty_area_with_marker.xml + A table-cell producing an empty area does currently not add any markers to a page. + See TODO entry in AreaAdditionUtil. + + + Border conditionality on table + table_border-width_conditionality.xml + The code should be ok, but the test case uses shorthands and therefore + is probably not expressing the indended outcome according to the spec. The test + case should be revisited. + + + fo:wrapper around block-level content (with id) + wrapper_block_id.xml + "id" attributes on fo:wrapper around block-level content don't get + added to the area tree. + + + Soft hyphen with normal hyphenation enabled + block_shy_linebreaking_hyph.xml + A soft hyphen should be a preferred as break compared to a + normal hyphenation point but is not. + + diff --git a/src/documentation/content/xdocs/0.95/output.xml b/src/documentation/content/xdocs/0.95/output.xml new file mode 100644 index 000000000..d6021414f --- /dev/null +++ b/src/documentation/content/xdocs/0.95/output.xml @@ -0,0 +1,859 @@ + + + + + + +
    + Apache FOP Output Formats + $Revision$ + + + + +
    + + +

    + FOP supports multiple output formats by using a different renderer for each format. + The renderers do not all have the same set of capabilities, sometimes because of + the output format itself, sometimes because some renderers get more development + attention than others. +

    +
    + General Information +
    + Fonts +

    + Most FOP renderers use a FOP-specific system for font registration. + However, the Java2D/AWT and print renderers use the Java AWT package, which gets its + font information from the operating system registration. + This can result in several differences, including actually using different fonts, + and having different font metrics for the same font. + The net effect is that the layout of a given FO document can be quite different between + renderers that do not use the same font information. +

    +
    +
    + Output to a Printer or Other Device +

    + The most obvious way to print your document is to use the FOP + print renderer, which uses the Java2D API (AWT). + However, you can also send output from the Postscript renderer directly to a Postscript + device, or output from the PCL renderer directly to a PCL device. +

    +

    + Here are Windows command-line examples for Postscript and PCL: +

    + + +

    + Here is some Java code to accomplish the task in UNIX: +

    + +

    + Set the output MIME type to "application/x-pcl" (MimeConstants.MIME_PCL) and + it happily sends the PCL to the UNIX printer queue. +

    +
    +
    +
    + PDF +

    + PDF is the best supported output format. It is also the most accurate + with text and layout. This creates a PDF document that is streamed out + as each page is rendered. This means that the internal page index + information is stored near the end of the document. + The PDF version supported is 1.4. PDF versions are forwards/backwards + compatible. +

    +

    + Note that FOP does not currently support "tagged PDF" or PDF/A-1a. + Support for PDF/A-1b and PDF/X has recently been added, however. +

    +
    + Fonts +

    + PDF has a set of fonts that are always available to all PDF viewers; + to quote from the PDF Specification: + + "PDF prescribes a set of 14 standard fonts that can be used without prior + definition. + These include four faces each of three Latin text typefaces (Courier, + Helvetica, and Times), as well as two symbolic fonts (Symbol and ITC Zapf + Dingbats). These fonts, or suitable substitute fonts with the same metrics, are + guaranteed to be available in all PDF viewer applications." +

    +
    +
    + Post-processing +

    + FOP does not currently support several desirable PDF features: watermarks and signatures. + One workaround is to use Adobe Acrobat (the full version, not the Reader) to process + the file manually or with scripting that it supports. +

    +

    + Another popular post-processing tool is iText, + which has tools for adding security features, document properties, watermarks, and many + other features to PDF files. +

    + + Caveat: iText may swallow PDF bookmarks. But + Jens Stavnstrup tells us + that this doesn't happen if you use iText's PDFStamper. + +

    + Here is some sample code that uses iText to encrypt a FOP-generated PDF. (Note that FOP now + supports PDF encryption. However the principles for using + iText for other PDF features are similar.) +

    + +

    + Check the iText tutorial and documentation for setting access flags, password, + encryption strength and other parameters. +

    +
    +
    + Watermarks +

    + In addition to the PDF Post-processing options, consider the following workarounds: +

    +
      +
    • + Use a background image for the body region. +
    • +
    • + (submitted by Trevor Campbell) Place an image in a + region that overlaps the flowing text. For example, make + region-before large enough to contain your image. Then include a + block (if necessary, use an absolutely positioned block-container) + containing the watermark image in the static-content for the + region-before. Note that the image will be drawn on top of the + normal content. +
    • +
    +
    +
    +
    + PostScript +

    + The PostScript renderer has been brought up to a similar quality as the + PDF renderer, but may still be missing certain features. It provides good + support for most text and layout. + Images and SVG are not fully supported, yet. Currently, the PostScript + renderer generates PostScript Level 3 with most DSC comments. Actually, + the only Level 3 features used are the FlateDecode and DCTDecode + filter (the latter is used for 1:1 embedding of JPEG images), everything + else is Level 2. +

    +
    + Configuration +

    + The PostScript renderer configuration currently allows the following settings: +

    + + false + 3 + false + false + true +]]> +

    + The default value for the "auto-rotate-landscape" setting is "false". Setting it + to "true" will automatically rotate landscape pages and will mark them as landscape. +

    +

    + The default value for the "language-level" setting is "3". This setting specifies + the PostScript language level which should be used by FOP. Set this to "2" + only if you don't have a Level 3 capable interpreter. +

    +

    + The default value for the "optimize-resources" setting is "false". Setting it + to "true" will produce the PostScript file in two steps. A temporary file will be + written first which will then be processed to add only the fonts which were really + used and images are added to the stream only once as PostScript forms. This will + reduce file size but can potentially increase the memory needed in the interpreter + to process. +

    +

    + The default value for the "safe-set-page-device" setting is "false". Setting it + to "true" will cause the renderer to invoke a postscript macro which guards against + the possibility of invalid/unsupported postscript key/values being issued to the + implementing postscript page device. +

    +

    + The default value for the "dsc-compliant" setting is "true". Setting it + to "false" will break DSC compliance by minimizing the number of setpagedevice + calls in the postscript document output. This feature may be useful when unwanted + blank pages are experienced in your postscript output. This problem is caused by + the particular postscript implementation issuing unwanted postscript subsystem + initgraphics/erasepage calls on each setpagedevice call. +

    +
    +
    + Limitations +
      +
    • Images and SVG may not be displayed correctly. SVG support is far from being complete. No image transparency is available.
    • +
    • Only Type 1 fonts are supported.
    • +
    • Multibyte characters are not supported.
    • +
    • PPD support is still missing.
    • +
    +
    +
    +
    + PCL +

    + This format is for the Hewlett-Packard PCL printers and other printers + supporting PCL. It should produce output as close to identical as possible + to the printed output of the PDFRenderer within the limitations of the + renderer, and output device. +

    +

    + The output created by the PCLRenderer is generic PCL 5, HP GL/2 and PJL. + This should allow any device fully supporting PCL 5 to be able to + print the output generated by the PCLRenderer. PJL is used to control the + print job and switch to the PCL language. PCL 5 is used for text, raster + graphics and rectangular fill graphics. HP GL/2 is used for more complex + painting operations. Certain painting operations are done off-screen and + rendered to PCL as bitmaps because of limitations in PCL 5. +

    +
    + References + +
    +
    + Limitations +
      +
    • + Text or graphics outside the left or top of the printable area are not + rendered properly. This is a limitation of PCL, not FOP. In general, + things that should print to the left of the printable area are shifted + to the right so that they start at the left edge of the printable area. +
    • +
    • + The Helvetica and Times fonts are not well supported among PCL printers + so Helvetica is mapped to Arial and Times is mapped to Times New. This + is done in the PCLRenderer, no changes are required in the FO's. The + metrics and appearance for Helvetica/Arial and Times/Times New are + nearly identical, so this has not been a problem so far. +
    • +
    • For the non-symbol fonts, the ISO 8859-1 symbol set is used (PCL set "0N").
    • +
    • + All fonts available to the Java2D subsystem are usable. The texts are + painted as bitmap much like the Windows PCL drivers do. +
    • +
    • Multibyte characters are not supported.
    • +
    • + At the moment, only monochrome output is supported. PCL5c color extensions + will only be implemented on demand. Color and grayscale images are converted + to monochrome bitmaps (1-bit). Dithering only occurs if the JAI image library + is available. +
    • +
    • + Images are scaled up to the next resolution level supported by PCL (75, + 100, 150, 200, 300, 600 dpi). For color and grayscale images an even + higher PCL resolution is selected to give the dithering algorithm a chance + to improve the bitmap quality. +
    • +
    • + Currently, there's no support for clipping and image transparency, largely + because PCL 5 has certain limitations. +
    • +
    +
    +
    + Configuration +

    + The PCL renderer configuration currently allows the following settings: +

    + + quality + bitmap + false +]]> +

    + The default value for the "rendering" setting is "speed" which causes borders + to be painted as plain rectangles. In this mode, no special borders (dotted, + dashed etc.) are available. If you want support for all border modes, set the + value to "quality" as indicated above. This will cause the borders to be painted + as bitmaps. +

    +

    + The default value for the "text-rendering" setting is "auto" which paints the + base fonts using PCL fonts. Non-base fonts are painted as bitmaps through Java2D. + If the mix of painting methods results in unwelcome output, you can set this + to "bitmap" which causes all text to be rendered as bitmaps. +

    +

    + The default value for the "disable-pjl" setting is "false". This means that + the PCL renderer usually generates PJL commands before and after the document + in order to switch a printer into PCL language. PJL commands can be disabled + if you set this value to "true". +

    +

    + You can control the output resolution for the PCL using the "target resolution" + setting on the FOUserAgent. The actual value will be rounded up to the next + supported PCL resolution. Currently, only 300 and 600 dpi are supported which + should be enough for most use cases. Note that this setting directly affects + the size of the output file and the print quality. +

    +
    +
    + Extensions +

    The PCL Renderer supports some PCL specific extensions which can be embedded + into the input FO document. To use the extensions the appropriate namespace must + be declared in the fo:root element like this:

    + +]]> +
    + Page Source (Tray selection) +

    + The page-source extension attribute on fo:simple-page-master allows to + select the paper tray the sheet for a particular simple-page-master is + to be taken from. Example: +

    + + + ... + + +]]> +

    + Note: the tray number is a positive integer and the value depends on + the target printer. Not all PCL printers support the same paper trays. + Usually, + "1" is the default tray, + "2" is the manual paper feed, + "3" is the manual envelope feed, + "4" is the "lower" tray and + "7" is "auto-select". + Consult the technical reference for your printer for all available values. +

    +
    +
    +
    +
    + AFP + The AFP Renderer is a new addition (27-Apr-2006) to the sandbox and as such not yet fully tested or feature complete. +

    + The FOP AFP Renderer deals with creating documents conforming to the IBM AFP document architecture + also refered to as MO:DCA (Mixed Object Document Content Architecture). +

    +
    + References + +
    +
    + Limitations +

    This list is most likely badly incomplete.

    +
      +
    • + Clipping of text and graphics is not supported. +
    • +
    • + Only IBM outline and raster fonts and to a limited extend the original fonts built into FOP are supported. + Support for TrueType fonts may be added later. +
    • +
    +
    +
    + Configuration +
    + Fonts +

    The AFP Renderer requires special configuration particularly related to fonts. + AFP Render configuration is done through the normal FOP configuration file. The MIME type + for the AFP Renderer is application/x-afp which means the AFP Renderer section in the FOP configuration file + looks like:

    + + + ... +]]> +

    There are 3 font configuration variants supported:

    +
      +
    1. IBM Raster fonts
    2. +
    3. IBM Outline fonts
    4. +
    5. FOP built-in Base14 fonts
    6. +
    +

    A typical raster font configuration looks like:

    + + + + + + + + + + + + + + + + + + + + + + + + ]]> +

    An outline font configuration is simpler as the individual font size entries are not required. + However, the characterset definition is now required within the afp-font element.

    + + + + + + +]]> +

    Experimentation has shown that the font metrics for the FOP built-in Base14 fonts are actually + very similar to some of the IBM outline and raster fonts. In cases were the IBM font files are not + available the path attribute in the afp-font element can be replaced by a base14-font attribute + giving the name of the matching Base14 font. In this case the AFP Renderer will take the + font metrics from the built-in font.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> +
    +
    + Output Resolution +

    By default the AFP Renderer creates output with a resolution of 240 dpi. + This can be overridden by the <renderer-resolution/> configuration element. Example:

    + 240]]> +
    +
    + Images +

    By default the AFP Renderer converts all images to 8 bit grey level. + This can be overridden by the <images> configuration element. Example:

    + +]]> +

    This will put images as RGB images into the AFP output stream. The default setting is:

    + +]]> +

    Only the values "color" and "b+w" are allowed for the mode attribute. The bits-per-pixel + attribute is ignored if mode is "color". For "b+w" mode is must be 1, 4, or 8.

    +
    +
    +
    + Extensions +

    The AFP Renderer supports some AFP specific extensions which can be embedded into the input + fo document. To use the extensions the appropriate namespace must be declared in the fo:root element like this:

    + +]]> +
    + Page Overlay Extension +

    The include-page-overlay extension element allows to define on a per simple-page-master basis a page overlay resource. Example:

    + + + + ... + + +]]> +

    The mandatory name attribute must refer to an 8 character (space padded) resource name that + must be known in the AFP processing environment.

    +
    +
    + Page Segment Extension +

    The include-page-segment extension element allows to define resource substitution for fo:external-graphics elements. + Example:

    + + + + + + + +]]> +

    The include-page-segment extension element can only occur within a simple-page-master. + Multiple include-page-segment extension elements within a simple-page-master are allowed. + The mandatory name attribute must refer to an 8 character + (space padded) resource name that must be known in the AFP processing environment. + The value of the mandatory src attribute is compared against the value of the src attribute in + fo:external-graphic elements and if it is identical (string matching is used) in the generated + AFP the external graphic is replaced by a reference to the given resource. +

    +
    +
    + Tag Logical Element Extension +

    The tag-logical-element extension element allows to injects TLEs into the AFP output stream. Example:

    + + + + + + + +]]> +

    The tag-logical-element extension element can only occur within a simple-page-master. + Multiple tag-logical-element extension elements within a simple-page-master are allowed. + The name and value attributes are mandatory. +

    +
    +
    + No Operation Extension +

    The no-operation extension provides the ability to carry up to 32K of comments or any other type + of unarchitected data into the AFP output stream. Example:

    + + + + insert up to 32k of character data here! + + +]]> +

    The no-operation extension element can only occur within a simple-page-master. + Multiple no-operation extension elements within a simple-page-master are allowed. + The name attribute is mandatory. +

    +
    +
    +
    +
    + RTF +

    + JFOR, an open source XSL-FO to RTF converter has been integrated into Apache FOP. + This will create an RTF (rich text format) document that will + attempt to contain as much information from the XSL-FO document as + possible. It should be noted that is not possible (due to RTF's limitations) to map all + XSL-FO features to RTF. For complex documents, the RTF output will never reach the feature + level from PDF, for example. Thus, using RTF output is only recommended for simple documents + such as letters. +

    +

    + The RTF output follows Microsoft's RTF specifications + and produces best results on Microsoft Word. +

    + RTF output is currently unmaintained and lacks many features compared to other output + formats. Using other editable formats like Open Document Format, instead of producing XSL-FO + then RTF through FOP, might give better results. +
    +
    + XML (Area Tree XML) +

    + This is primarily for testing and verification. The XML created is simply + a representation of the internal area tree put into XML. We use that to verify + the functionality of FOP's layout engine. +

    +

    + The other use case of the Area Tree XML is as FOP's "intermediate format". More information + on that can be found on the page dedicated to the Intermediate Format. +

    +
    +
    + Java2D/AWT +

    + The Java2DRenderer provides the basic functionality for all + Java2D-based output formats (AWT viewer, direct print, PNG, TIFF). +

    +

    + The AWT viewer shows a window with the pages displayed inside a + Java graphic. It displays one page at a time. + The fonts used for the formatting and viewing depend on the fonts + available to your JRE. +

    +
    +
    + Print +

    + It is possible to directly print the document from the command line. + This is done with the same code that renders to the Java2D/AWT renderer. +

    +
    +
    + Bitmap (TIFF/PNG) +

    + It is possible to directly create bitmap images from the individual + pages generated by the layout engine. + This is done with the same code that renders to the Java2D/AWT renderer. +

    +

    + Currently, two output formats are supported: PNG and TIFF. TIFF produces + one file with multiple pages, while PNG output produces one file per + page. The quality of the bitmap depends on the target resolution setting + on the FOUserAgent. +

    +
    + Configuration +

    + The TIFF and PNG renderer configuration currently allows the following settings: +

    + + true + +]]> +

    + The default value for the "transparent-page-background" setting is "false" which + paints an opaque, white background for the whole image. If you set this to true, + no such background will be painted and you will get a transparent image if + an alpha channel is available in the output format. +

    +
    +
    + TIFF-specific Configuration +

    + In addition to the above values the TIFF renderer configuration allows some additional + settings: +

    + + true + CCITT T.6 + +]]> +

    + The default value for the "compression" setting is "PackBits" which + which is a widely supported RLE compression scheme for TIFF. The set of compression + names to be used here matches the set that the Image I/O API uses. Note that + not all compression schemes may be available during runtime. This depends on the + actual codecs being available. Here is a list of possible values: +

    +
      +
    • NONE (no compression)
    • +
    • PackBits (RLE, run-length encoding)
    • +
    • JPEG
    • +
    • Deflate
    • +
    • LZW
    • +
    • ZLib
    • +
    • CCITT T.4 (Fax Group 3)
    • +
    • CCITT T.6 (Fax Group 4)
    • +
    + + If you want to use CCITT compression, please make sure you've got a J2SE 1.4 or later and + + Java Advanced Imaging Image I/O Tools + + in your classpath. The Sun JRE doesn't come with a TIFF codec built in, so it has to be + added separately. The internal TIFF codec from XML Graphics Commons only supports PackBits, + Deflate and JPEG compression for writing. + +
    +
    +
    + TXT +

    + The text renderer produces plain ASCII text output + that attempts to match the output of the PDFRenderer as closely as + possible. This was originally developed to accommodate an archive system + that could only accept plain text files, and is primarily useful for getting + a quick-and-dirty view of the document text. The renderer is very limited, + so do not be surprised if it gives unsatisfactory results. +

    +

    + The Text renderer works with a fixed size page buffer. The size of this + buffer is controlled with the textCPI and textLPI public variables. + The textCPI is the effective horizontal characters per inch to use. + The textLPI is the vertical lines per inch to use. From these values + and the page width and height the size of the buffer is calculated. + The formatting objects to be rendered are then mapped to this grid. + Graphic elements (lines, borders, etc) are assigned a lower priority + than text, so text will overwrite any graphic element representations. +

    +

    + Because FOP lays the text onto a grid during layout, there are frequently + extra or missing spaces between characters and lines, which is generally + unsatisfactory. + Users have reported that the optimal settings to avoid such spacing problems are: +

    +
      +
    • font-family="Courier"
    • +
    • font-size="7.3pt"
    • +
    • line-height="10.5pt"
    • +
    +
    +
    + Output Formats in the Sandbox +

    + Due to the state of certain renderers we moved some of them to a "sandbox" area until + they are ready for more serious use. The renderers and FOEventHandlers in the sandbox + can be found under src/sandbox and are compiled into build/fop-sandbox.jar during the + main build. The output formats in the sandbox are marked as such below. +

    +
    + MIF + The MIF handler is in the sandbox and not yet functional in FOP Trunk!!! Please help us ressurrect this feature. +

    + This format is the Maker Interchange Format which is used by + Adobe Framemaker. +

    +
    +
    + SVG + The SVG renderer is in the sandbox and may not work as expected in FOP Trunk!!! Please help us improve this feature. +

    + This format creates an SVG document that has links between the pages. + This is primarily for slides and creating svg images of pages. + Large documents will create SVG files that are far too large for + an SVG viewer to handle. Since FO documents usually have text the + SVG document will have a large number of text elements. + The font information for the text is obtained from the JVM in the + same way as for the AWT viewer. If the SVG is viewed on a + system where the fonts are different, such as another platform, + then the page may look wrong. +

    +
    +
    +
    + Wish list +

    + Apache FOP is easily extensible and allows you to add new output formats to enhance FOP's functionality. There's a number of output formats + which are on our wish list. We're looking for volunteers to help us implement them. +

    + +
    + + +
    + + diff --git a/src/documentation/content/xdocs/0.95/pdfa.xml b/src/documentation/content/xdocs/0.95/pdfa.xml new file mode 100644 index 000000000..1b3b75561 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/pdfa.xml @@ -0,0 +1,159 @@ + + + + + +
    + PDF/A (ISO 19005) + $Revision$ + + + +
    + +
    + Overview + + Support for PDF/A is available beginning with version 0.92. + +

    + PDF/A is a standard which turns PDF into an "electronic document file + format for long-term preservation". PDF/A-1 is the first part of the + standard and is documented in + ISO 19005-1:2005(E). + Work on PDF/A-2 is in progress at + AIIM. +

    +

    + Design documentation on PDF/A can be found on FOP's Wiki on the + PDFA1ConformanceNotes page. +

    +
    +
    + Implementation Status +

    + PDF/A-1b is implemented to the degree that FOP supports + the creation of the elements described in ISO 19005-1. +

    +

    + Tests have been performed against jHove and Adobe Acrobat 7.0.7 (Preflight function). + FOP does not validate completely against Apago's PDF Appraiser. Reasons unknown due to + lack of a full license to get a detailed error protocol. +

    +

    + PDF/A-1a is not implemented, yet. This is mostly because of the requirement + for tagged PDF which is not available in FOP, yet. +

    +
    +
    + Usage (command line) +

    + To activate PDF/A-1b from the command-line, specify "-pdfprofile PDF/A-1b" + as a parameter. If there is a violation of one of the validation rules for + PDF/A, an error message is presented and the processing stops. +

    +
    +
    + Usage (embedded) +

    + When FOP is embedded in another Java application you can set a special option + on the renderer options in the user agent to activate the PDF/A-1b profile. + Here's an example: +

    + +

    + If one of the validation rules of PDF/A is violated, an PDFConformanceException + (descendant of RuntimeException) is thrown. +

    +
    +
    + PDF/A in Action +

    + There are a number of things that must be looked after if you activate a PDF/A + profile. If you receive a PDFConformanceException, have a look at the following + list (not necessarily comprehensive): +

    +
      +
    • + Make sure all (!) fonts are embedded. If you use base 14 fonts (like Helvetica) + you need to obtain a license for them and embed them like any other font. +
    • +
    • + Don't use PDF encryption. PDF/A doesn't allow it. +
    • +
    • + Don't use CMYK images without an ICC color profile. PDF/A doesn't allow mixing + color spaces and FOP currently only properly supports the sRGB color space. Please + note that FOP embeds a standard sRGB ICC profile (sRGB IEC61966-2.1) as the + primary output intent for the PDF if no other output intent has been specified + in the configuration. +
    • +
    • + Don't use non-RGB colors in SVG images. Same issue as with CMYK images. +
    • +
    • + Don't use EPS graphics with fo:external-graphic. Embedding EPS graphics in PDF + is deprecated since PDF 1.4 and prohibited by PDF/A. +
    • +
    • + PDF is forced to version 1.4 if PDF/A-1 is activated. +
    • +
    • + No filter must be specified explicitely for metadata objects. Metadata must be + embedded in clear text so non-PDF-aware applications can extract the XMP metadata. +
    • +
    +
    +
    + PDF profile compatibility +

    + The PDF profiles "PDF/X-3:2003" and "PDF/A-1b" are compatible and can both be + activated at the same time. +

    +
    +
    + Interoperability +

    + There has been some confusion about the namespace for the PDF/A indicator in the XMP + metadata. At least three variants have been seen in the wild: +

    + + + + + + + + + + + + + +
    http://www.aiim.org/pdfa/ns/id.htmlobsolete, from an early draft of ISO-19005-1, used by Adobe Acrobat 7.x
    http://www.aiim.org/pdfa/ns/idobsolete, found in the original ISO 19005-1:2005 document
    http://www.aiim.org/pdfa/ns/id/correct, found in the technical corrigendum 1 of ISO 19005-1:2005
    +

    + If you get an error validating a PDF/A file in Adobe Acrobat 7.x it doesn't mean that + FOP did something wrong. It's Acrobat that is at fault. This is fixed in Adobe Acrobat 8.x + which uses the correct namespace as described in the technical corrigendum 1. +

    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/pdfencryption.xml b/src/documentation/content/xdocs/0.95/pdfencryption.xml new file mode 100644 index 000000000..c8cdbb29c --- /dev/null +++ b/src/documentation/content/xdocs/0.95/pdfencryption.xml @@ -0,0 +1,230 @@ + + + + + +
    + PDF encryption. + $Revision$ + + + + +
    + +
    + Overview +

    + FOP supports encryption of PDF output, thanks to Patrick + C. Lankswert. This feature is commonly used to prevent + unauthorized viewing, printing, editing, copying text from the + document and doing annotations. It is also possible to ask the + user for a password in order to view the contents. Note that + there already exist third party applications which can decrypt + an encrypted PDF without effort and allow the aforementioned + operations, therefore the degree of protection is limited. +

    +

    + For further information about features and restrictions regarding PDF + encryption, look at the documentation coming with Adobe Acrobat or the + technical documentation on the Adobe web site. +

    +
    +
    + Usage (command line) +

    + Encryption is enabled by supplying any of the encryption related + options. +

    +

    + An owner password is set with the -o option. This + password is actually used as encryption key. Many tools for + PDF processing ask for this password to disregard any + restriction imposed on the PDF document. +

    +

    + If no owner password has been supplied but FOP was asked to apply some + restrictions, a random password is used. In this case it is obviously + impossiible to disregard restrictions in PDF processing tools. +

    +

    + A user password, supplied with the -u option, will + cause the PDF display software to ask the reader for this password in + order to view the contents of the document. If no user password was + supplied, viewing the content is not restricted. +

    +

    + Further restrictions can be imposed by using the -noprint, + -nocopy, -noedit and + -noannotations options, which disable printing, copying + text, editing in Adobe Acrobat and making annotations, respectively. +

    +
    +
    + Usage (embedded) +

    + When FOP is embedded in another Java application you need to set an + options map on the renderer. These are the supported options: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescriptionValuesDefault
    ownerPasswordThe owner passwordString +
    userPasswordThe user passwordString +
    allowPrintAllows/disallows printing of the PDF"TRUE" or "FALSE""TRUE"
    allowCopyContentAllows/disallows copy/paste of content"TRUE" or "FALSE""TRUE"
    allowEditContentAllows/disallows editing of content"TRUE" or "FALSE""TRUE"
    allowEditAnnotationsAllows/disallows editing of annotations"TRUE" or "FALSE""TRUE"
    + + Encryption is enabled as soon as one of these options is set. + +

    + An example to enable PDF encryption in Java code: +

    + +

    + The parameters for the constructor of PDFEncryptionParams are: +

    +
      +
    1. userPassword: String, may be null
    2. +
    3. ownerPassword: String, may be null
    4. +
    5. allowPrint: true if printing is allowed
    6. +
    7. allowCopyContent: true if copying content is allowed
    8. +
    9. allowEditContent: true if editing content is allowed
    10. +
    11. allowEditAnnotations: true if editing annotations is allowed
    12. +
    +

    + Alternatively, you can set each value separately in the Map provided by + FOUserAgent.getRendererOptions() by using the following keys: +

    +
      +
    1. user-password: String
    2. +
    3. owner-password: String
    4. +
    5. noprint: Boolean or "true"/"false"
    6. +
    7. nocopy: Boolean or "true"/"false"
    8. +
    9. noedit: Boolean or "true"/"false"
    10. +
    11. noannotations: Boolean or "true"/"false"
    12. +
    +
    +
    + Environment +

    + In order to use PDF encryption, FOP has to be compiled with + cryptography support. Currently, only JCE + is supported. JCE is part of JDK 1.4. For earlier JDKs, it can + be installed separately. The build process automatically + detects JCE presence and installs PDF encryption support if + possible, otherwise a stub is compiled in. +

    +

    + Cryptography support must also be present at run time. In particular, a + provider for the RC4 cipher is needed. Unfortunately, the sample JCE + provider in Sun's JDK 1.4 does not provide RC4. If you + get a message saying +

    + "Cannot find any provider supporting RC4" +

    + then you don't have the needed infrastructure. +

    +

    + There are several commercial and a few Open Source packages which + provide RC4. A pure Java implementation is produced by The Legion of the Bouncy + Castle. Mozilla + JSS is an interface to a native implementation. +

    +
    +
    + Installing a crypto provider +

    + The pure Java implementation from Bouncy Castle is easy to + install. +

    +
      +
    1. + Download the binary distribution for your JDK version. If you have JDK + 1.3 or earlier you must also download a JCE from the same page. +
    2. +
    3. + Unpack the distribution. Add the jar file to your classpath. A + convenient way to use the jar on Linux is to simply drop it into the + FOP lib directory, it will be automatically picked up by + fop.sh. If you have JDK 1.3 or earlier don't forget to + install the JCE as well. +
    4. +
    5. + Open the java.security file and add
      + security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider,
      + preferably at the end of the block defining the other crypto + providers. For JDK 1.4 this is detailed on Sun's web site. +
    6. +
    +

    + If you have any experience with Mozilla JSS or any other + cryptography provider, please post it to the fop-user list. +

    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/pdfx.xml b/src/documentation/content/xdocs/0.95/pdfx.xml new file mode 100644 index 000000000..cf796c74d --- /dev/null +++ b/src/documentation/content/xdocs/0.95/pdfx.xml @@ -0,0 +1,136 @@ + + + + + +
    + PDF/X (ISO 15930) + $Revision$ + + + +
    + +
    + Overview + + Support for PDF/X is available beginning with version 0.93. This feature is new and + may not be 100% complete, yet. Feedback is welcome. + +

    + PDF/X is a standard which faciliates prepress digital data exchange using PDF. + Currently, only PDF/X-3:2003 is implemented out of the many different flavours of PDF/X + profiles. PDF/X-3:2003 is documented in + ISO 15930-6:2003(E). + More info on PDF/X can be found on the + PDF/X info site. +

    +
    +
    + Implementation Status +

    + PDF/X-3:2003 is implemented to the degree that FOP supports + the creation of the elements described in ISO 15930-6. +

    +

    + An important restriction of the current implementation is that all normal + RGB colors specified in XSL-FO and SVG are left unchanged in the sRGB color + space (XSL-FO and SVG both use sRGB as their default color space). + There's no conversion to a CMYK color space. Although sRGB is a + calibrated color space, its color space has a different size than a CMYK + color space which makes the conversion a lossy conversion and can lead to + unwanted results. Although the use of the calibrated sRGB has been promoted + for years, print shops usually prefer to convert an sRGB PDF to CMYK prior + to production. Until there's full CMYK support in FOP you will have to + work closely with your print service provider to make sure you get the + intended result. +

    +

    + Tests have been performed against Adobe Acrobat 7.0.7 (Preflight function). + Note that there are bugs in Adobe Acrobat which cause false alarms if both + PDF/A-1b and PDF/X-3:2003 are activated at the same time. +

    +
    +
    + Usage (command line) +

    + To activate PDF/X-3:2003 from the command-line, specify "-pdfprofile PDF/X-3:2003" + as a parameter. If there is a violation of one of the validation rules for + PDF/X, an error message is presented and the processing stops. +

    +
    +
    + Usage (embedded) +

    + When FOP is embedded in another Java application you can set a special option + on the renderer options in the user agent to activate the PDF/A-1b profile. + Here's an example: +

    + +

    + If one of the validation rules of PDF/X is violated, an PDFConformanceException + (descendant of RuntimeException) is thrown. +

    +
    +
    + PDF/X in Action +

    + There are a number of things that must be looked after if you activate a PDF/X + profile. If you receive a PDFConformanceException, have a look at the following + list (not necessarily comprehensive): +

    +
      +
    • + Make sure all (!) fonts are embedded. If you use base 14 fonts (like Helvetica) + you need to obtain a license for them and embed them like any other font. +
    • +
    • + Don't use PDF encryption. PDF/X doesn't allow it. +
    • +
    • + Don't use CMYK images without an ICC color profile. PDF/X doesn't allow mixing + color spaces and FOP currently only properly supports the sRGB color space. However, + you will need to specify an + output device profile + (usually a CMYK profile) in the configuration. sRGB won't work here since it's a + display device profile, not an output device profile. +
    • +
    • + Don't use non-RGB colors in SVG images. Same issue as with CMYK images. +
    • +
    • + Don't use EPS graphics with fo:external-graphic. Embedding EPS graphics in PDF + is deprecated since PDF 1.4 and prohibited by PDF/X-3:2003. +
    • +
    • + PDF is forced to version 1.4 if PDF/X-3:2003 is activated. +
    • +
    +
    +
    + PDF profile compatibility +

    + The PDF profiles "PDF/X-3:2003" and "PDF/A-1b" are compatible and can both be + activated at the same time. +

    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/running.xml b/src/documentation/content/xdocs/0.95/running.xml new file mode 100644 index 000000000..38df4be82 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/running.xml @@ -0,0 +1,350 @@ + + + + + +
    + Running Apache FOP + $Revision$ +
    + + +
    + System Requirements +

    The following software must be installed:

    +
      +
    • + Java 1.4.x or later Runtime Environment. +
        +
      • + Many JREs >=1.4 contain older JAXP implementations (which often contain bugs). It's + usually a good idea to replace them with a current implementation. +
      • +
      +
    • +
    • + Apache FOP. The FOP distribution includes all libraries that you will + need to run a basic FOP installation. These can be found in the [fop-root]/lib directory. These + libraries include the following: + +
    • +
    +

    The following software is optional, depending on your needs:

    +
      +
    • + Graphics libraries. Generally, FOP contains direct support for the most important + bitmap image formats (including PNG, JPEG and GIF). See + FOP: Graphics Formats for details. +
    • +
    • + PDF encryption. See FOP: PDF Encryption for details. +
    • +
    +

    In addition, the following system requirements apply:

    +
      +
    • + If you will be using FOP to process SVG, you must do so in a graphical environment. + See FOP: Graphics (Batik) for details. +
    • +
    +
    +
    + Installation +
    + Instructions +

    + Basic FOP installation consists of first unzipping the .gz file that is the + distribution medium, then unarchiving the resulting .tar file in a + directory/folder that is convenient on your system. Please consult your operating system + documentation or Zip application software documentation for instructions specific to your + site. +

    +
    +
    + Problems +

    + Some Mac OSX users have experienced filename truncation problems using Stuffit to unzip + and unarchive their distribution media. This is a legacy of older Mac operating systems, + which had a 31-character pathname limit. Several Mac OSX users have recommended that + Mac OSX users use the shell command tar -xzf instead. +

    +
    +
    +
    + Starting FOP as a Standalone Application +
    + Using the fop script or batch file +

    + The usual and recommended practice for starting FOP from the command line is to run the + batch file fop.bat (Windows) or the shell script fop (Unix/Linux). + These scripts require that the environment variable JAVA_HOME be + set to a path pointing to the appropriate Java installation on your system. Macintosh OSX + includes a Java environment as part of its distribution. We are told by Mac OSX users that + the path to use in this case is /Library/Java/Home. Caveat: + We suspect that, as Apple releases new Java environments and as FOP upgrades the minimum + Java requirements, the two will inevitably not match on some systems. Please see + Java on Mac OSX FAQ for information as + it becomes available. +

    + + [OPTIONS] + -d debug mode + -x dump configuration settings + -q quiet mode + -c cfg.xml use additional configuration file cfg.xml + -l lang the language to use for user information + -r relaxed/less strict validation (where available) + -dpi xxx target resolution in dots per inch (dpi) where xxx is a number + -s for area tree XML, down to block areas only + -v to show FOP version being used + + -o [password] PDF file will be encrypted with option owner password + -u [password] PDF file will be encrypted with option user password + -noprint PDF file will be encrypted without printing permission + -nocopy PDF file will be encrypted without copy content permission + -noedit PDF file will be encrypted without edit content permission + -noannotations PDF file will be encrypted without edit annotation permission + -pdfprofile prof PDF file will be generated with the specified profile + (Examples for prof: PDF/A-1b or PDF/X-3:2003) + + [INPUT] + infile xsl:fo input file (the same as the next) + -fo infile xsl:fo input file + -xml infile xml input file, must be used together with -xsl + -atin infile area tree input file + -xsl stylesheet xslt stylesheet + + -param name value to use for parameter in xslt stylesheet + (repeat '-param name value' for each parameter) + + [OUTPUT] + outfile input will be rendered as PDF into outfile + -pdf outfile input will be rendered as PDF (outfile req'd) + -pdfa1b outfile input will be rendered as PDF/A-1b compliant PDF + (outfile req'd, same as "-pdf outfile -pdfprofile PDF/A-1b") + -awt input will be displayed on screen + -rtf outfile input will be rendered as RTF (outfile req'd) + -pcl outfile input will be rendered as PCL (outfile req'd) + -ps outfile input will be rendered as PostScript (outfile req'd) + -afp outfile input will be rendered as AFP (outfile req'd) + -tiff outfile input will be rendered as TIFF (outfile req'd) + -png outfile input will be rendered as PNG (outfile req'd) + -txt outfile input will be rendered as plain text (outfile req'd) + -at [mime] out representation of area tree as XML (outfile req'd) + specify optional mime output to allow AT to be converted + to final format later + -print input file will be rendered and sent to the printer + see options with "-print help" + -out mime outfile input will be rendered using the given MIME type + (outfile req'd) Example: "-out application/pdf D:\out.pdf" + (Tip: "-out list" prints the list of supported MIME types) + -mif outfile input will be rendered as MIF (FrameMaker) (outfile req'd) + Experimental feature - requires additional fop-sandbox.jar. + -svg outfile input will be rendered as an SVG slides file (outfile req'd) + Experimental feature - requires additional fop-sandbox.jar. + + -foout outfile input will only be XSL transformed. The intermediate + XSL-FO file is saved and no rendering is performed. + (Only available if you use -xml and -xsl parameters) + + + [Examples] + Fop foo.fo foo.pdf + Fop -fo foo.fo -pdf foo.pdf (does the same as the previous line) + Fop -xml foo.xml -xsl foo.xsl -pdf foo.pdf + Fop -xml foo.xml -xsl foo.xsl -foout foo.fo + Fop foo.fo -mif foo.mif + Fop foo.fo -rtf foo.rtf + Fop foo.fo -print or Fop -print foo.fo + Fop foo.fo -awt]]> +

    + PDF encryption is only available if FOP was compiled with encryption support + and if compatible encryption support is available at run time. + Currently, only the JCE is supported. Check the Details. +

    +
    +
    + Writing your own script +

    FOP's entry point for your own scripts is the class +org.apache.fop.cli.Main. The general pattern for the + command line is: java -classpath <CLASSPATH> + org.apache.fop.cli.Main <arguments>. The arguments + consist of the options and infile and outfile specifications + as shown above for the standard scripts. You may wish to review + the standard scripts to make sure that + you get your environment properly configured. +

    +
    +
    + Running with java's <code>-jar</code> option +

    + As an alternative to the start scripts you can run java + -jar path/to/build/fop.jar <arguments>, relying on + FOP to build the classpath for running FOP dynamically, see below. If you use hyphenation, + you must put fop-hyph.jar in the lib + directory. +

    + +

    You can also run java -jar path/to/fop.jar + <arguments>, relying on the Class-Path + entry in the manifest file. This works if you put + fop.jar and all jar files from the lib + directory in a single directory. If you use hyphenation, you + must also put fop-hyph.jar in that directory.

    + +

    In both cases the arguments consist of the options and + infile and outfile specifications as shown above for the + standard scripts.

    +
    +
    + FOP's dynamical classpath construction + +

    If FOP is started without a proper classpath, it tries to + add its dependencies dynamically. If the system property + fop.home contains the name of a directory, then + FOP uses that directory as the base directory for its + search. Otherwise the current working directory is the base + directory. If the base directory is called build, + then its parent directory becomes the base directory.

    + +

    FOP expects to find fop.jar in the + build subdirectory of the base directory, and + adds it to the classpath. Subsequently FOP adds all + jar files in the lib directory to the + classpath. The lib directory is either the lib + subdirectory of the base directory, or, if that does not + exist, the base directory itself.

    + +

    If the system property fop.optional.lib + contains the name of a directory, then all jar + files in that directory are also added to the classpath. See + the methods getJARList and + checkDependencies in + org.apache.fop.cli.Main.

    + +
    +
    +
    + Using Xalan to Check XSL-FO Input +

    + FOP sessions that use -xml and -xsl input instead of -fo input are actually + controlling two distinct conversions: Tranforming XML to XSL-FO, then formatting + the XSL-FO to PDF (or another FOP output format). + Although FOP controls both of these processes, the first is included merely as + a convenience and for performance reasons. + Only the second is part of FOP's core processing. + If a user has a problem running FOP, it is important to determine which of these + two processes is causing the problem. + If the problem is in the first process, the user's stylesheet is likely the cause. + The FOP development team does not have resources to help with stylesheet issues, + although we have included links to some useful + Specifications and + Books/Articles. + If the problem is in the second process, FOP may have a bug or an unimplemented + feature that does require attention from the FOP development team. +

    + The user is always responsible to provide correct XSL-FO code to FOP. +

    + In the case of using -xml and -xsl input, although the user is responsible for + the XSL-FO code that is FOP's input, it is not visible to the user. To make the + intermediate FO file visible, the FOP distribution includes the "-foout" option + which causes FOP to run only the first (transformation) step, and write the + results to a file. (See also the Xalan command-line below) +

    + + When asking for help on the FOP mailing lists, never attach XML and + XSL to illustrate the issue. Always run the XSLT step (-foout) and send the + resulting XSL-FO file instead. Of course, be sure that the XSL-FO file is + correct before sending it. + +

    + The -foout option works the same way as if you would call the + Xalan command-line: +

    +

    + java org.apache.xalan.xslt.Process -IN xmlfile -XSL file -OUT outfile +

    +

    + Note that there are some subtle differences between the FOP and Xalan command-lines. +

    +
    +
    + Memory Usage +

    + FOP can consume quite a bit of memory, even though this has been continually improved. + This is partly inherent to the formatting process and partly caused by implementation choices. + All FO processors currently on the market have memory problems with certain layouts. +

    +

    + If you are running out of memory when using FOP, here are some ideas that may help: +

    +
      +
    • + Increase memory available to the JVM. See + the -Xmx option + for more information. + + It is usually unwise to increase the memory allocated to the JVM beyond the amount of + physical RAM, as this will generally cause significantly slower performance. + +
    • +
    • + Avoid forward references. + Forward references are references to some later part of a document. + Examples include page number citations which refer to pages which follow the citation, + tables of contents at the beginning of a document, and page numbering schemes that + include the total number of pages in the document + ("page N of TOTAL"). + Forward references cause all subsequent pages to be held in memory until the reference + can be resolved, i.e. until the page with the referenced element is encountered. + Forward references may be required by the task, but if you are getting a memory + overflow, at least consider the possibility of eliminating them. + A table of contents could be replaced by PDF bookmarks instead or moved to the end of + the document (reshuffle the paper could after printing). +
    • +
    • + Avoid large images, especially if they are scaled down. + If they need to be scaled, scale them in another application upstream from FOP. + For many image formats, memory consumption is driven mainly by the size of the image + file itself, not its dimensions (width*height), so increasing the compression rate + may help. +
    • +
    • + Use multiple page sequences. + FOP starts rendering after the end of a page sequence is encountered. + While the actual rendering is done page-by-page, some additional memory is + freed after the page sequence has been rendered. + This can be substantial if the page sequence contains lots of FO elements. +
    • +
    +
    +
    + Problems +

    If you have problems running FOP, please see the "How to get Help" page.

    +
    + +
    diff --git a/src/documentation/content/xdocs/0.95/servlets.xml b/src/documentation/content/xdocs/0.95/servlets.xml new file mode 100644 index 000000000..07c22312d --- /dev/null +++ b/src/documentation/content/xdocs/0.95/servlets.xml @@ -0,0 +1,325 @@ + + + + + +
    + Servlets + How to use Apache FOP in a Servlet + $Revision$ +
    + +
    + Overview +

    + This page discusses topic all around using Apache FOP in a servlet environment. +

    +
    +
    + Example Servlets in the FOP distribution +

    + In the directory {fop-dir}/src/java/org/apache/fop/servlet, you'll find a working example + of a FOP-enabled servlet. +

    +

    + The servlet is automatically built when you build Apache FOP using the supplied Ant script. After building + the servlet, drop fop.war into the webapps directory of Apache Tomcat (or any other web container). Then, you can use + URLs like the following to generate PDF files: +

    +
      +
    • http://localhost:8080/fop/fop?fo=/home/path/to/fofile.fo
    • +
    • http://localhost:8080/fop/fop?xml=/home/path/to/xmlfile.xml&xsl=/home/path/to/xslfile.xsl
    • +
    +

    +

    The source code for the servlet can be found under {fop-dir}/src/java/org/apache/fop/servlet/FopServlet.java.

    + + This example servlet should not be used on a public web server connected to the Internet as it does not contain + any measures to prevent Denial-of-Service-Attacks. It is provided as an example and as a starting point for + your own servlet. + +
    +
    + Create your own Servlet + + This section assumes you are familiar with embedding FOP. + +
    + A minimal Servlet +

    + Here is a minimal code snippet to demonstrate the basics: +

    + private FopFactory fopFactory = FopFactory.newInstance(); +private TransformerFactory tFactory = TransformerFactory.newInstance(); + +public void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException { + try { + response.setContentType("application/pdf"); + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, response.getOutputStream()); + Transformer transformer = tFactory.newTransformer(); + Source src = new StreamSource("foo.fo"); + Result res = new SAXResult(fop.getDefaultHandler()); + transformer.transform(src, res); + } catch (Exception ex) { + throw new ServletException(ex); + } +} + + There are numerous problems with the code snippet above. + Its purpose is only to demonstrate the basic concepts. + See below for details. + +
    +
    + Adding XSL tranformation (XSLT) +

    + A common requirement is to transform an XML source to + XSL-FO using an XSL transformation. It is recommended to use + JAXP for this task. The following snippet shows the basic + code: +

    + private FopFactory fopFactory = FopFactory.newInstance(); +private TransformerFactory tFactory = TransformerFactory.newInstance(); + +public void init() throws ServletException { + //Optionally customize the FopFactory and TransformerFactory here +} + +[..] + + //Setup a buffer to obtain the content length + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + //Setup FOP + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out); + + //Setup Transformer + Source xsltSrc = new StreamSource(new File("foo-xml2fo.xsl")); + Transformer transformer = tFactory.newTransformer(xsltSrc); + + //Make sure the XSL transformation's result is piped through to FOP + Result res = new SAXResult(fop.getDefaultHandler()); + + //Setup input + Source src = new StreamSource(new File("foo.xml")); + + //Start the transformation and rendering process + transformer.transform(src, res); + + //Prepare response + response.setContentType("application/pdf"); + response.setContentLength(out.size()); + + //Send content to Browser + response.getOutputStream().write(out.toByteArray()); + response.getOutputStream().flush(); + + Buffering the generated PDF in a ByteArrayOutputStream is done to avoid potential + problems with the Acrobat Reader Plug-in in Microsoft Internet Explorer. + +

    + The Source instance used above is simply an + example. If you have to read the XML from a string, supply + a new StreamSource(new + StringReader(xmlstring)). Constructing and reparsing + an XML string is generally less desirable than using a + SAXSource if you generate your XML. You can alternatively + supply a DOMSource as well. You may also use dynamically + generated XSL if you like. +

    +

    + Because you have an explicit Transformer object, you can also use it to + explicitely set parameters for the transformation run. +

    +
    +
    + Custom configuration +

    + You can easily set up your own FOUserAgent as demonstrated on the Embedding page. +

    +
    +
    + Improving performance +

    + There are several options to consider: +

    +
      +
    • + Instead of java.io.ByteArrayOutputStream consider using the ByteArrayOutputStream + implementation from the Jakarta Commons IO project which allocates less memory. + The full class name is: org.apache.commons.io.output.ByteArrayOutputStream +
    • +
    • + In certain cases it can help to write the generated PDF to a temporary file so + you can quickly reuse the file. This is especially useful, if Internet Explorer + calls the servlet multiple times with the same request or if you often generate + equal PDFs. +
    • +
    +

    + Of course, the + performance hints from the Embedding page + apply here, too. +

    +
    +
    + Accessing resources in your web application +

    + Often, you will want to use resources (stylesheets, images etc.) which are bundled with + your web application. FOP provides a URIResolver implementation that lets you access + files via the Servlet's ServletContext. The class is called + org.apache.fop.servlet.ServletContextURIResolver. +

    +

    + Here's how to set it up in your servlet. Instantiate a new instance in the servlet's + init() method: +

    + +

    + The ServletContextURIResolver reacts on URIs beginning with "servlet-context:". If you + want to access an image in a subdirectory of your web application, you could, for + example, use: "servlet-context:/images/myimage.png". Don't forget the leading slash + after the colon! +

    +

    + Further down, you can use the URIResolver for various things: +

    +
      +
    • + With the Transformer (JAXP/XSLT) so things like document() functions can resolver + "servlet-context:" URIs. +
    • +
    • + With the FopFactory so every resource FOP loads can be loaded using a "servlet-context:" + URI. +
    • +
    • + You can the ServletContextURIResolver yourself in your servlet code to access + stylesheets or XML files bundled with your web application. +
    • +
    +

    + Here are some example snippets: +

    + +
    +
    +
    + Notes on Microsoft Internet Explorer +

    + Some versions of Internet Explorer will not automatically show the PDF or call the servlet multiple times. + These are well-known limitations of Internet Explorer and are not a problem of the servlet. + However, Internet Explorer can still be used to download the PDF so that it can be viewed later. + Here are some suggestions in this context: +

    +
      +
    • + Use an URL ending in .pdf, like + http://myserver/servlet/stuff.pdf. Yes, the servlet can + be configured to handle this. If the URL has to contain parameters, + try to have both the base URL as well as the last parameter end in + .pdf, if necessary append a dummy parameter, like + http://myserver/servlet/stuff.pdf?par1=a&par2=b&d=.pdf. The + effect may depend on IEx version. +
    • +
    • + Give IEx the opportunity to cache. In particular, ensure the + server does not set any headers causing IEx not to cache the + content. This may be a real problem if the document is sent + over HTTPS, because most IEx installations will by default + not cache any content retrieved over HTTPS. + Setting the Expires header entry may help in + this case:
      response.setDateHeader("Expires", + System.currentTimeMillis() + cacheExpiringDuration * + 1000);
      Consult your server manual and the + relevant RFCs for further details on HTTP headers and + caching. +
    • +
    • + Cache in the server. It may help to include a parameter in + the URL which has a timestamp as the value min order to + decide whether a request is repeated. IEx is reported to + retrieve a document up to three times, but never more often. +
    • +
    +
    +
    + Servlet Engines +

    + When using a servlet engine, there are potential CLASSPATH issues, and potential conflicts + with existing XML/XSLT libraries. Servlet containers also often use their own classloaders + for loading webapps, which can cause bugs and security problems. +

    +
    + Tomcat +

    + Check Tomcat's documentation for detailed instructions about installing FOP and Cocoon. + There are known bugs that must be addressed, particularly for Tomcat 4.0.3. +

    +
    +
    + WebSphere 3.5 +

    + Put a copy of a working parser in some directory where WebSphere can access it. + For example, if /usr/webapps/yourapp/servlets is the CLASSPATH for your servlets, + copy the Xerces jar into it (any other directory would also be fine). + Do not add the jar to the servlet CLASSPATH, but add it to the CLASSPATH of the + application server which contains your web application. + In the WebSphere administration console, click on the "environment" button in the + "general" tab. In the "variable name" box, enter "CLASSPATH". + In the "value" box, enter the correct path to the parser jar file + (/usr/webapps/yourapp/servlets/Xerces.jar in our example here). + Press "OK", then apply the change and restart the application server. +

    +
    +
    +
    + Handling complex use cases +

    + Sometimes the requirements for a servlet get quite sophisticated: SQL data sources, + multiple XSL transformations, merging of several datasources etc. In such a case + consider using Apache Cocoon instead + of a custom servlet to accomplish your goal. +

    +
    + +
    \ No newline at end of file diff --git a/src/documentation/content/xdocs/0.95/upgrading.xml b/src/documentation/content/xdocs/0.95/upgrading.xml new file mode 100644 index 000000000..77925fbf8 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/upgrading.xml @@ -0,0 +1,126 @@ + + + + + +
    + Upgrading from an Earlier Version of Apache FOP + $Revision$ +
    + +
    + Important! +

    + If you're planning to upgrade to the latest FOP version there are a few very important things + to consider: +

    +
      +
    • + More than half of the codebase has been rewritten over the + last four years. With version 0.93 the code has reached + production level, and continues to improve with + version 0.94 and 0.95. +
    • +
    • + The API of FOP has changed considerably and is not + backwards-compatible with versions 0.20.5 and + 0.91beta. Version 0.92 introduced the new stable + API. +
    • +
    • + Since version 0.92 some deprecated methods which were part + of the old API have been removed. If you upgrade from 0.91 + beta, you will need to adjust your Java code. Similarly if + you upgrade from 0.92 and use deprecated methods. +
    • +
    • + If you are using a configuration file for version 0.20.5, you have to rebuild it in the new format. The format + of the configuration files has changed since version 0.20.5. See conf/fop.xconf for + an example configuration file. A XML Schema file can be found under + src/foschema/fop-configuration.xsd. +
    • +
    • + Beginning with version 0.94 you can skip the generation of + font metric files and remove the "font-metrics" attribute + in the font configuration. The font metrics files are, for + the moment, still required if you use a TrueType Collection (*.ttc) + and in that case you need to regenerate the font metrics file + if yours are from a FOP version before 0.93. +
    • +
    • +

      + The new code is much more strict about the interpretation of the XSL-FO 1.0 specification. + Things that worked fine in version 0.20.5 might start to produce warnings or even errors + now. FOP 0.20.5 contains many bugs which have been corrected in the new code. +

      + + While FOP 0.20.5 allowed you to have empty fo:table-cell elements, the new code + will complain about that (unless relaxed validation is enabled) because the specification + demands at least one block-level element ((%block;)+, see + XSL-FO 1.0, 6.7.10) + inside an fo:table-cell element. + +
    • +
    • + Extensions and Renderers written for version 0.20.5 will not work with the new code! The new FOP + extension for Barcode4J is available since + January 2007. +
    • +
    • + The SVG Renderer and the MIF Handler have not been resurrected, yet! They are currently non-functional + and hope for someone to step up and reimplement them. +
    • +
    +
    +
    + What you need to know when you upgrade! +

    + When you use your existing FO files or XML/XSL files which work fine with FOP version + 0.20.5 against this FOP version some things may not work as expected. The following + list will hopefully help you to identify and correct those problems. This does not mean + that the new FOP is at fault. Quite the opposite actually! See below: +

    +
      +
    • + Check the Compliance page for the feature causing + trouble. It may contain the necessary information to understand and resolve the problem. +
    • +
    • + As stated above empty table cells <fo:table-cell></fo:table-cell> + are not allowed by the specification. The same applies to empty static-content + and block-container elements, for example. +
    • +
    • + 0.20.5 is not XSL-FO compliant with respect to sizing images (external-graphic) + or instream-foreign-object + objects. If images or SVGs are sized differently in your outputs with the new FOP version + check Bug 37136 + as it contains some hints on what to do. The file + + "examples/fo/basic/images.fo" has + a number of good examples that show the new, more correct behaviour. +
    • +
    • + The fox:outline extension is not implemented in this version anymore. + It has been superseded by the new bookmark elements from XSL-FO 1.1. So please + update your stylesheets accordingly. +
    • +
    +
    + +
    diff --git a/src/documentation/content/xdocs/site.xml b/src/documentation/content/xdocs/site.xml index 8a30d0078..70bc57a9e 100644 --- a/src/documentation/content/xdocs/site.xml +++ b/src/documentation/content/xdocs/site.xml @@ -15,6 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> + + @@ -80,7 +80,7 @@ - + @@ -88,13 +88,13 @@ - + - + diff --git a/src/documentation/skinconf.xml b/src/documentation/skinconf.xml index 65a271a64..1eff8ace8 100644 --- a/src/documentation/skinconf.xml +++ b/src/documentation/skinconf.xml @@ -311,8 +311,8 @@ which will be used to configure the chosen Forrest skin. portrait). Supported text alignments are left, right, justify (default left). --> - - + + 1 - 1in - 1in + 0.5in + 0.5in 1in - 1in + 0.5in + - TXT - yes (used for layout but not for output) + AFP no - yes (used for layout but not for output) no + yes + yes - AWT + Java2D/AWT/Bitmap if available from OS yes yes @@ -95,19 +90,26 @@ n/a + TXT + yes (used for layout but not for output) + no + yes (used for layout but not for output) + no + + + XML yes @@ -120,8 +122,8 @@
    Base-14 Fonts

    - The Adobe PDF Specification specifies a set of 14 fonts that must be - available to every PDF reader: + The Adobe PostScript and PDF Specification specify a set of 14 fonts that must be + available to every PostScript interpreter and PDF reader: Helvetica (normal, bold, italic, bold italic), Times (normal, bold, italic, bold italic), Courier (normal, bold, italic, bold italic), @@ -147,73 +149,140 @@

    - AWT/Operating System Fonts -

    The AWT family of renderers (AWT, Print, SVG), use the Java AWT libraries for font metric information. Through operating system registration, the AWT libraries know what fonts are available on the system, and the font metrics for each one.

    + Java2D/AWT/Operating System Fonts +

    + The Java2D family of renderers (Java2D, AWT, Print, TIFF, PNG), use the + Java AWT subsystem for font metric information. Through operating system + registration, the AWT subsystem knows what fonts are available on the system, + and the font metrics for each one. +

    +

    + When working with one of these output formats and you're missing a font, just + install it in your operating system and they should be available for these + renderers. Please note that this is not true for other output formats such as + PDF or PostScript. +

    +
    Custom Fonts -

    Support for custom fonts is added by creating font metric files (written in XML) from the actual font files, and registering them with FOP. Currently only Type 1 and TrueType fonts can be added. -More information about fonts can be found at:

    +

    + Support for custom fonts is highly output format dependent (see above table). + This section shows how to add Type 1 and TrueType fonts to the PDF, PostScript and + Java2D-based renderers. Other renderers (like AFP) support other font formats. Details + in this case can be found on the page about output formats. +

    +

    + Prior to FOP version 0.94, it was always necessary to create an XML font metrics file + if you wanted to add a custom font. This unconvenient step has been removed and in + addition to that, FOP supports auto-registration of fonts, i.e. FOP can find fonts + installed in your operating system or can scan user-specified directories for fonts. + Font registration via XML font metrics file is still supported and is still necessary + if you want to use a TrueType Collection (*.ttc). Direct support for TrueType + collections may be added later. Furthermore, the XML font metrics files are still + required if you don't want to embed, but only reference a font. +

    +

    + Basic information about fonts can be found at: +

    +
    + +
    + Basic font configuration +

    + If you want FOP to use custom fonts, you need to tell it where to find them. This + is done in the configuration file and once per renderer (because each output format + is a little different). In the basic form, you can either tell FOP to find your + operating system fonts or you can specify directories that it will search for + support fonts. These fonts will then automatically be registered. +

    + + + C:\MyFonts1 + + + C:\MyFonts2 + + + +]]> + + Review the documentation for FOP Configuration + for instructions on making the FOP configuration available to FOP when it runs. + Otherwise, FOP has no way of finding your custom font information. It is currently + not possible to easily configure fonts from Java code. + +
    + +
    + Advanced font configuration +

    + The instructions found above should be sufficient for most users. Below are some + additional instructions in case the basic font configuration doesn't lead to + the desired results. +

    Type 1 Font Metrics

    FOP includes PFMReader, which reads the PFM file that normally comes with a Type 1 font, and generates an appropriate font metrics file for it. -To use it, run the class org.apache.fop.fonts.apps.PFMReader:

    + To use it, run the class org.apache.fop.fonts.apps.PFMReader:

    Windows (on JDK 1.4 and later):

    java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

    Windows (on JDK 1.3.x):

    java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar;lib\xml-apis.jar; - lib\xercesImpl.jar;lib\xalan.jar;lib\serializer.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file + lib\xercesImpl.jar;lib\xalan.jar;lib\serializer.jar + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

    Unix (on JDK 1.4 and later):

    java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

    Unix (on JDK 1.3.1):

    java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar:lib/xml-apis.jar: - lib/xercesImpl.jar:lib/xalan.jar:lib/serializer.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file + lib/xercesImpl.jar:lib/xalan.jar:lib/serializer.jar + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

    PFMReader [options]:

    • -fn <fontname> By default, FOP uses the fontname from the -.pfm file when embedding the font. Use the "-fn" option to override this name with one you have -chosen. This may be useful in some cases to ensure that applications using the output document -(Acrobat Reader for example) use the embedded font instead of a local font with the same -name.
    • + .pfm file when embedding the font. Use the "-fn" option to override this name with one you have + chosen. This may be useful in some cases to ensure that applications using the output document + (Acrobat Reader for example) use the embedded font instead of a local font with the same + name.
    The classpath in the above example has been simplified for readability. -You will have to adjust the classpath to the names of the actual JAR files in the lib directory. -xml-apis.jar, xercesImpl.jar, xalan.jar and serializer.jar are not necessary for JDK version 1.4 or later. + You will have to adjust the classpath to the names of the actual JAR files in the lib directory. + xml-apis.jar, xercesImpl.jar, xalan.jar and serializer.jar are not necessary for JDK version 1.4 or later. The tool will construct some values (FontBBox, StemV and ItalicAngle) based on assumptions and calculations which are only an approximation to the real values. -FontBBox and Italic Angle can be found in the human-readable part of the PFB file or in the AFM file. -The PFMReader tool does not yet interpret PFB or AFM files, so if you want to be correct, you may have to adjust the values in the XML file manually. -The constructed values however appear to have no visible influence. + FontBBox and Italic Angle can be found in the human-readable part of the PFB file or in the AFM file. + The PFMReader tool does not yet interpret PFB or AFM files, so if you want to be correct, you may have to adjust the values in the XML file manually. + The constructed values however appear to have no visible influence.
    TrueType Font Metrics

    FOP includes TTFReader, which reads the TTF file and generates an appropriate font metrics file for it. -Use it in a similar manner to PFMReader. -For example, to create such a metrics file in Windows from the TrueType font at c:\myfonts\cmr10.ttf:

    + Use it in a similar manner to PFMReader. + For example, to create such a metrics file in Windows from the TrueType font at c:\myfonts\cmr10.ttf:

    java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar - org.apache.fop.fonts.apps.TTFReader [options] - C:\myfonts\cmr10.ttf ttfcm.xml + org.apache.fop.fonts.apps.TTFReader [options] + C:\myfonts\cmr10.ttf ttfcm.xml

    TTFReader [options]:

    • -d <DEBUG | INFO > Sets the debug level (default is -INFO).
    • + INFO).
    • -fn <fontname> Same as for PFMReader.
    • -ttcname <fontname> If you're reading data from a -TrueType Collection (.ttc file) you must specify which font from the collection you will read -metrics from. -If you read from a .ttc file without this option, the fontnames will be listed for you.
    • + TrueType Collection (.ttc file) you must specify which font from the collection you will read + metrics from. + If you read from a .ttc file without this option, the fontnames will be listed for you.
    • -enc ansi Creates a WinAnsi-encoded font metrics file. -Without this option, a CID-keyed font metrics file is created. -The table below summarizes the differences between these two encoding options as currently -used within FOP. -Please note that this information only applies to TrueType fonts and TrueType collections:
    • + Without this option, a CID-keyed font metrics file is created. + The table below summarizes the differences between these two encoding options as currently + used within FOP. + Please note that this information only applies to TrueType fonts and TrueType collections:
    @@ -240,13 +309,13 @@ Please note that this information only applies to TrueType fonts and TrueType co
    TrueType Collections Font Metrics

    TrueType collections (.ttc files) contain more than one font. -To create metrics files for these fonts, you must specify which font in the collection should be generated, by using the "-ttcname" option with the TTFReader.

    + To create metrics files for these fonts, you must specify which font in the collection should be generated, by using the "-ttcname" option with the TTFReader.

    To get a list of the fonts in a collection, just start the TTFReader as if it were a normal TrueType file (without the -ttcname option). -It will display all of the font names and exit with an Exception.

    + It will display all of the font names and exit with an Exception.

    Here is an example of generating a metrics file for a .ttc file:

    java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar - org.apache.fop.fonts.apps.TTFReader -ttcname "MS Mincho" - msmincho.ttc msminch.xml + org.apache.fop.fonts.apps.TTFReader -ttcname "MS Mincho" + msmincho.ttc msminch.xml
    Register Fonts with FOP @@ -269,16 +338,16 @@ It will display all of the font names and exit with an Exception.

    ]]> - Review the documentation for FOP Configuration for instructions on making the FOP configuration available to FOP when it runs. Otherwise, FOP has no way of finding your custom font information.
    • URLs are used to access the font metric and font files. Relative URLs are resolved relative to the font-base property (or base) if available. See FOP: Configuration for more information.
    • +
    • The "metrics-url" attribute is generally not necessary except if you run into problems with certain fonts.
    • Either an "embed-url" or a "metrics-url" must be specified for font tag configurations.
    • -
    • The font "kerning" attribute is optional.
    • -
    • If embedding is off, the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.
    • +
    • The font "kerning" attribute is optional. Default is "true".
    • +
    • If embedding is off (i.e. embed-url is not set), the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.
    • When setting the "embed-url" attribute for Type 1 fonts, be sure to specify the PFB (actual font data), not PFM (font metrics) file that you used to generate the XML font metrics file.
    • The fonts "directory" tag can be used to register fonts contained within a single or list of directory paths. The "recursive" attribute can be specified to recursively add fonts from all sub directories.
    • The fonts "auto-detect" tag can be used to automatically register fonts that are found to be installed on the native operating system.
    • @@ -294,37 +363,38 @@ It will display all of the font names and exit with an Exception.

    Auto-Detect and auto-embedd feature -

    When the "auto-detect" flag is set in the configuration, FOP will automatically search for fonts in the default paths for your operating system.

    -

    FOP will also auto-detect fonts which are available in the classpath, if they are described as "application/x-font" in the MANIFEST.MF file. For example, if your .jar file contains font/myfont.ttf:

    - Manifest-Version: 1.0 - -Name: font/myfont.ttf -Content-Type: application/x-font -

    This feature allows you to create JAR files containing fonts. The JAR files can be added to fop by providem them in the classpath, e.g. copying them into the lib/ directory.

    +

    When the "auto-detect" flag is set in the configuration, FOP will automatically search for fonts in the default paths for your operating system.

    +

    FOP will also auto-detect fonts which are available in the classpath, if they are described as "application/x-font" in the MANIFEST.MF file. For example, if your .jar file contains font/myfont.ttf:

    + Manifest-Version: 1.0 + + Name: font/myfont.ttf + Content-Type: application/x-font +

    This feature allows you to create JAR files containing fonts. The JAR files can be added to fop by providem them in the classpath, e.g. copying them into the lib/ directory.

    Embedding The PostScript renderer does not yet support TrueType fonts, but can embed Type 1 fonts. The font is simply embedded into the PDF file, it is not converted.

    Font embedding is enabled in the userconfig.xml file and controlled by the embed-url attribute. -If you don't specify the embed-url attribute the font will not be embedded, but will only be referenced.

    + If you don't specify the embed-url attribute the font will not be embedded, but will only be referenced.

    Omitting the embed-url attribute for CID-encoded TrueType fonts will currently produce invalid PDF files! If you create the XML font metric file using the "-enc ansi" option, you can omit the embed-url attribute for TrueType fonts but you're restricted to the WinAnsi character set.

    When FOP embeds a font, it adds a prefix to the fontname to ensure that the name will not match the fontname of an installed font. -This is helpful with older versions of Acrobat Reader that preferred installed fonts over embedded fonts.

    + This is helpful with older versions of Acrobat Reader that preferred installed fonts over embedded fonts.

    When embedding PostScript fonts, the entire font is always embedded.

    When embedding TrueType fonts (ttf) or TrueType Collections (ttc), a subset of the original font, containing only the glyphs used, is embedded in the output document.

    + diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml index e12527fe3..af1de28f2 100644 --- a/src/documentation/content/xdocs/trunk/fonts.xml +++ b/src/documentation/content/xdocs/trunk/fonts.xml @@ -31,11 +31,6 @@
    Summary - The FOP Font subsystem is currently undergoing a significant change. - The details provided here especially related to the generation of FOP Font - Metrics files and the FOP Font configuration are likely to change substantially - in the future. -

    The following table summarizes the font capabilities of the various FOP renderers:

    @@ -59,22 +54,22 @@ - + - - + - + + - + @@ -95,19 +90,26 @@ + + + + + + + + @@ -120,8 +122,8 @@
    Base-14 Fonts

    - The Adobe PDF Specification specifies a set of 14 fonts that must be - available to every PDF reader: + The Adobe PostScript and PDF Specification specify a set of 14 fonts that must be + available to every PostScript interpreter and PDF reader: Helvetica (normal, bold, italic, bold italic), Times (normal, bold, italic, bold italic), Courier (normal, bold, italic, bold italic), @@ -147,73 +149,140 @@

    - AWT/Operating System Fonts -

    The AWT family of renderers (AWT, Print, SVG), use the Java AWT libraries for font metric information. Through operating system registration, the AWT libraries know what fonts are available on the system, and the font metrics for each one.

    + Java2D/AWT/Operating System Fonts +

    + The Java2D family of renderers (Java2D, AWT, Print, TIFF, PNG), use the + Java AWT subsystem for font metric information. Through operating system + registration, the AWT subsystem knows what fonts are available on the system, + and the font metrics for each one. +

    +

    + When working with one of these output formats and you're missing a font, just + install it in your operating system and they should be available for these + renderers. Please note that this is not true for other output formats such as + PDF or PostScript. +

    +
    Custom Fonts -

    Support for custom fonts is added by creating font metric files (written in XML) from the actual font files, and registering them with FOP. Currently only Type 1 and TrueType fonts can be added. -More information about fonts can be found at:

    +

    + Support for custom fonts is highly output format dependent (see above table). + This section shows how to add Type 1 and TrueType fonts to the PDF, PostScript and + Java2D-based renderers. Other renderers (like AFP) support other font formats. Details + in this case can be found on the page about output formats. +

    +

    + Prior to FOP version 0.94, it was always necessary to create an XML font metrics file + if you wanted to add a custom font. This unconvenient step has been removed and in + addition to that, FOP supports auto-registration of fonts, i.e. FOP can find fonts + installed in your operating system or can scan user-specified directories for fonts. + Font registration via XML font metrics file is still supported and is still necessary + if you want to use a TrueType Collection (*.ttc). Direct support for TrueType + collections may be added later. Furthermore, the XML font metrics files are still + required if you don't want to embed, but only reference a font. +

    +

    + Basic information about fonts can be found at: +

    +
    + +
    + Basic font configuration +

    + If you want FOP to use custom fonts, you need to tell it where to find them. This + is done in the configuration file and once per renderer (because each output format + is a little different). In the basic form, you can either tell FOP to find your + operating system fonts or you can specify directories that it will search for + support fonts. These fonts will then automatically be registered. +

    + + + C:\MyFonts1 + + + C:\MyFonts2 + + + +]]> + + Review the documentation for FOP Configuration + for instructions on making the FOP configuration available to FOP when it runs. + Otherwise, FOP has no way of finding your custom font information. It is currently + not possible to easily configure fonts from Java code. + +
    + +
    + Advanced font configuration +

    + The instructions found above should be sufficient for most users. Below are some + additional instructions in case the basic font configuration doesn't lead to + the desired results. +

    Type 1 Font Metrics

    FOP includes PFMReader, which reads the PFM file that normally comes with a Type 1 font, and generates an appropriate font metrics file for it. -To use it, run the class org.apache.fop.fonts.apps.PFMReader:

    + To use it, run the class org.apache.fop.fonts.apps.PFMReader:

    Windows (on JDK 1.4 and later):

    java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

    Windows (on JDK 1.3.x):

    java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar;lib\xml-apis.jar; - lib\xercesImpl.jar;lib\xalan.jar;lib\serializer.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file + lib\xercesImpl.jar;lib\xalan.jar;lib\serializer.jar + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

    Unix (on JDK 1.4 and later):

    java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

    Unix (on JDK 1.3.1):

    java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar:lib/xml-apis.jar: - lib/xercesImpl.jar:lib/xalan.jar:lib/serializer.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file + lib/xercesImpl.jar:lib/xalan.jar:lib/serializer.jar + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

    PFMReader [options]:

    • -fn <fontname> By default, FOP uses the fontname from the -.pfm file when embedding the font. Use the "-fn" option to override this name with one you have -chosen. This may be useful in some cases to ensure that applications using the output document -(Acrobat Reader for example) use the embedded font instead of a local font with the same -name.
    • + .pfm file when embedding the font. Use the "-fn" option to override this name with one you have + chosen. This may be useful in some cases to ensure that applications using the output document + (Acrobat Reader for example) use the embedded font instead of a local font with the same + name.
    The classpath in the above example has been simplified for readability. -You will have to adjust the classpath to the names of the actual JAR files in the lib directory. -xml-apis.jar, xercesImpl.jar, xalan.jar and serializer.jar are not necessary for JDK version 1.4 or later. + You will have to adjust the classpath to the names of the actual JAR files in the lib directory. + xml-apis.jar, xercesImpl.jar, xalan.jar and serializer.jar are not necessary for JDK version 1.4 or later. The tool will construct some values (FontBBox, StemV and ItalicAngle) based on assumptions and calculations which are only an approximation to the real values. -FontBBox and Italic Angle can be found in the human-readable part of the PFB file or in the AFM file. -The PFMReader tool does not yet interpret PFB or AFM files, so if you want to be correct, you may have to adjust the values in the XML file manually. -The constructed values however appear to have no visible influence. + FontBBox and Italic Angle can be found in the human-readable part of the PFB file or in the AFM file. + The PFMReader tool does not yet interpret PFB or AFM files, so if you want to be correct, you may have to adjust the values in the XML file manually. + The constructed values however appear to have no visible influence.
    TrueType Font Metrics

    FOP includes TTFReader, which reads the TTF file and generates an appropriate font metrics file for it. -Use it in a similar manner to PFMReader. -For example, to create such a metrics file in Windows from the TrueType font at c:\myfonts\cmr10.ttf:

    + Use it in a similar manner to PFMReader. + For example, to create such a metrics file in Windows from the TrueType font at c:\myfonts\cmr10.ttf:

    java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar - org.apache.fop.fonts.apps.TTFReader [options] - C:\myfonts\cmr10.ttf ttfcm.xml + org.apache.fop.fonts.apps.TTFReader [options] + C:\myfonts\cmr10.ttf ttfcm.xml

    TTFReader [options]:

    • -d <DEBUG | INFO > Sets the debug level (default is -INFO).
    • + INFO).
    • -fn <fontname> Same as for PFMReader.
    • -ttcname <fontname> If you're reading data from a -TrueType Collection (.ttc file) you must specify which font from the collection you will read -metrics from. -If you read from a .ttc file without this option, the fontnames will be listed for you.
    • + TrueType Collection (.ttc file) you must specify which font from the collection you will read + metrics from. + If you read from a .ttc file without this option, the fontnames will be listed for you.
    • -enc ansi Creates a WinAnsi-encoded font metrics file. -Without this option, a CID-keyed font metrics file is created. -The table below summarizes the differences between these two encoding options as currently -used within FOP. -Please note that this information only applies to TrueType fonts and TrueType collections:
    • + Without this option, a CID-keyed font metrics file is created. + The table below summarizes the differences between these two encoding options as currently + used within FOP. + Please note that this information only applies to TrueType fonts and TrueType collections:
    yes yes
    TXTyes (used for layout but not for output)AFP noyes (used for layout but not for output) noyesyes
    AWTJava2D/AWT/Bitmap if available from OS yes yesn/a
    TXTyes (used for layout but not for output)noyes (used for layout but not for output)no
    XML yes
    @@ -240,13 +309,13 @@ Please note that this information only applies to TrueType fonts and TrueType co
    TrueType Collections Font Metrics

    TrueType collections (.ttc files) contain more than one font. -To create metrics files for these fonts, you must specify which font in the collection should be generated, by using the "-ttcname" option with the TTFReader.

    + To create metrics files for these fonts, you must specify which font in the collection should be generated, by using the "-ttcname" option with the TTFReader.

    To get a list of the fonts in a collection, just start the TTFReader as if it were a normal TrueType file (without the -ttcname option). -It will display all of the font names and exit with an Exception.

    + It will display all of the font names and exit with an Exception.

    Here is an example of generating a metrics file for a .ttc file:

    java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar - org.apache.fop.fonts.apps.TTFReader -ttcname "MS Mincho" - msmincho.ttc msminch.xml + org.apache.fop.fonts.apps.TTFReader -ttcname "MS Mincho" + msmincho.ttc msminch.xml
    Register Fonts with FOP @@ -269,16 +338,16 @@ It will display all of the font names and exit with an Exception.

    ]]> - Review the documentation for FOP Configuration for instructions on making the FOP configuration available to FOP when it runs. Otherwise, FOP has no way of finding your custom font information.
    • URLs are used to access the font metric and font files. Relative URLs are resolved relative to the font-base property (or base) if available. See FOP: Configuration for more information.
    • +
    • The "metrics-url" attribute is generally not necessary except if you run into problems with certain fonts.
    • Either an "embed-url" or a "metrics-url" must be specified for font tag configurations.
    • -
    • The font "kerning" attribute is optional.
    • -
    • If embedding is off, the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.
    • +
    • The font "kerning" attribute is optional. Default is "true".
    • +
    • If embedding is off (i.e. embed-url is not set), the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.
    • When setting the "embed-url" attribute for Type 1 fonts, be sure to specify the PFB (actual font data), not PFM (font metrics) file that you used to generate the XML font metrics file.
    • The fonts "directory" tag can be used to register fonts contained within a single or list of directory paths. The "recursive" attribute can be specified to recursively add fonts from all sub directories.
    • The fonts "auto-detect" tag can be used to automatically register fonts that are found to be installed on the native operating system.
    • @@ -294,37 +363,38 @@ It will display all of the font names and exit with an Exception.

    Auto-Detect and auto-embedd feature -

    When the "auto-detect" flag is set in the configuration, FOP will automatically search for fonts in the default paths for your operating system.

    -

    FOP will also auto-detect fonts which are available in the classpath, if they are described as "application/x-font" in the MANIFEST.MF file. For example, if your .jar file contains font/myfont.ttf:

    - Manifest-Version: 1.0 - -Name: font/myfont.ttf -Content-Type: application/x-font -

    This feature allows you to create JAR files containing fonts. The JAR files can be added to fop by providem them in the classpath, e.g. copying them into the lib/ directory.

    +

    When the "auto-detect" flag is set in the configuration, FOP will automatically search for fonts in the default paths for your operating system.

    +

    FOP will also auto-detect fonts which are available in the classpath, if they are described as "application/x-font" in the MANIFEST.MF file. For example, if your .jar file contains font/myfont.ttf:

    + Manifest-Version: 1.0 + + Name: font/myfont.ttf + Content-Type: application/x-font +

    This feature allows you to create JAR files containing fonts. The JAR files can be added to fop by providem them in the classpath, e.g. copying them into the lib/ directory.

    Embedding The PostScript renderer does not yet support TrueType fonts, but can embed Type 1 fonts. The font is simply embedded into the PDF file, it is not converted.

    Font embedding is enabled in the userconfig.xml file and controlled by the embed-url attribute. -If you don't specify the embed-url attribute the font will not be embedded, but will only be referenced.

    + If you don't specify the embed-url attribute the font will not be embedded, but will only be referenced.

    Omitting the embed-url attribute for CID-encoded TrueType fonts will currently produce invalid PDF files! If you create the XML font metric file using the "-enc ansi" option, you can omit the embed-url attribute for TrueType fonts but you're restricted to the WinAnsi character set.

    When FOP embeds a font, it adds a prefix to the fontname to ensure that the name will not match the fontname of an installed font. -This is helpful with older versions of Acrobat Reader that preferred installed fonts over embedded fonts.

    + This is helpful with older versions of Acrobat Reader that preferred installed fonts over embedded fonts.

    When embedding PostScript fonts, the entire font is always embedded.

    When embedding TrueType fonts (ttf) or TrueType Collections (ttc), a subset of the original font, containing only the glyphs used, is embedded in the output document.

    + -- cgit v1.2.3 From 158c55f0bed883b2ec1b0295be9975b1137f432f Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 08:37:05 +0000 Subject: Removed 0.93 and 0.94, added 0.95. There's no noticeable difference between 0.94 and 0.95 so I removed a column to regain some space. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633389 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 449 +++-------------------- 1 file changed, 50 insertions(+), 399 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 27ca74a63..6e68fac59 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -195,7 +195,7 @@ XSL-FO Conformance Level - @@ -203,14 +203,12 @@ - - + - @@ -222,7 +220,6 @@ §6.4.2 - - - - - - - - - - - - - - - - - - - - @@ -535,7 +514,6 @@ §6.5.2 - - - @@ -579,7 +556,6 @@ §6.6.2 - - - - - - - - - - - @@ -752,7 +719,6 @@ §6.7.2 - - - - - - - - - - @@ -909,7 +867,6 @@ §6.8.2 - - - - - @@ -977,7 +931,6 @@ §6.9.2 - - - - - - - @@ -1081,7 +1029,6 @@ §6.11.1 in XSL 1.1 WD - - - - @@ -1143,7 +1088,6 @@ §6.10.2 - - - - @@ -1199,7 +1141,6 @@ §6.11.2 - - - - @@ -1262,14 +1201,12 @@ - - + - @@ -1281,7 +1218,6 @@ §7.4.1 - - - @@ -1317,7 +1252,6 @@ §7.5.1 - - - - - - @@ -1407,7 +1337,6 @@ §7.6.1 - - - - - - - - - - - - - - - - - - - @@ -1699,7 +1611,6 @@ §7.7.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2389,7 +2263,6 @@ §7.8.2 - - - - - - - - - @@ -2541,7 +2407,6 @@ §7.9.1 - - - - - - - - @@ -2671,7 +2530,6 @@ §7.10.1 - - - - - - - - - @@ -2831,7 +2682,6 @@ §7.11.1 - - - @@ -2867,7 +2716,6 @@ §7.12.1 - - @@ -2887,7 +2735,6 @@ §7.13.1 - - - - - - - @@ -2999,7 +2841,6 @@ §7.14.1 - - - - - - - - - - - - - @@ -3195,7 +3025,6 @@ §7.15.1 - - - - - - + @@ -3275,7 +3100,6 @@ §7.15.6 - - - - - - - - - @@ -3428,7 +3245,6 @@ §7.16.1 - - - - - - - - - @@ -3560,7 +3369,6 @@ §7.17.1 - - - - @@ -3612,7 +3418,6 @@ §7.18.1 - - - - @@ -3664,7 +3467,6 @@ §7.19.1 - - - - - - - - @@ -3804,7 +3600,6 @@ §7.20.1 - - - - - @@ -3878,7 +3670,6 @@ §7.21.1 - - - - - - - @@ -3994,7 +3780,6 @@ §7.22.1 - - - - - - - - - - - - - - - @@ -4225,7 +3997,6 @@ §7.23.1 - - - - - @@ -4293,7 +4061,6 @@ §7.24.1 - - - - - @@ -4361,7 +4125,6 @@ §7.25.1 - - - - - - - - - - - - - - - - - - @@ -4641,7 +4388,6 @@ §7.26.1 - - - - - - - - - - - - - - - - - - - @@ -4938,7 +4667,6 @@ §7.27.1 - - - - - - - - @@ -5054,7 +4776,6 @@ §7.28.1 - - - - - - - - - - @@ -5205,7 +4918,6 @@ §7.29.1 - - - - - - - - - - - - - - - - - - - - - - - - - - + +
    Citation + Support in FOP Comments
    0.20.5 (previous) 0.93 (stable) - 0.94 (stable) 0.95 (stable) develop- ment
    + Declarations and Pagination and Layout Formatting Objects (§6.4)
    yes yes yes @@ -238,7 +235,6 @@ §6.4.3 no no no @@ -254,7 +250,6 @@ §6.4.4 no no no @@ -270,7 +265,6 @@ §6.4.5 yes yes yes @@ -286,7 +280,6 @@ §6.4.6 yes yes yes @@ -302,7 +295,6 @@ §6.4.7 yes yes yes @@ -318,7 +310,6 @@ §6.4.8 yes yes yes @@ -334,7 +325,6 @@ §6.4.9 yes yes yes @@ -350,7 +340,6 @@ §6.4.10 yes yes yes @@ -366,7 +355,6 @@ §6.4.11 yes yes yes @@ -382,7 +370,6 @@ §6.4.12 yes partial partial @@ -403,7 +390,6 @@ §6.4.13 yes yes yes @@ -419,7 +405,6 @@ §6.4.14 yes yes yes @@ -435,7 +420,6 @@ §6.4.15 yes yes yes @@ -451,7 +435,6 @@ §6.4.16 yes yes yes @@ -467,7 +450,6 @@ §6.4.17 yes yes yes @@ -483,7 +465,6 @@ §6.4.18 yes yes yes @@ -499,7 +480,6 @@ §6.4.19 yes yes yes @@ -515,7 +495,6 @@ §6.4.20 no no no @@ -523,7 +502,7 @@  
    + Block Formatting Objects (§6.5)
    yes yes yes @@ -551,7 +529,6 @@ §6.5.3 partial partial partial @@ -567,7 +544,7 @@
    + Inline Formatting Objects (§6.6)
    no no no @@ -595,7 +571,6 @@ §6.6.3 yes yes yes @@ -611,7 +586,6 @@ §6.6.4 no no no @@ -627,7 +601,6 @@ §6.6.5 yes yes yes @@ -643,7 +616,6 @@ §6.6.6 yes yes yes @@ -662,7 +634,6 @@ §6.6.7 yes yes yes @@ -678,7 +649,6 @@ §6.6.8 no no no @@ -694,7 +664,6 @@ §6.6.9 partial yes yes @@ -710,7 +679,6 @@ §6.6.10 yes yes yes @@ -726,7 +694,6 @@ §6.6.11 partial partial partial @@ -740,7 +707,7 @@
    + Table Formatting Objects (§6.7)
    no no no @@ -768,7 +734,6 @@ §6.7.3 partial partial partial @@ -789,7 +754,6 @@ §6.7.4 partial yes yes @@ -809,7 +773,6 @@ §6.7.5 no no no @@ -825,7 +788,6 @@ §6.7.6 yes yes yes @@ -841,7 +803,6 @@ §6.7.7 yes yes yes @@ -857,7 +818,6 @@ §6.7.8 yes yes yes @@ -873,7 +833,6 @@ §6.7.9 yes yes yes @@ -889,7 +848,6 @@ §6.7.10 partial yes yes @@ -897,7 +855,7 @@  
    + List Formatting Objects (§6.8)
    yes yes yes @@ -925,7 +882,6 @@ §6.8.3 yes yes yes @@ -941,7 +897,6 @@ §6.8.4 yes yes yes @@ -957,7 +912,6 @@ §6.8.5 yes yes yes @@ -965,7 +919,7 @@  
    + Link and Multi Formatting Objects (§6.9)
    yes yes yes @@ -997,7 +950,6 @@ §6.9.3 no no no @@ -1013,7 +965,6 @@ §6.9.4 no no no @@ -1029,7 +980,6 @@ §6.9.5 no no no @@ -1045,7 +995,6 @@ §6.9.6 no no no @@ -1061,7 +1010,6 @@ §6.9.7 no no no @@ -1069,7 +1017,7 @@  
    + Formatting Objects for Bookmarks (§6.11 in XSL 1.1 WD)
    no yes yes @@ -1100,7 +1047,6 @@ §6.11.2 in XSL 1.1 WD no yes yes @@ -1119,7 +1065,6 @@ §6.11.3 in XSL 1.1 WD no partial partial @@ -1131,7 +1076,7 @@
    + Out-of-line Formatting Objects (§6.10)
    no no no @@ -1159,7 +1103,6 @@ §6.10.3 yes partial partial @@ -1179,7 +1122,6 @@ §6.10.4 yes yes yes @@ -1187,7 +1129,7 @@  
    + Other Formatting Objects (§6.11)
    yes partial partial @@ -1218,7 +1159,6 @@ §6.11.3 yes yes yes @@ -1234,7 +1174,6 @@ §6.11.4 yes yes yes @@ -1254,7 +1193,7 @@ XSL-FO Conformance Level Citation + Support in FOP Comments
    0.20.5 (previous) 0.93 (stable) - 0.94 (stable) 0.95 (stable) develop- ment
    + Common Accessibility Properties (§7.4)
    na na na @@ -1297,7 +1233,6 @@ §7.4.2 na na na @@ -1305,7 +1240,7 @@  
    + Common Absolute Position Properties (§7.5)
    no yes yes @@ -1339,7 +1273,6 @@ §7.5.2 yes yes yes @@ -1355,7 +1288,6 @@ §7.5.3 yes yes yes @@ -1371,7 +1303,6 @@ §7.5.4 yes yes yes @@ -1387,7 +1318,6 @@ §7.5.5 yes yes yes @@ -1395,7 +1325,7 @@  
    + Common Aural Properties (§7.6)
    na na na @@ -1423,7 +1352,6 @@ §7.6.2 na na na @@ -1439,7 +1367,6 @@ §7.6.3 na na na @@ -1455,7 +1382,6 @@ §7.6.4 na na na @@ -1471,7 +1397,6 @@ §7.6.5 na na na @@ -1487,7 +1412,6 @@ §7.6.6 na na na @@ -1503,7 +1427,6 @@ §7.6.7 na na na @@ -1519,7 +1442,6 @@ §7.6.8 na na na @@ -1535,7 +1457,6 @@ §7.6.9 na na na @@ -1551,7 +1472,6 @@ §7.6.10 na na na @@ -1567,7 +1487,6 @@ §7.6.11 na na na @@ -1583,7 +1502,6 @@ §7.6.12 na na na @@ -1599,7 +1517,6 @@ §7.6.13 na na na @@ -1615,7 +1532,6 @@ §7.6.14 na na na @@ -1631,7 +1547,6 @@ §7.6.15 na na na @@ -1647,7 +1562,6 @@ §7.6.16 na na na @@ -1663,7 +1577,6 @@ §7.6.17 na na na @@ -1679,7 +1592,6 @@ §7.6.18 na na na @@ -1687,7 +1599,7 @@  
    + Common Border, Padding, and Background Properties (§7.7)
    no no no @@ -1715,7 +1626,6 @@ §7.7.2 yes partial partial @@ -1735,7 +1645,6 @@ §7.7.3 yes partial partial @@ -1755,7 +1664,6 @@ §7.7.4 no yes yes @@ -1771,7 +1679,6 @@ §7.7.5 no yes yes @@ -1787,7 +1694,6 @@ §7.7.6 no yes yes @@ -1803,7 +1709,6 @@ §7.7.7 yes yes yes @@ -1819,7 +1724,6 @@ §7.7.8 partial yes yes @@ -1839,7 +1743,6 @@ §7.7.9 yes yes yes @@ -1855,7 +1758,6 @@ §7.7.10 yes yes yes @@ -1871,7 +1773,6 @@ §7.7.11 partial yes yes @@ -1891,7 +1792,6 @@ §7.7.12 yes yes yes @@ -1907,7 +1807,6 @@ §7.7.13 yes yes yes @@ -1923,7 +1822,6 @@ §7.7.14 partial yes yes @@ -1943,7 +1841,6 @@ §7.7.15 yes yes yes @@ -1959,7 +1856,6 @@ §7.7.16 yes yes yes @@ -1975,7 +1871,6 @@ §7.7.17 partial yes yes @@ -1995,7 +1890,6 @@ §7.7.18 yes yes yes @@ -2011,7 +1905,6 @@ §7.7.19 yes yes yes @@ -2027,7 +1920,6 @@ §7.7.20 partial yes yes @@ -2047,7 +1939,6 @@ §7.7.21 yes yes yes @@ -2063,7 +1954,6 @@ §7.7.22 yes yes yes @@ -2079,7 +1969,6 @@ §7.7.23 partial yes yes @@ -2099,7 +1988,6 @@ §7.7.24 yes yes yes @@ -2115,7 +2003,6 @@ §7.7.25 yes yes yes @@ -2131,7 +2018,6 @@ §7.7.26 partial yes yes @@ -2151,7 +2037,6 @@ §7.7.27 yes yes yes @@ -2167,7 +2052,6 @@ §7.7.28 yes yes yes @@ -2183,7 +2067,6 @@ §7.7.29 partial yes yes @@ -2203,7 +2086,6 @@ §7.7.30 yes yes yes @@ -2219,7 +2101,6 @@ §7.7.31 partial yes yes @@ -2245,7 +2126,6 @@ §7.7.32 partial yes yes @@ -2265,7 +2145,6 @@ §7.7.33 partial yes yes @@ -2285,7 +2164,6 @@ §7.7.34 partial yes yes @@ -2305,7 +2183,6 @@ §7.7.35 partial yes yes @@ -2325,7 +2202,6 @@ §7.7.36 partial yes yes @@ -2345,7 +2221,6 @@ §7.7.37 partial yes yes @@ -2365,7 +2240,6 @@ §7.7.38 partial yes yes @@ -2377,7 +2251,7 @@
    + Common Font Properties (§7.8)
    partial partial partial @@ -2411,7 +2284,6 @@ §7.8.3 no no no @@ -2427,7 +2299,6 @@ §7.8.4 partial yes yes @@ -2447,7 +2318,6 @@ §7.8.5 no no no @@ -2463,7 +2333,6 @@ §7.8.6 no no no @@ -2479,7 +2348,6 @@ §7.8.7 partial yes yes @@ -2499,7 +2367,6 @@ §7.8.8 yes no no @@ -2515,7 +2382,6 @@ §7.8.9 partial partial partial @@ -2529,7 +2395,7 @@
    + Common Hyphenation Properties (§7.9)
    yes yes yes @@ -2564,7 +2429,6 @@ §7.9.2 yes yes yes @@ -2587,7 +2451,6 @@ §7.9.3 no no no @@ -2603,7 +2466,6 @@ §7.9.4 yes yes yes @@ -2619,7 +2481,6 @@ §7.9.5 yes yes yes @@ -2635,7 +2496,6 @@ §7.9.6 yes yes yes @@ -2651,7 +2511,6 @@ §7.9.7 yes yes yes @@ -2659,7 +2518,7 @@  
    + Common Margin Properties - Block (§7.10)
    partial yes yes @@ -2691,7 +2549,6 @@ §7.10.2 partial yes yes @@ -2711,7 +2568,6 @@ §7.10.3 partial yes yes @@ -2731,7 +2587,6 @@ §7.10.4 partial yes yes @@ -2751,7 +2606,6 @@ §7.10.5 partial partial partial @@ -2773,7 +2627,6 @@ §7.10.6 partial partial partial @@ -2795,7 +2648,6 @@ §7.10.7 yes yes yes @@ -2811,7 +2663,6 @@ §7.10.8 yes yes yes @@ -2819,7 +2670,7 @@  
    + Common Margin Properties - Inline (§7.11)
    no no no @@ -2847,7 +2697,6 @@ §7.11.2 no no no @@ -2855,7 +2704,7 @@  
    + Common Relative Position Properties (§7.12)
    no no no @@ -2875,7 +2723,7 @@  
    + Area Alignment Properties (§7.13)
    no yes yes @@ -2903,7 +2750,6 @@ §7.13.2 no yes yes @@ -2919,7 +2765,6 @@ §7.13.3 partial yes yes @@ -2939,7 +2784,6 @@ §7.13.4 partial partial partial @@ -2963,7 +2807,6 @@ §7.13.5 no yes yes @@ -2979,7 +2822,6 @@ §7.13.6 no no no @@ -2987,7 +2829,7 @@  
    + Area Dimension Properties (§7.14)
    no yes yes @@ -3015,7 +2856,6 @@ §7.14.2 no yes yes @@ -3031,7 +2871,6 @@ §7.14.3 no yes yes @@ -3047,7 +2886,6 @@ §7.14.4 yes yes yes @@ -3063,7 +2901,6 @@ §7.14.5 no yes yes @@ -3079,7 +2916,6 @@ §7.14.6 no no no @@ -3095,7 +2931,6 @@ §7.14.7 no no no @@ -3111,7 +2946,6 @@ §7.14.8 no no no @@ -3127,7 +2961,6 @@ §7.14.9 no no no @@ -3143,7 +2976,6 @@ §7.14.10 no yes yes @@ -3159,7 +2991,6 @@ §7.14.11 no no no @@ -3175,7 +3006,6 @@ §7.14.12 yes yes yes @@ -3183,7 +3013,7 @@  
    + Block and Line-related Properties (§7.15)
    no no no @@ -3211,7 +3040,6 @@ §7.15.2 no yes yes @@ -3227,7 +3055,6 @@ §7.15.3 no yes yes @@ -3243,7 +3070,6 @@ §7.15.4 yes yes yes @@ -3257,13 +3083,12 @@ Extended §7.15.5 - no no no yes + yes  
    no partial partial @@ -3295,7 +3119,6 @@ §7.15.7 no yes yes @@ -3311,7 +3134,6 @@ §7.15.8 no partial partial @@ -3332,7 +3154,6 @@ §7.15.9 partial partial partial @@ -3352,7 +3173,6 @@ §7.15.10 partial partial partial @@ -3372,7 +3192,6 @@ §7.15.11 yes yes yes @@ -3388,7 +3207,6 @@ §7.15.12 yes yes yes @@ -3404,7 +3222,6 @@ §7.15.13 yes partial partial @@ -3416,7 +3233,7 @@
    + Character Properties (§7.16)
    yes yes yes @@ -3444,7 +3260,6 @@ §7.16.2 yes yes yes @@ -3460,7 +3275,6 @@ §7.16.3 no no no @@ -3476,7 +3290,6 @@ §7.16.4 yes yes yes @@ -3492,7 +3305,6 @@ §7.16.5 no no no @@ -3508,7 +3320,6 @@ §7.16.6 no yes yes @@ -3524,7 +3335,6 @@ §7.16.7 no no no @@ -3540,7 +3350,6 @@ §7.16.8 no yes yes @@ -3548,7 +3357,7 @@  
    + Color-related Properties (§7.17)
    yes yes yes @@ -3576,7 +3384,6 @@ §7.17.2 no no no @@ -3592,7 +3399,6 @@ §7.17.3 no no no @@ -3600,7 +3406,7 @@  
    + Float-related Properties (§7.18)
    no no no @@ -3628,7 +3433,6 @@ §7.18.2 no no no @@ -3644,7 +3448,6 @@ §7.18.3 no no no @@ -3652,7 +3455,7 @@  
    + Keeps and Breaks Properties (§7.19)
    yes yes yes @@ -3680,7 +3482,6 @@ §7.19.2 yes yes yes @@ -3696,7 +3497,6 @@ §7.19.3 partial partial partial @@ -3722,7 +3522,6 @@ §7.19.4 partial partial partial @@ -3746,7 +3545,6 @@ §7.19.5 partial partial partial @@ -3768,7 +3566,6 @@ §7.19.6 no yes yes @@ -3784,7 +3581,6 @@ §7.19.7 no yes yes @@ -3792,7 +3588,7 @@  
    + Layout-related Properties (§7.20)
    no no no @@ -3820,7 +3615,6 @@ §7.20.2 no yes yes @@ -3836,7 +3630,6 @@ §7.20.3 no yes yes @@ -3858,7 +3651,6 @@ §7.20.4 yes yes yes @@ -3866,7 +3658,7 @@  
    + Leader and Rule Properties (§7.21)
    partial no no @@ -3900,7 +3691,6 @@ §7.21.2 partial yes yes @@ -3922,7 +3712,6 @@ §7.21.3 yes yes yes @@ -3938,7 +3727,6 @@ §7.21.4 partial yes yes @@ -3958,7 +3746,6 @@ §7.21.5 yes yes yes @@ -3974,7 +3761,6 @@ §7.21.6 yes yes yes @@ -3982,7 +3768,7 @@  
    + Properties for Dynamic Effects Formatting Objects (§7.22)
    no no no @@ -4010,7 +3795,6 @@ §7.22.2 no no no @@ -4026,7 +3810,6 @@ §7.22.3 no no no @@ -4042,7 +3825,6 @@ §7.22.4 no no no @@ -4058,7 +3840,6 @@ §7.22.5 no no no @@ -4074,7 +3855,6 @@ §7.22.6 yes yes yes @@ -4090,7 +3870,6 @@ §7.22.7 no no no @@ -4106,7 +3885,6 @@ §7.22.8 yes yes yes @@ -4122,7 +3900,6 @@ §7.22.9 no no no @@ -4138,7 +3915,6 @@ §7.22.10 no partial partial @@ -4157,7 +3933,6 @@ §7.22.11 no no no @@ -4173,7 +3948,6 @@ §7.22.12 no no no @@ -4189,7 +3963,6 @@ §7.22.13 no no no @@ -4205,7 +3978,6 @@ §7.22.14 no no no @@ -4213,7 +3985,7 @@  
    + Properties for Markers (§7.23)
    no yes yes @@ -4241,7 +4012,6 @@ §7.23.2 no yes yes @@ -4257,7 +4027,6 @@ §7.23.3 no yes yes @@ -4273,7 +4042,6 @@ §7.23.4 no yes yes @@ -4281,7 +4049,7 @@  
    + Properties for Number to String Conversion (§7.24)
    no yes yes @@ -4309,7 +4076,6 @@ §7.24.2 no no no @@ -4325,7 +4091,6 @@ §7.24.3 no no no @@ -4341,7 +4106,6 @@ §7.24.4 no no no @@ -4349,7 +4113,7 @@  
    + Pagination and Layout Properties (§7.25)
    yes yes yes @@ -4377,7 +4140,6 @@ §7.25.2 yes yes yes @@ -4393,7 +4155,6 @@ §7.25.3 yes yes yes @@ -4409,7 +4170,6 @@ §7.25.4 yes yes yes @@ -4425,7 +4185,6 @@ §7.25.5 yes yes yes @@ -4441,7 +4200,6 @@ §7.25.6 no yes yes @@ -4457,7 +4215,6 @@ §7.25.7 yes yes yes @@ -4473,7 +4230,6 @@ §7.25.8 yes yes yes @@ -4489,7 +4245,6 @@ §7.25.9 yes yes yes @@ -4505,7 +4260,6 @@ §7.25.10 yes yes yes @@ -4521,7 +4275,6 @@ §7.25.11 no no no @@ -4537,7 +4290,6 @@ §7.25.12 yes yes yes @@ -4553,7 +4305,6 @@ §7.25.13 yes yes yes @@ -4569,7 +4320,6 @@ §7.25.14 partial yes yes @@ -4589,7 +4339,6 @@ §7.25.15 yes yes yes @@ -4605,7 +4354,6 @@ §7.25.16 no yes yes @@ -4621,7 +4369,6 @@ §7.25.17 yes yes yes @@ -4629,7 +4376,7 @@  
    + Table Properties (§7.26)
    no no no @@ -4657,7 +4403,6 @@ §7.26.2 no no no @@ -4672,7 +4417,6 @@ §7.26.3 partialno yes yes @@ -4690,7 +4434,6 @@ §7.26.4 no no no @@ -4706,7 +4449,6 @@ §7.26.5 no yes yes @@ -4722,7 +4464,6 @@ §7.26.6 no no no @@ -4738,7 +4479,6 @@ §7.26.7 no no no @@ -4754,7 +4494,6 @@ §7.26.8 no yes yes @@ -4770,7 +4509,6 @@ §7.26.9 partial yes yes @@ -4790,7 +4528,6 @@ §7.26.10 no yes yes @@ -4806,7 +4543,6 @@ §7.26.11 no yes yes @@ -4822,7 +4558,6 @@ §7.26.12 no yes yes @@ -4838,7 +4573,6 @@ §7.26.13 yes yes yes @@ -4854,7 +4588,6 @@ §7.26.14 yes yes yes @@ -4870,7 +4603,6 @@ §7.26.15 no yes yes @@ -4886,7 +4618,6 @@ §7.26.16 no no no @@ -4902,7 +4633,6 @@ §7.26.17 yes yes yes @@ -4918,7 +4648,6 @@ §7.26.18 yes yes yes @@ -4926,7 +4655,7 @@  
    + Writing-mode-related Properties (§7.27)
    no no no @@ -4954,7 +4682,6 @@ §7.27.2 no no no @@ -4970,7 +4697,6 @@ §7.27.3 no no no @@ -4986,7 +4712,6 @@ §7.27.4 no no no @@ -5002,7 +4727,6 @@ §7.27.5 no no no @@ -5018,7 +4742,6 @@ §7.27.6 no no no @@ -5034,7 +4757,6 @@ §7.27.7 no no no @@ -5042,7 +4764,7 @@  
    + Miscellaneous Properties (§7.28)
    no no no @@ -5070,7 +4791,6 @@ §7.28.2 yes partial partial @@ -5089,7 +4809,6 @@ §7.28.3 yes yes yes @@ -5105,7 +4824,6 @@ §7.28.4 yes yes yes @@ -5121,7 +4839,6 @@ §7.28.5 yes yes yes @@ -5137,7 +4854,6 @@ §7.28.6 no no no @@ -5153,7 +4869,6 @@ §7.28.7 yes yes yes @@ -5169,7 +4884,6 @@ §7.28.8 no no no @@ -5185,7 +4899,6 @@ §7.28.9 no no no @@ -5193,7 +4906,7 @@  
    + Shorthand Properties (§7.29)
    no no no @@ -5221,7 +4933,6 @@ §7.29.2 no yes yes @@ -5237,7 +4948,6 @@ §7.29.3 no yes yes @@ -5253,7 +4963,6 @@ §7.29.4 yes yes yes @@ -5269,7 +4978,6 @@ §7.29.5 partial yes yes @@ -5289,7 +4997,6 @@ §7.29.6 yes yes yes @@ -5305,7 +5012,6 @@ §7.29.7 yes yes yes @@ -5321,7 +5027,6 @@ §7.29.8 partial yes yes @@ -5341,7 +5046,6 @@ §7.29.9 no yes yes @@ -5357,7 +5061,6 @@ §7.29.10 yes yes yes @@ -5373,7 +5076,6 @@ §7.29.11 yes yes yes @@ -5389,7 +5091,6 @@ §7.29.12 na na na @@ -5405,7 +5106,6 @@ §7.29.13 no partial partial @@ -5425,7 +5125,6 @@ §7.29.14 partial yes yes @@ -5445,7 +5144,6 @@ §7.29.15 partial yes yes @@ -5471,7 +5169,6 @@ §7.29.16 no yes yes @@ -5487,7 +5184,6 @@ §7.29.17 no yes yes @@ -5503,7 +5199,6 @@ §7.29.18 no yes yes @@ -5519,7 +5214,6 @@ §7.29.19 na na na @@ -5535,7 +5229,6 @@ §7.29.20 partial yes yes @@ -5555,7 +5248,6 @@ §7.29.21 no no no @@ -5571,7 +5263,6 @@ §7.29.22 partial partial partial @@ -5593,7 +5284,6 @@ §7.29.23 no yes yes @@ -5609,12 +5299,11 @@ §7.29.24 no no - no yes [dev] Very basic parsing; no validation of the specified value. + yes [0.95] Very basic parsing; no validation of the specified value.

    XSL-FO Core Function Library Support Table (§5.10)

    @@ -5629,7 +5318,7 @@ XSL-FO Conformance Level Citation - + Support in FOP Comments @@ -5637,14 +5326,12 @@ 0.20.5 (previous) - - 0.93 (stable) - 0.94 (stable) + 0.95 (stable) develop- ment - + Number Functions (§5.10.1) @@ -5656,8 +5343,6 @@ §5.10.1 yes - - yes yes yes @@ -5672,8 +5357,6 @@ §5.10.1 yes - - yes yes yes @@ -5688,8 +5371,6 @@ §5.10.1 yes - - yes yes yes @@ -5704,8 +5385,6 @@ §5.10.1 yes - - yes yes yes @@ -5720,8 +5399,6 @@ §5.10.1 yes - - yes yes yes @@ -5736,15 +5413,13 @@ §5.10.1 yes - - yes yes yes   - + Color Functions (§5.10.2) @@ -5756,8 +5431,6 @@ §5.10.2 yes - - yes yes yes @@ -5772,8 +5445,6 @@ §5.10.2 no - - yes yes yes @@ -5788,15 +5459,13 @@ §5.10.2 no - - yes yes yes   - + Font Functions (§5.10.3) @@ -5808,15 +5477,13 @@ §5.10.3 no - - no no no   - + Property Value Functions (§5.10.4) @@ -5828,8 +5495,6 @@ §5.10.4 yes - - yes yes yes @@ -5844,8 +5509,6 @@ §5.10.4 yes - - yes yes yes @@ -5860,8 +5523,6 @@ §5.10.4 yes - - yes yes yes @@ -5876,8 +5537,6 @@ §5.10.4 yes - - yes yes yes @@ -5892,8 +5551,6 @@ §5.10.4 yes - - yes yes yes @@ -5908,8 +5565,6 @@ §5.10.4 no - - yes yes yes @@ -5924,8 +5579,6 @@ §5.10.4 yes - - yes yes yes @@ -5940,8 +5593,6 @@ §5.10.4 no - - no no no -- cgit v1.2.3 From de0383da95a77655252b0ddef6bee5a524363f60 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 08:39:12 +0000 Subject: Added ApacheCon US 2008. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633391 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/skinconf.xml | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/documentation/skinconf.xml b/src/documentation/skinconf.xml index 1eff8ace8..38b7638b0 100644 --- a/src/documentation/skinconf.xml +++ b/src/documentation/skinconf.xml @@ -375,6 +375,13 @@ which will be used to configure the chosen Forrest skin. 125 125 + + ApacheCon US 2008 + http://us.apachecon.com/ + http://apache.org/ads/ApacheCon/2008-usa-125x125.png + 125 + 125 + PDF created by Apache FOP -- cgit v1.2.3 From 820c3e17c9389299d57e72da4b5909e7d0acafca Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 09:06:03 +0000 Subject: Various updates. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633396 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/download.xml | 21 ++++++++++++++++++++- src/documentation/content/xdocs/site.xml | 2 +- src/documentation/content/xdocs/status.xml | 8 ++++---- src/documentation/content/xdocs/tabs.xml | 2 +- src/documentation/content/xdocs/team.xml | 27 ++++++++++++++++++++------- 5 files changed, 46 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/download.xml b/src/documentation/content/xdocs/download.xml index 40e42236b..6607f2ddb 100644 --- a/src/documentation/content/xdocs/download.xml +++ b/src/documentation/content/xdocs/download.xml @@ -84,7 +84,7 @@

    - + @@ -102,6 +102,25 @@ + + + + + + + + + + + diff --git a/src/documentation/content/xdocs/site.xml b/src/documentation/content/xdocs/site.xml index 70bc57a9e..79094c52d 100644 --- a/src/documentation/content/xdocs/site.xml +++ b/src/documentation/content/xdocs/site.xml @@ -96,7 +96,7 @@ - + diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index cb2c4aa0b..fa3e2e643 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -27,13 +27,13 @@
    Status -

    [last updated 9 January 2007]

    +

    [last updated 4 March 2008]

    This is the development status of Apache FOP. Development on the maintenance branch where FOP 0.20.5 came from has been halted. The code base has been largely redesigned. The new - code base has reached release 0.94. + code base has reached release 0.95.

    @@ -44,7 +44,7 @@ handle large documents.

    The redesign of the code base has largely been completed. The new code reached production quality with release 0.93. In the - course of 2007 we plan to release version 1.0.

    + course of 2008 or 2009 we hope to release version 1.0.

    If you're looking for a long-term road-map we have to disappoint you. This is Open Source and we're mostly volunteers working in their free time. What we have @@ -122,7 +122,7 @@

    - + diff --git a/src/documentation/content/xdocs/tabs.xml b/src/documentation/content/xdocs/tabs.xml index 3db01d4fa..5fe5763a9 100644 --- a/src/documentation/content/xdocs/tabs.xml +++ b/src/documentation/content/xdocs/tabs.xml @@ -22,7 +22,7 @@ - + diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index 23cb87708..e493e7f11 100644 --- a/src/documentation/content/xdocs/team.xml +++ b/src/documentation/content/xdocs/team.xml @@ -31,7 +31,6 @@ Active CommittersPlease don't write to any developer directly if you need help on using FOP. Only if you submit questions to the FOP User Mailing List will other FOP users be able to profit from answers given to your question. Another point is that a developer may have gone inactive or is on holidays in which case you may not get an answer in time.
      -
    • Finn Bock (FB)
    • Chris Bowditch (CB) is a Java/VB Programmer from England.
    • Jay Bryant (JB) is a @@ -51,10 +50,6 @@
    • Vincent Hennebert (VH), a Java developer from France; with an interest in typography, and in using Fop as a pdf renderer for book-like documents.
    • -
    • Peter Herweg (PH) is helping to - integrate the jfor project's RTF support into the upcoming FOP 1.0 version. - Born in 1978, he has been serving as an application developer for a small - industrial company in Germany since 1999.
    • Clay Leeds (CL) is a web/WAP/Palm developer from Laguna Beach, California, USA. A recent XML/XSL-FO convert, he has been nit-picking FAQs & assorted web @@ -78,7 +73,6 @@ from the TeX/LaTeX world. See his home page for some of his private projects.
    • Jörg Pietschmann (JP)
    • -
    • Oleg Tkachenko (OT)
    • Max Berger (MB) is currently a PostDoc pursuing an academic career in computer science. His main interest in FOP is to improve the DocBook to PDF tool-chain to produce high quality output, while still @@ -109,11 +103,16 @@
      Inactive Committers
        +
      • Finn Bock (FB)
      • Kelly Campbell
      • Steven Coffman
      • Bertrand Delacretaz
      • Tore Engvig
      • Stanislav Gorkhover
      • +
      • Peter Herweg (PH)
      • Fotis Jannidis
      • Karen Lease
      • Keiron Liddle
      • @@ -122,6 +121,7 @@
      • Jordan Naftolin
      • Arved Sandstrom
      • Eric Schaeffer
      • +
      • Oleg Tkachenko (OT)
      • Art Welch
      • Peter B. West
      @@ -264,7 +264,7 @@
    + + + ../../resources/images/bgimg72dpi.jpg + ../../resources/images/fop-logo-color-24bit.png + ../../../examples/fo/graphics/asf-logo.png + ../../../examples/fo/graphics/asf-logo.png +
    ../../resources/images/box1.png
    + + + + + + + + + + + + Before the table. + + + + + + Header 1.1 + Header 1.1 + Header 1.1 + Header 1.1 + Header 1.1 + + + Header 1.2 + Header 1.2 + Header 1.2 + Header 1.2 + Header 1.2 + + + + + Footer 1.1 + Footer 1.1 + + + Footer 1.2 + Footer 1.2 + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + + + + + Cell 2.2 + + + + + Cell 3.1 + Cell 3.1 + + + + + Cell 4.1 + Cell 4.1 + + + Cell 4.2 + + + + + + + Cell 5.1 + Cell 5.1 + Cell 5.1 + Cell 5.1 + Cell 5.1 Line 5 + Cell 5.1 + Cell 5.1 + Cell 5.1 + Cell 5.1 + Cell 5.1 Line 10 + Cell 5.1 + + + Cell 5.2 + Cell 5.2 + Cell 5.2 + Cell 5.2 + + + + + Cell 6.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From a50c4b9642d47a11f3fc288c2d714feeec69fd61 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 6 Mar 2008 08:21:06 +0000 Subject: Added some notes on getting the same output for PDF/PS and Java2D-based renderers. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@634187 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/0.95/output.xml | 29 ++++++++++++++++++++++++ src/documentation/content/xdocs/faq.xml | 15 ++++++++++++ src/documentation/content/xdocs/trunk/output.xml | 29 ++++++++++++++++++++++++ 3 files changed, 73 insertions(+) (limited to 'src') diff --git a/src/documentation/content/xdocs/0.95/output.xml b/src/documentation/content/xdocs/0.95/output.xml index d6021414f..628df1248 100644 --- a/src/documentation/content/xdocs/0.95/output.xml +++ b/src/documentation/content/xdocs/0.95/output.xml @@ -48,6 +48,35 @@ The net effect is that the layout of a given FO document can be quite different between renderers that do not use the same font information.

    +

    + Theoretically, there's some potential to make the output of the PDF/PS renderers match + the output of the Java2D-based renderers. If FOP used the font metrics from its own + font subsystem but still used Java2D for text painting in the Java2D-based renderers, + this could probably be achieved. However, this approach hasn't been implemented, yet. +

    +

    + With a work-around, it is possible to match the PDF/PS output in a Java2D-based + renderer pretty closely. The clue is to use the + intermediate format. The trick is to layout the + document using FOP's own font subsystem but then render the document using Java2D. + Here are the necessary steps (using the command-line): +

    +
      +
    1. + Produce an IF file: fop -fo myfile.fo -at application/pdf myfile.at.xml
      + Specifying "application/pdf" for the "-at" parameter causes FOP to use FOP's own + font subsystem (which is used by the PDF renderer). Note that no PDF file is created + in this step. +
    2. +
    3. Render to a PDF file: fop -atin myfile.at.xml -pdf myfile.pdf
    4. +
    5. Render to a Java2D-based renderer: +
        +
      • fop -atin myfile.at.xml -print
      • +
      • fop -atin myfile.at.xml -awt
      • +
      • fop -atin myfile.at.xml -tiff myfile.tiff
      • +
      +
    6. +
    Output to a Printer or Other Device diff --git a/src/documentation/content/xdocs/faq.xml b/src/documentation/content/xdocs/faq.xml index d488a1f3c..a75cd41e0 100644 --- a/src/documentation/content/xdocs/faq.xml +++ b/src/documentation/content/xdocs/faq.xml @@ -645,6 +645,21 @@ Check the following:

    + + Why is the output of Java2D/AWT-based renderers different than, for example, PDF or PS? + +

    + If you render the same document once to a PNG or TIFF and once into a PDF, the output + may not be the same, i.e. line breaks are different or lines may have different heights. + The reason for this: The Java2D-based renderers use the font subsystem of Java2D/AWT. The + PDF and PS renderers use FOP's own font subsystem which provides much better font metrics + than Java2D. These can lead to different layout decisions when the same document is + rendered with different renderers. An alternative approach to fix this problem might be + available but it hasn't been tested, yet. See also the + notes on fonts in the various output formats. +

    +
    +
    Embedding FOP. Using FOP in a servlet. diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index d6021414f..628df1248 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -48,6 +48,35 @@ The net effect is that the layout of a given FO document can be quite different between renderers that do not use the same font information.

    +

    + Theoretically, there's some potential to make the output of the PDF/PS renderers match + the output of the Java2D-based renderers. If FOP used the font metrics from its own + font subsystem but still used Java2D for text painting in the Java2D-based renderers, + this could probably be achieved. However, this approach hasn't been implemented, yet. +

    +

    + With a work-around, it is possible to match the PDF/PS output in a Java2D-based + renderer pretty closely. The clue is to use the + intermediate format. The trick is to layout the + document using FOP's own font subsystem but then render the document using Java2D. + Here are the necessary steps (using the command-line): +

    +
      +
    1. + Produce an IF file: fop -fo myfile.fo -at application/pdf myfile.at.xml
      + Specifying "application/pdf" for the "-at" parameter causes FOP to use FOP's own + font subsystem (which is used by the PDF renderer). Note that no PDF file is created + in this step. +
    2. +
    3. Render to a PDF file: fop -atin myfile.at.xml -pdf myfile.pdf
    4. +
    5. Render to a Java2D-based renderer: +
        +
      • fop -atin myfile.at.xml -print
      • +
      • fop -atin myfile.at.xml -awt
      • +
      • fop -atin myfile.at.xml -tiff myfile.tiff
      • +
      +
    6. +
    Output to a Printer or Other Device -- cgit v1.2.3 From 8bf1daae93a7cf5459835211fa3b5f6429b6b644 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 10 Mar 2008 10:06:37 +0000 Subject: Fixed NPE in BlockContainerLayoutManager when used as a child of an inline-level FO. Split IP and BP stack limits in LayoutContext (there's now a certain amount of redundancy with "refIPD" in LayoutContext which I didn't resolve). Areas are now generated for block-level FOs when used as children of inline-level FOs. ClassCastException in ListLayoutManager.mustKeepTogether() fixed (occured if used as child of an inline-level FO). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@635508 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/AbstractBreaker.java | 4 +- .../org/apache/fop/layoutmgr/AreaAdditionUtil.java | 2 +- .../fop/layoutmgr/BlockContainerLayoutManager.java | 35 +++---- .../apache/fop/layoutmgr/BlockLayoutManager.java | 3 +- .../fop/layoutmgr/BlockStackingLayoutManager.java | 5 +- .../apache/fop/layoutmgr/FlowLayoutManager.java | 2 +- .../org/apache/fop/layoutmgr/LayoutContext.java | 98 ++++++++++++++----- src/java/org/apache/fop/layoutmgr/PageBreaker.java | 2 +- .../fop/layoutmgr/StaticContentLayoutManager.java | 8 +- .../fop/layoutmgr/inline/ContentLayoutManager.java | 24 ++--- .../fop/layoutmgr/inline/InlineLayoutManager.java | 9 +- .../fop/layoutmgr/inline/LineLayoutManager.java | 13 +-- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 24 ++--- .../list/ListItemContentLayoutManager.java | 20 ++-- .../fop/layoutmgr/list/ListItemLayoutManager.java | 38 ++++---- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 3 +- .../layoutmgr/table/TableCellLayoutManager.java | 7 +- .../fop/layoutmgr/table/TableContentPosition.java | 2 + .../layoutmgr/table/TableHFPenaltyPosition.java | 5 + .../layoutmgr/table/TableHeaderFooterPosition.java | 5 + status.xml | 4 + .../inline_block-level_nested_1.xml | 104 +++++++++++++++++++++ 22 files changed, 293 insertions(+), 124 deletions(-) create mode 100644 test/layoutengine/standard-testcases/inline_block-level_nested_1.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 54fd315b1..65d537bcd 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -272,7 +272,7 @@ public abstract class AbstractBreaker { */ public void doLayout(int flowBPD, boolean autoHeight) { LayoutContext childLC = createLayoutContext(); - childLC.setStackLimit(new MinOptMax(flowBPD)); + childLC.setStackLimitBP(new MinOptMax(flowBPD)); if (getCurrentDisplayAlign() == Constants.EN_X_FILL) { //EN_X_FILL is non-standard (by LF) @@ -495,7 +495,7 @@ public abstract class AbstractBreaker { int averageLineLength = optimizeLineLength(effectiveList, startElementIndex, endElementIndex); if (averageLineLength != 0) { - childLC.setStackLimit(new MinOptMax(averageLineLength)); + childLC.setStackLimitBP(new MinOptMax(averageLineLength)); } } /* *** *** non-standard extension *** *** */ diff --git a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java index 80e0b74cc..1b0d02639 100644 --- a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java +++ b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java @@ -117,7 +117,7 @@ public class AreaAdditionUtil { // set space after for each LM, in order to implement // display-align = distribute lc.setSpaceAfter(layoutContext.getSpaceAfter()); - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitsFrom(layoutContext); childLM.addAreas(childPosIter, lc); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index fc60b561e..435f25b48 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -38,7 +38,6 @@ import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.BlockContainer; import org.apache.fop.fo.properties.CommonAbsolutePosition; -import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; @@ -201,7 +200,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); autoHeight = false; //boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); - int maxbpd = context.getStackLimit().opt; + int maxbpd = context.getStackLimitBP().opt; int allocBPD; if (height.getEnum() == EN_AUTO || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { @@ -280,8 +279,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager LayoutContext childLC = new LayoutContext(0); childLC.copyPendingMarksFrom(context); // curLM is a ? - childLC.setStackLimit(MinOptMax.subtract(context - .getStackLimit(), stackLimit)); + childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit)); childLC.setRefIPD(relDims.ipd); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); @@ -411,7 +409,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (isFixed()) { availHeight = (int)getCurrentPV().getViewArea().getHeight(); } else { - availHeight = context.getStackLimit().opt; + availHeight = context.getStackLimitBP().opt; } allocBPD = availHeight; allocBPD -= offset.y; @@ -444,7 +442,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } } else { - int maxbpd = context.getStackLimit().opt; + int maxbpd = context.getStackLimitBP().opt; allocBPD = maxbpd; if (!switchedProgressionDirection) { autoHeight = true; @@ -625,7 +623,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(context.getStackLimit()); + childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); @@ -854,7 +852,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // set last area flag lc.setFlags(LayoutContext.LAST_AREA, (layoutContext.isLastArea() && childLM == lastLM)); - /*LF*/lc.setStackLimit(layoutContext.getStackLimit()); + /*LF*/lc.setStackLimitBP(layoutContext.getStackLimitBP()); // Add the line areas to Area childLM.addAreas(childPosIter, lc); } @@ -992,30 +990,21 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepTogether() { //TODO Keeps will have to be more sophisticated sooner or later - return (!getBlockContainerFO().getKeepTogether().getWithinPage().isAuto() - || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto() - || (getParent() instanceof BlockLevelLayoutManager - && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) - || (getParent() instanceof InlineLayoutManager - && ((InlineLayoutManager) getParent()).mustKeepTogether())); + return super.mustKeepTogether() + || !getBlockContainerFO().getKeepTogether().getWithinPage().isAuto() + || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { return !getBlockContainerFO().getKeepWithPrevious().getWithinPage().isAuto() || !getBlockContainerFO().getKeepWithPrevious().getWithinColumn().isAuto(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithNext() { return !getBlockContainerFO().getKeepWithNext().getWithinPage().isAuto() || !getBlockContainerFO().getKeepWithNext().getWithinColumn().isAuto(); diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index bb39def8d..a65c0ed9b 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -25,6 +25,7 @@ import java.util.ListIterator; 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.area.LineArea; @@ -389,7 +390,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager // set last area flag lc.setFlags(LayoutContext.LAST_AREA, (layoutContext.isLastArea() && childLM == lastLM)); - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); // Add the line areas to Area childLM.addAreas(childPosIter, lc); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 5faad623c..541912a08 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -274,13 +274,14 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (curLM instanceof LineLayoutManager) { // curLM is a LineLayoutManager // set stackLimit for lines (stack limit is now i-p-direction, not b-p-direction!) - childLC.setStackLimit(new MinOptMax(getContentAreaIPD())); + childLC.setStackLimitBP(context.getStackLimitBP()); + childLC.setStackLimitIP(new MinOptMax(getContentAreaIPD())); childLC.setRefIPD(getContentAreaIPD()); } else { // curLM is a ? //childLC.setStackLimit(MinOptMax.subtract(context // .getStackLimit(), stackSize)); - childLC.setStackLimit(context.getStackLimit()); + childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(referenceIPD); } diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index a70dd0883..115532cf1 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -99,7 +99,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager //MinOptMax bpd = context.getStackLimit(); LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(context.getStackLimit()); + childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode()); diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 9eb38600b..ba06d70b1 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -74,12 +74,21 @@ public class LayoutContext { private int flags; // Contains some set of flags defined above /** * Total available stacking dimension for a "galley-level" layout - * manager (Line or Flow). It is passed by the parent LM. For LineLM, - * the block LM determines this based on indent properties. + * manager in block-progression-direction. It is passed by the + * parent LM. * These LM may wish to pass this information down to lower * level LM to allow them to optimize returned break possibilities. */ - private MinOptMax stackLimit; + private MinOptMax stackLimitBP; + /** + * Total available stacking dimension for a "galley-level" layout + * manager in inline-progression-direction. It is passed by the + * parent LM. For LineLM, the block LM determines this based on + * indent properties. + * These LM may wish to pass this information down to lower + * level LM to allow them to optimize returned break possibilities. + */ + private MinOptMax stackLimitIP; /** True if current element list is spanning in multi-column layout. */ private int nextSpan = Constants.NOT_SET; @@ -145,7 +154,7 @@ public class LayoutContext { this.flags = parentLC.flags; this.refIPD = parentLC.refIPD; this.writingMode = parentLC.writingMode; - this.stackLimit = null; // Don't reference parent MinOptMax! + setStackLimitsFrom(parentLC); this.leadingSpace = parentLC.leadingSpace; //??? this.trailingSpace = parentLC.trailingSpace; //??? this.hyphContext = parentLC.hyphContext; @@ -166,7 +175,8 @@ public class LayoutContext { public LayoutContext(int flags) { this.flags = flags; this.refIPD = 0; - stackLimit = new MinOptMax(0); + stackLimitBP = new MinOptMax(0); + stackLimitIP = new MinOptMax(0); leadingSpace = null; trailingSpace = null; } @@ -306,14 +316,47 @@ public class LayoutContext { } } - public void setStackLimit(MinOptMax limit) { - stackLimit = limit; + /** + * Sets the stack limit in block-progression-dimension. + * @param limit the stack limit + */ + public void setStackLimitBP(MinOptMax limit) { + stackLimitBP = limit; } - public MinOptMax getStackLimit() { - return stackLimit; + /** + * Returns the stack limit in block-progression-dimension. + * @return the stack limit + */ + public MinOptMax getStackLimitBP() { + return stackLimitBP; } + /** + * Sets the stack limit in inline-progression-dimension. + * @param limit the stack limit + */ + public void setStackLimitIP(MinOptMax limit) { + stackLimitIP = limit; + } + + /** + * Returns the stack limit in inline-progression-dimension. + * @return the stack limit + */ + public MinOptMax getStackLimitIP() { + return stackLimitIP; + } + + /** + * Sets (Copies) the stack limits in both directions from another layout context. + * @param context the layout context to taje the values from + */ + public void setStackLimitsFrom(LayoutContext context) { + setStackLimitBP(context.getStackLimitBP()); + setStackLimitIP(context.getStackLimitIP()); + } + /** * Sets the inline-progression-dimension of the nearest ancestor reference area. */ @@ -536,22 +579,27 @@ public class LayoutContext { /** {@inheritDoc} */ public String toString() { - return "Layout Context:" + - "\nStack Limit: \t" + (getStackLimit() == null ? "null" : getStackLimit().toString()) + - "\nTrailing Space: \t" + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString()) + - "\nLeading Space: \t" + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString()) + - "\nReference IPD: \t" + getRefIPD() + - "\nSpace Adjust: \t" + getSpaceAdjust() + - "\nIPD Adjust: \t" + getIPDAdjust() + - "\nResolve Leading Space: \t" + resolveLeadingSpace() + - "\nSuppress Leading Space: \t" + suppressLeadingSpace() + - "\nIs First Area: \t" + isFirstArea() + - "\nStarts New Area: \t" + startsNewArea() + - "\nIs Last Area: \t" + isLastArea() + - "\nTry Hyphenate: \t" + tryHyphenate() + - "\nKeeps: \t[" + (isKeepWithNextPending() ? "keep-with-next" : "") + "][" - + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending" + - "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" + return "Layout Context:" + + "\nStack Limit BPD: \t" + + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString()) + + "\nStack Limit IPD: \t" + + (getStackLimitIP() == null ? "null" : getStackLimitIP().toString()) + + "\nTrailing Space: \t" + + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString()) + + "\nLeading Space: \t" + + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString()) + + "\nReference IPD: \t" + getRefIPD() + + "\nSpace Adjust: \t" + getSpaceAdjust() + + "\nIPD Adjust: \t" + getIPDAdjust() + + "\nResolve Leading Space: \t" + resolveLeadingSpace() + + "\nSuppress Leading Space: \t" + suppressLeadingSpace() + + "\nIs First Area: \t" + isFirstArea() + + "\nStarts New Area: \t" + startsNewArea() + + "\nIs Last Area: \t" + isLastArea() + + "\nTry Hyphenate: \t" + tryHyphenate() + + "\nKeeps: \t[" + (isKeepWithNextPending() ? "keep-with-next" : "") + "][" + + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending" + + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]"; } diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index cf830a7ec..3e100cd50 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -156,7 +156,7 @@ public class PageBreaker extends AbstractBreaker { // element represents a line with footnote citations bFootnotesPresent = true; LayoutContext footnoteContext = new LayoutContext(context); - footnoteContext.setStackLimit(context.getStackLimit()); + footnoteContext.setStackLimitBP(context.getStackLimitBP()); footnoteContext.setRefIPD(pslm.getCurrentPV() .getRegionReference(Constants.FO_REGION_BODY).getIPD()); LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs(); diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index c8b89e6af..b1e414527 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -93,7 +93,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { //TODO Empty this method?!? // set layout dimensions setContentAreaIPD(context.getRefIPD()); - setContentAreaBPD(context.getStackLimit().opt); + setContentAreaBPD(context.getStackLimitBP().opt); //TODO Copied from elsewhere. May be worthwhile to factor out the common parts. // currently active LM @@ -111,10 +111,10 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } // Set up a LayoutContext - MinOptMax bpd = context.getStackLimit(); + MinOptMax bpd = context.getStackLimitBP(); LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(MinOptMax.subtract(bpd, stackSize)); + childLC.setStackLimitBP(MinOptMax.subtract(bpd, stackSize)); childLC.setRefIPD(context.getRefIPD()); // get elements from curLM @@ -307,7 +307,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(context.getStackLimit()); + childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(context.getWritingMode()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index 03e9b382a..ff7c5b3ce 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -19,9 +19,20 @@ package org.apache.fop.layoutmgr.inline; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; +import org.apache.fop.area.LineArea; +import org.apache.fop.area.inline.InlineArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.pagination.Title; import org.apache.fop.layoutmgr.AbstractBaseLayoutManager; @@ -34,19 +45,8 @@ import org.apache.fop.layoutmgr.PageSequenceLayoutManager; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.SpaceSpecifier; -import org.apache.fop.area.Area; -import org.apache.fop.area.LineArea; -import org.apache.fop.area.inline.InlineArea; - -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.ArrayList; -import java.util.Iterator; import org.apache.fop.traits.MinOptMax; -import org.apache.fop.area.Block; - /** * Content Layout Manager. * For use with objects that contain inline areas such as @@ -115,7 +115,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager childLC.setLeadingSpace(new SpaceSpecifier(false)); childLC.setTrailingSpace(new SpaceSpecifier(false)); // set stackLimit for lines - childLC.setStackLimit(new MinOptMax(ipd)); + childLC.setStackLimitIP(new MinOptMax(ipd)); childLC.setRefIPD(ipd); int lineHeight = 14000; diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index b449b6689..1f53e792e 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -19,12 +19,13 @@ package org.apache.fop.layoutmgr.inline; -import java.util.ListIterator; import java.util.LinkedList; import java.util.List; +import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineBlockParent; @@ -47,12 +48,12 @@ import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthSequence; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.NonLeafPosition; -import org.apache.fop.layoutmgr.SpaceSpecifier; -import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.NonLeafPosition; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.SpaceSpecifier; +import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 6df7ac00c..9037cf628 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -26,6 +26,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.LineArea; import org.apache.fop.area.Trait; @@ -583,7 +584,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager // Set up constraints for inline level managers // IPD remaining in line - MinOptMax availIPD = context.getStackLimit(); + MinOptMax availIPD = context.getStackLimitIP(); clearPrevIPD(); @@ -646,7 +647,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager InlineLevelLayoutManager curLM; LinkedList returnedList = null; - iLineWidth = context.getStackLimit().opt; + iLineWidth = context.getStackLimitIP().opt; // convert all the text in a sequence of paragraphs made // of KnuthBox, KnuthGlue and KnuthPenalty objects @@ -1687,7 +1688,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager */ if (false && textAlignment == EN_JUSTIFY) { // re-compute space adjust ratio - int updatedDifference = context.getStackLimit().opt + int updatedDifference = context.getStackLimitIP().opt - lbp.lineWidth + lbp.difference; double updatedRatio = 0.0; if (updatedDifference > 0) { @@ -1701,12 +1702,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager } else if (false && textAlignment == EN_CENTER) { // re-compute indent int updatedIndent = lbp.startIndent - + (context.getStackLimit().opt - lbp.lineWidth) / 2; + + (context.getStackLimitIP().opt - lbp.lineWidth) / 2; lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); } else if (false && textAlignment == EN_END) { // re-compute indent int updatedIndent = lbp.startIndent - + (context.getStackLimit().opt - lbp.lineWidth); + + (context.getStackLimitIP().opt - lbp.lineWidth); lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); } @@ -1770,7 +1771,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager // set last area flag blocklc.setFlags(LayoutContext.LAST_AREA, (context.isLastArea() && childLM == lastLM)); - blocklc.setStackLimit(context.getStackLimit()); + blocklc.setStackLimitsFrom(context); // Add the line areas to Area childLM.addAreas(childPosIter, blocklc); blocklc.setLeadingSpace(blocklc.getTrailingSpace()); diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index 470cbbe9c..e17880e59 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -19,29 +19,29 @@ package org.apache.fop.layoutmgr.list; +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.fo.flow.ListBlock; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListUtils; -import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.PositionIterator; 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 java.util.List; - /** * LayoutManager for a list-block FO. * A list block contains list items which are stacked within @@ -200,7 +200,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM); lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM); - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); childLM.addAreas(childPosIter, lc); } @@ -280,7 +280,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public boolean mustKeepTogether() { //TODO Keeps will have to be more sophisticated sooner or later - return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() + return super.mustKeepTogether() || !getListBlockFO().getKeepTogether().getWithinPage().isAuto() || !getListBlockFO().getKeepTogether().getWithinColumn().isAuto(); } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 853b1a128..363f6493f 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -19,24 +19,24 @@ package org.apache.fop.layoutmgr.list; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; import org.apache.fop.fo.flow.AbstractListItemPart; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; -import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition; -import org.apache.fop.area.Area; -import org.apache.fop.area.Block; - -import java.util.Iterator; -import java.util.List; -import java.util.LinkedList; /** * LayoutManager for a list-item-label or list-item-body FO. @@ -162,7 +162,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM); // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); childLM.addAreas(childPosIter, lc); } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index dc28e98e2..5c6e9aeb1 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -19,8 +19,16 @@ package org.apache.fop.layoutmgr.list; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + 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.fo.flow.ListItem; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; @@ -30,28 +38,21 @@ import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.ElementListUtils; -import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.KnuthBox; +import org.apache.fop.layoutmgr.KnuthElement; +import org.apache.fop.layoutmgr.KnuthPenalty; +import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.RelSide; import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; -import org.apache.fop.layoutmgr.KnuthElement; -import org.apache.fop.layoutmgr.KnuthBox; -import org.apache.fop.layoutmgr.KnuthPenalty; -import org.apache.fop.layoutmgr.KnuthPossPosIter; -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.ArrayList; -import java.util.List; -import java.util.LinkedList; -import java.util.ListIterator; - /** * LayoutManager for a list-item FO. * The list item contains a list item label and a list item body. @@ -115,6 +116,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager return iBodyLastIndex; } + /** {@inheritDoc} */ + public boolean generatesAreas() { + return true; + } + /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer("ListItemPosition:"); @@ -510,7 +516,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); // TO DO: use the right stack limit for the label - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); label.addAreas(labelIter, lc); } @@ -531,7 +537,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager // set the space adjustment ratio lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); // TO DO: use the right stack limit for the body - lc.setStackLimit(layoutContext.getStackLimit()); + lc.setStackLimitBP(layoutContext.getStackLimitBP()); body.addAreas(bodyIter, lc); } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index c2e26e18d..917e8296b 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -24,6 +24,7 @@ import java.util.List; 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; @@ -147,7 +148,7 @@ class RowGroupLayoutManager { } } LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimit(context.getStackLimit()); //necessary? + childLC.setStackLimitBP(context.getStackLimitBP()); //necessary? childLC.setRefIPD(spanWidth); //Get the element list for the cell contents diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 8e92a233b..7036f199b 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -23,6 +23,7 @@ import java.util.LinkedList; 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.area.Trait; @@ -146,7 +147,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * {@inheritDoc} */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { - MinOptMax stackLimit = new MinOptMax(context.getStackLimit()); + MinOptMax stackLimit = new MinOptMax(context.getStackLimitBP()); referenceIPD = context.getRefIPD(); cellIPD = referenceIPD; @@ -161,8 +162,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); // curLM is a ? - childLC.setStackLimit(MinOptMax.subtract(context - .getStackLimit(), stackLimit)); + childLC.setStackLimitBP(MinOptMax.subtract(context + .getStackLimitBP(), stackLimit)); childLC.setRefIPD(cellIPD); // get elements from curLM diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java index db34764b1..260b8cfdf 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java @@ -106,10 +106,12 @@ class TableContentPosition extends Position { } } + /** {@inheritDoc} */ public boolean generatesAreas() { return true; } + /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer("TableContentPosition:"); sb.append(getIndex()); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java index afa166985..3e504a45c 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java @@ -43,6 +43,11 @@ class TableHFPenaltyPosition extends Position { super(lm); } + /** {@inheritDoc} */ + public boolean generatesAreas() { + return true; + } + public String toString() { StringBuffer sb = new StringBuffer("TableHFPenaltyPosition:"); sb.append(getIndex()).append("("); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java index c3ae72c74..8d3b993b2 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java @@ -48,6 +48,11 @@ class TableHeaderFooterPosition extends Position { this.nestedElements = nestedElements; } + /** {@inheritDoc} */ + public boolean generatesAreas() { + return true; + } + public String toString() { StringBuffer sb = new StringBuffer("Table"); sb.append(header ? "Header" : "Footer"); diff --git a/status.xml b/status.xml index 594b113e1..34307f721 100644 --- a/status.xml +++ b/status.xml @@ -94,6 +94,10 @@

    + + Fixed exceptions when lists, tables or block-container are children of an inline-level + FO. + Added support for background on fo:table-column and fo:table-header/footer/body elements. diff --git a/test/layoutengine/standard-testcases/inline_block-level_nested_1.xml b/test/layoutengine/standard-testcases/inline_block-level_nested_1.xml new file mode 100644 index 000000000..6b6761dee --- /dev/null +++ b/test/layoutengine/standard-testcases/inline_block-level_nested_1.xml @@ -0,0 +1,104 @@ + + + + + +

    + This test checks fo:inline and nested block-level nodes. +

    +
    + + + + + + + + + + + before + + + + + + + Inline list item one. + + + + after + + + before + + " + + + + cell1 + + + cell2 + + + + + after + + + before + + block in block-container + + after + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + +
    -- cgit v1.2.3 From b7538be4dcd299f90ad3525fd24758614d10352e Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 10 Mar 2008 20:52:43 +0000 Subject: Bugfix: forced break ignored when the minimum height of a table-row isn't reached git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@635686 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 12 -- .../org/apache/fop/layoutmgr/MinOptMaxUtil.java | 13 +- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 123 ++++++++---- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 221 ++++++++++----------- .../org/apache/fop/layoutmgr/table/RowPainter.java | 23 ++- status.xml | 4 + .../table_border-collapse_separate_1.xml | 2 +- .../table_row-delay_fixed-row-height.xml | 6 +- 8 files changed, 217 insertions(+), 187 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 297a3176c..8af896fa2 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -238,18 +238,6 @@ public class PrimaryGridUnit extends GridUnit { return contentLength; } - /** @return true if cell/row has an explicit BPD/height */ - public boolean hasBPD() { - if (!getCell().getBlockProgressionDimension().getOptimum(null).isAuto()) { - return true; - } - if (getRow() != null - && !getRow().getBlockProgressionDimension().getOptimum(null).isAuto()) { - return true; - } - return false; - } - /** * Returns the grid units belonging to the same span as this one. * diff --git a/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java b/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java index ff9bdb1d9..b58af1cfe 100644 --- a/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java +++ b/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java @@ -68,19 +68,16 @@ public class MinOptMaxUtil { } /** - * Extend the minimum length to the given length. + * Extends the minimum length to the given length if necessary, and adjusts opt and + * max accordingly. + * * @param mom the min/opt/max trait * @param len the new minimum length - * @param optToLen if set adjusts the optimum length to be the smaller of the - * minimum length and the given length */ - public static void extendMinimum(MinOptMax mom, int len, boolean optToLen) { + public static void extendMinimum(MinOptMax mom, int len) { if (mom.min < len) { mom.min = len; mom.opt = Math.max(mom.min, mom.opt); - if (optToLen) { - mom.opt = Math.min(mom.min, len); - } mom.max = Math.max(mom.opt, mom.max); } } @@ -111,7 +108,7 @@ public class MinOptMaxUtil { ? 0 : prop.getMinimum(context).getLength().getValue(context)), (prop.getOptimum(context).isAuto() ? 0 : prop.getOptimum(context).getLength().getValue(context)), - (prop.getMinimum(context).isAuto() + (prop.getMaximum(context).isAuto() ? Integer.MAX_VALUE : prop.getMaximum(context).getLength().getValue(context))); return mom; diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 46544700b..4e41e909f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -33,6 +33,8 @@ import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; +import org.apache.fop.layoutmgr.MinOptMaxUtil; +import org.apache.fop.traits.MinOptMax; /** * A cell playing in the construction of steps for a row-group. @@ -133,6 +135,49 @@ class ActiveCell { } } + // TODO to be removed along with the RowPainter#computeContentLength method + /** See {@link ActiveCell#handleExplicitHeight(MinOptMax, MinOptMax)}. */ + private static class FillerPenalty extends KnuthPenalty { + + private int contentLength; + + FillerPenalty(KnuthPenalty p, int length) { + super(length, p.getP(), p.isFlagged(), p.getBreakClass(), + p.getPosition(), p.isAuxiliary()); + contentLength = p.getW(); + } + + FillerPenalty(int length) { + super(length, 0, false, null, true); + contentLength = 0; + } + } + + /** See {@link ActiveCell#handleExplicitHeight(MinOptMax, MinOptMax)}. */ + private static class FillerBox extends KnuthBox { + FillerBox(int length) { + super(length, null, true); + } + } + + /** + * Returns the actual length of the content represented by the given element. In the + * case where this element is used as a filler to match a row's fixed height, the + * value returned by the getW() method will be higher than the actual content. + * + * @param el an element + * @return the actual content length corresponding to the element + */ + static int getElementContentLength(KnuthElement el) { + if (el instanceof FillerPenalty) { + return ((FillerPenalty) el).contentLength; + } else if (el instanceof FillerBox) { + return 0; + } else { + return el.getW(); + } + } + ActiveCell(PrimaryGridUnit pgu, EffRow row, int rowIndex, int previousRowsLength, TableLayoutManager tableLM) { this.pgu = pgu; @@ -149,22 +194,10 @@ class ActiveCell { + pgu.getBeforeBorderWidth(0, ConditionalBorder.REST); bpAfterNormal = paddingAfterNormal + pgu.getAfterBorderWidth(ConditionalBorder.NORMAL); bpAfterTrailing = paddingAfterTrailing + pgu.getAfterBorderWidth(0, ConditionalBorder.REST); - boolean makeBoxForWholeRow = false; - if (row.getExplicitHeight().min > 0) { - boolean contentsSmaller = ElementListUtils.removeLegalBreaks( - pgu.getElements(), row.getExplicitHeight()); - if (contentsSmaller) { - makeBoxForWholeRow = true; - } - } - if (makeBoxForWholeRow) { - elementList = new java.util.ArrayList(1); - int height = row.getHeight().opt; - height -= bpBeforeNormal + bpAfterNormal; - elementList.add(new KnuthBoxCellWithBPD(height)); - } else { - elementList = pgu.getElements(); - } + elementList = pgu.getElements(); + handleExplicitHeight( + MinOptMaxUtil.toMinOptMax(pgu.getCell().getBlockProgressionDimension(), tableLM), + row.getExplicitHeight()); knuthIter = elementList.listIterator(); includedLength = -1; // Avoid troubles with cells having content of zero length totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); @@ -181,6 +214,46 @@ class ActiveCell { } } + /** + * Modifies the cell's element list by putting filler elements, so that the cell's or + * row's explicit height is always reached. + * + * TODO this will work properly only for the first break. Then the limitation + * explained on http://wiki.apache.org/xmlgraphics-fop/TableLayout/KnownProblems + * occurs. The list of elements needs to be re-adjusted after each break. + */ + private void handleExplicitHeight(MinOptMax cellBPD, MinOptMax rowBPD) { + int minBPD = Math.max(cellBPD.min, rowBPD.min); + if (minBPD > 0) { + ListIterator iter = elementList.listIterator(); + int cumulateLength = 0; + boolean prevIsBox = false; + while (iter.hasNext() && cumulateLength < minBPD) { + KnuthElement el = (KnuthElement) iter.next(); + if (el.isBox()) { + prevIsBox = true; + cumulateLength += el.getW(); + } else if (el.isGlue()) { + if (prevIsBox) { + elementList.add(iter.nextIndex() - 1, + new FillerPenalty(minBPD - cumulateLength)); + } + prevIsBox = false; + cumulateLength += el.getW(); + } else { + prevIsBox = false; + if (cumulateLength + el.getW() < minBPD) { + iter.set(new FillerPenalty((KnuthPenalty) el, minBPD - cumulateLength)); + } + } + } + } + int optBPD = Math.max(minBPD, Math.max(cellBPD.opt, rowBPD.opt)); + if (pgu.getContentLength() < optBPD) { + elementList.add(new FillerBox(optBPD - pgu.getContentLength())); + } + } + PrimaryGridUnit getPrimaryGridUnit() { return pgu; } @@ -444,13 +517,6 @@ class ActiveCell { return new CellPart(pgu, nextStep.start, previousStep.end, lastCellPart, 0, 0, previousStep.penaltyLength, bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing); - } else if (nextStep.start == 0 && nextStep.end == 0 - && elementList.size() == 1 - && elementList.get(0) instanceof KnuthBoxCellWithBPD) { - //Special case: Cell with fixed BPD - return new CellPart(pgu, 0, pgu.getElements().size() - 1, lastCellPart, - nextStep.condBeforeContentLength, length, nextStep.penaltyLength, - bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing); } else { return new CellPart(pgu, nextStep.start, nextStep.end, lastCellPart, nextStep.condBeforeContentLength, length, nextStep.penaltyLength, @@ -467,15 +533,4 @@ class ActiveCell { public String toString() { return "Cell " + (pgu.getRowIndex() + 1) + "." + (pgu.getColIndex() + 1); } - - - /** - * Marker class denoting table cells fitting in just one box (no legal break inside). - */ - private static class KnuthBoxCellWithBPD extends KnuthBox { - - public KnuthBoxCellWithBPD(int w) { - super(w, null, true); - } - } } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 917e8296b..9c97ca827 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -19,17 +19,16 @@ package org.apache.fop.layoutmgr.table; +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.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.TableColumn; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; @@ -95,137 +94,119 @@ class RowGroupLayoutManager { private void createElementsForRowGroup(LayoutContext context, int alignment, int bodyType, LinkedList returnList) { log.debug("Handling row group with " + rowGroup.length + " rows..."); + EffRow row; + for (int rgi = 0; rgi < rowGroup.length; rgi++) { + row = rowGroup[rgi]; + for (Iterator iter = row.getGridUnits().iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + if (gu.isPrimary()) { + PrimaryGridUnit primary = gu.getPrimary(); + // TODO a new LM must be created for every new static-content + primary.createCellLM(); + primary.getCellLM().setParent(tableLM); + //Calculate width of cell + int spanWidth = 0; + Iterator colIter = tableLM.getTable().getColumns().listIterator( + primary.getColIndex()); + for (int i = 0, c = primary.getCell().getNumberColumnsSpanned(); i < c; i++) { + spanWidth += ((TableColumn) colIter.next()).getColumnWidth().getValue( + tableLM); + } + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimitBP(context.getStackLimitBP()); //necessary? + childLC.setRefIPD(spanWidth); + + //Get the element list for the cell contents + LinkedList elems = primary.getCellLM().getNextKnuthElements( + childLC, alignment); + ElementListObserver.observe(elems, "table-cell", primary.getCell().getId()); + primary.setElements(elems); + } + } + } + computeRowHeights(); + LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context, + rowGroup, bodyType); + returnList.addAll(elements); + } + + /** + * Calculate the heights of the rows in the row group, see CSS21, 17.5.3 Table height + * algorithms. + * + * TODO this method will need to be adapted once clarification has been made by the + * W3C regarding whether borders or border-separation must be included or not + */ + private void computeRowHeights() { + log.debug("rowGroup:"); MinOptMax[] rowHeights = new MinOptMax[rowGroup.length]; - MinOptMax[] explicitRowHeights = new MinOptMax[rowGroup.length]; EffRow row; - List pgus = new java.util.ArrayList(); //holds a list of a row's primary grid units for (int rgi = 0; rgi < rowGroup.length; rgi++) { row = rowGroup[rgi]; - rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE); - explicitRowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE); - - pgus.clear(); - TableRow tableRow = null; - // The row's minimum content height; 0 if the row's height is auto, otherwise - // the .minimum component of the explicitly specified value - int minRowBPD = 0; // The BPD of the biggest cell in the row - int maxCellBPD = 0; - for (int j = 0; j < row.getGridUnits().size(); j++) { - GridUnit gu = row.getGridUnit(j); - if ((gu.isPrimary() || (gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan())) - && !gu.isEmpty()) { +// int maxCellBPD = 0; + MinOptMax explicitRowHeight; + TableRow tableRowFO = rowGroup[rgi].getTableRow(); + if (tableRowFO == null) { + rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE); + explicitRowHeight = new MinOptMax(0, 0, Integer.MAX_VALUE); + } else { + LengthRangeProperty rowBPD = tableRowFO.getBlockProgressionDimension(); + rowHeights[rgi] = MinOptMaxUtil.toMinOptMax(rowBPD, tableLM); + explicitRowHeight = MinOptMaxUtil.toMinOptMax(rowBPD, tableLM); + } + for (Iterator iter = row.getGridUnits().iterator(); iter.hasNext();) { + GridUnit gu = (GridUnit) iter.next(); + if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) { PrimaryGridUnit primary = gu.getPrimary(); - - if (gu.isPrimary()) { - // TODO a new LM must be created for every new static-content - primary.createCellLM(); - primary.getCellLM().setParent(tableLM); - - //Determine the table-row if any - if (tableRow == null && primary.getRow() != null) { - tableRow = primary.getRow(); - - //Check for bpd on row, see CSS21, 17.5.3 Table height algorithms - LengthRangeProperty rowBPD = tableRow.getBlockProgressionDimension(); - if (!rowBPD.getMinimum(tableLM).isAuto()) { - minRowBPD = Math.max(minRowBPD, - rowBPD.getMinimum(tableLM).getLength().getValue(tableLM)); - } - MinOptMaxUtil.restrict(explicitRowHeights[rgi], rowBPD, tableLM); - - } - - //Calculate width of cell - int spanWidth = 0; - for (int i = primary.getColIndex(); - i < primary.getColIndex() - + primary.getCell().getNumberColumnsSpanned(); - i++) { - if (tableLM.getColumns().getColumn(i + 1) != null) { - spanWidth += tableLM.getColumns().getColumn(i + 1) - .getColumnWidth().getValue(tableLM); - } - } - LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimitBP(context.getStackLimitBP()); //necessary? - childLC.setRefIPD(spanWidth); - - //Get the element list for the cell contents - LinkedList elems = primary.getCellLM().getNextKnuthElements( - childLC, alignment); - ElementListObserver.observe(elems, "table-cell", primary.getCell().getId()); - primary.setElements(elems); + int effectiveCellBPD = 0; + LengthRangeProperty cellBPD = primary.getCell().getBlockProgressionDimension(); + if (!cellBPD.getMinimum(tableLM).isAuto()) { + effectiveCellBPD = cellBPD.getMinimum(tableLM).getLength() + .getValue(tableLM); } - - //Calculate height of row, see CSS21, 17.5.3 Table height algorithms - if (gu.isLastGridUnitRowSpan()) { - // The effective cell's bpd, after taking into account bpd - // (possibly explicitly) set on the row or on the cell, and the - // cell's content length - int effectiveCellBPD = minRowBPD; - LengthRangeProperty cellBPD = primary.getCell() - .getBlockProgressionDimension(); - if (!cellBPD.getMinimum(tableLM).isAuto()) { - effectiveCellBPD = Math.max(effectiveCellBPD, - cellBPD.getMinimum(tableLM).getLength().getValue(tableLM)); - } - if (!cellBPD.getOptimum(tableLM).isAuto()) { - effectiveCellBPD = Math.max(effectiveCellBPD, - cellBPD.getOptimum(tableLM).getLength().getValue(tableLM)); - } - if (gu.getRowSpanIndex() == 0) { - //TODO ATM only non-row-spanned cells are taken for this - MinOptMaxUtil.restrict(explicitRowHeights[rgi], cellBPD, tableLM); - } - effectiveCellBPD = Math.max(effectiveCellBPD, - primary.getContentLength()); - - int borderWidths = primary.getBeforeAfterBorderWidth(); - int padding = 0; - maxCellBPD = Math.max(maxCellBPD, effectiveCellBPD); - CommonBorderPaddingBackground cbpb - = primary.getCell().getCommonBorderPaddingBackground(); - padding += cbpb.getPaddingBefore(false, primary.getCellLM()); - padding += cbpb.getPaddingAfter(false, primary.getCellLM()); - int effRowHeight = effectiveCellBPD - + padding + borderWidths; - for (int previous = 0; previous < gu.getRowSpanIndex(); previous++) { - effRowHeight -= rowHeights[rgi - previous - 1].opt; - } - if (effRowHeight > rowHeights[rgi].min) { - //This is the new height of the (grid) row - MinOptMaxUtil.extendMinimum(rowHeights[rgi], effRowHeight, false); - } + if (!cellBPD.getOptimum(tableLM).isAuto()) { + effectiveCellBPD = cellBPD.getOptimum(tableLM).getLength() + .getValue(tableLM); } - - if (gu.isPrimary()) { - pgus.add(primary); + if (gu.getRowSpanIndex() == 0) { + effectiveCellBPD = Math.max(effectiveCellBPD, explicitRowHeight.opt); + } + effectiveCellBPD = Math.max(effectiveCellBPD, primary.getContentLength()); + int borderWidths = primary.getBeforeAfterBorderWidth(); + int padding = 0; + CommonBorderPaddingBackground cbpb = primary.getCell() + .getCommonBorderPaddingBackground(); + padding += cbpb.getPaddingBefore(false, primary.getCellLM()); + padding += cbpb.getPaddingAfter(false, primary.getCellLM()); + int effRowHeight = effectiveCellBPD + padding + borderWidths; + for (int prev = rgi - 1; prev >= rgi - gu.getRowSpanIndex(); prev--) { + effRowHeight -= rowHeights[prev].opt; + } + if (effRowHeight > rowHeights[rgi].min) { + // This is the new height of the (grid) row + MinOptMaxUtil.extendMinimum(rowHeights[rgi], effRowHeight); } } } row.setHeight(rowHeights[rgi]); - row.setExplicitHeight(explicitRowHeights[rgi]); - if (maxCellBPD > row.getExplicitHeight().max) { - log.warn(FONode.decorateWithContextInfo( - "The contents of row " + (row.getIndex() + 1) - + " are taller than they should be (there is a" - + " block-progression-dimension or height constraint on the indicated row)." - + " Due to its contents the row grows" - + " to " + maxCellBPD + " millipoints, but the row shouldn't get" - + " any taller than " + row.getExplicitHeight() + " millipoints.", - row.getTableRow())); - } - } - if (log.isDebugEnabled()) { - log.debug("rowGroup:"); - for (int i = 0; i < rowHeights.length; i++) { - log.debug(" height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]); + row.setExplicitHeight(explicitRowHeight); + // TODO re-enable and improve after clarification +// if (maxCellBPD > row.getExplicitHeight().max) { +// log.warn(FONode.decorateWithContextInfo( +// "The contents of row " + (row.getIndex() + 1) +// + " are taller than they should be (there is a" +// + " block-progression-dimension or height constraint +// + " on the indicated row)." +// + " Due to its contents the row grows" +// + " to " + maxCellBPD + " millipoints, but the row shouldn't get" +// + " any taller than " + row.getExplicitHeight() + " millipoints.", +// row.getTableRow())); +// } + if (log.isDebugEnabled()) { + log.debug(" height=" + rowHeights[rgi] + " explicit=" + explicitRowHeight); } } - LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context, - rowGroup, bodyType); - returnList.addAll(elements); } } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 61f6b3aec..bed9c53ae 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -298,18 +299,22 @@ class RowPainter { // cell, in most cases) return 0; } else { - int actualStart = startIndex; + ListIterator iter = pgu.getElements().listIterator(startIndex); // Skip from the content length calculation glues and penalties occurring at the // beginning of the page - while (actualStart <= endIndex - && !((KnuthElement) pgu.getElements().get(actualStart)).isBox()) { - actualStart++; + boolean nextIsBox = false; + while (iter.nextIndex() <= endIndex && !nextIsBox) { + nextIsBox = ((KnuthElement) iter.next()).isBox(); } - int len = ElementListUtils.calcContentLength( - pgu.getElements(), actualStart, endIndex); - KnuthElement el = (KnuthElement)pgu.getElements().get(endIndex); - if (el.isPenalty()) { - len += el.getW(); + int len = 0; + if (((KnuthElement) iter.previous()).isBox()) { + while (iter.nextIndex() < endIndex) { + KnuthElement el = (KnuthElement) iter.next(); + if (el.isBox() || el.isGlue()) { + len += el.getW(); + } + } + len += ActiveCell.getElementContentLength((KnuthElement) iter.next()); } return len; } diff --git a/status.xml b/status.xml index 34307f721..1a01f73c2 100644 --- a/status.xml +++ b/status.xml @@ -94,6 +94,10 @@

    + + Bugfix: a forced break inside a cell was ignored when occurring before the minimum height + set on the enclosing row was set. + Fixed exceptions when lists, tables or block-container are children of an inline-level FO. diff --git a/test/layoutengine/standard-testcases/table_border-collapse_separate_1.xml b/test/layoutengine/standard-testcases/table_border-collapse_separate_1.xml index d0b11c1b0..8a9370a5c 100644 --- a/test/layoutengine/standard-testcases/table_border-collapse_separate_1.xml +++ b/test/layoutengine/standard-testcases/table_border-collapse_separate_1.xml @@ -31,7 +31,7 @@ - + diff --git a/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml b/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml index 70990de62..7b50996cc 100644 --- a/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml +++ b/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml @@ -144,9 +144,9 @@ 3 - - - + + + -- cgit v1.2.3 From 19860ebeca43a4b5f018b611f02dc6b91fa48f3f Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 10 Mar 2008 21:28:08 +0000 Subject: Need to clean up after myself. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@635701 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/LayoutContext.java | 2 ++ src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index ba06d70b1..a72fca9af 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -95,6 +95,8 @@ public class LayoutContext { /** inline-progression-dimension of nearest ancestor reference area */ private int refIPD; + //TODO After the split of stackLimit into stackLimitBP and stackLimitIP there's now some + //overlap with refIPD. Need to investigate how best to refactor that. /** the writing mode established by the nearest ancestor reference area */ private int writingMode = Constants.EN_LR_TB; diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 9037cf628..9a818232c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -583,9 +583,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager // Get a break from currently active child LM // Set up constraints for inline level managers - // IPD remaining in line - MinOptMax availIPD = context.getStackLimitIP(); - clearPrevIPD(); //PHASE 1: Create Knuth elements -- cgit v1.2.3 From a4c2cb03927957fcad3407a3e31afa72217433b9 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 10 Mar 2008 22:39:38 +0000 Subject: Bugfix for row/body/col background painting when padding is used in the table-cells. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@635741 13f79535-47bb-0310-9956-ffa450edef68 --- .../layoutmgr/table/TableCellLayoutManager.java | 22 ++-- .../standard-testcases/table_backgrounds_2.xml | 113 +++++++++++++++++++++ 2 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table_backgrounds_2.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 7036f199b..b99df4eb3 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -354,11 +354,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager CommonBorderPaddingBackground padding = primaryGridUnit.getCell() .getCommonBorderPaddingBackground(); - int cellBPD = totalHeight - borderBeforeWidth - borderAfterWidth; + int paddingRectBPD = totalHeight - borderBeforeWidth - borderAfterWidth; + int cellBPD = paddingRectBPD; cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this); cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this); - addBackgroundAreas(painter, firstRowHeight, borderBeforeWidth, cellBPD); + addBackgroundAreas(painter, firstRowHeight, borderBeforeWidth, paddingRectBPD); if (isSeparateBorderModel()) { if (!emptyCell || getTableCell().showEmptyCells()) { @@ -488,22 +489,23 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager /** Adds background areas for the column, body and row, if any. */ private void addBackgroundAreas(RowPainter painter, int firstRowHeight, int borderBeforeWidth, - int cellBPD) { + int paddingRectBPD) { TableColumn column = getTable().getColumn(primaryGridUnit.getColIndex()); if (column.getCommonBorderPaddingBackground().hasBackground()) { - Block colBackgroundArea = getBackgroundArea(cellBPD, borderBeforeWidth); + Block colBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); ((TableLayoutManager) parentLM).registerColumnBackgroundArea(column, colBackgroundArea, -startIndent); } TableBody body = primaryGridUnit.getTableBody(); if (body.getCommonBorderPaddingBackground().hasBackground()) { - painter.registerPartBackgroundArea(getBackgroundArea(cellBPD, borderBeforeWidth)); + painter.registerPartBackgroundArea( + getBackgroundArea(paddingRectBPD, borderBeforeWidth)); } TableRow row = primaryGridUnit.getRow(); if (row != null && row.getCommonBorderPaddingBackground().hasBackground()) { - Block rowBackgroundArea = getBackgroundArea(cellBPD, borderBeforeWidth); + Block rowBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); ((TableLayoutManager) parentLM).addBackgroundArea(rowBackgroundArea); TraitSetter.addBackground(rowBackgroundArea, row.getCommonBorderPaddingBackground(), (TableLayoutManager) parentLM, @@ -541,12 +543,16 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } private Block getBackgroundArea(int bpd, int borderBeforeWidth) { + CommonBorderPaddingBackground padding = getTableCell().getCommonBorderPaddingBackground(); + int paddingStart = padding.getPaddingStart(false, this); + int paddingEnd = padding.getPaddingStart(false, this); + Block block = new Block(); TraitSetter.setProducerID(block, getTable().getId()); block.setPositioning(Block.ABSOLUTE); - block.setIPD(cellIPD); + block.setIPD(cellIPD + paddingStart + paddingEnd); block.setBPD(bpd); - block.setXOffset(xoffset + startIndent); + block.setXOffset(xoffset + startIndent - paddingStart); block.setYOffset(yoffset + borderBeforeWidth); return block; } diff --git a/test/layoutengine/standard-testcases/table_backgrounds_2.xml b/test/layoutengine/standard-testcases/table_backgrounds_2.xml new file mode 100644 index 000000000..11d6d67f9 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_backgrounds_2.xml @@ -0,0 +1,113 @@ + + + + + +

    + This test checks background painting for fo:table-row, fo:table-body and fo:table-column + when the cells use padding. +

    +
    + + + + + + + + + + + + + + + background on cell + + + background on cell + + + + + background on row + + + background on row + + + + + + + background on body + + + background on body + + + + + + + + + + background on column + + + background on column + + + + + + + + + + background on table + + + background on table + + + + + + + + + + + + + + + + + + + + + + + + +
    -- cgit v1.2.3 From ce020dd650cbb124e2922b41fe6a0731e1990bdf Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 11 Mar 2008 11:02:27 +0000 Subject: Fixed a copy-paste error (getPaddingStart instead of getPaddingEnd) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@635884 13f79535-47bb-0310-9956-ffa450edef68 --- .../layoutmgr/table/TableCellLayoutManager.java | 2 +- .../standard-testcases/table_backgrounds_2.xml | 30 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index b99df4eb3..f86554dbd 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -545,7 +545,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager private Block getBackgroundArea(int bpd, int borderBeforeWidth) { CommonBorderPaddingBackground padding = getTableCell().getCommonBorderPaddingBackground(); int paddingStart = padding.getPaddingStart(false, this); - int paddingEnd = padding.getPaddingStart(false, this); + int paddingEnd = padding.getPaddingEnd(false, this); Block block = new Block(); TraitSetter.setProducerID(block, getTable().getId()); diff --git a/test/layoutengine/standard-testcases/table_backgrounds_2.xml b/test/layoutengine/standard-testcases/table_backgrounds_2.xml index 11d6d67f9..300d54234 100644 --- a/test/layoutengine/standard-testcases/table_backgrounds_2.xml +++ b/test/layoutengine/standard-testcases/table_backgrounds_2.xml @@ -36,28 +36,28 @@ - + background on cell - + background on cell - + background on row - + background on row - + background on body - + background on body @@ -68,10 +68,10 @@ background-color="violet"/> - + background on column - + background on column @@ -81,10 +81,10 @@ - + background on table - + background on table @@ -95,17 +95,17 @@ - + - + - + - + - + -- cgit v1.2.3 From 733c4e9f491ee3a1eeb57a49948d6c95a8177ff9 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 12 Mar 2008 10:51:09 +0000 Subject: Since compliance.ihtml is now the source file and it would cost too much to revert to an xml version, tidied the file a bit. No content change. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@636276 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 11726 ++++++++++++--------- 1 file changed, 6475 insertions(+), 5251 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 6e68fac59..a6eac4fb0 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -1,5 +1,5 @@ +"http://www.w3.org/TR/html4/loose.dtd"> + Apache FOP Compliance Page - +

    W3C XSL-FO 1.0 Standard

    -

    - One of FOP's design goals is conformance to the - W3C XSL-FO 1.0 standard, which specifies three levels - of "conformance": basic, extended, and complete. Although FOP does not currently conform to - any of these levels, it is nevertheless a useful work-in-progress for many applications. - The information presented here demonstrates FOP's progress toward the goal of conformance, - which progress consists of implementation of specific objects and properties in the standard. - The information presented is useful not only to the developers as a sort of "to do" list, - but also for setting proper expectations for users and potential users. -

    -

    - In the tables below, "yes" (green background) indicates conformance, "no" (red background) - indicates a lack of conformance, "partial" (greyish background) indicates partial conformance, - and "na" indicates that the item is "not applicable" to FOP usually because FOP supports only - visual media. -

    + +

    One of FOP's design goals is conformance to the W3C XSL-FO 1.0 standard, which specifies three + levels of "conformance": basic, extended, and complete. Although FOP does not currently conform + to any of these levels, it is nevertheless a useful work-in-progress for many applications. The + information presented here demonstrates FOP's progress toward the goal of conformance, which + progress consists of implementation of specific objects and properties in the standard. The + information presented is useful not only to the developers as a sort of "to do" list, but also + for setting proper expectations for users and potential users.

    + +

    In the tables below, "yes" (green background) indicates conformance, "no" (red background) + indicates a lack of conformance, "partial" (greyish background) indicates partial conformance, + and "na" indicates that the item is "not applicable" to FOP usually because FOP supports only + visual media.

    +

    XSL-FO Object Support

    + -

    XSL-FO Property Support

    - + +

    XSL-FO Property Support

    + + +

    XSL-FO Core Function Library Support

    + -

    XSL-FO Object Support Table (§6)

    -

    - The following is a summary of FOP's current support for the standard XSL-FO objects. -

    + +

    XSL-FO Object Support Table (§6)

    + +

    The following is a summary of FOP's current support for the standard XSL-FO objects.

    +
    Latest ReleaseLatest Stable Release
    Repository URL
    Latest Release
    Repository URL + + http://svn.apache.org/repos/asf/xmlgraphics/fop/tags/fop-0_95rc/ + +
    Web view + + http://svn.apache.org/viewvc/xmlgraphics/fop/tags/fop-0_95rc/ + +
    Trunk
    Image Supportstable, but in need of a redesignbeta (recently rewritten)
    Hyphenation Subsystem - + X @@ -298,6 +298,19 @@
    AFP + + + + + + + + + +
    Forrest -- cgit v1.2.3 From 50dc623e3669fa544c5b0072bede459fe878d6f2 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 09:15:50 +0000 Subject: Using Forrest Trunk from now on (in order to use FOP 0.94 for PDFs). We'll switch to a stable release as soon as a release with a new FOP version is available. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633397 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/dev/doc.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/dev/doc.xml b/src/documentation/content/xdocs/dev/doc.xml index a9d054316..4fd6bce78 100644 --- a/src/documentation/content/xdocs/dev/doc.xml +++ b/src/documentation/content/xdocs/dev/doc.xml @@ -97,9 +97,9 @@ Maintenance branch releases either copy the trunk content to the maintenance bra Step-by-step instructions for the deployment process again:

    - Please make sure you use Forrest from the 0.7 branch for the time being. You will need + Please make sure you use Forrest from the Trunk (revision 632959 or later) for the time being. You will need to download it directly from SVN: - http://svn.apache.org/repos/asf/forrest/branches/forrest_07_branch + http://svn.apache.org/repos/asf/forrest/trunk
    • Modify the sources of the website and check locally with Forrest (run "forrest run" or just "forrest").
    • -- cgit v1.2.3 From 9892073fa4312ae1b58122be32a27a68580c539a Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 11:50:34 +0000 Subject: Renamed to 0.95beta. Made changes and release notes work again by switching to the projectInfo plug-in rather than relying on our local copy of the stylesheets. There's a little bug (missing images) in the release notes for which I submitted a patch (https://issues.apache.org/jira/browse/FOR-1076) to Forrest. Brought status.xml more in line with the official status DTD. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633437 13f79535-47bb-0310-9956-ffa450edef68 --- forrest.properties | 3 +- forrest.properties.xml | 22 +++++ src/documentation/content/xdocs/site.xml | 6 +- src/documentation/content/xdocs/tabs.xml | 2 +- src/documentation/sitemap.xmap | 31 ------- status.xml | 141 +++++++++++++++++++------------ 6 files changed, 112 insertions(+), 93 deletions(-) create mode 100644 forrest.properties.xml (limited to 'src') diff --git a/forrest.properties b/forrest.properties index 40e6cf06c..95260e665 100644 --- a/forrest.properties +++ b/forrest.properties @@ -107,5 +107,4 @@ bugtracking-url=http://issues.apache.org/bugzilla/show_bug.cgi?id= # The names of plugins that are required to build the project # comma separated list (no spaces) # project.required.plugins= -#project.required.plugins=org.apache.forrest.plugin.input.projectInfo,org.apache.forrest.plugin.output.pdf -project.required.plugins=org.apache.forrest.plugin.output.pdf +project.required.plugins=org.apache.forrest.plugin.input.projectInfo,org.apache.forrest.plugin.output.pdf diff --git a/forrest.properties.xml b/forrest.properties.xml new file mode 100644 index 000000000..d0c01bf4a --- /dev/null +++ b/forrest.properties.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/src/documentation/content/xdocs/site.xml b/src/documentation/content/xdocs/site.xml index 79094c52d..18716903c 100644 --- a/src/documentation/content/xdocs/site.xml +++ b/src/documentation/content/xdocs/site.xml @@ -96,10 +96,10 @@ - + - - + + diff --git a/src/documentation/content/xdocs/tabs.xml b/src/documentation/content/xdocs/tabs.xml index 5fe5763a9..a42fc9bd7 100644 --- a/src/documentation/content/xdocs/tabs.xml +++ b/src/documentation/content/xdocs/tabs.xml @@ -22,7 +22,7 @@ - + diff --git a/src/documentation/sitemap.xmap b/src/documentation/sitemap.xmap index 21e289547..470db0b7b 100644 --- a/src/documentation/sitemap.xmap +++ b/src/documentation/sitemap.xmap @@ -20,37 +20,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/status.xml b/status.xml index 197d599b4..3765b5aed 100644 --- a/status.xml +++ b/status.xml @@ -16,23 +16,50 @@ limitations under the License. --> + - + + + + + + + - - - - + + + + + + + + + + + - + + + Slight improvement for thin lines in Java2D/AWT output. @@ -42,7 +69,7 @@ Turned on XInclude processing for the main source given on the command line. - + Improved the font auto-detection so fonts accessed using the font-family name are selected with higher accuracy. @@ -284,31 +311,21 @@ Added a configuration setting for the renderer/device resolution to the AFP renderer. -

      - Facilitate the implementation for font-selection-strategy: -

      -
        -
      • Changed FontInfo.fontLookup to always return an array of FontTriplet
      • -
      • Changed CommonFont.getFontState to return an array of FontTriplet
      • -
      • Initial modifications to the related LMs: initialized with - the font corresponding to the first of the triplets
      • -
      + Facilitate the implementation for font-selection-strategy:
      + • Changed FontInfo.fontLookup to always return an array of FontTriplet.
      + • Changed CommonFont.getFontState to return an array of FontTriplet.
      + • Initial modifications to the related LMs: initialized with + the font corresponding to the first of the triplets.
      -

      PropertyCache phase 2:

      -
        -
      • - improvement of the PropertyCache itself should now guarantee acceptable + PropertyCache phase 2:
        + • improvement of the PropertyCache itself should now guarantee acceptable performance of the static caches in multi-session environments, which is - a possible problem with synchronizedMap -
      • -
      • - changed CommonFont to use the cache: + a possible problem with synchronizedMap.
        + • changed CommonFont to use the cache: added CachedCommonFont to contain the properties that are always cacheable - CommonFont itself is only cached if the remaining properties are absolutes -
      • -
      • changed CommonHyphenation, KeepProperty, ColorProperty and FontFamilyProperty to use the cache
      • -
      + CommonFont itself is only cached if the remaining properties are absolutes.
      + • changed CommonHyphenation, KeepProperty, ColorProperty and FontFamilyProperty to use the cache.
      Fixed swallowing PCDATA in text-node children of @@ -468,33 +485,36 @@
      -

      This is the first production grade release of the new FOP - codebase.

      -
        -
      • It contains the new API first introduced in release 0.92 - beta. The preceding API has been removed. -
      • -
      • - See the compliance page for an - overview of the compliance of this release with the XSL 1.0 and - 1.1 recommendations. -
      • -
      • - This release again contains many bug fixes and new features. See - below for details. -
      • -
      • - See the known issues page - for an overview of the known issues with this release. -
      • -
      -

      Caveats:

      -
        -
      • - You may experience different behaviour compared to version 0.20.5. - Please consult the "Upgrading" page for details. -
      • -
      +
      + Notes +

      This is the first production grade release of the new FOP + codebase.

      +
        +
      • It contains the new API first introduced in release 0.92 + beta. The preceding API has been removed. +
      • +
      • + See the compliance page for an + overview of the compliance of this release with the XSL 1.0 and + 1.1 recommendations. +
      • +
      • + This release again contains many bug fixes and new features. See + below for details. +
      • +
      • + See the known issues page + for an overview of the known issues with this release. +
      • +
      +

      Caveats:

      +
        +
      • + You may experience different behaviour compared to version 0.20.5. + Please consult the "Upgrading" page for details. +
      • +
      +
      Added support for the use of Open Type fonts @@ -1069,9 +1089,18 @@ For the change log for the maintenance branch (where FOP 0.20.5 came from), please see the "CHANGES" file in the distribution, or - the CHANGES file in the SVN repository. + the CHANGES file in the SVN repository.
      + + + + + Improve the documentation. + + + +
      -- cgit v1.2.3 From c215e307c9665643fe21f09997bd377bfb0f1f8e Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 12:59:57 +0000 Subject: Copyright year git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633460 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/skinconf.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/documentation/skinconf.xml b/src/documentation/skinconf.xml index 38b7638b0..47c8d5e55 100644 --- a/src/documentation/skinconf.xml +++ b/src/documentation/skinconf.xml @@ -91,7 +91,7 @@ which will be used to configure the chosen Forrest skin. - 1999-2007 + 1999-2008 The Apache Software Foundation. http://www.apache.org/licenses/ -- cgit v1.2.3 From 2000a8302a33bfd45beeab08f3e9e2ed77397d35 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 16:13:17 +0000 Subject: Bugfix: Without the system ID (base URI), the XSLT processor cannot resolve document(, .) function calls correctly. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633525 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/cli/InputHandler.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/cli/InputHandler.java b/src/java/org/apache/fop/cli/InputHandler.java index f565a7a93..7ad89bfab 100644 --- a/src/java/org/apache/fop/cli/InputHandler.java +++ b/src/java/org/apache/fop/cli/InputHandler.java @@ -39,16 +39,18 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.render.awt.viewer.Renderable; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; /** * Class for handling files input from command line @@ -150,6 +152,7 @@ public class InputHandler implements ErrorListener, Renderable { try { InputSource is = new InputSource(new FileInputStream( this.sourcefile)); + is.setSystemId(this.sourcefile.toURI().toASCIIString()); SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setFeature("http://xml.org/sax/features/namespaces", true); spf.setFeature("http://apache.org/xml/features/xinclude", true); -- cgit v1.2.3 From ac24860f95758975e6e7cf51aeb203a9ed02cb30 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 17:30:40 +0000 Subject: Bugfix: If there's shrink available in an auto-height situation, the difference is now set to 0 in order to avoid unwanted effects. IOW, never shrink in an auto-height situation. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633557 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/PageBreakingAlgorithm.java | 8 ++- ...ock-container_absolute-position_no-height_3.xml | 63 ++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 test/layoutengine/standard-testcases/block-container_absolute-position_no-height_3.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 57fc4600e..d98d29b5c 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -364,7 +364,13 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { } else { // there are no footnotes } - return getLineWidth(activeNode.line) - actualWidth; + int diff = getLineWidth(activeNode.line) - actualWidth; + if (autoHeight && diff < 0) { + //getLineWidth() for auto-height parts return 0 so the diff will be negative + return 0; //...but we don't want to shrink in this case. Stick to optimum. + } else { + return diff; + } } /** Checks whether footnotes from preceding pages may be deferred to the page after diff --git a/test/layoutengine/standard-testcases/block-container_absolute-position_no-height_3.xml b/test/layoutengine/standard-testcases/block-container_absolute-position_no-height_3.xml new file mode 100644 index 000000000..d2eba0d3c --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_absolute-position_no-height_3.xml @@ -0,0 +1,63 @@ + + + + + +

      + This test checks absolutely positioned block-containers with auto-height and shrinks. +

      +
      + + + + + + + + + + + + Lorem ipsum dolor sit amet. + + + Lorem ipsum dolor sit amet. + + + Lorem ipsum dolor sit amet. + + + + + + + + + + + + + + +
      -- cgit v1.2.3 From 8fd9c919c4bb6a39eb7479a873e7f72ee06dcf7b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 17:35:52 +0000 Subject: Update FOP poster for OpenExpo 2008 in Bern. This fixes various warnings, updates the history and simplifies configuration (if you're on Windows, it will work out of the box because all fonts are available). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633559 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/poster/cfg/VERDANA.ttf.xml | 1817 -------------------- src/documentation/poster/cfg/VERDANAB.ttf.xml | 1167 ------------- src/documentation/poster/cfg/fop.xconf | 12 +- src/documentation/poster/cfg/lucon.ttf.xml | 925 ---------- .../poster/svg/pepe-business-card.svg | 3 +- .../poster/xml/business-card-demo.xml | 19 +- src/documentation/poster/xml/fop-history.xml | 11 +- src/documentation/poster/xml/fop-poster.xml | 10 +- .../poster/xml/fop-transformation-chain.xml | 2 +- src/documentation/poster/xml/fop-use-cases.xml | 3 +- src/documentation/poster/xslt/common.xsl | 6 +- src/documentation/poster/xslt/fop-poster.xsl | 13 +- 12 files changed, 34 insertions(+), 3954 deletions(-) delete mode 100644 src/documentation/poster/cfg/VERDANA.ttf.xml delete mode 100644 src/documentation/poster/cfg/VERDANAB.ttf.xml delete mode 100644 src/documentation/poster/cfg/lucon.ttf.xml (limited to 'src') diff --git a/src/documentation/poster/cfg/VERDANA.ttf.xml b/src/documentation/poster/cfg/VERDANA.ttf.xml deleted file mode 100644 index 1c113be9d..000000000 --- a/src/documentation/poster/cfg/VERDANA.ttf.xml +++ /dev/null @@ -1,1817 +0,0 @@ - - - - - Verdana - - 727 - 545 - 764 - -206 - - -49 - -206 - 1446 - 1000 - - 33 - 0 - 0 - TYPE0 - - CIDFontType2 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/documentation/poster/cfg/VERDANAB.ttf.xml b/src/documentation/poster/cfg/VERDANAB.ttf.xml deleted file mode 100644 index 0666d19b2..000000000 --- a/src/documentation/poster/cfg/VERDANAB.ttf.xml +++ /dev/null @@ -1,1167 +0,0 @@ - - - - - Verdana,Bold - - 727 - 548 - 764 - -206 - - -73 - -207 - 1707 - 1000 - - 33 - 0 - 0 - TYPE0 - - CIDFontType2 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/documentation/poster/cfg/fop.xconf b/src/documentation/poster/cfg/fop.xconf index 93b89465c..788d58920 100644 --- a/src/documentation/poster/cfg/fop.xconf +++ b/src/documentation/poster/cfg/fop.xconf @@ -17,23 +17,13 @@ --> - . 72 300 - - - - - - - - - - + diff --git a/src/documentation/poster/cfg/lucon.ttf.xml b/src/documentation/poster/cfg/lucon.ttf.xml deleted file mode 100644 index 27daebf6c..000000000 --- a/src/documentation/poster/cfg/lucon.ttf.xml +++ /dev/null @@ -1,925 +0,0 @@ - - - - - LucidaConsole - - 626 - 530 - 783 - -205 - - 0 - -210 - 602 - 789 - - 35 - 0 - 0 - TYPE0 - - CIDFontType2 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/documentation/poster/svg/pepe-business-card.svg b/src/documentation/poster/svg/pepe-business-card.svg index 6183e8cf2..559c87abe 100644 --- a/src/documentation/poster/svg/pepe-business-card.svg +++ b/src/documentation/poster/svg/pepe-business-card.svg @@ -16,7 +16,8 @@ limitations under the License. --> - diff --git a/src/documentation/poster/xml/business-card-demo.xml b/src/documentation/poster/xml/business-card-demo.xml index bfd56d793..9b7f80029 100644 --- a/src/documentation/poster/xml/business-card-demo.xml +++ b/src/documentation/poster/xml/business-card-demo.xml @@ -37,13 +37,13 @@ - +

      - - + + @@ -65,11 +65,11 @@ - - -

      The XSLT stylesheet which contains the rules to convert the business card XML to XSL-FO:

      - + + +

      The XSLT stylesheet which contains the rules to convert the business card XML to XSL-FO:

      + @@ -77,7 +77,8 @@ - + diff --git a/src/documentation/poster/xml/fop-history.xml b/src/documentation/poster/xml/fop-history.xml index ea8cc133f..0baa6340f 100644 --- a/src/documentation/poster/xml/fop-history.xml +++ b/src/documentation/poster/xml/fop-history.xml @@ -39,13 +39,12 @@

      In 2005, the redesign finally took a leap forward, which resulted in the first release from - the new codebase (FOP 0.90alpha). Shortly thereafter, FOP 0.91beta was released in December - 2005 and FOP 0.92beta in April 2006. Although 0.92beta still carries the beta tag, - it has many advantages over the old version 0.20.5. + the new codebase (FOP 0.90alpha). The project team has published a number of releases + since then. FOP made big steps forward.

      - The next version, to be released shortly, will be 0.93. This version should be the last release - before the long-awaited version 1.0, for which the team only has to implement a handful of - additional features. + The next version, to be released in March 2008, will be 0.95. Although FOP still carries + pre 1.0 version numbers it is production-ready. Some features are still missing before + version 1.0 can be released.

      diff --git a/src/documentation/poster/xml/fop-poster.xml b/src/documentation/poster/xml/fop-poster.xml index 67b44480b..419378b27 100644 --- a/src/documentation/poster/xml/fop-poster.xml +++ b/src/documentation/poster/xml/fop-poster.xml @@ -21,11 +21,11 @@
      -
      -
      -
      +
      +
      +
      -
      +
      -
      +
      diff --git a/src/documentation/poster/xml/fop-transformation-chain.xml b/src/documentation/poster/xml/fop-transformation-chain.xml index 7a713fdb2..58c8de856 100644 --- a/src/documentation/poster/xml/fop-transformation-chain.xml +++ b/src/documentation/poster/xml/fop-transformation-chain.xml @@ -19,7 +19,7 @@
      Transformation Chain - +

      This diagram shows a complete transformation chain (exemplary). It begins with your data source, diff --git a/src/documentation/poster/xml/fop-use-cases.xml b/src/documentation/poster/xml/fop-use-cases.xml index 250a6436c..d2f4878a5 100644 --- a/src/documentation/poster/xml/fop-use-cases.xml +++ b/src/documentation/poster/xml/fop-use-cases.xml @@ -19,8 +19,7 @@

      Use Cases - - + diff --git a/src/documentation/poster/xslt/common.xsl b/src/documentation/poster/xslt/common.xsl index ad8ac0109..5b02f52fd 100644 --- a/src/documentation/poster/xslt/common.xsl +++ b/src/documentation/poster/xslt/common.xsl @@ -37,14 +37,14 @@ + space-after.optimum="0.3em" space-after.maximum="1em"> + space-before.optimum="0.3em" space-before.maximum="1em" + space-after.optimum="0.3em" space-after.maximum="1em"> diff --git a/src/documentation/poster/xslt/fop-poster.xsl b/src/documentation/poster/xslt/fop-poster.xsl index 9c0b1a82b..dca0f6cfc 100644 --- a/src/documentation/poster/xslt/fop-poster.xsl +++ b/src/documentation/poster/xslt/fop-poster.xsl @@ -60,9 +60,6 @@ - - - @@ -84,14 +81,14 @@ - + Apache FOP - The leading open source XSL-FO formatter A product of the Apache XML Graphics Project - + For more details, please visit: http://xmlgraphics.apache.org/fop/ @@ -111,7 +108,7 @@ - + - + -- cgit v1.2.3 From 3fc5d3af38b065c8298c1f56efbc810f399213c7 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 4 Mar 2008 17:39:08 +0000 Subject: Update README. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633561 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/poster/README.txt | 5 +++-- src/documentation/poster/cfg/README.txt | 7 ------- 2 files changed, 3 insertions(+), 9 deletions(-) delete mode 100644 src/documentation/poster/cfg/README.txt (limited to 'src') diff --git a/src/documentation/poster/README.txt b/src/documentation/poster/README.txt index bc21dcc37..d5ef2c0a2 100644 --- a/src/documentation/poster/README.txt +++ b/src/documentation/poster/README.txt @@ -5,7 +5,8 @@ created for OpenExpo '06 (http://www.openexpo.ch). To create the PDF just call go.bat. -The fully reconstruct the PDF you need to copy some fonts into -the cfg directory. Please see the README.txt there for details. +The fully reconstruct the PDF you need some fonts installed in +your operating system: Verdana and Lucida Console which are +available in every Windows installation. You will also need English hyphenation patterns. \ No newline at end of file diff --git a/src/documentation/poster/cfg/README.txt b/src/documentation/poster/cfg/README.txt deleted file mode 100644 index b63dc83dd..000000000 --- a/src/documentation/poster/cfg/README.txt +++ /dev/null @@ -1,7 +0,0 @@ -The following files are missing here for license reasons: - -lucon.ttf - Lucida Console Font -verdana.ttf - Verdana Font -verdanab.ttf - Verdana Bold Font - -They can be found in every MS Windows installation. \ No newline at end of file -- cgit v1.2.3 From 77c8566a57472e33049c8e02dd753dd79944e2ad Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 5 Mar 2008 18:22:06 +0000 Subject: - Fixed the rendering of the area of a table corresponding to border-separation, which must be filled with the background of the table, and not the rows. - Improved conformance: even if a table-cell spans several rows its background must correspond to the first row spanned. - Added support for background on fo:table-column and fo:table-header/footer/body TODO more testcases needed, especially tables with collapsing border model and tables broken over pages git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@633961 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/TraitSetter.java | 86 ++++- .../org/apache/fop/layoutmgr/table/RowPainter.java | 93 ++++- .../layoutmgr/table/TableCellLayoutManager.java | 85 +++-- .../layoutmgr/table/TableContentLayoutManager.java | 164 ++++----- .../fop/layoutmgr/table/TableContentPosition.java | 5 + .../fop/layoutmgr/table/TableLayoutManager.java | 69 +++- status.xml | 11 + .../table-cell_conditional-spaces_2.xml | 64 ++-- .../table-footer_omit-footer-at-break.xml | 38 +- .../table-header_omit-header-at-break.xml | 34 +- .../table-header_table-footer_1.xml | 40 ++- .../table-header_table-footer_2.xml | 46 +-- .../table-row_background-image.xml | 20 +- .../standard-testcases/table-row_height.xml | 34 +- .../standard-testcases/table_backgrounds.xml | 392 +++++++++++++++++++++ 15 files changed, 930 insertions(+), 251 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table_backgrounds.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java index 841a94705..189212eb8 100644 --- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java +++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java @@ -280,6 +280,90 @@ public class TraitSetter { } } + /** + * Add background to an area. This method is mainly used by table-related layout + * managers to add background for column, body or row. Since the area corresponding to + * border-separation must be filled with the table's background, for every cell an + * additional area with the same dimensions is created to hold the background for the + * corresponding column/body/row. An additional shift must then be added to + * background-position-horizontal/vertical to ensure the background images are + * correctly placed. Indeed the placement of images must be made WRT the + * column/body/row and not the cell. + * + *

      Note: The area's IPD and BPD must be set before calling this method.

      + * + *

      TODO the regular + * {@link #addBackground(Area, CommonBorderPaddingBackground, PercentBaseContext)} + * method should be used instead, and a means to retrieve the original area's + * dimensions must be found.

      + * + *

      TODO the placement of images in the x- or y-direction will be incorrect if + * background-repeat is set for that direction.

      + * + * @param area the area to set the traits on + * @param backProps the background properties + * @param context Property evaluation context + * @param ipdShift horizontal shift to affect to the background, in addition to the + * value of the background-position-horizontal property + * @param bpdShift vertical shift to affect to the background, in addition to the + * value of the background-position-vertical property + * @param referenceIPD value to use as a reference for percentage calculation + * @param referenceBPD value to use as a reference for percentage calculation + */ + public static void addBackground(Area area, + CommonBorderPaddingBackground backProps, + PercentBaseContext context, + int ipdShift, int bpdShift, int referenceIPD, int referenceBPD) { + if (!backProps.hasBackground()) { + return; + } + Trait.Background back = new Trait.Background(); + back.setColor(backProps.backgroundColor); + + if (backProps.getImageInfo() != null) { + back.setURL(backProps.backgroundImage); + back.setImageInfo(backProps.getImageInfo()); + back.setRepeat(backProps.backgroundRepeat); + if (backProps.backgroundPositionHorizontal != null) { + if (back.getRepeat() == Constants.EN_NOREPEAT + || back.getRepeat() == Constants.EN_REPEATY) { + if (area.getIPD() > 0) { + PercentBaseContext refContext = new SimplePercentBaseContext(context, + LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, + (referenceIPD - back.getImageInfo().getSize().getWidthMpt())); + + back.setHoriz(ipdShift + + backProps.backgroundPositionHorizontal.getValue(refContext)); + } else { + // TODO Area IPD has to be set for this to work + log.warn("Horizontal background image positioning ignored" + + " because the IPD was not set on the area." + + " (Yes, it's a bug in FOP)"); + } + } + } + if (backProps.backgroundPositionVertical != null) { + if (back.getRepeat() == Constants.EN_NOREPEAT + || back.getRepeat() == Constants.EN_REPEATX) { + if (area.getBPD() > 0) { + PercentBaseContext refContext = new SimplePercentBaseContext(context, + LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL, + (referenceBPD - back.getImageInfo().getSize().getHeightMpt())); + back.setVertical(bpdShift + + backProps.backgroundPositionVertical.getValue(refContext)); + } else { + // TODO Area BPD has to be set for this to work + log.warn("Vertical background image positioning ignored" + + " because the BPD was not set on the area." + + " (Yes, it's a bug in FOP)"); + } + } + } + } + + area.addTrait(Trait.BACKGROUND, back); + } + /** * Add background to an area. * Layout managers that create areas with a background can use this to @@ -312,7 +396,7 @@ public class TraitSetter { back.setHoriz(backProps.backgroundPositionHorizontal.getValue( new SimplePercentBaseContext(context, LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, - (width - back.getImageInfo().getSize().getHeightMpt()) + (width - back.getImageInfo().getSize().getWidthMpt()) ) )); } else { diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index 022ff0589..61f6b3aec 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -26,22 +26,23 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.area.Block; import org.apache.fop.fo.flow.table.ConditionalBorder; 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.fo.flow.table.TableBody; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.SpaceResolver; +import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.BorderProps; class RowPainter { private static Log log = LogFactory.getLog(RowPainter.class); - /** The fo:table-row containing the currently handled grid rows. */ - private TableRow rowFO = null; private int colCount; private int currentRowOffset = 0; /** Currently handled row (= last encountered row). */ @@ -71,6 +72,13 @@ class RowPainter { private CellPart[] firstCellParts; private CellPart[] lastCellParts; + /** y-offset of the current table part. */ + private int tablePartOffset = 0; + /** See {@link RowPainter#registerPartBackgroundArea(Block)}. */ + private CommonBorderPaddingBackground tablePartBackground; + /** See {@link RowPainter#registerPartBackgroundArea(Block)}. */ + private List tablePartBackgroundAreas; + private TableContentLayoutManager tclm; RowPainter(TableContentLayoutManager tclm, LayoutContext layoutContext) { @@ -85,6 +93,44 @@ class RowPainter { this.firstRowOnPageIndex = -1; } + void startTablePart(TableBody tablePart) { + CommonBorderPaddingBackground background = tablePart.getCommonBorderPaddingBackground(); + if (background.hasBackground()) { + tablePartBackground = background; + if (tablePartBackgroundAreas == null) { + tablePartBackgroundAreas = new ArrayList(); + } + } + tablePartOffset = currentRowOffset; + } + + /** + * Signals that the end of the current table part is reached. + * + * @param lastInBody true if the part is the last table-body element to be displayed + * on the current page. In which case all the cells must be flushed even if they + * aren't finished, plus the proper collapsed borders must be selected (trailing + * instead of normal, or rest if the cell is unfinished) + * @param lastOnPage true if the part is the last to be displayed on the current page. + * In which case collapsed after borders for the cells on the last row must be drawn + * in the outer mode + */ + void endTablePart(boolean lastInBody, boolean lastOnPage) { + addAreasAndFlushRow(lastInBody, lastOnPage); + + if (tablePartBackground != null) { + TableLayoutManager tableLM = tclm.getTableLM(); + for (Iterator iter = tablePartBackgroundAreas.iterator(); iter.hasNext();) { + Block backgroundArea = (Block) iter.next(); + TraitSetter.addBackground(backgroundArea, tablePartBackground, tableLM, + -backgroundArea.getXOffset(), tablePartOffset - backgroundArea.getYOffset(), + tableLM.getContentAreaIPD(), currentRowOffset - tablePartOffset); + } + tablePartBackground = null; + tablePartBackgroundAreas.clear(); + } + } + int getAccumulatedBPD() { return currentRowOffset; } @@ -108,7 +154,6 @@ class RowPainter { currentRow = row; } } - rowFO = currentRow.getTableRow(); if (firstRowIndex < 0) { firstRowIndex = currentRow.getIndex(); if (firstRowOnPageIndex < 0) { @@ -148,7 +193,7 @@ class RowPainter { * displayed on the current page. In which case collapsed after borders must be drawn * in the outer mode */ - void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) { + private void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) { if (log.isDebugEnabled()) { log.debug("Remembering yoffset for row " + currentRow.getIndex() + ": " + currentRowOffset); @@ -182,8 +227,6 @@ class RowPainter { } // Then add areas for cells finishing on the current row - tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), - currentRowOffset); for (int i = 0; i < colCount; i++) { GridUnit currentGU = currentRow.getGridUnit(i); if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 @@ -278,8 +321,20 @@ class RowPainter { * Determine the index of the first row of this cell that will be displayed on the * current page. */ - int startRowIndex = Math.max(pgu.getRowIndex(), firstRowIndex); int currentRowIndex = currentRow.getIndex(); + int startRowIndex; + int firstRowHeight; + if (pgu.getRowIndex() >= firstRowIndex) { + startRowIndex = pgu.getRowIndex(); + if (startRowIndex < currentRowIndex) { + firstRowHeight = getRowOffset(startRowIndex + 1) - getRowOffset(startRowIndex); + } else { + firstRowHeight = rowHeight; + } + } else { + startRowIndex = firstRowIndex; + firstRowHeight = 0; + } /* * In collapsing-border model, if the cell spans over several columns/rows then @@ -319,7 +374,25 @@ class RowPainter { cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(), startPos, endPos + 1), layoutContext, spannedGridRowHeights, startRowIndex - pgu.getRowIndex(), currentRowIndex - pgu.getRowIndex(), borderBeforeWhich, borderAfterWhich, - startRowIndex == firstRowOnPageIndex, lastOnPage); + startRowIndex == firstRowOnPageIndex, lastOnPage, this, firstRowHeight); + } + + + /** + * Registers the given area, that will be used to render the part of + * table-header/footer/body background covered by a table-cell. If percentages are + * used to place the background image, the final bpd of the (fraction of) table part + * 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 + * {@link #addAreasAndFlushRow(boolean, boolean)}. + * + * @param backgroundArea the block of the cell's dimensions that will hold the part + * background + */ + void registerPartBackgroundArea(Block backgroundArea) { + tclm.getTableLM().addBackgroundArea(backgroundArea); + tablePartBackgroundAreas.add(backgroundArea); } /** @@ -357,11 +430,13 @@ class RowPainter { } // TODO get rid of that + /** Signals that the first table-body instance has started. */ void startBody() { Arrays.fill(firstCellOnPage, true); } // TODO get rid of that + /** Signals that the last table-body instance has ended. */ void endBody() { Arrays.fill(firstCellOnPage, false); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 289785d68..8e92a233b 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -27,12 +27,14 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.Trait; import org.apache.fop.datatypes.PercentBaseContext; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; 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.TableCell; +import org.apache.fop.fo.flow.table.TableColumn; +import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.layoutmgr.AreaAdditionUtil; @@ -71,7 +73,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager private int xoffset; private int yoffset; private int cellIPD; - private int rowHeight; + private int totalHeight; private int usedBPD; private int borderAndPaddingBPD; private boolean emptyCell = true; @@ -116,11 +118,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * @return the table owning this cell */ public Table getTable() { - FONode node = fobj.getParent(); - while (!(node instanceof Table)) { - node = node.getParent(); - } - return (Table)node; + return getTableCell().getTable(); } @@ -303,7 +301,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * @param h the height of cell */ public void setTotalHeight(int h) { - rowHeight = h; + totalHeight = h; } /** @@ -330,6 +328,10 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * which case collapsed before borders must be drawn in the outer mode * @param lastOnPage true if the cell will be the very last one on the page, in which * case collapsed after borders must be drawn in the outer mode + * @param painter painter + * @param firstRowHeight height of the first row spanned by this cell (may be zero if + * this row is placed on a previous page). Used to calculate the placement of the + * row's background image if any */ public void addAreas(PositionIterator parentIter, LayoutContext layoutContext, @@ -339,13 +341,24 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager int borderBeforeWhich, int borderAfterWhich, boolean firstOnPage, - boolean lastOnPage) { + boolean lastOnPage, + RowPainter painter, + int firstRowHeight) { getParentArea(null); getPSLM().addIDToPage(getTableCell().getId()); int borderBeforeWidth = primaryGridUnit.getBeforeBorderWidth(startRow, borderBeforeWhich); int borderAfterWidth = primaryGridUnit.getAfterBorderWidth(endRow, borderAfterWhich); + + CommonBorderPaddingBackground padding = primaryGridUnit.getCell() + .getCommonBorderPaddingBackground(); + int cellBPD = totalHeight - borderBeforeWidth - borderAfterWidth; + cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this); + cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this); + + addBackgroundAreas(painter, firstRowHeight, borderBeforeWidth, cellBPD); + if (isSeparateBorderModel()) { if (!emptyCell || getTableCell().showEmptyCells()) { if (borderBeforeWidth > 0) { @@ -437,18 +450,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } } - CommonBorderPaddingBackground padding = primaryGridUnit.getCell() - .getCommonBorderPaddingBackground(); TraitSetter.addPadding(curBlockArea, padding, borderBeforeWhich == ConditionalBorder.REST, borderAfterWhich == ConditionalBorder.REST, false, false, this); - int cellBPD = rowHeight - borderBeforeWidth - borderAfterWidth; - cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this); - cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this); - //Handle display-align if (usedBPD < cellBPD) { if (getTableCell().getDisplayAlign() == EN_CENTER) { @@ -468,16 +475,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager curBlockArea.setBPD(cellBPD); // Add background after we know the BPD - if (isSeparateBorderModel()) { - if (!emptyCell || getTableCell().showEmptyCells()) { - TraitSetter.addBackground(curBlockArea, - getTableCell().getCommonBorderPaddingBackground(), - this); - } - } else { + if (!isSeparateBorderModel() || !emptyCell || getTableCell().showEmptyCells()) { TraitSetter.addBackground(curBlockArea, - getTableCell().getCommonBorderPaddingBackground(), - this); + getTableCell().getCommonBorderPaddingBackground(), this); } flush(); @@ -485,6 +485,32 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager curBlockArea = null; } + /** Adds background areas for the column, body and row, if any. */ + private void addBackgroundAreas(RowPainter painter, int firstRowHeight, int borderBeforeWidth, + int cellBPD) { + TableColumn column = getTable().getColumn(primaryGridUnit.getColIndex()); + if (column.getCommonBorderPaddingBackground().hasBackground()) { + Block colBackgroundArea = getBackgroundArea(cellBPD, borderBeforeWidth); + ((TableLayoutManager) parentLM).registerColumnBackgroundArea(column, colBackgroundArea, + -startIndent); + } + + TableBody body = primaryGridUnit.getTableBody(); + if (body.getCommonBorderPaddingBackground().hasBackground()) { + painter.registerPartBackgroundArea(getBackgroundArea(cellBPD, borderBeforeWidth)); + } + + TableRow row = primaryGridUnit.getRow(); + if (row != null && row.getCommonBorderPaddingBackground().hasBackground()) { + Block rowBackgroundArea = getBackgroundArea(cellBPD, borderBeforeWidth); + ((TableLayoutManager) parentLM).addBackgroundArea(rowBackgroundArea); + TraitSetter.addBackground(rowBackgroundArea, row.getCommonBorderPaddingBackground(), + (TableLayoutManager) parentLM, + -xoffset - startIndent, -borderBeforeWidth, + parentLM.getContentAreaIPD(), firstRowHeight); + } + } + private void addBorder(Block[][] blocks, int i, int j, Integer side, BorderInfo border, boolean outer) { if (blocks[i][j] == null) { @@ -513,6 +539,17 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager block.setBPD(block.getBPD() + amount); } + private Block getBackgroundArea(int bpd, int borderBeforeWidth) { + Block block = new Block(); + TraitSetter.setProducerID(block, getTable().getId()); + block.setPositioning(Block.ABSOLUTE); + block.setIPD(cellIPD); + block.setBPD(bpd); + block.setXOffset(xoffset + startIndent); + block.setYOffset(yoffset + borderBeforeWidth); + return block; + } + /** * Return an Area which can contain the passed childArea. The childArea * may not yet have any content, but it has essential traits set. diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 5fad1e4c5..7cdeb79d5 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -27,8 +27,6 @@ import java.util.Map; 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,7 +34,6 @@ import org.apache.fop.fo.flow.table.EffRow; 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; @@ -46,7 +43,6 @@ 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; @@ -293,7 +289,7 @@ public class TableContentLayoutManager implements PercentBaseContext { 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; @@ -330,7 +326,7 @@ public class TableContentLayoutManager implements PercentBaseContext { //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); @@ -359,21 +355,23 @@ public class TableContentLayoutManager implements PercentBaseContext { 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(); @@ -384,105 +382,73 @@ public class TableContentLayoutManager implements PercentBaseContext { } } + private void addHeaderFooterAreas(List elements, TableBody part, RowPainter painter, + boolean lastOnPage) { + 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) { + lst.add((TableContentPosition) pos); + } + } + addTablePartAreas(lst, painter, part, true, true, true, lastOnPage); + } + /** - * Iterates over a part of the table (header, footer, body) and paints the related - * elements. + * 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 Position elements. Those positions correspond to the - * elements of the table present on the current page + * @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 corresponding part will be the last on the page - * (either body or footer, obviously) + * @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) */ - private void iterateAndPaintPositions(Iterator iterator, RowPainter painter, + private void addBodyAreas(Iterator iterator, RowPainter painter, boolean lastOnPage) { + painter.startBody(); List lst = new ArrayList(); - boolean firstPos = false; - TableBody body = null; + 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()) { - Position pos = (Position)iterator.next(); - if (pos instanceof TableContentPosition) { - TableContentPosition tcpos = (TableContentPosition)pos; - lst.add(tcpos); - CellPart part = (CellPart)tcpos.cellParts.get(0); - if (body == null) { - body = part.pgu.getTableBody(); - } - if (tcpos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP) - && tcpos.getRow().getFlag(EffRow.FIRST_IN_PART)) { - firstPos = true; - - } - if (tcpos.getFlag(TableContentPosition.LAST_IN_ROWGROUP) - && tcpos.getRow().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(); - } + 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); } - 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); + 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(); } /** - * 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 + * Adds the areas corresponding to a single fo:table-header/footer/body element. */ - 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 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); } - /** - * 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 - */ - 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()); - } - } - - /** * Sets the overall starting x-offset. Used for proper placement of cells. * @param startXOffset starting x-offset (table's start-indent) diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java index e702c58a9..db34764b1 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java @@ -22,6 +22,7 @@ package org.apache.fop.layoutmgr.table; 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; @@ -79,6 +80,10 @@ class TableContentPosition extends Position { return row; } + TableBody getTableBody() { + return ((CellPart) cellParts.get(0)).pgu.getTableBody(); + } + /** * Returns a flag for this GridUnit. * @param which the requested flag diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 1cbc3e50a..0b3967643 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -19,8 +19,10 @@ 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; @@ -79,7 +81,27 @@ public class TableLayoutManager extends BlockStackingLayoutManager 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 @@ -263,7 +285,30 @@ public class TableLayoutManager extends BlockStackingLayoutManager 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. @@ -298,6 +343,17 @@ public class TableLayoutManager extends BlockStackingLayoutManager 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(), @@ -366,6 +422,15 @@ public class TableLayoutManager extends BlockStackingLayoutManager } } + /** + * 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} */ public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) { // TODO Auto-generated method stub diff --git a/status.xml b/status.xml index e622c589f..594b113e1 100644 --- a/status.xml +++ b/status.xml @@ -94,6 +94,17 @@

      + + Added support for background on fo:table-column and fo:table-header/footer/body elements. + + + Fixed the rendering of the area of a table corresponding to border-separation, which must + be filled with the background of the table, and not the rows. + + + Improved conformance: even if a table-cell spans several rows its background must + correspond to the first row spanned. + Slight improvement for thin lines in Java2D/AWT output. diff --git a/test/layoutengine/standard-testcases/table-cell_conditional-spaces_2.xml b/test/layoutengine/standard-testcases/table-cell_conditional-spaces_2.xml index 1a9940e38..9a0920cf1 100644 --- a/test/layoutengine/standard-testcases/table-cell_conditional-spaces_2.xml +++ b/test/layoutengine/standard-testcases/table-cell_conditional-spaces_2.xml @@ -168,94 +168,108 @@ + - - - + + + - - + + + + - - + + + + - - - + + + - - + + + + - - - + + + + - - + + + - - + + + + - - - + + + - + + - + + - + + diff --git a/test/layoutengine/standard-testcases/table-footer_omit-footer-at-break.xml b/test/layoutengine/standard-testcases/table-footer_omit-footer-at-break.xml index 7b2cc6904..59c60f72e 100644 --- a/test/layoutengine/standard-testcases/table-footer_omit-footer-at-break.xml +++ b/test/layoutengine/standard-testcases/table-footer_omit-footer-at-break.xml @@ -97,35 +97,35 @@ - - - + + + - - - - - - + + + + + + - + - - - + + + - - + + - - - - + + + + diff --git a/test/layoutengine/standard-testcases/table-header_omit-header-at-break.xml b/test/layoutengine/standard-testcases/table-header_omit-header-at-break.xml index 6834deeac..5ec211645 100644 --- a/test/layoutengine/standard-testcases/table-header_omit-header-at-break.xml +++ b/test/layoutengine/standard-testcases/table-header_omit-header-at-break.xml @@ -32,7 +32,7 @@ - + @@ -97,23 +97,23 @@ - - - + + + - - - - - - + + + + + + - - - - + + + + @@ -122,8 +122,8 @@ - - - + + + diff --git a/test/layoutengine/standard-testcases/table-header_table-footer_1.xml b/test/layoutengine/standard-testcases/table-header_table-footer_1.xml index df45e328b..00cbcde54 100644 --- a/test/layoutengine/standard-testcases/table-header_table-footer_1.xml +++ b/test/layoutengine/standard-testcases/table-header_table-footer_1.xml @@ -32,7 +32,7 @@ - + @@ -82,31 +82,41 @@ - + + + + + + - - - + + + - - - - + + + + - - - - - + - + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/table-header_table-footer_2.xml b/test/layoutengine/standard-testcases/table-header_table-footer_2.xml index 9cf3db4c0..7716dfe58 100644 --- a/test/layoutengine/standard-testcases/table-header_table-footer_2.xml +++ b/test/layoutengine/standard-testcases/table-header_table-footer_2.xml @@ -32,7 +32,7 @@ - + @@ -97,40 +97,40 @@ - - - + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + diff --git a/test/layoutengine/standard-testcases/table-row_background-image.xml b/test/layoutengine/standard-testcases/table-row_background-image.xml index fa29f1b8e..f4dc65ae7 100644 --- a/test/layoutengine/standard-testcases/table-row_background-image.xml +++ b/test/layoutengine/standard-testcases/table-row_background-image.xml @@ -34,10 +34,8 @@ - - - - + + @@ -82,8 +80,20 @@ - + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/table-row_height.xml b/test/layoutengine/standard-testcases/table-row_height.xml index b158113f6..934afa69f 100644 --- a/test/layoutengine/standard-testcases/table-row_height.xml +++ b/test/layoutengine/standard-testcases/table-row_height.xml @@ -81,27 +81,37 @@ - - + + + - + + + + + - - - - + - + + + + + + + + + - - - - + + + + diff --git a/test/layoutengine/standard-testcases/table_backgrounds.xml b/test/layoutengine/standard-testcases/table_backgrounds.xml new file mode 100644 index 000000000..30564ecf7 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_backgrounds.xml @@ -0,0 +1,392 @@ + + + + + +

      + This test checks backgrounds on table elements. +

      +
      + + ../../resources/images/fop-logo-gray-8bit.png
      +
    - - - - - + + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - +
      +
    • [0.93 and later] The page width may not change among pages of the same page-sequence + unless a forced break is inserted.
    • +
    + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + - + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + +
  • [0.20.5] Currently only works as direct child of fo:flow.
  • + +
  • [0.20.5] For absolute positioning, use 'position="absolute"' (as + 'absolute-position="absolute"' is not implemented), and specify all four of "left", + "top", "width" and "height"
  • + +
  • [0.93 and later] No known restrictions.
  • + + + - - - - - - - + + - - - - - - - + + + + + + + + + + + + + -
    - Object Name - XSL-FO Conformance Level - Citation - Support in FOP - Comments Object NameXSL-FO Conformance LevelCitationSupport in FOPComments
    - 0.20.5 (previous) 0.20.5 (previous)0.95 (stable) - develop- ment
    - Declarations and Pagination and Layout Formatting Objects (§6.4)
    - root - Basic - §6.4.2 - yes - yes - yes  
    - declarations - Basic - §6.4.3 - no - no - no  
    - color-profile - Extended - §6.4.4 - no - no - no  
    - page-sequence - Basic - §6.4.5 - yes - yes - yes  
    - layout-master-set - Basic - §6.4.6 - yes - yes - yes  
    - page-sequence-master - Basic - §6.4.7 - yes - yes - yes  
    - single-page-master-reference - Basic - §6.4.8 - yes - yes - yes  
    - repeatable-page-master-reference - Basic - §6.4.9 - yes - yes - yes  
    - repeatable-page-master-alternatives - Extended - §6.4.10 - yes - yes - yes  
    - conditional-page-master-reference - Extended - §6.4.11 - yes - yes - yes  
    - simple-page-master - Basic - §6.4.12 - yes - partial - partial -
      -
    • - [0.93 and later] The page width may not change among pages of the same page-sequence - unless a forced break is inserted.
    • -
    develop- ment
    - region-body - Basic - §6.4.13 - yes - yes - yes
    - region-before - Extended - §6.4.14 - yes - yes - yes  
    - region-after - Extended - §6.4.15 - yes - yes - yes  
    - region-start - Extended - §6.4.16 - yes - yes - yes  
    - region-end - Extended - §6.4.17 - yes - yes - yes  
    - flow - Basic - §6.4.18 - yes - yes - yes  
    - static-content - Extended - §6.4.19 - yes - yes - yes  
    - title - Extended - §6.4.20 - no - no - no   Declarations and Pagination and Layout Formatting Objects + (§6.4)
    - Block Formatting Objects (§6.5) rootBasic§6.4.2yesyesyes 
    - block - Basic - §6.5.2 - yes - yes - yes  
    - block-container - Extended - §6.5.3 - partial - partial - partial -
      -
    • - [0.20.5] Currently only works as direct child of fo:flow.
    • -
    • - [0.20.5] For absolute positioning, use 'position="absolute"' (as 'absolute-position="absolute"' is not implemented), and specify all four of "left", "top", "width" and "height"
    • -
    • - [0.93 and later] No known restrictions.
    • -
    declarationsBasic§6.4.3nonono 
    - Inline Formatting Objects (§6.6) color-profileExtended§6.4.4nonono 
    - bidi-override - Extended - §6.6.2 - no - no - no  
    - character - Basic - §6.6.3 - yes - yes - yes  
    - initial-property-set - Extended - §6.6.4 - no - no - no  
    - external-graphic - Basic - §6.6.5 - yes - yes - yes  
    - instream-foreign-object - Extended - §6.6.6 - yes - yes - yes -
      -
    • Built-in support for SVG only, additional namespaces through optional extensions.
    • -
    page-sequenceBasic§6.4.5yesyesyes 
    - inline - Basic - §6.6.7 - yes - yes - yes  
    - inline-container - Extended - §6.6.8 - no - no - no  
    - leader - Basic - §6.6.9 - partial - yes - yes  
    - page-number - Basic - §6.6.10 - yes - yes - yes  
    - page-number-citation - Extended - §6.6.11 - partial - partial - partial -
      -
    • - [0.20.5] Only works for table of contents without any problems. The case where the page number doesn't fit on a line isn't handled, and any text on the same line and after the page-number might not appear exactly where you want it to.
    • -
    • - [0.93 and later] After the page number is known, no relayout is performed. The appearance may be suboptimal depending on the use case.
    • -
    layout-master-setBasic§6.4.6yesyesyes 
    - Table Formatting Objects (§6.7) page-sequence-masterBasic§6.4.7yesyesyes 
    - table-and-caption - Basic - §6.7.2 - no - no - no  
    - table - Basic - §6.7.3 - partial - partial - partial -
      -
    • [0.20.5–0.93] Only border-collapse="separate"
    • -
    • [All] No support for auto layout yet
    • -
    -
    single-page-master-referenceBasic§6.4.8yesyesyes 
    - table-column - Basic - §6.7.4 - partial - yes - yes -
      -
    • - [0.20.5] You must explicitly specify column widths.
    • -
    repeatable-page-master-referenceBasic§6.4.9yesyesyes 
    - table-caption - Extended - §6.7.5 - no - no - no  
    - table-header - Basic - §6.7.6 - yes - yes - yes  
    - table-footer - Extended - §6.7.7 - yes - yes - yes  
    - table-body - Basic - §6.7.8 - yes - yes - yes  
    - table-row - Basic - §6.7.9 - yes - yes - yes  
    - table-cell - Basic - §6.7.10 - partial - yes - yes   repeatable-page-master-alternativesExtended + §6.4.10yesyesyes 
    - List Formatting Objects (§6.8) conditional-page-master-referenceExtended + §6.4.11yesyesyes 
    - list-block - Basic - §6.8.2 - yes - yes - yes  
    - list-item - Basic - §6.8.3 - yes - yes - yes  
    - list-item-body - Basic - §6.8.4 - yes - yes - yes  
    - list-item-label - Extended simple-page-masterBasic§6.4.12yespartialpartial - §6.8.5 - yes - yes - yes  
    - Link and Multi Formatting Objects (§6.9) region-bodyBasic§6.4.13yesyesyes
    - basic-link - Extended - §6.9.2 - yes - yes - yes -
      -
    • - both internal and external supported
    • -
    - multi-switch - Extended - §6.9.3 - no - no - no  
    - multi-case - Basic - §6.9.4 - no - no - no  
    - multi-toggle - Extended - §6.9.5 - no - no - no  
    - multi-properties - Extended - §6.9.6 - no - no - no  
    - multi-property-set - Extended - §6.9.7 - no - no - no   region-beforeExtended§6.4.14yesyesyes 
    - Formatting Objects for Bookmarks (§6.11 in XSL 1.1 WD) region-afterExtended§6.4.15yesyesyes 
    - bookmark-tree (since XSL 1.1) - Extended - §6.11.1 in XSL 1.1 WD - no - yes - yes -
      -
    • [0.20.5] Uses the proprietary fox:outline extension.
    • -
    region-startExtended§6.4.16yesyesyes 
    - bookmark (since XSL 1.1) - Extended - §6.11.2 in XSL 1.1 WD - no - yes - yes -
      -
    • [0.20.5] Uses the proprietary fox:outline extension.
    • -
    region-endExtended§6.4.17yesyesyes 
    - bookmark-title (since XSL 1.1) - Extended - §6.11.3 in XSL 1.1 WD - no - partial - partial -
      -
    • [0.20.5] Uses the proprietary fox:outline extension.
    • -
    • [0.93 and later] color, font-style and font-weight are not supported, yet.
    • -
    flowBasic§6.4.18yesyesyes 
    - Out-of-line Formatting Objects (§6.10) static-contentExtended§6.4.19yesyesyes 
    - float - Extended - §6.10.2 - no - no - no  
    - footnote - Extended - §6.10.3 - yes - partial - partial -
      -
    • [0.20.5] Footnotes sometimes overlap with the main content
    • -
    • [0.93 and later] Restrictions with multi-column documents.
    • -
    titleExtended§6.4.20nonono 
    - footnote-body - Extended - §6.10.4 - yes - yes - yes   Block Formatting Objects (§6.5)
    - Other Formatting Objects (§6.11) blockBasic§6.5.2yesyesyes 
    - wrapper - Basic - §6.11.2 - yes - partial - partial block-containerExtended§6.5.3partialpartialpartial
      -
    • [0.93 and later] Only works as expected with inline-level content.
    • -
    - marker - Extended - §6.11.3 - yes - yes - yes  Inline Formatting Objects (§6.6)
    - retrieve-marker - Extended - §6.11.4 - yes - yes - yes   bidi-overrideExtended§6.6.2nonono 
    -

    XSL-FO Property Support Table (§7)

    -

    - The following is a summary of FOP's current support for the standard XSL-FO properties. -

    - + - - - - - + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + - - - - +
      +
    • Built-in support for SVG only, additional namespaces through optional + extensions.
    • +
    + + - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + +
  • [0.20.5–0.93] Only border-collapse="separate"
  • + +
  • [All] No support for auto layout yet
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + +
  • [0.20.5] You must explicitly specify column widths.
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + - - - - - - + + + + + + + + + + + + +
  • both internal and external supported
  • + + + - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + +
  • [0.20.5] Footnotes sometimes overlap with the main content
  • + +
  • [0.93 and later] Restrictions with multi-column documents.
  • + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + - - - - - - + + + + + + + + + + + + +
  • [0.93 and later] Only works as expected with inline-level content.
  • + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + +
    - Property Name - XSL-FO Conformance Level - Citation - Support in FOP - Comments characterBasic§6.6.3yesyesyes 
    - 0.20.5 (previous) 0.95 (stable) - develop- ment initial-property-setExtended§6.6.4nonono 
    - Common Accessibility Properties (§7.4) external-graphicBasic§6.6.5yesyesyes 
    - source-document - Basic - §7.4.1 - na - na - na  
    - role - Basic instream-foreign-objectExtended§6.6.6yesyesyes - §7.4.2 - na - na - na  
    - Common Absolute Position Properties (§7.5) inlineBasic§6.6.7yesyesyes 
    - absolute-position - Complete - §7.5.1 - no - yes - yes -
      -
    • - [0.20.5] Use shorthand position="absolute" as a workaround.
    • -
    • - [0.93 and later] No restrictions. The 0.20.5 work-around is not supported.
    • -
    inline-containerExtended§6.6.8nonono 
    - top - Extended - §7.5.2 - yes - yes - yes  
    - right - Extended - §7.5.3 - yes - yes - yes  
    - bottom - Extended - §7.5.4 - yes - yes - yes  
    - left - Extended - §7.5.5 - yes - yes - yes   leaderBasic§6.6.9partialyesyes 
    - Common Aural Properties (§7.6) page-numberBasic§6.6.10yesyesyes 
    - azimuth - Basic - §7.6.1 - na - na - na  
    - cue-after - Basic - §7.6.2 - na - na - na  
    - cue-before - Basic - §7.6.3 - na - na - na  
    - elevation - Basic - §7.6.4 - na - na - na  
    - pause-after - Basic - §7.6.5 - na - na - na  
    - pause-before - Basic - §7.6.6 - na - na - na  
    - pitch - Basic - §7.6.7 - na - na - na  
    - pitch-range - Basic - §7.6.8 - na - na - na  
    - play-during - Basic - §7.6.9 - na - na - na  
    - richness - Basic - §7.6.10 - na - na - na  
    - speak - Basic - §7.6.11 - na - na - na  
    - speak-header - Basic - §7.6.12 - na - na - na  
    - speak-numeral - Basic - §7.6.13 - na - na - na  
    - speak-punctuation - Basic - §7.6.14 - na - na - na  
    - speech-rate - Basic - §7.6.15 - na - na - na  
    - stress - Basic - §7.6.16 - na - na - na  
    - voice-family - Basic - §7.6.17 - na - na - na  
    - volume - Basic - §7.6.18 - na - na - na   page-number-citationExtended§6.6.11partialpartialpartial +
      +
    • [0.20.5] Only works for table of contents without any problems. The case where the + page number doesn't fit on a line isn't handled, and any text on the same line and after + the page-number might not appear exactly where you want it to.
    • + +
    • [0.93 and later] After the page number is known, no relayout is performed. The + appearance may be suboptimal depending on the use case.
    • +
    +
    - Common Border, Padding, and Background Properties (§7.7) Table Formatting Objects (§6.7)
    - background-attachment - Extended - §7.7.1 - no - no - no  
    - background-color - Basic - §7.7.2 - yes - partial - partial -
      -
    • - [0.93 and later] not yet implemented for table-column, table-body, table-header and table-footer.
    • -
    table-and-captionBasic§6.7.2nonono 
    - background-image - Extended - §7.7.3 - yes - partial - partial tableBasic§6.7.3partialpartialpartial
      -
    • - [0.93 and later] not yet implemented for table-column, table-body, table-header and table-footer.
    • -
    - background-repeat - Extended - §7.7.4 - no - yes - yes  
    - background-position-horizontal - Extended - §7.7.5 - no - yes - yes  
    - background-position-vertical - Extended - §7.7.6 - no - yes - yes  
    - border-before-color - Basic - §7.7.7 - yes - yes - yes  
    - border-before-style - Basic - §7.7.8 - partial - yes - yes table-columnBasic§6.7.4partialyesyes
      -
    • - [0.20.5] only "solid" works
    • -
    - border-before-width - Basic - §7.7.9 - yes - yes - yes  
    - border-after-color - Basic - §7.7.10 - yes - yes - yes  
    - border-after-style - Basic - §7.7.11 - partial - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-captionExtended§6.7.5nonono 
    - border-after-width - Basic - §7.7.12 - yes - yes - yes  
    - border-start-color - Basic - §7.7.13 - yes - yes - yes  
    - border-start-style - Basic - §7.7.14 - partial - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-headerBasic§6.7.6yesyesyes 
    - border-start-width - Basic - §7.7.15 - yes - yes - yes  
    - border-end-color - Basic - §7.7.16 - yes - yes - yes  
    - border-end-style - Basic - §7.7.17 - partial - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-footerExtended§6.7.7yesyesyes 
    - border-end-width - Basic - §7.7.18 - yes - yes - yes  
    - border-top-color - Basic - §7.7.19 - yes - yes - yes  
    - border-top-style - Basic - §7.7.20 - partial - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-bodyBasic§6.7.8yesyesyes 
    - border-top-width - Basic - §7.7.21 - yes - yes - yes  
    - border-bottom-color - Basic - §7.7.22 - yes - yes - yes  
    - border-bottom-style - Basic - §7.7.23 - partial - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-rowBasic§6.7.9yesyesyes 
    - border-bottom-width - Basic - §7.7.24 - yes - yes - yes  
    - border-left-color - Basic - §7.7.25 - yes - yes - yes  
    - border-left-style - Basic - §7.7.26 - partial - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-cellBasic§6.7.10partialyesyes 
    - border-left-width - Basic - §7.7.27 - yes - yes - yes  
    - border-right-color - Basic - §7.7.28 - yes - yes - yes  
    - border-right-style - Basic - §7.7.29 - partial - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    List Formatting Objects (§6.8)
    - border-right-width - Basic - §7.7.30 - yes - yes - yes  
    - padding-before - Basic - §7.7.31 - partial - yes - yes -
      -
    • - [0.20.5] only one value allowed
    • -
    • - [0.20.5] only implemented for blocks
    • -
    • - [0.20.5] can't be used to make extra space (use indents + spaces instead)
    • -
    • - [0.20.5] can be used to control how much the background-color extends beyond the content rectangle
    • -
    - padding-after - Basic - §7.7.32 - partial - yes - yes -
      -
    • - [0.20.5] same limitations as padding-before
    • -
    list-blockBasic§6.8.2yesyesyes 
    - padding-start - Basic - §7.7.33 - partial - yes - yes -
      -
    • - [0.20.5] same limitations as padding-before
    • -
    list-itemBasic§6.8.3yesyesyes 
    - padding-end - Basic - §7.7.34 - partial - yes - yes -
      -
    • - [0.20.5] same limitations as padding-before
    • -
    list-item-bodyBasic§6.8.4yesyesyes 
    - padding-top - Basic - §7.7.35 - partial - yes - yes -
      -
    • - [0.20.5] same limitations as padding-before
    • -
    list-item-labelExtended§6.8.5yesyesyes 
    - padding-bottom - Basic - §7.7.36 - partial - yes - yes -
      -
    • - [0.20.5] same limitations as padding-before
    • -
    Link and Multi Formatting Objects (§6.9)
    - padding-left - Basic - §7.7.37 - partial - yes - yes basic-linkExtended§6.9.2yesyesyes
      -
    • - [0.20.5] same limitations as padding-before
    • -
    - padding-right - Basic - §7.7.38 - partial - yes - yes -
      -
    • - [0.20.5] same limitations as padding-before
    • -
    multi-switchExtended§6.9.3nonono 
    - Common Font Properties (§7.8) multi-caseBasic§6.9.4nonono 
    - font-family - Basic - §7.8.2 - partial - partial - partial -
      -
    • - [0.20.5] font-family lists are not supported, use a single font-family name
    • -
    • - [0.93 and later] font-family lists are allowed but glyph based font selection is not supported
    • -
    multi-toggleExtended§6.9.5nonono 
    - font-selection-strategy - Complete - §7.8.3 - no - no - no  
    - font-size - Basic - §7.8.4 - partial - yes - yes -
      -
    • - [0.20.5] "smaller" and "larger" not implemented
    • -
    multi-propertiesExtended§6.9.6nonono 
    - font-stretch - Extended - §7.8.5 - no - no - no  
    - font-size-adjust - Extended - §7.8.6 - no - no - no  
    - font-style - Basic - §7.8.7 - partial - yes - yes -
      -
    • - [0.20.5] "normal" is not supported
    • -
    multi-property-setExtended§6.9.7nonono 
    - font-variant - Basic - §7.8.8 - yes - no - no  
    - font-weight - Basic - §7.8.9 - partial - partial - partial -
      -
    • - [0.20.5] "normal", "bolder" and "lighter" are not supported
    • -
    • - [0.93 and later] TODO <relative> font weights
    • -
    Formatting Objects for Bookmarks (§6.11 in XSL 1.1 WD)
    - Common Hyphenation Properties (§7.9) bookmark-tree (since + XSL 1.1)Extended§6.11.1 in XSL + 1.1 WDnoyesyes +
      +
    • [0.20.5] Uses the proprietary fox:outline extension.
    • +
    +
    - country - Extended - §7.9.1 - yes - yes - yes bookmark (since XSL 1.1)Extended§6.11.2 in XSL 1.1 + WDnoyesyes
      -
    • - [0.94 and earlier] Only used for controlling hyphenation.
    • -
    • - [trunk] For PDF output: Only 2-letter codes from ISO 3166 are supported properly to identify the natural language!
    • +
    • [0.20.5] Uses the proprietary fox:outline extension.
    - language - Extended - §7.9.2 - yes - yes - yes bookmark-title + (since XSL 1.1)Extended§6.11.3 in + XSL 1.1 WDnopartialpartial
      -
    • - [0.94 and earlier] Only used for controlling hyphenation.
    • -
    • - [trunk] For PDF output: Only 2-letter codes from ISO 639 are supported properly to identify the natural language!
    • +
    • [0.20.5] Uses the proprietary fox:outline extension.
    • + +
    • [0.93 and later] color, font-style and font-weight are not supported, yet.
    - script - Extended - §7.9.3 - no - no - no  
    - hyphenate - Extended - §7.9.4 - yes - yes - yes  
    - hyphenation-character - Extended - §7.9.5 - yes - yes - yes  
    - hyphenation-push-character-count - Extended - §7.9.6 - yes - yes - yes  
    - hyphenation-remain-character-count - Extended - §7.9.7 - yes - yes - yes   Out-of-line Formatting Objects (§6.10)
    - Common Margin Properties - Block (§7.10) floatExtended§6.10.2nonono 
    - margin-top - Basic - §7.10.1 - partial - yes - yes footnoteExtended§6.10.3yespartialpartial
      -
    • - [0.20.5] only on pages and regions
    • -
    - margin-bottom - Basic - §7.10.2 - partial - yes - yes -
      -
    • - [0.20.5] only on pages and regions
    • -
    footnote-bodyExtended§6.10.4yesyesyes 
    - margin-left - Basic - §7.10.3 - partial - yes - yes -
      -
    • - [0.20.5] only on pages and regions
    • -
    Other Formatting Objects (§6.11)
    - margin-right - Basic - §7.10.4 - partial - yes - yes wrapperBasic§6.11.2yespartialpartial
      -
    • - [0.20.5] only on pages and regions
    • -
    - space-before - Basic - §7.10.5 - partial - partial - partial -
      -
    • - [0.20.5] space-before.optimum supported
    • -
    • - [0.93 and later] Space adjustment may not fully work everywhere, yet.
    • -
    markerExtended§6.11.3yesyesyes 
    - space-after - Basic - §7.10.6 - partial - partial - partial -
      -
    • - [0.20.5] space-after.optimum supported
    • -
    • - [0.93 and later] Space adjustment may not fully work everywhere, yet.
    • -
    retrieve-markerExtended§6.11.4yesyesyes 
    + +

    XSL-FO Property Support Table + (§7)

    + +

    The following is a summary of FOP's current support for the standard XSL-FO properties.

    + + - - - - - - - - - - - - - - - - + + + + + + + + + + - + + + + + + - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  • [0.20.5] Use shorthand position="absolute" as a workaround.
  • + +
  • [0.93 and later] No restrictions. The 0.20.5 work-around is not supported.
  • + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  • [0.93 and later] not yet implemented for table-column, table-body, table-header and + table-footer.
  • + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + +
  • [0.20.5] only "solid" works
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + +
  • [0.20.5] only "solid" works
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + +
  • [0.20.5] only "solid" works
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + +
  • [0.20.5] only "solid" works
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  • [0.20.5] only "solid" works
  • + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + -
    - start-indent - Basic - §7.10.7 - yes - yes - yes  
    - end-indent - Basic - §7.10.8 - yes - yes - yes   Property NameXSL-FO Conformance LevelCitationSupport in FOPComments
    - Common Margin Properties - Inline (§7.11) 0.20.5 (previous)0.95 (stable)develop- ment
    - space-end - Basic - §7.11.1 - no - no - no  
    - space-start - Basic - §7.11.2 - no - no - no   Common Accessibility Properties (§7.4)
    - Common Relative Position Properties (§7.12) source-documentBasic§7.4.1nanana 
    - relative-position - Extended - §7.12.1 - no - no - no   roleBasic§7.4.2nanana 
    - Area Alignment Properties (§7.13) Common Absolute Position Properties (§7.5)
    - alignment-adjust - Basic - §7.13.1 - no - yes - yes  
    - alignment-baseline - Basic - §7.13.2 - no - yes - yes  
    - baseline-shift - Basic - §7.13.3 - partial - yes - yes absolute-positionComplete§7.5.1noyesyes
      -
    • - [0.20.5] Only values "super" and "sub" have been implemented.
    • -
    - display-align - Extended - §7.13.4 - partial - partial - partial -
      -
    • - [0.20.5] Implemented only for table-cell and block-container.
    • -
    • - [0.20.5] For table-cell, the "height" attribute must be set for the parent table-row; setting the height of the table or the table-cell results in vertical centering having no effect.
    • -
    • - [0.93 and later] TODO Check e-g, i-f-o.
    • -
    - dominant-baseline - Basic - §7.13.5 - no - yes - yes  
    - relative-align - Extended - §7.13.6 - no - no - no  
    - Area Dimension Properties (§7.14) topExtended§7.5.2yesyesyes 
    - block-progression-dimension - Basic - §7.14.1 - no - yes - yes  
    - content-height - Extended - §7.14.2 - no - yes - yes  
    - content-width - Extended - §7.14.3 - no - yes - yes  
    - height - Basic - §7.14.4 - yes - yes - yes  
    - inline-progression-dimension - Basic - §7.14.5 - no - yes - yes  
    - max-height - Complete - §7.14.6 - no - no - no  
    - max-width - Complete - §7.14.7 - no - no - no  
    - min-height - Complete - §7.14.8 - no - no - no  
    - min-width - Complete - §7.14.9 - no - no - no  
    - scaling - Extended - §7.14.10 - no - yes - yes  
    - scaling-method - Extended - §7.14.11 - no - no - no  
    - width - Basic - §7.14.12 - yes - yes - yes   rightExtended§7.5.3yesyesyes 
    - Block and Line-related Properties (§7.15) bottomExtended§7.5.4yesyesyes 
    - hyphenation-keep - Extended - §7.15.1 - no - no - no  
    - hyphenation-ladder-count - Extended - §7.15.2 - no - yes - yes  
    - last-line-end-indent - Extended - §7.15.3 - no - yes - yes  
    - line-height - Basic - §7.15.4 - yes - yes - yes  
    - line-height-shift-adjustment - Extended - §7.15.5 - no - yes - yes  
    - line-stacking-strategy - Basic - §7.15.6 - no - partial - partial -
      -
    • - [0.93 and later] value "line-height" not supported
    • -
    leftExtended§7.5.5yesyesyes 
    - linefeed-treatment - Extended - §7.15.7 - no - yes - yes  
    - white-space-treatment - Extended - §7.15.8 - no - partial - partial -
      -
    • - [0.93 and later] inline elements may interfere with correct handling of this property - in some cases
    • -
    Common Aural Properties (§7.6)
    - text-align - Basic - §7.15.9 - partial - partial - partial -
      -
    • - Only start, end, center and justify are supported
    • -
    azimuthBasic§7.6.1nanana 
    - text-align-last - Extended - §7.15.10 - partial - partial - partial -
      -
    • - Only start, end, center and justify are supported
    • -
    cue-afterBasic§7.6.2nanana 
    - text-indent - Basic - §7.15.11 - yes - yes - yes  
    - white-space-collapse - Extended - §7.15.12 - yes - yes - yes  
    - wrap-option - Basic - §7.15.13 - yes - partial - partial -
      -
    • - [0.93 and later] Only supported on fo:block.
    • -
    cue-beforeBasic§7.6.3nanana 
    - Character Properties (§7.16) elevationBasic§7.6.4nanana 
    - character - Basic - §7.16.1 - yes - yes - yes  
    - letter-spacing - Extended - §7.16.2 - yes - yes - yes  
    - suppress-at-line-break - Extended - §7.16.3 - no - no - no  
    - text-decoration - Extended - §7.16.4 - yes - yes - yes  
    - text-shadow - Extended - §7.16.5 - no - no - no  
    - text-transform - Extended - §7.16.6 - no - yes - yes  
    - treat-as-word-space - Extended - §7.16.7 - no - no - no  
    - word-spacing - Extended - §7.16.8 - no - yes - yes   pause-afterBasic§7.6.5nanana 
    - Color-related Properties (§7.17) pause-beforeBasic§7.6.6nanana 
    - color - Basic - §7.17.1 - yes - yes - yes  
    - color-profile-name - Extended - §7.17.2 - no - no - no  
    - rendering-intent - Extended - §7.17.3 - no - no - no   pitchBasic§7.6.7nanana 
    - Float-related Properties (§7.18) pitch-rangeBasic§7.6.8nanana 
    - clear - Extended - §7.18.1 - no - no - no  
    - float - Extended - §7.18.2 - no - no - no  
    - intrusion-displace - Extended - §7.18.3 - no - no - no   play-duringBasic§7.6.9nanana 
    - Keeps and Breaks Properties (§7.19) richnessBasic§7.6.10nanana 
    - break-after - Basic - §7.19.1 - yes - yes - yes  
    - break-before - Basic - §7.19.2 - yes - yes - yes  
    - keep-together - Extended - §7.19.3 - partial - partial - partial -
      -
    • - [0.20.5] works only in table rows
    • -
    • - [0.93] works on all implemented block-level FOs, but not on inline-level FOs.
    • -
    • - [0.93 and later] <integer> values are not supported. -
    • -
    -
    speakBasic§7.6.11nanana 
    - keep-with-next - Basic - §7.19.4 - partial - partial - partial -
      -
    • - [0.20.5] works only in table rows
    • -
    • - [0.93 and later] works on all implemented block-level FOs, but not on inline-level FOs.
    • -
    • - [0.93 and later] <integer> values are not supported.
    • -
    - keep-with-previous - Basic - §7.19.5 - partial - partial - partial -
      -
    • [0.20.5] works only in table rows
    • -
    • [0.93 and later] works on all implemented FOs, except list- and - table-related and inline-level FOs.
    • -
    • [0.93 and later] <integer> values are not supported.
    • -
    speak-headerBasic§7.6.12nanana 
    - orphans - Basic - §7.19.6 - no - yes - yes  
    - widows - Basic - §7.19.7 - no - yes - yes   speak-numeralBasic§7.6.13nanana 
    - Layout-related Properties (§7.20) speak-punctuationBasic§7.6.14nanana 
    - clip - Extended - §7.20.1 - no - no - no  
    - overflow - Basic - §7.20.2 - no - yes - yes  
    - reference-orientation - Extended - §7.20.3 - no - yes - yes -
      -
    • - [0.20.5] Workaround for page-orientation (portrait vs. landscape) is to swap the page-width and page-height properties.
    • -
    • - [0.20.5] Workaround for block-container is to use SVG.
    • -
    speech-rateBasic§7.6.15nanana 
    - span - Extended - §7.20.4 - yes - yes - yes   stressBasic§7.6.16nanana 
    - Leader and Rule Properties (§7.21)
    - leader-alignment - Extended - §7.21.1 - partial - no - no -
      -
    • - [0.20.5] not value "page"
    • -
    • - [0.93 and later] Not supported
    • -
    - leader-pattern - Basic - §7.21.2 - partial - yes - yes -
      -
    • - [0.20.5] not value "use-content"
    • -
    • - [0.93 and later] Value "use-content" does not work in all circumstances.
    • -
    voice-familyBasic§7.6.17nanana 
    - leader-pattern-width - Extended - §7.21.3 - yes - yes - yes  
    - leader-length - Basic - §7.21.4 - partial - yes - yes -
      -
    • - [0.20.5] leader-length.minimum is not used at all
    • -
    volumeBasic§7.6.18nanana 
    - rule-style - Basic - §7.21.5 - yes - yes - yes  
    - rule-thickness - Basic - §7.21.6 - yes - yes - yes   Common Border, Padding, and Background Properties + (§7.7)
    - Properties for Dynamic Effects Formatting Objects (§7.22) background-attachmentExtended§7.7.1nonono 
    - active-state - Extended - §7.22.1 - no - no - no  
    - auto-restore - Extended - §7.22.2 - no - no - no  
    - case-name - Extended - §7.22.3 - no - no - no  
    - case-title - Extended - §7.22.4 - no - no - no  
    - destination-placement-offset - Extended - §7.22.5 - no - no - no  
    - external-destination - Basic - §7.22.6 - yes - yes - yes  
    - indicate-destination - Extended - §7.22.7 - no - no - no  
    - internal-destination - Extended - §7.22.8 - yes - yes - yes  
    - show-destination - Extended - §7.22.9 - no - no - no  
    - starting-state - Extended - §7.22.10 - no - partial - partial background-colorBasic§7.7.2yespartialpartial
      -
    • [0.93 and later] support for starting-state on fo:bookmark
    • -
    - switch-to - Extended - §7.22.11 - no - no - no  
    - target-presentation-context - Extended - §7.22.12 - no - no - no  
    - target-processing-context - Extended - §7.22.13 - no - no - no  
    - target-stylesheet - Extended - §7.22.14 - no - no - no  
    - Properties for Markers (§7.23) background-imageExtended§7.7.3yespartialpartial +
      +
    • [0.93 and later] not yet implemented for table-column, table-body, table-header and + table-footer.
    • +
    +
    - marker-class-name - Extended - §7.23.1 - no - yes - yes  
    - retrieve-class-name - Extended - §7.23.2 - no - yes - yes  
    - retrieve-position - Extended - §7.23.3 - no - yes - yes  
    - retrieve-boundary - Extended - §7.23.4 - no - yes - yes   background-repeatExtended§7.7.4noyesyes 
    - Properties for Number to String Conversion (§7.24) background-position-horizontalExtended§7.7.5noyesyes 
    - format - Basic - §7.24.1 - no - yes - yes  
    - grouping-separator - Extended - §7.24.2 - no - no - no  
    - grouping-size - Extended - §7.24.3 - no - no - no  
    - letter-value - Basic - §7.24.4 - no - no - no   background-position-verticalExtended§7.7.6noyesyes 
    - Pagination and Layout Properties (§7.25) border-before-colorBasic§7.7.7yesyesyes 
    - blank-or-not-blank - Extended - §7.25.1 - yes - yes - yes  
    - column-count - Extended - §7.25.2 - yes - yes - yes  
    - column-gap - Extended - §7.25.3 - yes - yes - yes  
    - extent - Extended - §7.25.4 - yes - yes - yes  
    - flow-name - Basic - §7.25.5 - yes - yes - yes  
    - force-page-count - Extended - §7.25.6 - no - yes - yes  
    - initial-page-number - Basic - §7.25.7 - yes - yes - yes  
    - master-name - Basic - §7.25.8 - yes - yes - yes  
    - master-reference - Basic - §7.25.9 - yes - yes - yes  
    - maximum-repeats - Extended - §7.25.10 - yes - yes - yes  
    - media-usage - Extended - §7.25.11 - no - no - no  
    - odd-or-even - Extended - §7.25.12 - yes - yes - yes  
    - page-height - Basic - §7.25.13 - yes - yes - yes  
    - page-position - Extended - §7.25.14 - partial - yes - yes border-before-styleBasic§7.7.8partialyesyes
      -
    • - [0.20.5] "last" isn't implemented!
    • -
    - page-width - Basic - §7.25.15 - yes - yes - yes  
    - precedence - Extended - §7.25.16 - no - yes - yes  
    - region-name - Basic - §7.25.17 - yes - yes - yes   border-before-widthBasic§7.7.9yesyesyes 
    - Table Properties (§7.26) border-after-colorBasic§7.7.10yesyesyes 
    - border-after-precedence - Basic - §7.26.1 - no - no - no  
    - border-before-precedence - Basic - §7.26.2 - no - no - no  
    - border-collapse - Extended - §7.26.3 border-after-styleBasic§7.7.11partialyesyes
      -
    • [0.94 and later] Some small limitations
    • +
    • [0.20.5] only "solid" works
    - border-end-precedence - Basic - §7.26.4 - no - no - no  
    - border-separation - Extended - §7.26.5 - no - yes - yes  
    - border-start-precedence - Basic - §7.26.6 - no - no - no  
    - caption-side - Complete - §7.26.7 - no - no - no  
    - column-number - Basic - §7.26.8 - no - yes - yes  
    - column-width - Basic - §7.26.9 - partial - yes - yes -
      -
    • - [0.20.5] "percentage" not implemented. Workaround is to use the XSL-FO "proportional-column-width" function.
    • -
    border-after-widthBasic§7.7.12yesyesyes 
    - empty-cells - Extended - §7.26.10 - no - yes - yes  
    - ends-row - Extended - §7.26.11 - no - yes - yes  
    - number-columns-repeated - Basic - §7.26.12 - no - yes - yes  
    - number-columns-spanned - Basic - §7.26.13 - yes - yes - yes  
    - number-rows-spanned - Basic - §7.26.14 - yes - yes - yes  
    - starts-row - Extended - §7.26.15 - no - yes - yes  
    - table-layout - Extended - §7.26.16 - no - no - no  
    - table-omit-footer-at-break - Extended - §7.26.17 - yes - yes - yes  
    - table-omit-header-at-break - Extended - §7.26.18 - yes - yes - yes   border-start-colorBasic§7.7.13yesyesyes 
    - Writing-mode-related Properties (§7.27) border-start-styleBasic§7.7.14partialyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    - direction - Basic - §7.27.1 - no - no - no  
    - glyph-orientation-horizontal - Extended - §7.27.2 - no - no - no  
    - glyph-orientation-vertical - Extended - §7.27.3 - no - no - no  
    - text-altitude - Extended - §7.27.4 - no - no - no  
    - text-depth - Extended - §7.27.5 - no - no - no  
    - unicode-bidi - Extended - §7.27.6 - no - no - no  
    - writing-mode - Basic - §7.27.7 - no - no - no   border-start-widthBasic§7.7.15yesyesyes 
    - Miscellaneous Properties (§7.28) border-end-colorBasic§7.7.16yesyesyes 
    - content-type - Extended - §7.28.1 - no - no - no  
    - id - Basic - §7.28.2 - yes - partial - partial border-end-styleBasic§7.7.17partialyesyes
      -
    • [0.93 and later] IDs on table-header, table-footer, table-body, table-row, table-and-caption, table-caption, inline-container and bidi-override are not available, yet.
    • -
    - provisional-label-separation - Basic - §7.28.3 - yes - yes - yes  
    - provisional-distance-between-starts - Basic - §7.28.4 - yes - yes - yes  
    - ref-id - Extended - §7.28.5 - yes - yes - yes  
    - score-spaces - Extended - §7.28.6 - no - no - no  
    - src - Basic - §7.28.7 - yes - yes - yes  
    - visibility - Extended - §7.28.8 - no - no - no  
    - z-index - Extended - §7.28.9 - no - no - no   border-end-widthBasic§7.7.18yesyesyes 
    - Shorthand Properties (§7.29) border-top-colorBasic§7.7.19yesyesyes 
    - background - Complete - §7.29.1 - no - no - no  
    - background-position - Complete - §7.29.2 - no - yes - yes  
    - border - Complete - §7.29.3 - no - yes - yes  
    - border-bottom - Complete - §7.29.4 - yes - yes - yes  
    - border-color - Complete - §7.29.5 - partial - yes - yes border-top-styleBasic§7.7.20partialyesyes
      -
    • - [0.20.5] only one value allowed
    • -
    - border-left - Complete - §7.29.6 - yes - yes - yes  
    - border-right - Complete - §7.29.7 - yes - yes - yes  
    - border-style - Complete - §7.29.8 - partial - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    border-top-widthBasic§7.7.21yesyesyes 
    - border-spacing - Complete - §7.29.9 - no - yes - yes  
    - border-top - Complete - §7.29.10 - yes - yes - yes  
    - border-width - Complete - §7.29.11 - yes - yes - yes  
    - cue - Complete - §7.29.12 - na - na - na  
    - font - Complete - §7.29.13 - no - partial - partial -
      -
    • - [0.93 and later] Enum values other than "inherit" not yet supported.
    • -
    border-bottom-colorBasic§7.7.22yesyesyes 
    - margin - Complete - §7.29.14 - partial - yes - yes border-bottom-styleBasic§7.7.23partialyesyes
      -
    • - [0.20.5] only on pages and regions
    • -
    - padding - Complete - §7.29.15 - partial - yes - yes -
      -
    • - [0.20.5] only one value allowed
    • -
    • - [0.20.5] only implemented for blocks
    • -
    • - [0.20.5] can't be used to make extra space (use indents + spaces instead)
    • -
    • - [0.20.5] can be used to control how much the background-color extends beyond the content rectangle
    • -
    - page-break-after - Complete - §7.29.16 - no - yes - yes  
    - page-break-before - Complete - §7.29.17 - no - yes - yes  
    - page-break-inside - Complete - §7.29.18 - no - yes - yes  
    - pause - Complete - §7.29.19 - na - na - na  
    - position - Complete - §7.29.20 - partial - yes - yes -
      -
    • - [0.20.5] "inherit" not handled
    • -
    border-bottom-widthBasic§7.7.24yesyesyes 
    - size - Complete - §7.29.21 - no - no - no  
    - vertical-align - Complete - §7.29.22 - partial - partial - partial border-left-colorBasic§7.7.25yesyesyes 
    border-left-styleBasic§7.7.26partialyesyes
      -
    • - [0.20.5] Only works as a shorthand for baseline-shift property.
    • -
    • - [0.93 and later] Percentages are not supported, yet.
    • -
    - white-space - Complete - §7.29.23 - no - yes - yes  
    - xml:lang - Complete - §7.29.24 - no - yes - yes [0.95] Very basic parsing; no validation of the specified value.border-left-widthBasic§7.7.27yesyesyes 
    -

    XSL-FO Core Function Library Support Table (§5.10)

    -

    - The following is a summary of FOP's current support for the XSL-FO Core Function Library. -

    - + - - - - - + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    - Function Name - XSL-FO Conformance Level - Citation - Support in FOP - Comments border-right-colorBasic§7.7.28yesyesyes 
    - 0.20.5 (previous) 0.95 (stable) - develop- ment border-right-styleBasic§7.7.29partialyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    - Number Functions (§5.10.1) border-right-widthBasic§7.7.30yesyesyes 
    - floor - Basic - §5.10.1 - yes yes - yes  
    - ceiling - Basic - §5.10.1 - yes yes - yes  
    - round - Basic - §5.10.1 - yes yes - yes  
    - min - Basic - §5.10.1 - yes yes - yes  
    - max - Basic - §5.10.1 - yes yes - yes  
    - abs - Basic - §5.10.1 - yes yes - yes   padding-beforeBasic§7.7.31partialyesyes +
      +
    • [0.20.5] only one value allowed
    • + +
    • [0.20.5] only implemented for blocks
    • + +
    • [0.20.5] can't be used to make extra space (use indents + spaces instead)
    • + +
    • [0.20.5] can be used to control how much the background-color extends beyond the + content rectangle
    • +
    +
    - Color Functions (§5.10.2) padding-afterBasic§7.7.32partialyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-startBasic§7.7.33partialyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-endBasic§7.7.34partialyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-topBasic§7.7.35partialyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-bottomBasic§7.7.36partialyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-leftBasic§7.7.37partialyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-rightBasic§7.7.38partialyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    Common Font Properties (§7.8)
    font-familyBasic§7.8.2partialpartialpartial +
      +
    • [0.20.5] font-family lists are not supported, use a single font-family name
    • + +
    • [0.93 and later] font-family lists are allowed but glyph based font selection is not + supported
    • +
    +
    font-selection-strategyComplete§7.8.3nonono 
    font-sizeBasic§7.8.4partialyesyes +
      +
    • [0.20.5] "smaller" and "larger" not implemented
    • +
    +
    font-stretchExtended§7.8.5nonono 
    font-size-adjustExtended§7.8.6nonono 
    font-styleBasic§7.8.7partialyesyes +
      +
    • [0.20.5] "normal" is not supported
    • +
    +
    font-variantBasic§7.8.8yesnono 
    font-weightBasic§7.8.9partialpartialpartial +
      +
    • [0.20.5] "normal", "bolder" and "lighter" are not supported
    • + +
    • [0.93 and later] TODO <relative> font weights
    • +
    +
    Common Hyphenation Properties (§7.9)
    countryExtended§7.9.1yesyesyes +
      +
    • [0.94 and earlier] Only used for controlling hyphenation.
    • + +
    • [trunk] For PDF output: Only 2-letter codes from ISO 3166 are supported properly to + identify the natural language!
    • +
    +
    languageExtended§7.9.2yesyesyes +
      +
    • [0.94 and earlier] Only used for controlling hyphenation.
    • + +
    • [trunk] For PDF output: Only 2-letter codes from ISO 639 are supported properly to + identify the natural language!
    • +
    +
    scriptExtended§7.9.3nonono 
    hyphenateExtended§7.9.4yesyesyes 
    hyphenation-characterExtended§7.9.5yesyesyes 
    hyphenation-push-character-countExtended§7.9.6yesyesyes 
    hyphenation-remain-character-countExtended§7.9.7yesyesyes 
    Common Margin Properties - Block (§7.10)
    margin-topBasic§7.10.1partialyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    margin-bottomBasic§7.10.2partialyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    margin-leftBasic§7.10.3partialyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    margin-rightBasic§7.10.4partialyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    space-beforeBasic§7.10.5partialpartialpartial +
      +
    • [0.20.5] space-before.optimum supported
    • + +
    • [0.93 and later] Space adjustment may not fully work everywhere, yet.
    • +
    +
    space-afterBasic§7.10.6partialpartialpartial +
      +
    • [0.20.5] space-after.optimum supported
    • + +
    • [0.93 and later] Space adjustment may not fully work everywhere, yet.
    • +
    +
    start-indentBasic§7.10.7yesyesyes 
    end-indentBasic§7.10.8yesyesyes 
    Common Margin Properties - Inline (§7.11)
    space-endBasic§7.11.1nonono 
    space-startBasic§7.11.2nonono 
    Common Relative Position Properties (§7.12)
    relative-positionExtended§7.12.1nonono 
    Area Alignment Properties (§7.13)
    alignment-adjustBasic§7.13.1noyesyes 
    alignment-baselineBasic§7.13.2noyesyes 
    baseline-shiftBasic§7.13.3partialyesyes +
      +
    • [0.20.5] Only values "super" and "sub" have been implemented.
    • +
    +
    display-alignExtended§7.13.4partialpartialpartial +
      +
    • [0.20.5] Implemented only for table-cell and block-container.
    • + +
    • [0.20.5] For table-cell, the "height" attribute must be set for the parent table-row; + setting the height of the table or the table-cell results in vertical centering having no + effect.
    • + +
    • [0.93 and later] TODO Check e-g, i-f-o.
    • +
    +
    dominant-baselineBasic§7.13.5noyesyes 
    relative-alignExtended§7.13.6nonono 
    Area Dimension Properties (§7.14)
    block-progression-dimensionBasic§7.14.1noyesyes 
    content-heightExtended§7.14.2noyesyes 
    content-widthExtended§7.14.3noyesyes 
    heightBasic§7.14.4yesyesyes 
    inline-progression-dimensionBasic§7.14.5noyesyes 
    max-heightComplete§7.14.6nonono 
    max-widthComplete§7.14.7nonono 
    min-heightComplete§7.14.8nonono 
    min-widthComplete§7.14.9nonono 
    scalingExtended§7.14.10noyesyes 
    scaling-methodExtended§7.14.11nonono 
    widthBasic§7.14.12yesyesyes 
    Block and Line-related Properties (§7.15)
    hyphenation-keepExtended§7.15.1nonono 
    hyphenation-ladder-countExtended§7.15.2noyesyes 
    last-line-end-indentExtended§7.15.3noyesyes 
    line-heightBasic§7.15.4yesyesyes 
    line-height-shift-adjustmentExtended§7.15.5noyesyes 
    line-stacking-strategyBasic§7.15.6nopartialpartial +
      +
    • [0.93 and later] value "line-height" not supported
    • +
    +
    linefeed-treatmentExtended§7.15.7noyesyes 
    white-space-treatmentExtended§7.15.8nopartialpartial +
      +
    • [0.93 and later] inline elements may interfere with correct handling of this property + in some cases
    • +
    +
    text-alignBasic§7.15.9partialpartialpartial +
      +
    • Only start, end, center and justify are supported
    • +
    +
    text-align-lastExtended§7.15.10partialpartialpartial +
      +
    • Only start, end, center and justify are supported
    • +
    +
    text-indentBasic§7.15.11yesyesyes 
    white-space-collapseExtended§7.15.12yesyesyes 
    wrap-optionBasic§7.15.13yespartialpartial +
      +
    • [0.93 and later] Only supported on fo:block.
    • +
    +
    Character Properties (§7.16)
    characterBasic§7.16.1yesyesyes 
    letter-spacingExtended§7.16.2yesyesyes 
    suppress-at-line-breakExtended§7.16.3nonono 
    text-decorationExtended§7.16.4yesyesyes 
    text-shadowExtended§7.16.5nonono 
    text-transformExtended§7.16.6noyesyes 
    treat-as-word-spaceExtended§7.16.7nonono 
    word-spacingExtended§7.16.8noyesyes 
    Color-related Properties (§7.17)
    colorBasic§7.17.1yesyesyes 
    color-profile-nameExtended§7.17.2nonono 
    rendering-intentExtended§7.17.3nonono 
    Float-related Properties (§7.18)
    clearExtended§7.18.1nonono 
    floatExtended§7.18.2nonono 
    intrusion-displaceExtended§7.18.3nonono 
    Keeps and Breaks Properties (§7.19)
    break-afterBasic§7.19.1yesyesyes 
    break-beforeBasic§7.19.2yesyesyes 
    keep-togetherExtended§7.19.3partialpartialpartial +
      +
    • [0.20.5] works only in table rows
    • + +
    • [0.93] works on all implemented block-level FOs, but not on inline-level FOs.
    • + +
    • [0.93 and later] <integer> values are not supported.
    • +
    +
    keep-with-nextBasic§7.19.4partialpartialpartial +
      +
    • [0.20.5] works only in table rows
    • + +
    • [0.93 and later] works on all implemented block-level FOs, but not on inline-level + FOs.
    • + +
    • [0.93 and later] <integer> values are not supported.
    • +
    +
    keep-with-previousBasic§7.19.5partialpartialpartial +
      +
    • [0.20.5] works only in table rows
    • + +
    • [0.93 and later] works on all implemented FOs, except list- and table-related and + inline-level FOs.
    • + +
    • [0.93 and later] <integer> values are not supported.
    • +
    +
    orphansBasic§7.19.6noyesyes 
    widowsBasic§7.19.7noyesyes 
    Layout-related Properties (§7.20)
    clipExtended§7.20.1nonono 
    overflowBasic§7.20.2noyesyes 
    reference-orientationExtended§7.20.3noyesyes +
      +
    • [0.20.5] Workaround for page-orientation (portrait vs. landscape) is to swap the + page-width and page-height properties.
    • + +
    • [0.20.5] Workaround for block-container is to use SVG.
    • +
    +
    spanExtended§7.20.4yesyesyes 
    Leader and Rule Properties (§7.21)
    leader-alignmentExtended§7.21.1partialnono +
      +
    • [0.20.5] not value "page"
    • + +
    • [0.93 and later] Not supported
    • +
    +
    leader-patternBasic§7.21.2partialyesyes +
      +
    • [0.20.5] not value "use-content"
    • + +
    • [0.93 and later] Value "use-content" does not work in all circumstances.
    • +
    +
    leader-pattern-widthExtended§7.21.3yesyesyes 
    leader-lengthBasic§7.21.4partialyesyes +
      +
    • [0.20.5] leader-length.minimum is not used at all
    • +
    +
    rule-styleBasic§7.21.5yesyesyes 
    rule-thicknessBasic§7.21.6yesyesyes 
    Properties for Dynamic Effects Formatting Objects + (§7.22)
    active-stateExtended§7.22.1nonono 
    auto-restoreExtended§7.22.2nonono 
    case-nameExtended§7.22.3nonono 
    case-titleExtended§7.22.4nonono 
    destination-placement-offsetExtended§7.22.5nonono 
    external-destinationBasic§7.22.6yesyesyes 
    indicate-destinationExtended§7.22.7nonono 
    internal-destinationExtended§7.22.8yesyesyes 
    show-destinationExtended§7.22.9nonono 
    starting-stateExtended§7.22.10nopartialpartial +
      +
    • [0.93 and later] support for starting-state on fo:bookmark
    • +
    +
    switch-toExtended§7.22.11nonono 
    target-presentation-contextExtended§7.22.12nonono 
    target-processing-contextExtended§7.22.13nonono 
    target-stylesheetExtended§7.22.14nonono 
    Properties for Markers (§7.23)
    marker-class-nameExtended§7.23.1noyesyes 
    retrieve-class-nameExtended§7.23.2noyesyes 
    retrieve-positionExtended§7.23.3noyesyes 
    retrieve-boundaryExtended§7.23.4noyesyes 
    Properties for Number to String Conversion (§7.24)
    formatBasic§7.24.1noyesyes 
    grouping-separatorExtended§7.24.2nonono 
    grouping-sizeExtended§7.24.3nonono 
    letter-valueBasic§7.24.4nonono 
    Pagination and Layout Properties (§7.25)
    blank-or-not-blankExtended§7.25.1yesyesyes 
    column-countExtended§7.25.2yesyesyes 
    column-gapExtended§7.25.3yesyesyes 
    extentExtended§7.25.4yesyesyes 
    flow-nameBasic§7.25.5yesyesyes 
    force-page-countExtended§7.25.6noyesyes 
    initial-page-numberBasic§7.25.7yesyesyes 
    master-nameBasic§7.25.8yesyesyes 
    master-referenceBasic§7.25.9yesyesyes 
    maximum-repeatsExtended§7.25.10yesyesyes 
    media-usageExtended§7.25.11nonono 
    odd-or-evenExtended§7.25.12yesyesyes 
    page-heightBasic§7.25.13yesyesyes 
    page-positionExtended§7.25.14partialyesyes +
      +
    • [0.20.5] "last" isn't implemented!
    • +
    +
    page-widthBasic§7.25.15yesyesyes 
    precedenceExtended§7.25.16noyesyes 
    region-nameBasic§7.25.17yesyesyes 
    Table Properties (§7.26)
    border-after-precedenceBasic§7.26.1nonono 
    border-before-precedenceBasic§7.26.2nonono 
    border-collapseExtended§7.26.3partialyesyes +
      +
    • [0.94 and later] Some small limitations
    • +
    +
    border-end-precedenceBasic§7.26.4nonono 
    border-separationExtended§7.26.5noyesyes 
    border-start-precedenceBasic§7.26.6nonono 
    caption-sideComplete§7.26.7nonono 
    column-numberBasic§7.26.8noyesyes 
    column-widthBasic§7.26.9partialyesyes +
      +
    • [0.20.5] "percentage" not implemented. Workaround is to use the XSL-FO + "proportional-column-width" function.
    • +
    +
    empty-cellsExtended§7.26.10noyesyes 
    ends-rowExtended§7.26.11noyesyes 
    number-columns-repeatedBasic§7.26.12noyesyes 
    number-columns-spannedBasic§7.26.13yesyesyes 
    number-rows-spannedBasic§7.26.14yesyesyes 
    starts-rowExtended§7.26.15noyesyes 
    table-layoutExtended§7.26.16nonono 
    table-omit-footer-at-breakExtended§7.26.17yesyesyes 
    table-omit-header-at-breakExtended§7.26.18yesyesyes 
    Writing-mode-related Properties (§7.27)
    directionBasic§7.27.1nonono 
    glyph-orientation-horizontalExtended§7.27.2nonono 
    glyph-orientation-verticalExtended§7.27.3nonono 
    text-altitudeExtended§7.27.4nonono 
    text-depthExtended§7.27.5nonono 
    unicode-bidiExtended§7.27.6nonono 
    writing-modeBasic§7.27.7nonono 
    Miscellaneous Properties (§7.28)
    content-typeExtended§7.28.1nonono 
    idBasic§7.28.2yespartialpartial +
      +
    • [0.93 and later] IDs on table-header, table-footer, table-body, table-row, + table-and-caption, table-caption, inline-container and bidi-override are not available, + yet.
    • +
    +
    provisional-label-separationBasic§7.28.3yesyesyes 
    provisional-distance-between-startsBasic§7.28.4yesyesyes 
    ref-idExtended§7.28.5yesyesyes 
    score-spacesExtended§7.28.6nonono 
    srcBasic§7.28.7yesyesyes 
    visibilityExtended§7.28.8nonono 
    z-indexExtended§7.28.9nonono 
    Shorthand Properties (§7.29)
    backgroundComplete§7.29.1nonono 
    background-positionComplete§7.29.2noyesyes 
    borderComplete§7.29.3noyesyes 
    border-bottomComplete§7.29.4yesyesyes 
    border-colorComplete§7.29.5partialyesyes +
      +
    • [0.20.5] only one value allowed
    • +
    +
    border-leftComplete§7.29.6yesyesyes 
    border-rightComplete§7.29.7yesyesyes 
    border-styleComplete§7.29.8partialyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-spacingComplete§7.29.9noyesyes 
    border-topComplete§7.29.10yesyesyes 
    border-widthComplete§7.29.11yesyesyes 
    cueComplete§7.29.12nanana 
    fontComplete§7.29.13nopartialpartial +
      +
    • [0.93 and later] Enum values other than "inherit" not yet supported.
    • +
    +
    marginComplete§7.29.14partialyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    paddingComplete§7.29.15partialyesyes +
      +
    • [0.20.5] only one value allowed
    • + +
    • [0.20.5] only implemented for blocks
    • + +
    • [0.20.5] can't be used to make extra space (use indents + spaces instead)
    • + +
    • [0.20.5] can be used to control how much the background-color extends beyond the + content rectangle
    • +
    +
    page-break-afterComplete§7.29.16noyesyes 
    page-break-beforeComplete§7.29.17noyesyes 
    page-break-insideComplete§7.29.18noyesyes 
    pauseComplete§7.29.19nanana 
    positionComplete§7.29.20partialyesyes +
      +
    • [0.20.5] "inherit" not handled
    • +
    +
    sizeComplete§7.29.21nonono 
    vertical-alignComplete§7.29.22partialpartialpartial +
      +
    • [0.20.5] Only works as a shorthand for baseline-shift property.
    • + +
    • [0.93 and later] Percentages are not supported, yet.
    • +
    +
    white-spaceComplete§7.29.23noyesyes 
    xml:langComplete§7.29.24noyesyes[0.95] Very basic parsing; no validation of the specified value.
    + +

    XSL-FO Core + Function Library Support Table (§5.10)

    + +

    The following is a summary of FOP's current support for the XSL-FO Core Function Library.

    + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Function NameXSL-FO Conformance LevelCitationSupport in FOPComments
    - rgb - Basic - §5.10.2 - yes yes - yes  
    - rgb-icc - Basic - §5.10.2 - no yes - yes  
    - system-color - Basic - §5.10.2 - no yes - yes   0.20.5 (previous)0.95 (stable)develop- ment
    - Font Functions (§5.10.3) Number Functions (§5.10.1)
    - system-font - Basic - §5.10.3 - no floorBasic§5.10.1yesyesyes 
    ceilingBasic§5.10.1yesyesyes 
    roundBasic§5.10.1yesyesyes 
    minBasic§5.10.1yesyesyes 
    maxBasic§5.10.1yesyesyes 
    absBasic§5.10.1yesyesyes 
    Color Functions (§5.10.2)
    rgbBasic§5.10.2yesyesyes 
    rgb-iccBasic§5.10.2noyesyes 
    system-colorBasic§5.10.2noyesyes 
    Font Functions (§5.10.3)
    system-fontBasic§5.10.3nonono - no    
    - Property Value Functions (§5.10.4) Property Value Functions (§5.10.4)
    - inherited-property-value - Basic - §5.10.4 - yes yes - yes  
    - label-end - Basic - §5.10.4 - yes yes - yes  
    - body-start - Basic - §5.10.4 - yes yes - yes  
    - from-parent - Basic - §5.10.4 - yes yes - yes  
    - from-nearest-specified-value - Basic - §5.10.4 - yes yes - yes  
    - from-table-column - Basic - §5.10.4 - no yes - yes  
    - proportional-column-width - Basic - §5.10.4 - yes yes - yes  
    - merge-property-values - Basic - §5.10.4 - no no - no   inherited-property-valueBasic + §5.10.4yesyesyes 
    label-endBasic + §5.10.4yesyesyes 
    body-startBasic + §5.10.4yesyesyes 
    from-parentBasic + §5.10.4yesyesyes 
    from-nearest-specified-valueBasic + §5.10.4yesyesyes 
    from-table-columnBasic + §5.10.4noyesyes 
    proportional-column-widthBasic + §5.10.4yesyesyes 
    merge-property-valuesBasic + §5.10.4nonono 
    -- cgit v1.2.3 From b18e6c0cc3506f86f8908fce064c226a0e05783b Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 12 Mar 2008 12:14:51 +0000 Subject: Updated the compliance page. Re-added the 0.94 column since there are some noteworthy changes between the 0.94 and 0.95 versions git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@636293 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 865 ++++++++++++++++++++--- 1 file changed, 771 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index a6eac4fb0..2b25b89d7 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -482,21 +482,23 @@ Citation - Support in FOP + Support in FOP Comments - 0.20.5 (previous) + 0.20.5 (ancient) - 0.95 (stable) + 0.94 (stable) + + 0.95 (beta) develop- ment - Declarations and Pagination and Layout Formatting Objects (§6.4) @@ -516,6 +518,8 @@ yes + yes +   @@ -533,6 +537,8 @@ no + no +   @@ -550,6 +556,8 @@ no + no +   @@ -567,6 +575,8 @@ yes + yes +   @@ -585,6 +595,8 @@ yes + yes +   @@ -603,6 +615,8 @@ yes + yes +   @@ -621,6 +635,8 @@ yes + yes +   @@ -639,6 +655,8 @@ yes + yes +   @@ -658,6 +676,8 @@ yes + yes +   @@ -677,6 +697,8 @@ yes + yes +   @@ -695,9 +717,11 @@ partial + partial +
      -
    • [0.93 and later] The page width may not change among pages of the same page-sequence +
    • [0.94 and later] The page width may not change among pages of the same page-sequence unless a forced break is inserted.
    @@ -717,6 +741,8 @@ yes + yes + @@ -734,6 +760,8 @@ yes + yes +   @@ -751,6 +779,8 @@ yes + yes +   @@ -768,6 +798,8 @@ yes + yes +   @@ -785,6 +817,8 @@ yes + yes +   @@ -802,6 +836,8 @@ yes + yes +   @@ -819,6 +855,8 @@ yes + yes +   @@ -836,11 +874,13 @@ no + no +   - Block Formatting Objects (§6.5) @@ -859,6 +899,8 @@ yes + yes +   @@ -877,21 +919,23 @@ partial + partial +
      -
    • [0.20.5] Currently only works as direct child of fo:flow.
    • +
    • [0.20.5] Only works as direct child of fo:flow.
    • [0.20.5] For absolute positioning, use 'position="absolute"' (as 'absolute-position="absolute"' is not implemented), and specify all four of "left", "top", "width" and "height"
    • -
    • [0.93 and later] No known restrictions.
    • +
    • [0.94 and later] No known restrictions.
    - Inline Formatting Objects (§6.6) @@ -910,6 +954,8 @@ no + no +   @@ -927,6 +973,8 @@ yes + yes +   @@ -945,6 +993,8 @@ no + no +   @@ -963,6 +1013,8 @@ yes + yes +   @@ -981,6 +1033,8 @@ yes + yes +
    • Built-in support for SVG only, additional namespaces through optional @@ -1003,6 +1057,8 @@ yes + yes +   @@ -1021,6 +1077,8 @@ no + no +   @@ -1038,6 +1096,8 @@ yes + yes +   @@ -1055,6 +1115,8 @@ yes + yes +   @@ -1073,20 +1135,22 @@ partial + partial +
      • [0.20.5] Only works for table of contents without any problems. The case where the page number doesn't fit on a line isn't handled, and any text on the same line and after the page-number might not appear exactly where you want it to.
      • -
      • [0.93 and later] After the page number is known, no relayout is performed. The +
      • [0.94 and later] After the page number is known, no relayout is performed. The appearance may be suboptimal depending on the use case.
      - Table Formatting Objects (§6.7) @@ -1106,6 +1170,8 @@ no + no +   @@ -1123,9 +1189,11 @@ partial + partial +
        -
      • [0.20.5–0.93] Only border-collapse="separate"
      • +
      • [0.20.5] Only border-collapse="separate"
      • [All] No support for auto layout yet
      @@ -1146,6 +1214,8 @@ yes + yes +
      • [0.20.5] You must explicitly specify column widths.
      • @@ -1167,6 +1237,8 @@ no + no +   @@ -1184,6 +1256,8 @@ yes + yes +   @@ -1201,6 +1275,8 @@ yes + yes +   @@ -1218,6 +1294,8 @@ yes + yes +   @@ -1235,6 +1313,8 @@ yes + yes +   @@ -1252,11 +1332,13 @@ yes + yes +   - List Formatting Objects (§6.8) @@ -1275,6 +1357,8 @@ yes + yes +   @@ -1292,6 +1376,8 @@ yes + yes +   @@ -1309,6 +1395,8 @@ yes + yes +   @@ -1327,11 +1415,13 @@ yes + yes +   - Link and Multi Formatting Objects (§6.9) @@ -1350,6 +1440,8 @@ yes + yes +
        • both internal and external supported
        • @@ -1371,6 +1463,8 @@ no + no +   @@ -1388,6 +1482,8 @@ no + no +   @@ -1405,6 +1501,8 @@ no + no +   @@ -1423,6 +1521,8 @@ no + no +   @@ -1441,11 +1541,13 @@ no + no +   - Formatting Objects for Bookmarks (§6.11 in XSL 1.1 WD) @@ -1465,6 +1567,8 @@ yes + yes +
          • [0.20.5] Uses the proprietary fox:outline extension.
          • @@ -1486,6 +1590,8 @@ yes + yes +
            • [0.20.5] Uses the proprietary fox:outline extension.
            • @@ -1508,17 +1614,19 @@ partial + partial +
              • [0.20.5] Uses the proprietary fox:outline extension.
              • -
              • [0.93 and later] color, font-style and font-weight are not supported, yet.
              • +
              • [0.94 and later] color, font-style and font-weight are not supported, yet.
              - Out-of-line Formatting Objects (§6.10) @@ -1537,6 +1645,8 @@ no + no +   @@ -1554,11 +1664,13 @@ partial + partial +
              • [0.20.5] Footnotes sometimes overlap with the main content
              • -
              • [0.93 and later] Restrictions with multi-column documents.
              • +
              • [0.94 and later] Restrictions with multi-column documents.
              @@ -1577,11 +1689,13 @@ yes + yes +   - Other Formatting Objects (§6.11) @@ -1600,9 +1714,11 @@ partial + partial +
                -
              • [0.93 and later] Only works as expected with inline-level content.
              • +
              • [0.94 and later] Only works as expected with inline-level content.
              @@ -1621,6 +1737,8 @@ yes + yes +   @@ -1639,6 +1757,8 @@ yes + yes +   @@ -1656,21 +1776,23 @@ Citation - Support in FOP + Support in FOP Comments - 0.20.5 (previous) + 0.20.5 (ancient) - 0.95 (stable) + 0.94 (stable) + + 0.95 (beta) develop- ment - Common Accessibility Properties (§7.4) @@ -1690,6 +1812,8 @@ na + na +   @@ -1707,11 +1831,13 @@ na + na +   - Common Absolute Position Properties (§7.5) @@ -1731,11 +1857,13 @@ yes + yes +
              • [0.20.5] Use shorthand position="absolute" as a workaround.
              • -
              • [0.93 and later] No restrictions. The 0.20.5 work-around is not supported.
              • +
              • [0.94 and later] No restrictions. The 0.20.5 work-around is not supported.
              @@ -1754,6 +1882,8 @@ yes + yes +   @@ -1771,6 +1901,8 @@ yes + yes +   @@ -1788,6 +1920,8 @@ yes + yes +   @@ -1805,11 +1939,13 @@ yes + yes +   - Common Aural Properties (§7.6) @@ -1828,6 +1964,8 @@ na + na +   @@ -1845,6 +1983,8 @@ na + na +   @@ -1862,6 +2002,8 @@ na + na +   @@ -1879,6 +2021,8 @@ na + na +   @@ -1896,6 +2040,8 @@ na + na +   @@ -1913,6 +2059,8 @@ na + na +   @@ -1930,6 +2078,8 @@ na + na +   @@ -1947,6 +2097,8 @@ na + na +   @@ -1964,6 +2116,8 @@ na + na +   @@ -1981,6 +2135,8 @@ na + na +   @@ -1998,6 +2154,8 @@ na + na +   @@ -2015,6 +2173,8 @@ na + na +   @@ -2032,6 +2192,8 @@ na + na +   @@ -2050,6 +2212,8 @@ na + na +   @@ -2067,6 +2231,8 @@ na + na +   @@ -2084,6 +2250,8 @@ na + na +   @@ -2101,6 +2269,8 @@ na + na +   @@ -2118,11 +2288,13 @@ na + na +   - Common Border, Padding, and Background Properties (§7.7) @@ -2143,6 +2315,8 @@ no + no +   @@ -2159,11 +2333,13 @@ partial - partial + yes + + yes
                -
              • [0.93 and later] not yet implemented for table-column, table-body, table-header and +
              • [0.94] not yet implemented for table-column, table-body, table-header and table-footer.
              @@ -2182,11 +2358,13 @@ partial - partial + yes + + yes
                -
              • [0.93 and later] not yet implemented for table-column, table-body, table-header and +
              • [0.94] not yet implemented for table-column, table-body, table-header and table-footer.
              @@ -2207,6 +2385,8 @@ yes + yes +   @@ -2221,11 +2401,14 @@ no - yes + partial - yes + partial -   + partial + + [0.94 and later] Ignored when background-repeat set to + "repeat" or "repeat-x" @@ -2239,11 +2422,14 @@ no - yes + partial - yes + partial -   + partial + + [0.94 and later] Ignored when background-repeat set to + "repeat" or "repeat-y" @@ -2261,6 +2447,8 @@ yes + yes +   @@ -2279,6 +2467,8 @@ yes + yes +
              • [0.20.5] only "solid" works
              • @@ -2297,11 +2487,17 @@ yes + partial + yes yes -   + +
                  +
                • [0.94] .conditionality not supported on fo:table-cell
                • +
                + @@ -2319,6 +2515,8 @@ yes + yes +   @@ -2337,6 +2535,8 @@ yes + yes +
                • [0.20.5] only "solid" works
                • @@ -2355,11 +2555,17 @@ yes + partial + yes yes -   + +
                    +
                  • [0.94] .conditionality not supported on fo:table-cell
                  • +
                  + @@ -2377,6 +2583,8 @@ yes + yes +   @@ -2395,6 +2603,8 @@ yes + yes +
                  • [0.20.5] only "solid" works
                  • @@ -2417,6 +2627,8 @@ yes + yes +   @@ -2435,6 +2647,8 @@ yes + yes +   @@ -2453,6 +2667,8 @@ yes + yes +
                    • [0.20.5] only "solid" works
                    • @@ -2475,6 +2691,8 @@ yes + yes +   @@ -2493,6 +2711,8 @@ yes + yes +   @@ -2511,6 +2731,8 @@ yes + yes +
                      • [0.20.5] only "solid" works
                      • @@ -2533,6 +2755,8 @@ yes + yes +   @@ -2551,6 +2775,8 @@ yes + yes +   @@ -2569,6 +2795,8 @@ yes + yes +
                        • [0.20.5] only "solid" works
                        • @@ -2591,6 +2819,8 @@ yes + yes +   @@ -2609,6 +2839,8 @@ yes + yes +   @@ -2627,6 +2859,8 @@ yes + yes +
                          • [0.20.5] only "solid" works
                          • @@ -2649,6 +2883,8 @@ yes + yes +   @@ -2667,6 +2903,8 @@ yes + yes +   @@ -2685,6 +2923,8 @@ yes + yes +
                            • [0.20.5] only "solid" works
                            • @@ -2707,6 +2947,8 @@ yes + yes +   @@ -2725,6 +2967,8 @@ yes + yes +
                              • [0.20.5] only one value allowed
                              • @@ -2753,6 +2997,8 @@ yes + yes +
                                • [0.20.5] same limitations as padding-before
                                • @@ -2774,6 +3020,8 @@ yes + yes +
                                  • [0.20.5] same limitations as padding-before
                                  • @@ -2795,6 +3043,8 @@ yes + yes +
                                    • [0.20.5] same limitations as padding-before
                                    • @@ -2816,6 +3066,8 @@ yes + yes +
                                      • [0.20.5] same limitations as padding-before
                                      • @@ -2838,6 +3090,8 @@ yes + yes +
                                        • [0.20.5] same limitations as padding-before
                                        • @@ -2859,6 +3113,8 @@ yes + yes +
                                          • [0.20.5] same limitations as padding-before
                                          • @@ -2880,6 +3136,8 @@ yes + yes +
                                            • [0.20.5] same limitations as padding-before
                                            • @@ -2888,7 +3146,7 @@ - Common Font Properties (§7.8) @@ -2907,11 +3165,13 @@ partial + partial +
                                              • [0.20.5] font-family lists are not supported, use a single font-family name
                                              • -
                                              • [0.93 and later] font-family lists are allowed but glyph based font selection is not +
                                              • [0.94 and later] font-family lists are allowed but glyph based font selection is not supported
                                              @@ -2932,6 +3192,8 @@ no + no +   @@ -2949,6 +3211,8 @@ yes + yes +
                                              • [0.20.5] "smaller" and "larger" not implemented
                                              • @@ -2970,6 +3234,8 @@ no + no +   @@ -2988,6 +3254,8 @@ no + no +   @@ -3005,6 +3273,8 @@ yes + yes +
                                                • [0.20.5] "normal" is not supported
                                                • @@ -3026,6 +3296,8 @@ no + no +   @@ -3043,17 +3315,19 @@ partial + partial +
                                                  • [0.20.5] "normal", "bolder" and "lighter" are not supported
                                                  • -
                                                  • [0.93 and later] TODO <relative> font weights
                                                  • +
                                                  • [0.94 and later] TODO <relative> font weights
                                                  - Common Hyphenation Properties (§7.9) @@ -3072,6 +3346,8 @@ yes + yes +
                                                  • [0.94 and earlier] Only used for controlling hyphenation.
                                                  • @@ -3096,6 +3372,8 @@ yes + yes +
                                                    • [0.94 and earlier] Only used for controlling hyphenation.
                                                    • @@ -3120,6 +3398,8 @@ no + no +   @@ -3137,6 +3417,8 @@ yes + yes +   @@ -3155,6 +3437,8 @@ yes + yes +   @@ -3173,6 +3457,8 @@ yes + yes +   @@ -3191,11 +3477,13 @@ yes + yes +   - Common Margin Properties - Block (§7.10) @@ -3214,6 +3502,8 @@ yes + yes +
                                                      • [0.20.5] only on pages and regions
                                                      • @@ -3235,6 +3525,8 @@ yes + yes +
                                                        • [0.20.5] only on pages and regions
                                                        • @@ -3256,6 +3548,8 @@ yes + yes +
                                                          • [0.20.5] only on pages and regions
                                                          • @@ -3277,6 +3571,8 @@ yes + yes +
                                                            • [0.20.5] only on pages and regions
                                                            • @@ -3298,11 +3594,13 @@ partial + partial +
                                                              • [0.20.5] space-before.optimum supported
                                                              • -
                                                              • [0.93 and later] Space adjustment may not fully work everywhere, yet.
                                                              • +
                                                              • [0.94 and later] Space adjustment may not fully work everywhere, yet.
                                                              @@ -3321,11 +3619,13 @@ partial + partial +
                                                              • [0.20.5] space-after.optimum supported
                                                              • -
                                                              • [0.93 and later] Space adjustment may not fully work everywhere, yet.
                                                              • +
                                                              • [0.94 and later] Space adjustment may not fully work everywhere, yet.
                                                              @@ -3344,6 +3644,8 @@ yes + yes +   @@ -3361,11 +3663,13 @@ yes + yes +   - Common Margin Properties - Inline (§7.11) @@ -3384,6 +3688,8 @@ no + no +   @@ -3401,11 +3707,13 @@ no + no +   - Common Relative Position Properties (§7.12) @@ -3425,11 +3733,13 @@ no + no +   - Area Alignment Properties (§7.13) @@ -3449,6 +3759,8 @@ yes + yes +   @@ -3467,6 +3779,8 @@ yes + yes +   @@ -3485,6 +3799,8 @@ yes + yes +
                                                              • [0.20.5] Only values "super" and "sub" have been implemented.
                                                              • @@ -3506,6 +3822,8 @@ partial + partial +
                                                                • [0.20.5] Implemented only for table-cell and block-container.
                                                                • @@ -3514,7 +3832,7 @@ setting the height of the table or the table-cell results in vertical centering having no effect. -
                                                                • [0.93 and later] TODO Check e-g, i-f-o.
                                                                • +
                                                                • [0.94 and later] TODO Check e-g, i-f-o.
                                                                @@ -3534,6 +3852,8 @@ yes + yes +   @@ -3552,11 +3872,13 @@ no + no +   - Area Dimension Properties (§7.14) @@ -3576,6 +3898,8 @@ yes + yes +   @@ -3594,6 +3918,8 @@ yes + yes +   @@ -3611,6 +3937,8 @@ yes + yes +   @@ -3628,6 +3956,8 @@ yes + yes +   @@ -3646,6 +3976,8 @@ yes + yes +   @@ -3663,6 +3995,8 @@ no + no +   @@ -3680,6 +4014,8 @@ no + no +   @@ -3697,6 +4033,8 @@ no + no +   @@ -3714,6 +4052,8 @@ no + no +   @@ -3731,6 +4071,8 @@ yes + yes +   @@ -3749,6 +4091,8 @@ no + no +   @@ -3766,11 +4110,13 @@ yes + yes +   - Block and Line-related Properties (§7.15) @@ -3790,6 +4136,8 @@ no + no +   @@ -3808,6 +4156,8 @@ yes + yes +   @@ -3826,6 +4176,8 @@ yes + yes +   @@ -3843,6 +4195,8 @@ yes + yes +   @@ -3861,6 +4215,8 @@ yes + yes +   @@ -3879,9 +4235,11 @@ partial + partial +
                                                                  -
                                                                • [0.93 and later] value "line-height" not supported
                                                                • +
                                                                • [0.94 and later] value "line-height" not supported
                                                                @@ -3901,6 +4259,8 @@ yes + yes +   @@ -3919,9 +4279,11 @@ partial + partial +
                                                                  -
                                                                • [0.93 and later] inline elements may interfere with correct handling of this property +
                                                                • [0.94 and later] inline elements may interfere with correct handling of this property in some cases
                                                                @@ -3941,6 +4303,8 @@ partial + partial +
                                                                • Only start, end, center and justify are supported
                                                                • @@ -3963,6 +4327,8 @@ partial + partial +
                                                                  • Only start, end, center and justify are supported
                                                                  • @@ -3984,6 +4350,8 @@ yes + yes +   @@ -4002,6 +4370,8 @@ yes + yes +   @@ -4019,15 +4389,17 @@ partial + partial +
                                                                      -
                                                                    • [0.93 and later] Only supported on fo:block.
                                                                    • +
                                                                    • [0.94 and later] Only supported on fo:block.
                                                                    - Character Properties (§7.16) @@ -4046,6 +4418,8 @@ yes + yes +   @@ -4064,6 +4438,8 @@ yes + yes +   @@ -4082,6 +4458,8 @@ no + no +   @@ -4100,6 +4478,8 @@ yes + yes +   @@ -4117,6 +4497,8 @@ no + no +   @@ -4135,6 +4517,8 @@ yes + yes +   @@ -4153,6 +4537,8 @@ no + no +   @@ -4170,11 +4556,13 @@ yes + yes +   - Color-related Properties (§7.17) @@ -4193,6 +4581,8 @@ yes + yes +   @@ -4211,6 +4601,8 @@ no + no +   @@ -4229,11 +4621,13 @@ no + no +   - Float-related Properties (§7.18) @@ -4252,6 +4646,8 @@ no + no +   @@ -4269,6 +4665,8 @@ no + no +   @@ -4287,11 +4685,13 @@ no + no +   - Keeps and Breaks Properties (§7.19) @@ -4306,11 +4706,17 @@ yes + partial + yes yes -   + +
                                                                      +
                                                                    • [0.94] Doesn't work on the last row of a table
                                                                    • +
                                                                    + @@ -4323,11 +4729,19 @@ yes + partial + yes yes -   + +
                                                                      +
                                                                    • [0.94] Doesn't work on the first row of a table
                                                                    • +
                                                                    • [0.94] When set on the first child of an fo:table-cell, + the border-before is still painted on the previous page
                                                                    • +
                                                                    + @@ -4344,13 +4758,13 @@ partial + partial +
                                                                    • [0.20.5] works only in table rows
                                                                    • -
                                                                    • [0.93] works on all implemented block-level FOs, but not on inline-level FOs.
                                                                    • - -
                                                                    • [0.93 and later] <integer> values are not supported.
                                                                    • +
                                                                    • [0.94 and later] <integer> values are not supported.
                                                                    @@ -4370,14 +4784,16 @@ partial + partial +
                                                                    • [0.20.5] works only in table rows
                                                                    • -
                                                                    • [0.93 and later] works on all implemented block-level FOs, but not on inline-level +
                                                                    • [0.94 and later] works on all implemented block-level FOs, but not on inline-level FOs.
                                                                    • -
                                                                    • [0.93 and later] <integer> values are not supported.
                                                                    • +
                                                                    • [0.94 and later] <integer> values are not supported.
                                                                    @@ -4397,14 +4813,19 @@ partial + partial +
                                                                    • [0.20.5] works only in table rows
                                                                    • -
                                                                    • [0.93 and later] works on all implemented FOs, except list- and table-related and +
                                                                    • [0.94] works on all implemented FOs, except list- and table-related and inline-level FOs.
                                                                    • -
                                                                    • [0.93 and later] <integer> values are not supported.
                                                                    • +
                                                                    • [0.95] works on all implemented FOs, except list- and inline-level + FOs.
                                                                    • + +
                                                                    • [0.94 and later] <integer> values are not supported.
                                                                    @@ -4423,6 +4844,8 @@ yes + yes +   @@ -4440,11 +4863,13 @@ yes + yes +   - Layout-related Properties (§7.20) @@ -4463,6 +4888,8 @@ no + no +   @@ -4480,6 +4907,8 @@ yes + yes +   @@ -4498,6 +4927,8 @@ yes + yes +
                                                                    • [0.20.5] Workaround for page-orientation (portrait vs. landscape) is to swap the @@ -4522,11 +4953,13 @@ yes + yes +   - Leader and Rule Properties (§7.21) @@ -4546,11 +4979,13 @@ no + no +
                                                                      • [0.20.5] not value "page"
                                                                      • -
                                                                      • [0.93 and later] Not supported
                                                                      • +
                                                                      • [0.94 and later] Not supported
                                                                      @@ -4570,11 +5005,13 @@ yes + yes +
                                                                      • [0.20.5] not value "use-content"
                                                                      • -
                                                                      • [0.93 and later] Value "use-content" does not work in all circumstances.
                                                                      • +
                                                                      • [0.94 and later] Value "use-content" does not work in all circumstances.
                                                                      @@ -4594,6 +5031,8 @@ yes + yes +   @@ -4611,6 +5050,8 @@ yes + yes +
                                                                      • [0.20.5] leader-length.minimum is not used at all
                                                                      • @@ -4632,6 +5073,8 @@ yes + yes +   @@ -4650,11 +5093,13 @@ yes + yes +   - Properties for Dynamic Effects Formatting Objects (§7.22) @@ -4674,6 +5119,8 @@ no + no +   @@ -4691,6 +5138,8 @@ no + no +   @@ -4708,6 +5157,8 @@ no + no +   @@ -4725,6 +5176,8 @@ no + no +   @@ -4743,6 +5196,8 @@ no + no +   @@ -4761,6 +5216,8 @@ yes + yes +   @@ -4779,6 +5236,8 @@ no + no +   @@ -4797,6 +5256,8 @@ yes + yes +   @@ -4815,6 +5276,8 @@ no + no +   @@ -4833,9 +5296,11 @@ partial + partial + @@ -4855,6 +5320,8 @@ no + no +   @@ -4873,6 +5340,8 @@ no + no +   @@ -4891,6 +5360,8 @@ no + no +   @@ -4909,11 +5380,13 @@ no + no +   - Properties for Markers (§7.23) @@ -4933,6 +5406,8 @@ yes + yes +   @@ -4951,6 +5426,8 @@ yes + yes +   @@ -4969,6 +5446,8 @@ yes + yes +   @@ -4987,11 +5466,13 @@ yes + yes +   - Properties for Number to String Conversion (§7.24) @@ -5010,6 +5491,8 @@ yes + yes +   @@ -5028,6 +5511,8 @@ no + no +   @@ -5045,6 +5530,8 @@ no + no +   @@ -5062,11 +5549,13 @@ no + no +   - Pagination and Layout Properties (§7.25) @@ -5086,6 +5575,8 @@ yes + yes +   @@ -5103,6 +5594,8 @@ yes + yes +   @@ -5120,6 +5613,8 @@ yes + yes +   @@ -5137,6 +5632,8 @@ yes + yes +   @@ -5154,6 +5651,8 @@ yes + yes +   @@ -5172,6 +5671,8 @@ yes + yes +   @@ -5190,6 +5691,8 @@ yes + yes +   @@ -5207,6 +5710,8 @@ yes + yes +   @@ -5225,6 +5730,8 @@ yes + yes +   @@ -5243,6 +5750,8 @@ yes + yes +   @@ -5260,6 +5769,8 @@ no + no +   @@ -5277,6 +5788,8 @@ yes + yes +   @@ -5294,6 +5807,8 @@ yes + yes +   @@ -5311,6 +5826,8 @@ yes + yes +
                                                                        • [0.20.5] "last" isn't implemented!
                                                                        • @@ -5332,6 +5849,8 @@ yes + yes +   @@ -5349,6 +5868,8 @@ yes + yes +   @@ -5366,11 +5887,13 @@ yes + yes +   - Table Properties (§7.26) @@ -5390,6 +5913,8 @@ no + no +   @@ -5408,6 +5933,8 @@ no + no +   @@ -5426,6 +5953,8 @@ yes + yes +
                                                                          • [0.94 and later] Some small limitations
                                                                          • @@ -5448,6 +5977,8 @@ no + no +   @@ -5466,6 +5997,8 @@ yes + yes +   @@ -5484,6 +6017,8 @@ no + no +   @@ -5501,6 +6036,8 @@ no + no +   @@ -5518,6 +6055,8 @@ yes + yes +   @@ -5535,6 +6074,8 @@ yes + yes +
                                                                            • [0.20.5] "percentage" not implemented. Workaround is to use the XSL-FO @@ -5553,9 +6094,11 @@ no - yes + no - yes + no + + no   @@ -5574,6 +6117,8 @@ yes + yes +   @@ -5592,6 +6137,8 @@ yes + yes +   @@ -5610,6 +6157,8 @@ yes + yes +   @@ -5628,6 +6177,8 @@ yes + yes +   @@ -5645,6 +6196,8 @@ yes + yes +   @@ -5662,6 +6215,8 @@ no + no +   @@ -5680,6 +6235,8 @@ yes + yes +   @@ -5698,11 +6255,13 @@ yes + yes +   - Writing-mode-related Properties (§7.27) @@ -5721,6 +6280,8 @@ no + no +   @@ -5739,6 +6300,8 @@ no + no +   @@ -5757,6 +6320,8 @@ no + no +   @@ -5774,6 +6339,8 @@ no + no +   @@ -5791,6 +6358,8 @@ no + no +   @@ -5808,6 +6377,8 @@ no + no +   @@ -5825,11 +6396,13 @@ no + no +   - Miscellaneous Properties (§7.28) @@ -5848,6 +6421,8 @@ no + no +   @@ -5865,9 +6440,11 @@ partial + partial +
                                                                                -
                                                                              • [0.93 and later] IDs on table-header, table-footer, table-body, table-row, +
                                                                              • [0.94 and later] IDs on table-header, table-footer, table-body, table-row, table-and-caption, table-caption, inline-container and bidi-override are not available, yet.
                                                                              @@ -5889,6 +6466,8 @@ yes + yes +   @@ -5907,6 +6486,8 @@ yes + yes +   @@ -5924,6 +6505,8 @@ yes + yes +   @@ -5941,6 +6524,8 @@ no + no +   @@ -5958,6 +6543,8 @@ yes + yes +   @@ -5975,6 +6562,8 @@ no + no +   @@ -5992,11 +6581,13 @@ no + no +   - Shorthand Properties (§7.29) @@ -6015,6 +6606,8 @@ no + no +   @@ -6033,6 +6626,8 @@ yes + yes +   @@ -6050,6 +6645,8 @@ yes + yes +   @@ -6067,6 +6664,8 @@ yes + yes +   @@ -6084,6 +6683,8 @@ yes + yes +
                                                                              • [0.20.5] only one value allowed
                                                                              • @@ -6105,6 +6706,8 @@ yes + yes +   @@ -6122,6 +6725,8 @@ yes + yes +   @@ -6139,6 +6744,8 @@ yes + yes +
                                                                                • [0.20.5] only "solid" works
                                                                                • @@ -6161,6 +6768,8 @@ yes + yes +   @@ -6178,6 +6787,8 @@ yes + yes +   @@ -6195,6 +6806,8 @@ yes + yes +   @@ -6212,6 +6825,8 @@ na + na +   @@ -6229,9 +6844,11 @@ partial + partial +
                                                                                    -
                                                                                  • [0.93 and later] Enum values other than "inherit" not yet supported.
                                                                                  • +
                                                                                  • [0.94 and later] Enum values other than "inherit" not yet supported.
                                                                                  @@ -6250,6 +6867,8 @@ yes + yes +
                                                                                  • [0.20.5] only on pages and regions
                                                                                  • @@ -6271,6 +6890,8 @@ yes + yes +
                                                                                    • [0.20.5] only one value allowed
                                                                                    • @@ -6300,6 +6921,8 @@ yes + yes +   @@ -6318,6 +6941,8 @@ yes + yes +   @@ -6336,6 +6961,8 @@ yes + yes +   @@ -6353,6 +6980,8 @@ na + na +   @@ -6370,6 +6999,8 @@ yes + yes +
                                                                                      • [0.20.5] "inherit" not handled
                                                                                      • @@ -6391,6 +7022,8 @@ no + no +   @@ -6409,11 +7042,13 @@ partial + partial +
                                                                                        • [0.20.5] Only works as a shorthand for baseline-shift property.
                                                                                        • -
                                                                                        • [0.93 and later] Percentages are not supported, yet.
                                                                                        • +
                                                                                        • [0.94 and later] Percentages are not supported, yet.
                                                                                        @@ -6432,6 +7067,8 @@ yes + yes +   @@ -6449,6 +7086,8 @@ yes + yes + [0.95] Very basic parsing; no validation of the specified value. @@ -6467,21 +7106,23 @@ Citation - Support in FOP + Support in FOP Comments - 0.20.5 (previous) + 0.20.5 (ancient) + + 0.94 (stable) - 0.95 (stable) + 0.95 (beta) develop- ment - Number Functions (§5.10.1) @@ -6500,6 +7141,8 @@ yes + yes +   @@ -6517,6 +7160,8 @@ yes + yes +   @@ -6534,6 +7179,8 @@ yes + yes +   @@ -6551,6 +7198,8 @@ yes + yes +   @@ -6568,6 +7217,8 @@ yes + yes +   @@ -6585,11 +7236,13 @@ yes + yes +   - Color Functions (§5.10.2) @@ -6608,6 +7261,8 @@ yes + yes +   @@ -6625,6 +7280,8 @@ yes + yes +   @@ -6642,11 +7299,13 @@ yes + yes +   - Font Functions (§5.10.3) @@ -6665,11 +7324,13 @@ no + no +   - Property Value Functions (§5.10.4) @@ -6690,6 +7351,8 @@ yes + yes +   @@ -6708,6 +7371,8 @@ yes + yes +   @@ -6726,6 +7391,8 @@ yes + yes +   @@ -6744,6 +7411,8 @@ yes + yes +   @@ -6763,6 +7432,8 @@ yes + yes +   @@ -6782,6 +7453,8 @@ yes + yes +   @@ -6801,6 +7474,8 @@ yes + yes +   @@ -6820,6 +7495,8 @@ no + no +   -- cgit v1.2.3 From 2c051186afbd874cc4f4629ba05267a5f21f9358 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 12 Mar 2008 12:19:15 +0000 Subject: Update of the documentation before the release. Added notes about improved checks and conformance in tables. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@636295 13f79535-47bb-0310-9956-ffa450edef68 --- README | 40 ++++++++++++++++++ src/documentation/content/.htaccess | 4 +- .../content/xdocs/0.95/known-issues.xml | 4 -- .../xdocs/0.95/layoutengine/disabled-testcases.xml | 48 ---------------------- src/documentation/content/xdocs/download.xml | 8 ++-- src/documentation/content/xdocs/index.xml | 7 ++-- status.xml | 28 +++++++++++-- 7 files changed, 75 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/README b/README index 67a3b0fe1..133232276 100644 --- a/README +++ b/README @@ -90,6 +90,46 @@ http://xmlgraphics.apache.org/fop/stable/running.html RELEASE NOTES ============================================================================== +Version 0.95beta +================ + +This is a pre-version of the third production grade release of the new FOP +codebase. It contains many bug fixes and new features. See below for details. + +Compliance +---------- + +This release implements the XSL 1.0 and 1.1 recommendations to a high +degree of compliance. See the compliance page +http://xmlgraphics.apache.org/fop/compliance.html for a detailed +overview. + +Known issues +------------ + +The known issues of this release are listed at +http://xmlgraphics.apache.org/fop/0.95/knownissues_overview.html. + +Major Changes in Version 0.95 +----------------------------- + +* Add new fox:external-document extension element that allows to insert whole + documents into a page-sequence (JM) +* Add support for background on fo:table-column and fo:table-header/footer/body + elements (VH) +* Add support for conditional borders in tables (VH) +* Add support for scale-down-to-fit and scale-up-to-fit (JM) +* Fix various bugs and performance problems with external graphics by + introducing a new image loading framework (JM) + +The long list of changes in this release is available at +http://xmlgraphics.apache.org/fop/0.95/changes_0.95.html. + +The long list of changes in this and earlier releases is available at +http://xmlgraphics.apache.org/fop/changes.html. + + + Version 0.94 ============ diff --git a/src/documentation/content/.htaccess b/src/documentation/content/.htaccess index db766b7c4..561900fde 100644 --- a/src/documentation/content/.htaccess +++ b/src/documentation/content/.htaccess @@ -18,8 +18,8 @@ RedirectMatch Permanent ^/fop/upgrading(.*) http://xmlgraphics.apache.org/fop/0. # redirect to versioned documentation Redirect Temp /fop/stable http://xmlgraphics.apache.org/fop/0.94 -Redirect Temp /fop/current http://xmlgraphics.apache.org/fop/0.94 -Redirect Temp /fop/unstable http://xmlgraphics.apache.org/fop/trunk +Redirect Temp /fop/current http://xmlgraphics.apache.org/fop/0.95 +Redirect Temp /fop/unstable http://xmlgraphics.apache.org/fop/0.95 Redirect Temp /fop/latest http://xmlgraphics.apache.org/fop/trunk Redirect Temp /fop/maintenance http://xmlgraphics.apache.org/fop/0.93 Redirect Temp /fop/previous http://xmlgraphics.apache.org/fop/0.93 diff --git a/src/documentation/content/xdocs/0.95/known-issues.xml b/src/documentation/content/xdocs/0.95/known-issues.xml index 568fec8d9..6e28e3fb7 100644 --- a/src/documentation/content/xdocs/0.95/known-issues.xml +++ b/src/documentation/content/xdocs/0.95/known-issues.xml @@ -63,10 +63,6 @@ Not all FO elements can be referenced by their "id", most notably: table-body, table-header, table-footer and table-row. - - The backgrounds of table-body, table-header, table-footer and - table-column are not painted, yet. - Column balancing in multi-column documents may not work as expected (Bugzilla #36356) diff --git a/src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml b/src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml index 15ac8aa48..b4de16ef4 100644 --- a/src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml +++ b/src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml @@ -232,54 +232,6 @@ region-body_column-count_bug36356.xml Column balancing doesn't work as expected. - - No background-images on table-body - table-body_background-image.xml - The backgrounds of table-body, table-header, - table-footer and table-column are not painted, yet. - - - Collapsing Border Model NYI - table_border-collapse_collapse_1.xml - Border-collapse="collapse" is not yet - implemented. - - - Collapsing Border Model NYI - table_border-collapse_collapse_2.xml - Border-collapse="collapse" is not yet - implemented. - - - Problems with border and padding on tables - table_border_padding.xml - The element list seems to not be fully correct, yet, causing - the layout to look odd. - - - keep-with-previous doesn't work inside tables - table-cell_block_keep-with-previous.xml - Keep-with-previous doesn't work inside tables and - lists, yet. - - - Border and padding conditionality is NYI on table-cells - table-cell_border_padding_conditionality.xml - Border and padding conditionality are not supported - on table-cells, yet. - - - No background-images on table-header - table-header_background-image.xml - The backgrounds of table-body, table-header, - table-footer and table-column are not painted, yet. - - - keep-with-previous doesn't work on table-rows - table-row_keep-with-previous.xml - Keep-with-previous doesn't work inside tables and - lists, yet. - table-cell empty area with marker.xml table-cell_empty_area_with_marker.xml diff --git a/src/documentation/content/xdocs/download.xml b/src/documentation/content/xdocs/download.xml index 6607f2ddb..f0a2a0a61 100644 --- a/src/documentation/content/xdocs/download.xml +++ b/src/documentation/content/xdocs/download.xml @@ -108,16 +108,16 @@ Repository URL - - http://svn.apache.org/repos/asf/xmlgraphics/fop/tags/fop-0_95rc/ + + http://svn.apache.org/repos/asf/xmlgraphics/fop/tags/fop-0_95beta/ Web view - - http://svn.apache.org/viewvc/xmlgraphics/fop/tags/fop-0_95rc/ + + http://svn.apache.org/viewvc/xmlgraphics/fop/tags/fop-0_95beta/ diff --git a/src/documentation/content/xdocs/index.xml b/src/documentation/content/xdocs/index.xml index b0f44fac3..9ed040184 100644 --- a/src/documentation/content/xdocs/index.xml +++ b/src/documentation/content/xdocs/index.xml @@ -29,14 +29,15 @@

                                                                                        Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java application that reads a formatting object (FO) tree and renders the resulting - pages to a specified output. Output formats + pages to a specified output. Output formats currently supported include PDF, PS, PCL, AFP, XML (area tree representation), Print, AWT and PNG, and to a lesser extent, RTF and TXT. The primary output target is PDF.

                                                                                        - The latest stable version of FOP (0.94) is the second - stable release after a large redesign effort and implements a large subset of the + A beta release of the latest version of FOP (0.95) is now + available. After a short testing period it will become the third + stable release after the large redesign effort and will implement a large subset of the XSL-FO Version 1.1 W3C Recommendation.

                                                                                        diff --git a/status.xml b/status.xml index 1a01f73c2..8a4fc3da9 100644 --- a/status.xml +++ b/status.xml @@ -59,7 +59,7 @@ --> - +
                                                                                        Notes @@ -69,8 +69,8 @@

                                                                                        • - Improvements and bugfixes for tables (keep and break support, border - conditionality etc.) + Many bugfixes in tables, plus some new features (full support for keeps and + breaks, border conditionality, background on columns and header/footer/body)
                                                                                        • Improvements and bugfixes for font handling and font @@ -85,6 +85,28 @@ Please note that with this release, we've dropped support for Java 1.3. FOP will, from now on, require at least Java 1.4.

                                                                                          +

                                                                                          + There have been a few changes in tables that make FOP both more strict and more + compliant to the Recommendation: +

                                                                                            +
                                                                                          • XSL-FO 1.1 explicitly states that a row-spanning fo:table-cell element is not + allowed to span further than its enclosing fo:table-header/footer/body element + (see bottom of section + 6.7.3). From now on FOP will give a validation error if a document + contains such an erroneous cell. +
                                                                                          • +
                                                                                          • +

                                                                                            If an fo:table element contains explicit fo:table-column children, then those + elements set the total number of columns in the table. This means that a + validation error will now occur if a row contains more cells than available + columns. This change allows to improve performance, since the rendering of the + table may start as soon as the table-column elements have been parsed.

                                                                                            +

                                                                                            If more flexibility is needed, then the fo:table-column elements may be just + omitted. The final number of columns will then be set by the row that has the + most cells.

                                                                                            +
                                                                                          • +
                                                                                          +

                                                                                          The image libraries Jimi and JAI are no longer needed (and used). Instead we rely completely on the Image I/O API that has been introduced with Java 1.4. If you still -- cgit v1.2.3 From 107b703b63ee45bc0e04f1de603affa875cd3c6d Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 12 Mar 2008 19:24:05 +0000 Subject: Removed no longer used borderAndPaddingBPD field git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@636471 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/table/TableCellLayoutManager.java | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index f86554dbd..df23838f9 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -76,7 +76,6 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager private int cellIPD; private int totalHeight; private int usedBPD; - private int borderAndPaddingBPD; private boolean emptyCell = true; /** @@ -99,22 +98,6 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager return getTable().isSeparateBorderModel(); } - /** {@inheritDoc} */ - public void initialize() { - borderAndPaddingBPD = 0; - borderAndPaddingBPD += getTableCell() - .getCommonBorderPaddingBackground().getBorderBeforeWidth(false); - borderAndPaddingBPD += getTableCell() - .getCommonBorderPaddingBackground().getBorderAfterWidth(false); - if (!isSeparateBorderModel()) { - borderAndPaddingBPD /= 2; - } - borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground() - .getPaddingBefore(false, this); - borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground() - .getPaddingAfter(false, this); - } - /** * @return the table owning this cell */ -- cgit v1.2.3 From 5ed52d9f31436a693484dd9179b422c544b004bb Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 14 Mar 2008 11:15:24 +0000 Subject: Bugzilla #44412: Bugfix: When there was a forced break after a block with (conditional) borders the border-after wasn't painted. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@637057 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/BlockContainerLayoutManager.java | 3 + .../fop/layoutmgr/BlockStackingLayoutManager.java | 3 + .../org/apache/fop/layoutmgr/LayoutContext.java | 8 +- status.xml | 8 +- .../block-level_break-after_bug44412.xml | 112 +++++++++++++++++++++ 5 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 435f25b48..5e5613898 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -386,6 +386,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); + + //All child content is processed. Only break-after can occur now, so... + context.clearPendingMarks(); addKnuthElementsForBreakAfter(returnList, context); setFinished(true); diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 541912a08..96e2c82fb 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -393,6 +393,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); + + //All child content is processed. Only break-after can occur now, so... + context.clearPendingMarks(); if (forcedBreakAfterLast == null) { addKnuthElementsForBreakAfter(returnList, context); } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index a72fca9af..79b5e232f 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -285,12 +285,8 @@ public class LayoutContext { * Clears all pending marks on the LayoutContext. */ public void clearPendingMarks() { - if (this.pendingBeforeMarks != null) { - this.pendingBeforeMarks.clear(); - } - if (this.pendingAfterMarks != null) { - this.pendingAfterMarks.clear(); - } + this.pendingBeforeMarks = null; + this.pendingAfterMarks = null; } /** diff --git a/status.xml b/status.xml index 8a4fc3da9..7dd97654a 100644 --- a/status.xml +++ b/status.xml @@ -52,13 +52,17 @@ - + - + + Bugfix: When there was a forced break after a block with (conditional) borders the + border-after wasn't painted. + +

                                                                                          diff --git a/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml b/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml new file mode 100644 index 000000000..523d22c6f --- /dev/null +++ b/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml @@ -0,0 +1,112 @@ + + + + + +

                                                                                          + This test checks Bugzilla #44412 where the border-after of an fo:block wasn't painted in + case break-after is present. +

                                                                                          +
                                                                                          + + + + + + + + + + Before the block + A block with + borders and break-before and break-after. + After the block + + + + + + A block-container with borders and break-after. + + After the block-container + + + + + + + + + + + Blaaaaaah + + + + After the list-block + + + + + + + + + + + Blaaaaaah + + + + After the list-item + + + + + + + + + + Blaaaaah + + + + + After the table + + + + + + + + + + + + + + + + + + + + +
                                                                                          -- cgit v1.2.3 From b0644700fd13beb3286888fbea4dd4a0461d6d54 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 14 Mar 2008 12:22:44 +0000 Subject: Reverting changes of rev. 637057. I applied the changes to the 0.95 branch instead so that they make their way into the 0.95 release. I will merge them back to the Trunk via svnmerge git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@637076 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/BlockContainerLayoutManager.java | 3 - .../fop/layoutmgr/BlockStackingLayoutManager.java | 3 - .../org/apache/fop/layoutmgr/LayoutContext.java | 8 +- status.xml | 8 +- .../block-level_break-after_bug44412.xml | 112 --------------------- 5 files changed, 8 insertions(+), 126 deletions(-) delete mode 100644 test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 5e5613898..435f25b48 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -386,9 +386,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); - - //All child content is processed. Only break-after can occur now, so... - context.clearPendingMarks(); addKnuthElementsForBreakAfter(returnList, context); setFinished(true); diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 96e2c82fb..541912a08 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -393,9 +393,6 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); - - //All child content is processed. Only break-after can occur now, so... - context.clearPendingMarks(); if (forcedBreakAfterLast == null) { addKnuthElementsForBreakAfter(returnList, context); } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 79b5e232f..a72fca9af 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -285,8 +285,12 @@ public class LayoutContext { * Clears all pending marks on the LayoutContext. */ public void clearPendingMarks() { - this.pendingBeforeMarks = null; - this.pendingAfterMarks = null; + if (this.pendingBeforeMarks != null) { + this.pendingBeforeMarks.clear(); + } + if (this.pendingAfterMarks != null) { + this.pendingAfterMarks.clear(); + } } /** diff --git a/status.xml b/status.xml index 7dd97654a..8a4fc3da9 100644 --- a/status.xml +++ b/status.xml @@ -52,17 +52,13 @@ - + - - Bugfix: When there was a forced break after a block with (conditional) borders the - border-after wasn't painted. - - +
                                                                                          diff --git a/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml b/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml deleted file mode 100644 index 523d22c6f..000000000 --- a/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - - - -

                                                                                          - This test checks Bugzilla #44412 where the border-after of an fo:block wasn't painted in - case break-after is present. -

                                                                                          -
                                                                                          - - - - - - - - - - Before the block - A block with - borders and break-before and break-after. - After the block - - - - - - A block-container with borders and break-after. - - After the block-container - - - - - - - - - - - Blaaaaaah - - - - After the list-block - - - - - - - - - - - Blaaaaaah - - - - After the list-item - - - - - - - - - - Blaaaaah - - - - - After the table - - - - - - - - - - - - - - - - - - - - -
                                                                                          -- cgit v1.2.3 From bc8128695c25fdeb81f4e15aacc7247200a420d2 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 18 Mar 2008 15:01:43 +0000 Subject: Merged revisions 636400-636405,636407-638388 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95 ........ r636403 | vhennebert | 2008-03-12 16:24:48 +0000 (Wed, 12 Mar 2008) | 2 lines Updated copyright years ........ r637075 | vhennebert | 2008-03-14 12:19:45 +0000 (Fri, 14 Mar 2008) | 4 lines Bugzilla #44412: Bugfix: When there was a forced break after a block with (conditional) borders the border-after wasn't painted. Changes made by Jeremias ........ r637119 | jeremias | 2008-03-14 14:41:03 +0000 (Fri, 14 Mar 2008) | 2 lines Bugzilla #44412: Bugfix: The before border of a block is no longer swallowed if its first child issues a break-before. ........ r637791 | jeremias | 2008-03-17 08:59:51 +0000 (Mon, 17 Mar 2008) | 3 lines Removed old image adapters. Removed support for Java 1.3 building as it didn't work anymore anyway. Added a check to require Java 1.4 for building. ........ r637857 | jeremias | 2008-03-17 12:24:33 +0000 (Mon, 17 Mar 2008) | 3 lines Partially reverted revision 637791: Restored JAI as a required dependency for distribution builds (used for error diffusion dithering in the PCL Renderer). It is optional otherwise. Updated the licensing info and release notes to make the changes clear. ........ r637993 | vhennebert | 2008-03-17 17:48:44 +0000 (Mon, 17 Mar 2008) | 3 lines Bugzilla #44621: when the after border of a cell, in the trailing case, is bigger than in the normal case, the generated sequence of Knuth elements was wrong, leading to content being swallowed This is a partial fix only: the content is no longer swallowed, but the penalty is wrong (shorter than it should be). This will lead to the table overflowing the region-body without warning. ........ r638048 | vhennebert | 2008-03-17 20:00:36 +0000 (Mon, 17 Mar 2008) | 2 lines Changed the documentation to reflect the move to Java 1.4 as a minimum requirement ........ r638308 | vhennebert | 2008-03-18 10:26:32 +0000 (Tue, 18 Mar 2008) | 2 lines Simplified the getNextKnuthElements method a little bit ........ r638316 | vhennebert | 2008-03-18 11:06:59 +0000 (Tue, 18 Mar 2008) | 2 lines Removed the 'jdk1.4' suffix appended to the binary artifacts. There's no point in making the distinction anymore since there is only one binary now ........ r638317 | vhennebert | 2008-03-18 11:08:29 +0000 (Tue, 18 Mar 2008) | 2 lines Updated the probable date of the release ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@638396 13f79535-47bb-0310-9956-ffa450edef68 --- build.properties | 4 +- build.xml | 80 +-- lib/README.txt | 12 +- src/documentation/content/xdocs/0.95/compiling.xml | 4 +- src/documentation/content/xdocs/0.95/fonts.xml | 12 +- .../content/xdocs/0.95/pdfencryption.xml | 7 +- src/documentation/content/xdocs/0.95/running.xml | 2 +- src/documentation/content/xdocs/dev/release.xml | 2 +- .../content/xdocs/trunk/compiling.xml | 4 +- src/documentation/content/xdocs/trunk/fonts.xml | 12 +- .../content/xdocs/trunk/pdfencryption.xml | 6 +- src/documentation/content/xdocs/trunk/running.xml | 2 +- .../org/apache/fop/svg/GraphicsConfiguration.java | 31 - .../org/apache/fop/image/ImageIOImage.java | 237 ------- .../org/apache/fop/image/JpegImageIOImage.java | 161 ----- .../org/apache/fop/svg/GraphicsConfiguration.java | 51 -- src/java/org/apache/fop/apps/FopFactory.java | 10 - src/java/org/apache/fop/fo/FOPropertyMapping.java | 6 + src/java/org/apache/fop/fo/FOTreeBuilder.java | 5 - .../org/apache/fop/image/AbstractFopImage.java | 376 ----------- src/java/org/apache/fop/image/BmpImage.java | 220 ------- src/java/org/apache/fop/image/EPSImage.java | 122 ---- src/java/org/apache/fop/image/EmfImage.java | 51 -- src/java/org/apache/fop/image/FopImage.java | 207 ------ .../org/apache/fop/image/FopImageConsumer.java | 211 ------ src/java/org/apache/fop/image/GifImage.java | 218 ------- src/java/org/apache/fop/image/ImageCache.java | 72 --- src/java/org/apache/fop/image/ImageFactory.java | 708 --------------------- src/java/org/apache/fop/image/ImageLoader.java | 64 -- src/java/org/apache/fop/image/JAIImage.java | 194 ------ src/java/org/apache/fop/image/JimiImage.java | 186 ------ src/java/org/apache/fop/image/JpegImage.java | 239 ------- src/java/org/apache/fop/image/PNGImage.java | 87 --- .../fop/image/RegisterableImageProvider.java | 49 -- src/java/org/apache/fop/image/TIFFImage.java | 207 ------ src/java/org/apache/fop/image/XMLImage.java | 78 --- .../apache/fop/image/XmlGraphicsCommonsImage.java | 239 ------- .../org/apache/fop/image/analyser/BMPReader.java | 134 ---- .../org/apache/fop/image/analyser/EMFReader.java | 162 ----- .../org/apache/fop/image/analyser/EPSReader.java | 253 -------- .../org/apache/fop/image/analyser/GIFReader.java | 104 --- .../org/apache/fop/image/analyser/ImageReader.java | 56 -- .../fop/image/analyser/ImageReaderFactory.java | 108 ---- .../org/apache/fop/image/analyser/JPEGReader.java | 264 -------- .../org/apache/fop/image/analyser/PNGReader.java | 115 ---- .../org/apache/fop/image/analyser/SVGReader.java | 188 ------ .../org/apache/fop/image/analyser/SVGZReader.java | 53 -- .../org/apache/fop/image/analyser/TIFFReader.java | 117 ---- .../org/apache/fop/image/analyser/XMLReader.java | 167 ----- .../org/apache/fop/image/analyser/package.html | 23 - src/java/org/apache/fop/image/package.html | 2 +- .../fop/layoutmgr/BlockContainerLayoutManager.java | 3 + .../fop/layoutmgr/BlockStackingLayoutManager.java | 16 +- .../org/apache/fop/layoutmgr/LayoutContext.java | 8 +- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 18 +- .../org/apache/fop/render/ps/PSImageUtils.java | 73 --- .../org/apache/fop/render/rtf/SVGConverter.java | 70 -- .../org/apache/fop/svg/GraphicsConfiguration.java | 51 ++ status.xml | 22 +- .../java/org/apache/fop/URIResolutionTestCase.java | 11 +- .../block-level_break-after_bug44412.xml | 112 ++++ .../block_break-before_bug44412.xml | 64 ++ .../standard-testcases/table_bug44621.xml | 105 +++ .../table_row-delay_fixed-row-height.xml | 2 +- 64 files changed, 435 insertions(+), 6042 deletions(-) delete mode 100644 src/java-1.3/org/apache/fop/svg/GraphicsConfiguration.java delete mode 100644 src/java-1.4/org/apache/fop/image/ImageIOImage.java delete mode 100644 src/java-1.4/org/apache/fop/image/JpegImageIOImage.java delete mode 100644 src/java-1.4/org/apache/fop/svg/GraphicsConfiguration.java delete mode 100644 src/java/org/apache/fop/image/AbstractFopImage.java delete mode 100644 src/java/org/apache/fop/image/BmpImage.java delete mode 100644 src/java/org/apache/fop/image/EPSImage.java delete mode 100644 src/java/org/apache/fop/image/EmfImage.java delete mode 100644 src/java/org/apache/fop/image/FopImage.java delete mode 100644 src/java/org/apache/fop/image/FopImageConsumer.java delete mode 100644 src/java/org/apache/fop/image/GifImage.java delete mode 100644 src/java/org/apache/fop/image/ImageCache.java delete mode 100644 src/java/org/apache/fop/image/ImageFactory.java delete mode 100644 src/java/org/apache/fop/image/ImageLoader.java delete mode 100644 src/java/org/apache/fop/image/JAIImage.java delete mode 100644 src/java/org/apache/fop/image/JimiImage.java delete mode 100644 src/java/org/apache/fop/image/JpegImage.java delete mode 100644 src/java/org/apache/fop/image/PNGImage.java delete mode 100644 src/java/org/apache/fop/image/RegisterableImageProvider.java delete mode 100644 src/java/org/apache/fop/image/TIFFImage.java delete mode 100644 src/java/org/apache/fop/image/XMLImage.java delete mode 100644 src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java delete mode 100644 src/java/org/apache/fop/image/analyser/BMPReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/EMFReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/EPSReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/GIFReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/ImageReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/ImageReaderFactory.java delete mode 100644 src/java/org/apache/fop/image/analyser/JPEGReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/PNGReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/SVGReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/SVGZReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/TIFFReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/XMLReader.java delete mode 100644 src/java/org/apache/fop/image/analyser/package.html delete mode 100644 src/java/org/apache/fop/render/ps/PSImageUtils.java delete mode 100644 src/java/org/apache/fop/render/rtf/SVGConverter.java create mode 100644 src/java/org/apache/fop/svg/GraphicsConfiguration.java create mode 100644 test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml create mode 100644 test/layoutengine/standard-testcases/block_break-before_bug44412.xml create mode 100644 test/layoutengine/standard-testcases/table_bug44621.xml (limited to 'src') diff --git a/build.properties b/build.properties index 06630b4b3..2a8b4c80c 100644 --- a/build.properties +++ b/build.properties @@ -24,8 +24,8 @@ # javac.debug = on # javac.optimize = off # javac.deprecation = on -# javac.source = 1.3 -# javac.target = 1.3 +# javac.source = 1.4 +# javac.target = 1.4 # javac.fork = on ## JUnit task switches diff --git a/build.xml b/build.xml index 18bf3e8d7..2169003f8 100644 --- a/build.xml +++ b/build.xml @@ -131,10 +131,6 @@ list of possible build targets. - - - - @@ -148,7 +144,7 @@ list of possible build targets. - + @@ -214,7 +210,7 @@ list of possible build targets. - + @@ -224,18 +220,6 @@ list of possible build targets. - - - - - - - - - - - @@ -261,7 +245,8 @@ list of possible build targets. - + + @@ -292,22 +277,6 @@ list of possible build targets. - - - - - - - - - - - - - - - - @@ -401,12 +370,9 @@ list of possible build targets. source="${javac.source}" target="${javac.target}"> - - - @@ -543,7 +509,6 @@ list of possible build targets. - @@ -1032,7 +997,6 @@ NOTE: - @@ -1206,37 +1170,24 @@ NOTE: --> - - - - - - - - - - - - - - - - + - + - - - + + + + + @@ -1252,10 +1203,9 @@ NOTE: - - + + destfile="${name}-${version}-bin.tar"> @@ -1264,8 +1214,8 @@ NOTE: - - + + diff --git a/lib/README.txt b/lib/README.txt index 46c716b77..2f307b2cf 100644 --- a/lib/README.txt +++ b/lib/README.txt @@ -142,8 +142,16 @@ Please make sure you've read the license of each package. https://jai-imageio.dev.java.net/ BSD license - Note: Not the whole JAI is needed, only the ImageIO-compatible codecs - packaged as "Image I/O Tools". The name may be misleading. + Note: This is not the same as JAI! Only the ImageIO-compatible codecs + are packaged as "Image I/O Tools". The name may be misleading. + + - JAI (Java Advanced Imaging API) + + http://java.sun.com/products/java-media/jai + Java Research License and Java Distribution License (Check which one applies to you!) + + Currently used for: + - Grayscale error diffusion dithering in the PCL Renderer - JEuclid (MathML implementation, for the MathML extension) diff --git a/src/documentation/content/xdocs/0.95/compiling.xml b/src/documentation/content/xdocs/0.95/compiling.xml index c6c17a3c0..57761429f 100644 --- a/src/documentation/content/xdocs/0.95/compiling.xml +++ b/src/documentation/content/xdocs/0.95/compiling.xml @@ -41,7 +41,7 @@
                                                                                          JDK

                                                                                          - Building FOP requires a minimum Java Development Kit (JDK/SDK) of 1.3 + Building FOP requires a minimum Java Development Kit (JDK/SDK) of 1.4 (A Java Runtime Environment is not sufficient).

                                                                                          @@ -59,7 +59,7 @@

                                                                                          The build script uses Apache Ant, a popular Java-based build tool, which usually requires that the environment variable JAVA_HOME point to - your local JDK root directory. This is true even if you use JDK 1.3 or above, which normally + your local JDK root directory. This is true even if you use JDK 1.4 or above, which normally does not need this setting.

                                                                                          diff --git a/src/documentation/content/xdocs/0.95/fonts.xml b/src/documentation/content/xdocs/0.95/fonts.xml index af1de28f2..423eaad11 100644 --- a/src/documentation/content/xdocs/0.95/fonts.xml +++ b/src/documentation/content/xdocs/0.95/fonts.xml @@ -231,20 +231,12 @@ Type 1 Font Metrics

                                                                                          FOP includes PFMReader, which reads the PFM file that normally comes with a Type 1 font, and generates an appropriate font metrics file for it. To use it, run the class org.apache.fop.fonts.apps.PFMReader:

                                                                                          -

                                                                                          Windows (on JDK 1.4 and later):

                                                                                          +

                                                                                          Windows:

                                                                                          java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file -

                                                                                          Windows (on JDK 1.3.x):

                                                                                          - java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar;lib\xml-apis.jar; - lib\xercesImpl.jar;lib\xalan.jar;lib\serializer.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file -

                                                                                          Unix (on JDK 1.4 and later):

                                                                                          +

                                                                                          Unix:

                                                                                          java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file -

                                                                                          Unix (on JDK 1.3.1):

                                                                                          - java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar:lib/xml-apis.jar: - lib/xercesImpl.jar:lib/xalan.jar:lib/serializer.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

                                                                                          PFMReader [options]:

                                                                                          • -fn <fontname> By default, FOP uses the fontname from the diff --git a/src/documentation/content/xdocs/0.95/pdfencryption.xml b/src/documentation/content/xdocs/0.95/pdfencryption.xml index c8cdbb29c..cda301aab 100644 --- a/src/documentation/content/xdocs/0.95/pdfencryption.xml +++ b/src/documentation/content/xdocs/0.95/pdfencryption.xml @@ -203,16 +203,11 @@ Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent); install.

                                                                                              -
                                                                                            1. - Download the binary distribution for your JDK version. If you have JDK - 1.3 or earlier you must also download a JCE from the same page. -
                                                                                            2. Unpack the distribution. Add the jar file to your classpath. A convenient way to use the jar on Linux is to simply drop it into the FOP lib directory, it will be automatically picked up by - fop.sh. If you have JDK 1.3 or earlier don't forget to - install the JCE as well. + fop.sh.
                                                                                            3. Open the java.security file and add
                                                                                              diff --git a/src/documentation/content/xdocs/0.95/running.xml b/src/documentation/content/xdocs/0.95/running.xml index 38df4be82..38e31cc6c 100644 --- a/src/documentation/content/xdocs/0.95/running.xml +++ b/src/documentation/content/xdocs/0.95/running.xml @@ -305,7 +305,7 @@ Fop [options] [-fo|-xml] infile [-xsl file] [-awt|-pdf|-mif|-rtf|-tiff|-png|-pcl
                                                                                              • Increase memory available to the JVM. See - the -Xmx option + the -Xmx option for more information. It is usually unwise to increase the memory allocated to the JVM beyond the amount of diff --git a/src/documentation/content/xdocs/dev/release.xml b/src/documentation/content/xdocs/dev/release.xml index fa4dbfa37..641758d78 100644 --- a/src/documentation/content/xdocs/dev/release.xml +++ b/src/documentation/content/xdocs/dev/release.xml @@ -73,7 +73,7 @@ The purpose of documenting it here is to facilitate consistency, ensure that the fop-hyph.jar to lib/ (e.g. from http://sourceforge.net/projects/offo
                                                                                              • Alternatively, create a build-local.properties file that points to the above libs.
                                                                                              • -
                                                                                              • Run build[.sh] dist. Do this once using Sun JDK 1.3.1_15 or later and once with Sun JDK 1.4.2_08 or later. A Forrest installation is needed.
                                                                                              • +
                                                                                              • Run build[.sh] dist. Do this using Sun JDK 1.4.2_08 or later. A Forrest installation is needed.
                                                                                              • Create signatures. Don't forget to upload your KEY: gpg -a -b --force-v3-sigs fop-0.94-src.tar.gz etc.
                                                                                              • Upload the dist and signature files to your web directory diff --git a/src/documentation/content/xdocs/trunk/compiling.xml b/src/documentation/content/xdocs/trunk/compiling.xml index c6c17a3c0..57761429f 100644 --- a/src/documentation/content/xdocs/trunk/compiling.xml +++ b/src/documentation/content/xdocs/trunk/compiling.xml @@ -41,7 +41,7 @@
                                                                                                JDK

                                                                                                - Building FOP requires a minimum Java Development Kit (JDK/SDK) of 1.3 + Building FOP requires a minimum Java Development Kit (JDK/SDK) of 1.4 (A Java Runtime Environment is not sufficient).

                                                                                                @@ -59,7 +59,7 @@

                                                                                                The build script uses Apache Ant, a popular Java-based build tool, which usually requires that the environment variable JAVA_HOME point to - your local JDK root directory. This is true even if you use JDK 1.3 or above, which normally + your local JDK root directory. This is true even if you use JDK 1.4 or above, which normally does not need this setting.

                                                                                          diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml index af1de28f2..423eaad11 100644 --- a/src/documentation/content/xdocs/trunk/fonts.xml +++ b/src/documentation/content/xdocs/trunk/fonts.xml @@ -231,20 +231,12 @@ Type 1 Font Metrics

                                                                                          FOP includes PFMReader, which reads the PFM file that normally comes with a Type 1 font, and generates an appropriate font metrics file for it. To use it, run the class org.apache.fop.fonts.apps.PFMReader:

                                                                                          -

                                                                                          Windows (on JDK 1.4 and later):

                                                                                          +

                                                                                          Windows:

                                                                                          java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file -

                                                                                          Windows (on JDK 1.3.x):

                                                                                          - java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar;lib\xml-apis.jar; - lib\xercesImpl.jar;lib\xalan.jar;lib\serializer.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file -

                                                                                          Unix (on JDK 1.4 and later):

                                                                                          +

                                                                                          Unix:

                                                                                          java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file -

                                                                                          Unix (on JDK 1.3.1):

                                                                                          - java -cp build/fop.jar:lib/avalon-framework.jar:lib/commons-logging.jar:lib/commons-io.jar:lib/xml-apis.jar: - lib/xercesImpl.jar:lib/xalan.jar:lib/serializer.jar - org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file

                                                                                          PFMReader [options]:

                                                                                          • -fn <fontname> By default, FOP uses the fontname from the diff --git a/src/documentation/content/xdocs/trunk/pdfencryption.xml b/src/documentation/content/xdocs/trunk/pdfencryption.xml index c8cdbb29c..22d965057 100644 --- a/src/documentation/content/xdocs/trunk/pdfencryption.xml +++ b/src/documentation/content/xdocs/trunk/pdfencryption.xml @@ -204,15 +204,13 @@ Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent);

                                                                                            1. - Download the binary distribution for your JDK version. If you have JDK - 1.3 or earlier you must also download a JCE from the same page. + Download the binary distribution for your JDK version.
                                                                                            2. Unpack the distribution. Add the jar file to your classpath. A convenient way to use the jar on Linux is to simply drop it into the FOP lib directory, it will be automatically picked up by - fop.sh. If you have JDK 1.3 or earlier don't forget to - install the JCE as well. + fop.sh.
                                                                                            3. Open the java.security file and add
                                                                                              diff --git a/src/documentation/content/xdocs/trunk/running.xml b/src/documentation/content/xdocs/trunk/running.xml index 38df4be82..38e31cc6c 100644 --- a/src/documentation/content/xdocs/trunk/running.xml +++ b/src/documentation/content/xdocs/trunk/running.xml @@ -305,7 +305,7 @@ Fop [options] [-fo|-xml] infile [-xsl file] [-awt|-pdf|-mif|-rtf|-tiff|-png|-pcl
                                                                                              • Increase memory available to the JVM. See - the -Xmx option + the -Xmx option for more information. It is usually unwise to increase the memory allocated to the JVM beyond the amount of diff --git a/src/java-1.3/org/apache/fop/svg/GraphicsConfiguration.java b/src/java-1.3/org/apache/fop/svg/GraphicsConfiguration.java deleted file mode 100644 index 76bb3e4bc..000000000 --- a/src/java-1.3/org/apache/fop/svg/GraphicsConfiguration.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - - -package org.apache.fop.svg; -/** - * Adapter to allow subclassing java.awt.GraphicsConfiguration without - * compilation errors. - * The version for JDK 1.3 is just empty. - * - */ -abstract public class GraphicsConfiguration extends java.awt.GraphicsConfiguration { - - -} diff --git a/src/java-1.4/org/apache/fop/image/ImageIOImage.java b/src/java-1.4/org/apache/fop/image/ImageIOImage.java deleted file mode 100644 index 7ec6b9004..000000000 --- a/src/java-1.4/org/apache/fop/image/ImageIOImage.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// AWT -import java.awt.Color; -import java.awt.color.ColorSpace; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.BufferedImage; -import java.util.Iterator; - -// ImageIO -import javax.imageio.ImageIO; -import javax.imageio.ImageReadParam; -import javax.imageio.ImageReader; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.stream.ImageInputStream; - -import org.apache.commons.io.IOUtils; -import org.apache.fop.util.UnitConv; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -/** - * FopImage object using ImageIO. - * @see AbstractFopImage - * @see FopImage - */ -public class ImageIOImage extends AbstractFopImage { - - private byte[] softMask = null; - - /** - * Creates a new ImageIOImage. - * @param info the image info from the ImageReader - */ - public ImageIOImage(FopImage.ImageInfo info) { - super(info); - if ("image/png".equals(info.mimeType) - || "image/tiff".equals(info.mimeType)) { - this.loaded = 0; //TODO The PNG and TIFF Readers cannot read the resolution, yet. - } - } - - /** - * @see org.apache.fop.image.AbstractFopImage#loadDimensions() - */ - protected boolean loadDimensions() { - if (this.bitmaps == null) { - return loadBitmap(); - } - return true; - } - - private Element getChild(Element el, String name) { - NodeList nodes = el.getElementsByTagName(name); - if (nodes.getLength() > 0) { - return (Element)nodes.item(0); - } else { - return null; - } - } - - /** @see org.apache.fop.image.AbstractFopImage#loadBitmap() */ - protected boolean loadBitmap() { - if (this.bitmaps != null) { - return true; - } - try { - inputStream.reset(); - ImageInputStream imgStream = ImageIO.createImageInputStream(inputStream); - Iterator iter = ImageIO.getImageReaders(imgStream); - if (!iter.hasNext()) { - log.error("No ImageReader found."); - return false; - } - ImageReader reader = (ImageReader)iter.next(); - ImageReadParam param = reader.getDefaultReadParam(); - reader.setInput(imgStream, true, false); - BufferedImage imageData = reader.read(0, param); - - //Read image resolution - IIOMetadata iiometa = reader.getImageMetadata(0); - if (iiometa != null && iiometa.isStandardMetadataFormatSupported()) { - Element metanode = (Element)iiometa.getAsTree("javax_imageio_1.0"); - Element dim = getChild(metanode, "Dimension"); - if (dim != null) { - Element child; - child = getChild(dim, "HorizontalPixelSize"); - if (child != null) { - this.dpiHorizontal = UnitConv.IN2MM - / Float.parseFloat(child.getAttribute("value")); - } - child = getChild(dim, "VerticalPixelSize"); - if (child != null) { - this.dpiVertical = UnitConv.IN2MM - / Float.parseFloat(child.getAttribute("value")); - } - } - } - imgStream.close(); - reader.dispose(); - - this.height = imageData.getHeight(); - this.width = imageData.getWidth(); - - ColorModel cm = imageData.getColorModel(); - this.bitsPerPixel = cm.getComponentSize(0); //only use first, we assume all are equal - //this.colorSpace = cm.getColorSpace(); - //We currently force the image to sRGB - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); - - int[] tmpMap = imageData.getRGB(0, 0, this.width, - this.height, null, 0, this.width); - - if (cm.hasAlpha()) { - // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT - int transparencyType = cm.getTransparency(); - - if (transparencyType == java.awt.Transparency.OPAQUE) { - this.isTransparent = false; - } else if (transparencyType == java.awt.Transparency.BITMASK) { - if (cm instanceof IndexColorModel) { - this.isTransparent = false; - byte[] alphas = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] reds = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] greens = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] blues = new byte[ - ((IndexColorModel) cm).getMapSize()]; - ((IndexColorModel) cm).getAlphas(alphas); - ((IndexColorModel) cm).getReds(reds); - ((IndexColorModel) cm).getGreens(greens); - ((IndexColorModel) cm).getBlues(blues); - for (int i = 0; - i < ((IndexColorModel) cm).getMapSize(); - i++) { - if ((alphas[i] & 0xFF) == 0) { - this.isTransparent = true; - this.transparentColor = new Color( - (int)(reds[i] & 0xFF), - (int)(greens[i] & 0xFF), - (int)(blues[i] & 0xFF)); - break; - } - } - } else { - //TODO Is there another case? - this.isTransparent = false; - } - } else { - // TRANSLUCENT - this.softMask = new byte[width * height]; - imageData.getAlphaRaster().getDataElements( - 0, 0, width, height, this.softMask); - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - for (int i = 0; i < this.height; i++) { - for (int j = 0; j < this.width; j++) { - int p = tmpMap[i * this.width + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - this.bitmaps[3 * (i * this.width + j)] - = (byte)(r & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 1] - = (byte)(g & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 2] - = (byte)(b & 0xFF); - } - } - - } catch (Exception ex) { - log.error("Error while loading image: " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - return true; - } - - /** @see org.apache.fop.image.AbstractFopImage#loadOriginalData() */ - protected boolean loadOriginalData() { - if (inputStream == null && getBitmaps() != null) { - return false; - } else { - return loadDefaultOriginalData(); - } - } - - /** @see org.apache.fop.image.FopImage#hasSoftMask() */ - public boolean hasSoftMask() { - if (this.bitmaps == null && this.raw == null) { - loadBitmap(); - } - - return (this.softMask != null); - } - - /** @see org.apache.fop.image.FopImage#getSoftMask() */ - public byte[] getSoftMask() { - if (this.bitmaps == null) { - loadBitmap(); - } - - return this.softMask; - } - -} - diff --git a/src/java-1.4/org/apache/fop/image/JpegImageIOImage.java b/src/java-1.4/org/apache/fop/image/JpegImageIOImage.java deleted file mode 100644 index 86d78f666..000000000 --- a/src/java-1.4/org/apache/fop/image/JpegImageIOImage.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// AWT -import java.awt.Color; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.BufferedImage; - -// ImageIO -import javax.imageio.ImageIO; - -import org.apache.commons.io.IOUtils; - -/** - * FopImage object using ImageIO. - * Special class to allow the use of JpegImage for those - * renderers which can embed Jpeg directly but for renderers - * which require the decoded data this class delivers it. - * @see AbstractFopImage - * @see JpegImage - */ -public class JpegImageIOImage extends JpegImage { - - /** - * Creates a new JpegImageIOImage. - * @param info the image info from the ImageReader - */ - public JpegImageIOImage(FopImage.ImageInfo info) { - super(info); - } - - /** - * @see org.apache.fop.image.AbstractFopImage#loadDimensions() - */ - protected boolean loadDimensions() { - if (this.bitmaps == null) { - return loadBitmap(); - } - return true; - } - - /** @see org.apache.fop.image.AbstractFopImage#loadBitmap() */ - protected boolean loadBitmap() { - try { - inputStream.reset(); - BufferedImage imageData = ImageIO.read(inputStream); - - this.height = imageData.getHeight(); - this.width = imageData.getWidth(); - - ColorModel cm = imageData.getColorModel(); - this.bitsPerPixel = cm.getComponentSize(0); //only use first, we assume all are equal - this.colorSpace = cm.getColorSpace(); - - int[] tmpMap = imageData.getRGB(0, 0, this.width, - this.height, null, 0, this.width); - - if (cm.hasAlpha()) { - // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT - int transparencyType = cm.getTransparency(); - - if (transparencyType == java.awt.Transparency.OPAQUE) { - this.isTransparent = false; - } else if (transparencyType == java.awt.Transparency.BITMASK) { - if (cm instanceof IndexColorModel) { - this.isTransparent = false; - byte[] alphas = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] reds = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] greens = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] blues = new byte[ - ((IndexColorModel) cm).getMapSize()]; - ((IndexColorModel) cm).getAlphas(alphas); - ((IndexColorModel) cm).getReds(reds); - ((IndexColorModel) cm).getGreens(greens); - ((IndexColorModel) cm).getBlues(blues); - for (int i = 0; - i < ((IndexColorModel) cm).getMapSize(); - i++) { - if ((alphas[i] & 0xFF) == 0) { - this.isTransparent = true; - this.transparentColor = new Color( - (int)(reds[i] & 0xFF), - (int)(greens[i] & 0xFF), - (int)(blues[i] & 0xFF)); - break; - } - } - } else { - // TRANSLUCENT - /* - * this.isTransparent = false; - * for (int i = 0; i < this.width * this.height; i++) { - * if (cm.getAlpha(tmpMap[i]) == 0) { - * this.isTransparent = true; - * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]), - * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i])); - * break; - * } - * } - * // or use special API... - */ - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - for (int i = 0; i < this.height; i++) { - for (int j = 0; j < this.width; j++) { - int p = tmpMap[i * this.width + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - this.bitmaps[3 * (i * this.width + j)] - = (byte)(r & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 1] - = (byte)(g & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 2] - = (byte)(b & 0xFF); - } - } - - } catch (Exception ex) { - log.error("Error while loading image: " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - return true; - } - -} - diff --git a/src/java-1.4/org/apache/fop/svg/GraphicsConfiguration.java b/src/java-1.4/org/apache/fop/svg/GraphicsConfiguration.java deleted file mode 100644 index a92baed27..000000000 --- a/src/java-1.4/org/apache/fop/svg/GraphicsConfiguration.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - - -package org.apache.fop.svg; - -import java.awt.image.VolatileImage; - -/** - * Adapter to allow subclassing java.awt.GraphicsConfiguration without - * compilation errors. - * The version for JDK 1.4 needs to add an override for the abstract - * createCompatibleVolatileImage() method. It can't be overidden - * for JDK 1.3 because there is no VolatileImage there. - * - */ -abstract public class GraphicsConfiguration extends java.awt.GraphicsConfiguration { - - /** - * @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int) - * @since JDK 1.4 - */ - public VolatileImage createCompatibleVolatileImage(int width, int height) { - return null; - } - - /** - * @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int, int) - * @since JDK 1.5 - */ - public VolatileImage createCompatibleVolatileImage(int width, int height, int transparency) { - return null; - } - -} diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index e6ac70d67..ce77d9040 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -46,7 +46,6 @@ import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.ElementMappingRegistry; import org.apache.fop.fonts.FontCache; import org.apache.fop.hyphenation.HyphenationTreeResolver; -import org.apache.fop.image.ImageFactory; import org.apache.fop.layoutmgr.LayoutManagerMaker; import org.apache.fop.render.RendererFactory; import org.apache.fop.render.XMLHandlerRegistry; @@ -82,9 +81,6 @@ public class FopFactory implements ImageContext { private ColorSpaceCache colorSpaceCache = null; - /** Image factory for creating fop image objects */ - private ImageFactory imageFactory; - /** Image manager for loading and caching image objects */ private ImageManager imageManager; @@ -155,7 +151,6 @@ public class FopFactory implements ImageContext { this.elementMappingRegistry = new ElementMappingRegistry(this); this.foURIResolver = new FOURIResolver(validateUserConfigStrictly()); this.colorSpaceCache = new ColorSpaceCache(foURIResolver); - this.imageFactory = new ImageFactory(); this.imageManager = new ImageManager(this); this.rendererFactory = new RendererFactory(); this.xmlHandlers = new XMLHandlerRegistry(); @@ -290,11 +285,6 @@ public class FopFactory implements ImageContext { return this.contentHandlerFactoryRegistry; } - /** @return the image factory */ - public ImageFactory getImageFactory() { - return this.imageFactory; - } - /** * Returns the image manager. * @return the image manager diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 9910f1ce7..539648f5a 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -412,6 +412,7 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.setDefault("auto"); + l.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT); addPropertyMaker("top", l); // right @@ -419,6 +420,7 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.setDefault("auto"); + l.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH); addPropertyMaker("right", l); // bottom @@ -426,6 +428,7 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.setDefault("auto"); + l.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT); addPropertyMaker("bottom", l); // left @@ -433,6 +436,7 @@ public final class FOPropertyMapping implements Constants { l.setInherited(false); l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); l.setDefault("auto"); + l.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH); addPropertyMaker("left", l); } @@ -1161,6 +1165,7 @@ public final class FOPropertyMapping implements Constants { m = new LengthProperty.Maker(PR_START_INDENT); m.setInherited(true); m.setDefault("0pt"); + m.setPercentBase(LengthBase.CONTAINING_REFAREA_WIDTH); IndentPropertyMaker sCorr = new IndentPropertyMaker(m); sCorr.setCorresponding(PR_MARGIN_LEFT, PR_MARGIN_RIGHT, PR_MARGIN_TOP); sCorr.setUseParent(false); @@ -1177,6 +1182,7 @@ public final class FOPropertyMapping implements Constants { m = new LengthProperty.Maker(PR_END_INDENT); m.setInherited(true); m.setDefault("0pt"); + m.setPercentBase(LengthBase.CONTAINING_REFAREA_WIDTH); IndentPropertyMaker eCorr = new IndentPropertyMaker(m); eCorr.setCorresponding(PR_MARGIN_RIGHT, PR_MARGIN_LEFT, PR_MARGIN_BOTTOM); eCorr.setUseParent(false); diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index c12a20afe..d02a058fe 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -38,7 +38,6 @@ import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.fo.ElementMapping.Maker; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.pagination.Root; -import org.apache.fop.image.ImageFactory; import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; import org.apache.fop.util.ContentHandlerFactory.ObjectSource; @@ -155,10 +154,6 @@ public class FOTreeBuilder extends DefaultHandler { log.debug("Parsing of document complete"); } foEventHandler.endDocument(); - - //Notify the image factory that this user agent has expired. - ImageFactory imageFactory = userAgent.getFactory().getImageFactory(); - imageFactory.removeContext(this.userAgent); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/image/AbstractFopImage.java b/src/java/org/apache/fop/image/AbstractFopImage.java deleted file mode 100644 index 8d5180149..000000000 --- a/src/java/org/apache/fop/image/AbstractFopImage.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// Java -import java.awt.color.ColorSpace; -import java.awt.color.ICC_ColorSpace; -import java.awt.color.ICC_Profile; -import java.io.InputStream; -import java.awt.Color; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.datatypes.Length; - -/** - * Base class to implement the FopImage interface. - * - * @see FopImage - */ -public abstract class AbstractFopImage implements FopImage { - - /** - * logging instance - */ - protected static Log log = LogFactory.getLog(AbstractFopImage.class); - - /** - * Keeps track of what has been loaded. - */ - protected int loaded = 0; - - /** - * Image width (in pixel). - */ - protected int width = 0; - - /** - * Image height (in pixel). - */ - protected int height = 0; - - /** Horizontal bitmap resolution (in dpi) */ - protected double dpiHorizontal = 72.0f; - - /** Vertical bitmap resolution (in dpi) */ - protected double dpiVertical = 72.0f; - - /** - * Image input stream. - */ - protected InputStream inputStream = null; - - /** - * ImageReader object (to obtain image header informations). - */ - protected FopImage.ImageInfo imageInfo = null; - - /** - * Image color space (java.awt.color.ColorSpace). - */ - protected ColorSpace colorSpace = null; - - /** - * Bits per pixel. - */ - protected int bitsPerPixel = 0; - - /** - * Image data (pixels, uncompressed). - */ - protected byte[] bitmaps = null; - - /** - * Image data (undecoded, compressed, for image formats that can be embedded without decoding. - */ - protected byte[] raw = null; - - /** - * Image transparency. - */ - protected boolean isTransparent = false; - - /** - * Transparent color (java.awt.Color). - */ - protected Color transparentColor = null; - - /** - * Photoshop generated CMYK JPEGs are inverted. - */ - protected boolean invertImage = false; - - /** - * Constructor. - * Construct a new FopImage object and initialize its default properties: - *
                                                                                                  - *
                                                                                                • image width - *
                                                                                                • image height - *
                                                                                                - * The image data isn't kept in memory. - * @param info image information - */ - public AbstractFopImage(FopImage.ImageInfo info) { - this.inputStream = info.inputStream; - this.imageInfo = info; - if (this.imageInfo.width != -1) { - width = imageInfo.width; - height = imageInfo.height; - dpiHorizontal = imageInfo.dpiHorizontal; - dpiVertical = imageInfo.dpiVertical; - loaded = loaded | DIMENSIONS; - } - } - - /** - * Get the mime type for this image. - * - * @return the mime type for the image - */ - public String getMimeType() { - return imageInfo.mimeType; - } - - /** {@inheritDoc} */ - public String getOriginalURI() { - return this.imageInfo.originalURI; - } - - /** - * Load image data and initialize its properties. - * - * @param type the type of loading to do - * @return true if the loading was successful - */ - public synchronized boolean load(int type) { - if ((loaded & type) != 0) { - return true; - } - boolean success = true; - if (((type & DIMENSIONS) != 0) && ((loaded & DIMENSIONS) == 0)) { - success = success && loadDimensions(); - - if (!success) { - return false; - } - loaded = loaded | DIMENSIONS; - } - if (((type & BITMAP) != 0) && ((loaded & BITMAP) == 0)) { - success = success && loadBitmap(); - if (success) { - loaded = loaded | BITMAP; - } - } - if (((type & ORIGINAL_DATA) != 0) && ((loaded & ORIGINAL_DATA) == 0)) { - success = success && loadOriginalData(); - if (success) { - loaded = loaded | ORIGINAL_DATA; - } - } - return success; - } - - /** - * Load the dimensions of the image. - * All implementations should override this to get and - * return the dimensions. - * - * @return true if the loading was successful - */ - protected boolean loadDimensions() { - return false; - } - - /** - * Load a bitmap array of the image. - * If the renderer requires a bitmap image then the - * implementations should override this to load the bitmap. - * - * @return true if the loading was successful - */ - protected boolean loadBitmap() { - return false; - } - - /** - * Load the original image data. - * In some cases the original data can be used by the renderer. - * This should load the data and any other associated information. - * - * @return true if the loading was successful - */ - protected boolean loadOriginalData() { - return false; - } - - /** - * Load the original image data. This is generic code for use by any - * subclass that wants to use this from a loadOriginalData() implementation. - * - * @return true if the loading was successful - */ - protected boolean loadDefaultOriginalData() { - if (inputStream == null) { - throw new IllegalStateException("inputStream is already null or was never set"); - } - try { - this.raw = IOUtils.toByteArray(inputStream); - } catch (java.io.IOException ex) { - log.error("Error while reading raw image: " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - return true; - } - - /** - * @return the image width (in pixels) - */ - public int getWidth() { - return this.width; - } - - /** - * @return the image height (in pixels) - */ - public int getHeight() { - return this.height; - } - - /** {@inheritDoc} */ - public int getIntrinsicWidth() { - return (int)(getWidth() * 72000 / getHorizontalResolution()); - } - - /** {@inheritDoc} */ - public int getIntrinsicHeight() { - return (int)(getHeight() * 72000 / getVerticalResolution()); - } - - /** {@inheritDoc} */ - public Length getIntrinsicAlignmentAdjust() { - return this.imageInfo.alignmentAdjust; - } - - /** {@inheritDoc} */ - public double getHorizontalResolution() { - return this.dpiHorizontal; - } - - /** {@inheritDoc} */ - public double getVerticalResolution() { - return this.dpiVertical; - } - - /** - * Return the image color space. - * @return the image color space (java.awt.color.ColorSpace) - */ - public ColorSpace getColorSpace() { - return this.colorSpace; - } - - /** - * Get ICC profile for this image. - * @return the icc profile or null if not applicable - */ - public ICC_Profile getICCProfile() { - if (this.colorSpace != null && this.colorSpace instanceof ICC_ColorSpace) { - return ((ICC_ColorSpace)this.colorSpace).getProfile(); - } - return null; - } - - /** - * Return the number of bits per pixel. - * @return number of bits per pixel - */ - public int getBitsPerPixel() { - return this.bitsPerPixel; - } - - /** - * Return the image transparency. - * @return true if the image is transparent - */ - public boolean isTransparent() { - return this.isTransparent; - } - - /** - * Check if this image has a soft mask. - * - * @return true if the image also has a soft transparency mask - */ - public boolean hasSoftMask() { - return false; - } - - /** - * Get the soft mask. - * The soft mask should have the same bitdepth as the image data. - * - * @return the data array of soft mask values - */ - public byte[] getSoftMask() { - return null; - } - - /** - * Return the transparent color. - * @return the transparent color (java.awt.Color) - */ - public Color getTransparentColor() { - return this.transparentColor; - } - - /** @return true for CMYK images generated by Adobe Photoshop */ - public boolean isInverted() { - return this.invertImage; - } - - /** - * Return the image data (pixels, uncompressed). - * @return the image data - */ - public byte[] getBitmaps() { - return this.bitmaps; - } - - /** - * Return the image data size (number of bytes taken up by the uncompressed pixels). - * @return the image data size - */ - public int getBitmapsSize() { - return (bitmaps != null ? bitmaps.length : 0); - } - - /** - * Return the original image data (compressed). - * @return the original image data - */ - public byte[] getRessourceBytes() { - return raw; - } - - /** - * Return the original image data size (compressed). - * @return the original image data size - */ - public int getRessourceBytesSize() { - return (raw != null ? raw.length : 0); - } - -} - diff --git a/src/java/org/apache/fop/image/BmpImage.java b/src/java/org/apache/fop/image/BmpImage.java deleted file mode 100644 index 5ebf522e9..000000000 --- a/src/java/org/apache/fop/image/BmpImage.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// Java -import java.io.IOException; -import java.awt.color.ColorSpace; - -import org.apache.commons.io.IOUtils; - -/** - * Bitmap image. - * This supports loading a bitmap image into bitmap data. - * - * @see AbstractFopImage - * @see FopImage - */ -public class BmpImage extends AbstractFopImage { - /** - * Create a bitmap image with the image data. - * - * @param imgInfo the image information - */ - public BmpImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * Load the bitmap. - * This laods the bitmap data from the bitmap image. - * - * @return true if it was loaded successfully - */ - protected boolean loadBitmap() { - int wpos = 18; - int hpos = 22; // offset positioning for w and height in bmp files - int[] headermap = new int[54]; - int filepos = 0; - byte[] palette = null; - try { - boolean eof = false; - while ((!eof) && (filepos < 54)) { - int input = inputStream.read(); - if (input == -1) { - eof = true; - } else { - headermap[filepos++] = input; - } - } - - if (headermap[28] == 4 || headermap[28] == 8) { - int palettesize = 1 << headermap[28]; - palette = new byte[palettesize * 3]; - int countr = 0; - while (!eof && countr < palettesize) { - int count2 = 2; - while (!eof && count2 >= -1) { - int input = inputStream.read(); - if (input == -1) { - eof = true; - } else if (count2 >= 0) { - palette[countr * 3 + count2] = (byte)(input & 0xFF); - } - count2--; - filepos++; - } - countr++; - } - } - } catch (IOException ex) { - log.error("Error while loading image (Bmp): " + ex.getMessage(), ex); - IOUtils.closeQuietly(inputStream); - inputStream = null; - return false; - } - // gets h & w from headermap - this.width = headermap[wpos] - + headermap[wpos + 1] * 256 - + headermap[wpos + 2] * 256 * 256 - + headermap[wpos + 3] * 256 * 256 * 256; - this.height = headermap[hpos] - + headermap[hpos + 1] * 256 - + headermap[hpos + 2] * 256 * 256 - + headermap[hpos + 3] * 256 * 256 * 256; - - int imagestart = headermap[10] - + headermap[11] * 256 - + headermap[12] * 256 * 256 - + headermap[13] * 256 * 256 * 256; - this.bitsPerPixel = headermap[28]; - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); - int bytes = 0; - if (this.bitsPerPixel == 1) { - bytes = (this.width + 7) / 8; - } else if (this.bitsPerPixel == 24) { - bytes = this.width * 3; - } else if (this.bitsPerPixel == 4 || this.bitsPerPixel == 8) { - bytes = this.width / (8 / this.bitsPerPixel); - } else { - log.error("Image (" + "" - + ") has " + this.bitsPerPixel - + " which is not a supported BMP format."); - return false; - } - if ((bytes & 0x03) != 0) { - bytes |= 0x03; - bytes++; - } - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - - int[] temp = new int[bytes * this.height]; - try { - int input; - int count = 0; - inputStream.skip((long)(imagestart - filepos)); - while ((input = inputStream.read()) != -1) { - if (count >= temp.length) { - log.warn("Data longer than expected while loading image"); - break; - } else { - temp[count++] = input; - } - } - } catch (IOException ex) { - log.error("Error while loading image (Bmp): " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - for (int i = 0; i < this.height; i++) { - int x = 0; - int j = 0; - while (j < bytes) { - int p = temp[(this.height - i - 1) * bytes + j]; - - if (this.bitsPerPixel == 24 && x < this.width) { - int countr = 2; - do { - this.bitmaps[3 * (i * this.width + x) + countr] - = (byte)(temp[(this.height - i - 1) * bytes + j] & 0xFF); - j++; - } while (--countr >= 0) - ; - x++; - } else if (this.bitsPerPixel == 1) { - for (int countr = 0; - countr < 8 && x < this.width; countr++) { - if ((p & 0x80) != 0) { - this.bitmaps[3 * (i * this.width + x)] = (byte) 0xFF; - this.bitmaps[3 * (i * this.width + x) + 1] = (byte) 0xFF; - this.bitmaps[3 * (i * this.width + x) + 2] = (byte) 0xFF; - } else { - this.bitmaps[3 * (i * this.width + x)] = (byte) 0; - this.bitmaps[3 * (i * this.width + x) + 1] = (byte) 0; - this.bitmaps[3 * (i * this.width + x) + 2] = (byte) 0; - } - p <<= 1; - x++; - } - j++; - } else if (this.bitsPerPixel == 4) { - for (int countr = 0; - countr < 2 && x < this.width; countr++) { - int pal = ((p & 0xF0) >> 4) * 3; - this.bitmaps[3 * (i * this.width + x)] = palette[pal]; - this.bitmaps[3 * (i * this.width + x) + 1] = palette[pal + 1]; - this.bitmaps[3 * (i * this.width + x) + 2] = palette[pal + 2]; - p <<= 4; - x++; - } - j++; - } else if (this.bitsPerPixel == 8) { - if (x < this.width) { - p *= 3; - this.bitmaps[3 * (i * this.width + x)] = palette[p]; - this.bitmaps[3 * (i * this.width + x) + 1] = palette[p + 1]; - this.bitmaps[3 * (i * this.width + x) + 2] = palette[p + 2]; - j++; - x++; - } else { - j = bytes; - } - } else { - j++; - } - } - } - - // This seems really strange to me, but I noticed that - // JimiImage hardcodes bitsPerPixel to 8. If I do not - // do this Acrobat is unable to read the resultant PDF, - // so we will hardcode this... - this.bitsPerPixel = 8; - - return true; - } - -} - diff --git a/src/java/org/apache/fop/image/EPSImage.java b/src/java/org/apache/fop/image/EPSImage.java deleted file mode 100644 index ab708f2a4..000000000 --- a/src/java/org/apache/fop/image/EPSImage.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - - -/** - * EPS image handler. - * This handles the Encapulated PostScript images. - * It gets the dimensions and original data from the analyser. - * - * @see AbstractFopImage - * @see FopImage - */ -public class EPSImage extends AbstractFopImage { - - private String docName; - private int[] bbox; - - private EPSData epsData = null; - - /** - * Create an EPS image with the image information. - * - * @param imgInfo the information containing the data and bounding box - */ - public EPSImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - init(""); - if (imgInfo.data instanceof EPSData) { - epsData = (EPSData) imgInfo.data; - bbox = new int[4]; - bbox[0] = (int) epsData.bbox[0]; - bbox[1] = (int) epsData.bbox[1]; - bbox[2] = (int) epsData.bbox[2]; - bbox[3] = (int) epsData.bbox[3]; - - loaded = loaded | ORIGINAL_DATA; - } - } - - /** - * Initialize docName and bounding box. - * @param name the document name - */ - private void init(String name) { - bbox = new int[4]; - bbox[0] = 0; - bbox[1] = 0; - bbox[2] = 0; - bbox[3] = 0; - - docName = name; - } - - /** - * Return the name of the eps - * @return the name of the eps - */ - public String getDocName() { - return docName; - } - - /** - * Return the bounding box - * @return an int array containing the bounding box - */ - public int[] getBBox() { - return bbox; - } - - /** - * Get the eps image. - * - * @return the original eps image data - */ - public byte[] getEPSImage() { - if (epsData.epsFile == null) { - //log.error("ERROR LOADING EXTERNAL EPS"); - } - return epsData.epsFile; - } - - /** - * Data for EPS image. - */ - public static class EPSData { - public long[] bbox; - public boolean isAscii; // True if plain ascii eps file - - // offsets if not ascii - public long psStart = 0; - public long psLength = 0; - public long wmfStart = 0; - public long wmfLength = 0; - public long tiffStart = 0; - public long tiffLength = 0; - - /** raw eps file */ - public byte[] rawEps; - /** eps part */ - public byte[] epsFile; - public byte[] preview = null; - } - -} diff --git a/src/java/org/apache/fop/image/EmfImage.java b/src/java/org/apache/fop/image/EmfImage.java deleted file mode 100644 index 73bbad232..000000000 --- a/src/java/org/apache/fop/image/EmfImage.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -/** - * Enhanced metafile image. - * This supports loading a EMF image. - * - * @see AbstractFopImage - * @see FopImage - */ -public class EmfImage extends AbstractFopImage { - - /** - * Create a bitmap image with the image data. - * - * @param imgInfo the image information - */ - public EmfImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * Load the original EMF data. - * This loads the original EMF data and reads the color space, - * and icc profile if any. - * - * @return true if loaded false for any error - */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } -} - diff --git a/src/java/org/apache/fop/image/FopImage.java b/src/java/org/apache/fop/image/FopImage.java deleted file mode 100644 index 0f780ad57..000000000 --- a/src/java/org/apache/fop/image/FopImage.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -import java.io.InputStream; -import java.awt.color.ColorSpace; -import java.awt.color.ICC_Profile; -import java.awt.Color; - -import org.apache.fop.datatypes.Length; - -/** - * Fop image interface for loading images. - */ -public interface FopImage { - /** - * Flag for loading dimensions. - */ - int DIMENSIONS = 1; - - /** - * Flag for loading original data. - */ - int ORIGINAL_DATA = 2; - - /** - * Flag for loading bitmap data. - */ - int BITMAP = 4; - - /** - * Get the mime type of this image. - * This is used so that when reading from the image it knows - * what type of image it is. - * - * @return the mime type string - */ - String getMimeType(); - - /** @return the original URI used to access this image. */ - String getOriginalURI(); - - /** - * Load particular inforamtion for this image - * This must be called before attempting to get - * the information. - * - * @param type the type of loading required - * @return boolean true if the information could be loaded - */ - boolean load(int type); - - /** - * Returns the image width. - * @return the width in pixels - */ - int getWidth(); - - /** - * Returns the image height. - * @return the height in pixels - */ - int getHeight(); - - /** - * @return the intrinsic image width (in millipoints) - */ - int getIntrinsicWidth(); - - /** - * @return the intrinsic image width (in millipoints) - */ - int getIntrinsicHeight(); - - /** - * @return the intrinsic alignment-adjust value or NULL if the image does - * not have one. - */ - Length getIntrinsicAlignmentAdjust(); - - /** - * @return the horizontal bitmap resolution (in dpi) - */ - double getHorizontalResolution(); - - /** - * @return the vertical bitmap resolution (in dpi) - */ - double getVerticalResolution(); - - /** - * Returns the color space of the image. - * @return the color space - */ - ColorSpace getColorSpace(); - - /** - * Returns the ICC profile. - * @return the ICC profile, null if none is available - */ - ICC_Profile getICCProfile(); - - /** - * Returns the number of bits per pixel for the image. - * @return the number of bits per pixel - */ - int getBitsPerPixel(); - - /** - * Indicates whether the image is transparent. - * @return True if it is transparent - */ - boolean isTransparent(); - - /** - * For transparent images. Returns the transparent color. - * @return the transparent color - */ - Color getTransparentColor(); - - /** - * Indicates whether the image has a Soft Mask (See section 7.5.4 in the - * PDF specs) - * @return True if a Soft Mask exists - */ - boolean hasSoftMask(); - - /** - * For images with a Soft Mask. Returns the Soft Mask as an array. - * @return the Soft Mask - */ - byte[] getSoftMask(); - - /** @return true for CMYK images generated by Adobe Photoshop */ - boolean isInverted(); - - /** - * Returns the decoded and uncompressed image as a array of - * width * height * [colorspace-multiplicator] pixels. - * @return the bitmap - */ - byte[] getBitmaps(); - /** - * Returns the size of the image. - * width * (bitsPerPixel / 8) * height, no ? - * @return the size - */ - int getBitmapsSize(); - - /** - * Returns the encoded/compressed image as an array of bytes. - * @return the raw image - */ - byte[] getRessourceBytes(); - - /** - * Returns the number of bytes of the raw image. - * @return the size in bytes - */ - int getRessourceBytesSize(); - - /** - * Image info class. - * Information loaded from analyser and passed to image object. - */ - public static class ImageInfo { - /** InputStream to load the image from */ - public InputStream inputStream; - /** Original URI the image was accessed with */ - public String originalURI; - /** image width (in pixels) */ - public int width; - /** image height (in pixels) */ - public int height; - /** horizontal bitmap resolution (in dpi) */ - public double dpiHorizontal = 72.0f; - /** vertical bitmap resolution (in dpi) */ - public double dpiVertical = 72.0f; - /** implementation-specific data object (ex. a SVG DOM for SVG images) */ - public Object data; - /** MIME type of the image */ - public String mimeType; - /** implementation-specific String (ex. the namespace for XML-based images) */ - public String str; - /** intrinsic alignment-adjust or null if there is none */ - public Length alignmentAdjust; - } - -} - diff --git a/src/java/org/apache/fop/image/FopImageConsumer.java b/src/java/org/apache/fop/image/FopImageConsumer.java deleted file mode 100644 index 4e4d7be48..000000000 --- a/src/java/org/apache/fop/image/FopImageConsumer.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// Java -import java.util.Hashtable; -import java.awt.image.ColorModel; -import java.awt.image.ImageConsumer; -import java.awt.image.ImageProducer; -import java.awt.image.PixelGrabber; - -/** - * ImageConsumer implementation for FopImage classes. - */ -public class FopImageConsumer implements ImageConsumer { - - /** Image width in pixels */ - protected int width = -1; - /** Image height in pixels */ - protected int height = -1; - /** Image status */ - protected Integer imageStatus = new Integer(-1); - /** hints */ - protected int hints = 0; - /** Image properties */ - protected Hashtable properties = null; - /** Color model */ - protected ColorModel cm = null; - /** Image producer */ - protected ImageProducer ip = null; - - /** - * Main constructor - * @param iprod ImageProducer to use - */ - public FopImageConsumer(ImageProducer iprod) { - this.ip = iprod; - } - - /** - * {@inheritDoc} - */ - public void imageComplete(int status) { - /* - * log.error("Status "); - * if (status == ImageConsumer.COMPLETESCANLINES) { - * log.error("CompleteScanLines"); - * } else if (status == ImageConsumer.IMAGEABORTED) { - * log.error("ImageAborted"); - * } else if (status == ImageConsumer.IMAGEERROR) { - * log.error("ImageError"); - * } else if (status == ImageConsumer.RANDOMPIXELORDER) { - * log.error("RandomPixelOrder"); - * } else if (status == ImageConsumer.SINGLEFRAME) { - * log.error("SingleFrame"); - * } else if (status == ImageConsumer.SINGLEFRAMEDONE) { - * log.error("SingleFrameDone"); - * } else if (status == ImageConsumer.SINGLEPASS) { - * log.error("SinglePass"); - * } else if (status == ImageConsumer.STATICIMAGEDONE) { - * log.error("StaticImageDone"); - * } else if (status == ImageConsumer.TOPDOWNLEFTRIGHT) { - * log.error("TopDownLeftRight"); - * } - */ - synchronized (this.imageStatus) { - // Need to stop status if image done - if (imageStatus.intValue() != ImageConsumer.STATICIMAGEDONE - && imageStatus.intValue() != ImageConsumer.SINGLEFRAMEDONE) { - this.imageStatus = new Integer(status); - } - } - } - - /** - * {@inheritDoc} - */ - public void setColorModel(ColorModel model) { - // log.error("setColorModel: " + model); - this.cm = model; - } - - /** - * {@inheritDoc} - */ - public void setDimensions(int width, int height) { - // log.error("setDimension: w=" + width + " h=" + height); - this.width = width; - this.height = height; - } - - /** - * {@inheritDoc} - */ - public void setHints(int hintflags) { - // log.error("setHints: " + hintflags); - this.hints = hintflags; - } - - /** - * {@inheritDoc} - */ - public void setProperties(Hashtable props) { - // log.error("setProperties: " + props); - this.properties = props; - } - - /** - * {@inheritDoc} - */ - public void setPixels(int x, int y, int w, int h, ColorModel model, - byte[] pixels, int off, int scansize) { - } - - /** - * {@inheritDoc} - */ - public void setPixels(int x, int y, int w, int h, ColorModel model, - int[] pixels, int off, int scansize) { - } - - /** - * Indicates whether the image is ready. - * @return boolean True if the image is ready, false if it's still loading - * @throws Exception If an error happened while loading the image - */ - public boolean isImageReady() throws Exception { - /**@todo Use a better exception than Exception */ - synchronized (this.imageStatus) { - if (this.imageStatus.intValue() == ImageConsumer.IMAGEABORTED) { - throw new Exception("Image aborted"); - } - if (this.imageStatus.intValue() == ImageConsumer.IMAGEERROR) { - throw new Exception("Image error"); - } - - if (imageStatus.intValue() == ImageConsumer.STATICIMAGEDONE - || imageStatus.intValue() == ImageConsumer.SINGLEFRAMEDONE) { - return true; - } - - return false; - } - } - - /** - * Returns the image width - * @return the width in pixels - */ - public int getWidth() { - return this.width; - } - - /** - * Returns the image height - * @return the height in pixels - */ - public int getHeight() { - return this.height; - } - - /** - * Returns the color model of the image - * @return the color model - */ - public ColorModel getColorModel() { - return this.cm; - } - - /** - * Returns the bitmap as an array. - * @return the bitmap as an array. - * @throws Exception if an error occured while generating the array - */ - public int[] getImage() throws Exception { - int tmpMap[] = new int[this.width * this.height]; - PixelGrabber pg = new PixelGrabber(this.ip, 0, 0, this.width, - this.height, tmpMap, 0, this.width); - pg.setDimensions(this.width, this.height); - pg.setColorModel(this.cm); - pg.setHints(this.hints); - pg.setProperties(this.properties); - try { - pg.grabPixels(); - } catch (InterruptedException intex) { - /**@todo Use a better exception than Exception */ - throw new Exception("Image grabbing interrupted : " - + intex.getMessage()); - } - return tmpMap; - } - -} - diff --git a/src/java/org/apache/fop/image/GifImage.java b/src/java/org/apache/fop/image/GifImage.java deleted file mode 100644 index 27e81c4fc..000000000 --- a/src/java/org/apache/fop/image/GifImage.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// Java -import java.awt.image.ImageProducer; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.color.ColorSpace; -import java.awt.Color; -import java.io.InputStream; -import java.io.IOException; -import java.net.URLConnection; - -import org.apache.commons.io.IOUtils; - -/** - * FopImage object for GIF images, using Java native classes. - * - * @see AbstractFopImage - * @see FopImage - */ -public class GifImage extends AbstractFopImage { - - /** - * Create a new gif image. - * - * @param imgInfo the image info for this gif image - */ - public GifImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * Load the bitmap for this gif image. - * This loads the data and creates a bitmap byte array - * of the image data. - * To decode the image a dummy URLConnection is used that - * will do the conversion. - * - * @return True if the load process succeeded - */ - protected boolean loadBitmap() { - int[] tmpMap = null; - try { - URLConnection con = new DummyConnection(inputStream); - - ImageProducer ip = (ImageProducer) con.getContent(); - if (ip == null) { - return false; - } - FopImageConsumer consumer = new FopImageConsumer(ip); - ip.startProduction(consumer); - - //Load the image into memory - while (!consumer.isImageReady()) { - Thread.sleep(500); - } - - this.height = consumer.getHeight(); - this.width = consumer.getWidth(); - - try { - tmpMap = consumer.getImage(); - } catch (Exception ex) { - log.error("Image grabbing interrupted : " - + ex.getMessage(), ex); - return false; - } - - ColorModel cm = consumer.getColorModel(); - this.bitsPerPixel = 8; - // this.bitsPerPixel = cm.getPixelSize(); - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); - if (cm.hasAlpha()) { - // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT - int transparencyType = cm.getTransparency(); - - if (transparencyType == java.awt.Transparency.OPAQUE) { - this.isTransparent = false; - } else if (transparencyType == java.awt.Transparency.BITMASK) { - if (cm instanceof IndexColorModel) { - IndexColorModel indexcm = (IndexColorModel) cm; - this.isTransparent = false; - byte[] alphas = new byte[indexcm.getMapSize()]; - byte[] reds = new byte[indexcm.getMapSize()]; - byte[] greens = new byte[indexcm.getMapSize()]; - byte[] blues = new byte[indexcm.getMapSize()]; - indexcm.getAlphas(alphas); - indexcm.getReds(reds); - indexcm.getGreens(greens); - indexcm.getBlues(blues); - for (int i = 0; - i < indexcm.getMapSize(); - i++) { - if ((alphas[i] & 0xFF) == 0) { - this.isTransparent = true; - this.transparentColor = new Color( - (int)(reds[i] & 0xFF), - (int)(greens[i] & 0xFF), - (int)(blues[i] & 0xFF)); - break; - } - } - } else { - // TRANSLUCENT - /* - * this.isTransparent = false; - * for (int i = 0; i < this.width * this.height; i++) { - * if (cm.getAlpha(tmpMap[i]) == 0) { - * this.isTransparent = true; - * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]), - * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i])); - * break; - * } - * } - */ - // use special API... - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } catch (Exception ex) { - log.error("Error while loading image (Gif): " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - for (int i = 0; i < this.height; i++) { - for (int j = 0; j < this.width; j++) { - int p = tmpMap[i * this.width + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF); - } - } - return true; - } - - /** {@inheritDoc} */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } - - /** - * A dummy url connection for a gif image in an input stream. - */ - protected static class DummyConnection extends URLConnection { - private InputStream inputStream; - - DummyConnection(InputStream is) { - super(null); - inputStream = is; - } - - /** - * {@inheritDoc} - */ - public InputStream getInputStream() throws IOException { - return inputStream; - } - - /** - * {@inheritDoc} - */ - public void connect() throws IOException { - // do nothing - } - - /** - * {@inheritDoc} - */ - public String getContentType() { - return "image/gif"; - } - - /** - * {@inheritDoc} - */ - public int getContentLength() { - try { - return inputStream.available(); - } catch (IOException e) { - return -1; - } - } - - } -} - diff --git a/src/java/org/apache/fop/image/ImageCache.java b/src/java/org/apache/fop/image/ImageCache.java deleted file mode 100644 index 3dd639823..000000000 --- a/src/java/org/apache/fop/image/ImageCache.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// FOP -import org.apache.fop.apps.FOUserAgent; - -/** - * Image cache holder. - * This interface is used for caching images. - */ -public interface ImageCache { - - /** - * Get an image from the cache. - * - * @param url the url and key for the image - * @param context the user agent context - * @return the requested image - */ - FopImage getImage(String url, FOUserAgent context); - - /** - * Release an image in the current context. - * - * @param url the url and key for the image - * @param context the user agent context - */ - void releaseImage(String url, FOUserAgent context); - - /** - * Invalidate image. - * If during loading this image is found to be invalid - * it will be invalidated to prevent further attempts at - * loading the image. - * - * @param url the url and key for the image - * @param context the user agent context - */ - void invalidateImage(String url, FOUserAgent context); - - /** - * Remove a context and handle all images in the context. - * - * @param context the user agent context - */ - void removeContext(FOUserAgent context); - - /** - * Forces the cache to fully cleared. - */ - void clearAll(); - -} - diff --git a/src/java/org/apache/fop/image/ImageFactory.java b/src/java/org/apache/fop/image/ImageFactory.java deleted file mode 100644 index 5c9f198e8..000000000 --- a/src/java/org/apache/fop/image/ImageFactory.java +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// Java -import java.io.InputStream; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.datatypes.URISpecification; -import org.apache.fop.image.analyser.ImageReaderFactory; -import org.apache.xmlgraphics.util.Service; - -/** - * Create FopImage objects (with a configuration file - not yet implemented). - * @author Eric SCHAEFFER - */ -public final class ImageFactory { - - /** - * logging instance - */ - protected static Log log = LogFactory.getLog(FopImage.class); - - private HashMap imageMimeTypes = new HashMap(); - - private ImageCache cache = new ContextImageCache(true); - - /** - * Main constructor for the ImageFactory. - */ - public ImageFactory() { - /* @todo The mappings set up below of image mime types to implementing - * classes should be made externally configurable - */ - ImageProvider jaiImage = new ImageProvider("JAIImage", "org.apache.fop.image.JAIImage"); - ImageProvider jimiImage = new ImageProvider("JIMIImage", "org.apache.fop.image.JimiImage"); - ImageProvider imageIoImage = new ImageProvider( - "ImageIOImage", "org.apache.fop.image.ImageIOImage"); - ImageProvider gifImage = new ImageProvider("GIFImage", "org.apache.fop.image.GifImage"); - ImageProvider jpegImage = new ImageProvider("JPEGImage", "org.apache.fop.image.JpegImage"); - ImageProvider jpegImageIOImage = new ImageProvider( - "JPEGImage", "org.apache.fop.image.JpegImageIOImage"); - ImageProvider bmpImage = new ImageProvider("BMPImage", "org.apache.fop.image.BmpImage"); - ImageProvider epsImage = new ImageProvider("EPSImage", "org.apache.fop.image.EPSImage"); - ImageProvider pngImage = new ImageProvider("PNGImage", "org.apache.fop.image.PNGImage"); - ImageProvider tiffImage = new ImageProvider("TIFFImage", "org.apache.fop.image.TIFFImage"); - ImageProvider xmlImage = new ImageProvider("XMLImage", "org.apache.fop.image.XMLImage"); - ImageProvider emfImage = new ImageProvider("EMFImage", "org.apache.fop.image.EmfImage"); - - ImageMimeType imt = new ImageMimeType("image/gif"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(imageIoImage); - imt.addProvider(jaiImage); - imt.addProvider(jimiImage); - imt.addProvider(gifImage); - - imt = new ImageMimeType("image/jpeg"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(jpegImageIOImage); - imt.addProvider(jpegImage); - - imt = new ImageMimeType("image/bmp"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(bmpImage); - - imt = new ImageMimeType("image/eps"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(epsImage); - - imt = new ImageMimeType("image/png"); - imageMimeTypes.put(imt.getMimeType(), imt); - //Image I/O is faster and more memory-efficient than own codec for PNG - imt.addProvider(imageIoImage); - imt.addProvider(pngImage); - - imt = new ImageMimeType("image/tga"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(jaiImage); - imt.addProvider(imageIoImage); - imt.addProvider(jimiImage); - - imt = new ImageMimeType("image/tiff"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(tiffImage); //Slower but supports CCITT embedding - imt.addProvider(imageIoImage); //Fast but doesn't support CCITT embedding - imt.addProvider(jaiImage); //Fast but doesn't support CCITT embedding - - imt = new ImageMimeType("image/svg+xml"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(xmlImage); - - imt = new ImageMimeType("text/xml"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(xmlImage); - - imt = new ImageMimeType("image/emf"); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(emfImage); - - Iterator iter = Service.providers(RegisterableImageProvider.class, true); - while (iter.hasNext()) { - RegisterableImageProvider impl = (RegisterableImageProvider)iter.next(); - imt = new ImageMimeType(impl.getSupportedMimeType()); - imageMimeTypes.put(imt.getMimeType(), imt); - imt.addProvider(new ImageProvider(impl.getName(), impl.getClassName())); - } - } - - /** - * Get the url string from a wrapped url. - * - * @param href the input wrapped url - * @return the raw url - */ - public static String getURL(String href) { - return URISpecification.getURL(href); - } - - /** - * Get the image from the cache or load. - * If this returns null then the image could not be loaded - * due to an error. Messages should be logged. - * Before calling this the getURL(url) must be used. - * - * @param url the url for the image - * @param context the user agent context - * @return the fop image instance - */ - public FopImage getImage(String url, FOUserAgent context) { - return cache.getImage(url, context); - } - - /** - * Release an image from the cache. - * This can be used if the renderer has its own cache of - * the image. - * The image should then be put into the weak cache. - * - * @param url the url for the image - * @param context the user agent context - */ - public void releaseImage(String url, FOUserAgent context) { - cache.releaseImage(url, context); - } - - /** - * Release the context and all images in the context. - * - * @param context the context to remove - */ - public void removeContext(FOUserAgent context) { - cache.removeContext(context); - } - - /** - * Create an FopImage objects. - * @param href the url for the image - * @param ua the user agent context - * @return the fop image instance - */ - public FopImage loadImage(String href, FOUserAgent ua) { - - Source source = ua.resolveURI(href); - if (source == null) { - return null; - } - - // Got a valid source, obtain an InputStream from it - InputStream in = null; - if (source instanceof StreamSource) { - in = ((StreamSource)source).getInputStream(); - } - if (in == null) { - try { - in = new java.net.URL(source.getSystemId()).openStream(); - } catch (Exception ex) { - log.error("Unable to obtain stream from id '" - + source.getSystemId() + "'"); - } - } - if (in == null) { - return null; - } - - //Make sure the InputStream is decorated with a BufferedInputStream - if (!(in instanceof java.io.BufferedInputStream)) { - in = new java.io.BufferedInputStream(in); - } - - // Check image type - FopImage.ImageInfo imgInfo = null; - try { - imgInfo = ImageReaderFactory.make(source.getSystemId(), in, ua); - } catch (Exception e) { - log.error("Error while recovering image information (" - + href + ") : " + e.getMessage(), e); - return null; - } - if (imgInfo == null) { - try { - in.close(); - in = null; - } catch (Exception e) { - log.debug("Error closing the InputStream for the image", e); - } - log.error("No ImageReader for this type of image (" + href + ")"); - return null; - } - // Associate mime-type to FopImage class - String imgMimeType = imgInfo.mimeType; - Class imageClass = getImageClass(imgMimeType); - if (imageClass == null) { - log.error("Unsupported image type (" + href + "): " + imgMimeType); - return null; - } else { - if (log.isDebugEnabled()) { - log.debug("Loading " + imgMimeType + " with " + imageClass.getName() - + ": " + href); - } - } - - // load the right image class - // return new - Object imageInstance = null; - try { - Class[] imageConstructorParameters = new Class[1]; - imageConstructorParameters[0] = org.apache.fop.image.FopImage.ImageInfo.class; - Constructor imageConstructor = imageClass.getDeclaredConstructor( - imageConstructorParameters); - Object[] initArgs = new Object[1]; - initArgs[0] = imgInfo; - imageInstance = imageConstructor.newInstance(initArgs); - } catch (java.lang.reflect.InvocationTargetException ex) { - Throwable t = ex.getTargetException(); - String msg; - if (t != null) { - msg = t.getMessage(); - } else { - msg = ex.getMessage(); - } - log.error("Error creating FopImage object (" - + href + "): " + msg, (t == null) ? ex : t); - return null; - } catch (InstantiationException ie) { - log.error("Error creating FopImage object (" - + href + "): Could not instantiate " + imageClass.getName() + " instance"); - return null; - } catch (Exception ex) { - log.error("Error creating FopImage object (" - + href + "): " + ex.getMessage(), ex); - return null; - } - if (!(imageInstance instanceof org.apache.fop.image.FopImage)) { - log.error("Error creating FopImage object (" + href + "): " + "class " - + imageClass.getName() - + " doesn't implement org.apache.fop.image.FopImage interface"); - return null; - } - return (FopImage) imageInstance; - } - - private Class getImageClass(String imgMimeType) { - ImageMimeType imt = (ImageMimeType)imageMimeTypes.get(imgMimeType); - if (imt == null) { - return null; - } - return imt.getFirstImplementingClass(); - } - - /** - * Forces all the image caches to be cleared. This should normally only be used in - * testing environments. If you happen to think that you need to call this yourself - * in a production environment, please notify the development team so we can look - * into the issue. A call like this shouldn't be necessary anymore like it may have - * been with FOP 0.20.5. - */ - public void clearCaches() { - cache.clearAll(); - } -} - -/** - * Basic image cache. - * This keeps track of invalid images. - */ -class BasicImageCache implements ImageCache { - - private Set invalid = Collections.synchronizedSet(new java.util.HashSet()); - //private Map contextStore = Collections.synchronizedMap(new java.util.HashMap()); - - public FopImage getImage(String url, FOUserAgent context) { - if (invalid.contains(url)) { - return null; - } - //TODO Doesn't seem to be fully implemented. Do we need it at all? Not referenced. - return null; - } - - public void releaseImage(String url, FOUserAgent context) { - // do nothing - } - - public void invalidateImage(String url, FOUserAgent context) { - // cap size of invalid list - if (invalid.size() > 100) { - invalid.clear(); - } - invalid.add(url); - } - - public void removeContext(FOUserAgent context) { - // do nothing - } - - /** {@inheritDoc} */ - public void clearAll() { - invalid.clear(); - } - -} - -/** - * This is the context image cache. - * This caches images on the basis of the given context. - * Common images in different contexts are currently not handled. - * There are two possiblities, each context handles its own images - * and renderers can cache information or images are shared and - * all information is retained. - * Once a context is removed then all images are placed into a - * weak hashmap so they may be garbage collected. - */ -class ContextImageCache implements ImageCache { - - // if this cache is collective then images can be shared - // among contexts, this implies that the base directory - // is either the same or does not effect the images being - // loaded - private boolean collective; - private Map contextStore = Collections.synchronizedMap(new java.util.HashMap()); - private Set invalid = null; - private Map refStore = null; - private ReferenceQueue refQueue = new ReferenceQueue(); - - public ContextImageCache(boolean col) { - collective = col; - if (collective) { - refStore = Collections.synchronizedMap(new java.util.HashMap()); - invalid = Collections.synchronizedSet(new java.util.HashSet()); - } - } - - // sync around lookups and puts - // another sync around load for a particular image - public FopImage getImage(String url, FOUserAgent context) { - ImageLoader im = null; - // this protects the finding or creating of a new - // ImageLoader for multi threads - synchronized (this) { - if (collective && invalid.contains(url)) { - return null; - } - Context con = (Context) contextStore.get(context); - if (con == null) { - con = new Context(context, collective); - contextStore.put(context, con); - } else { - if (con.invalid(url)) { - return null; - } - im = con.getImage(url); - } - if (im == null && collective) { - Iterator i = contextStore.values().iterator(); - while (i.hasNext()) { - Context c = (Context)i.next(); - if (c != con) { - im = c.getImage(url); - if (im != null) { - break; - } - } - } - if (im == null) { - Reference ref = (Reference)refStore.get(url); - if (ref != null) { - im = (ImageLoader) ref.get(); - if (im == null) { - //Remove key if its value has been garbage collected - refStore.remove(url); - } - } - } - } - - if (im != null) { - con.putImage(url, im); - } else { - im = con.getImage(url, this); - } - } - - // the ImageLoader is synchronized so images with the - // same url will not be loaded at the same time - if (im != null) { - return im.loadImage(); - } - return null; - } - - public void releaseImage(String url, FOUserAgent context) { - Context con = (Context) contextStore.get(context); - if (con != null) { - if (collective) { - ImageLoader im = con.getImage(url); - refStore.put(url, wrapInReference(im, url)); - } - con.releaseImage(url); - } - } - - public void invalidateImage(String url, FOUserAgent context) { - if (collective) { - // cap size of invalid list - if (invalid.size() > 100) { - invalid.clear(); - } - invalid.add(url); - } - Context con = (Context) contextStore.get(context); - if (con != null) { - con.invalidateImage(url); - } - } - - private Reference wrapInReference(Object obj, Object key) { - return new SoftReferenceWithKey(obj, key, refQueue); - } - - private static class SoftReferenceWithKey extends SoftReference { - - private Object key; - - public SoftReferenceWithKey(Object referent, Object key, ReferenceQueue q) { - super(referent, q); - this.key = key; - } - } - - public void removeContext(FOUserAgent context) { - Context con = (Context) contextStore.get(context); - if (con != null) { - if (collective) { - Map images = con.getImages(); - Iterator iter = images.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry = (Entry)iter.next(); - refStore.put(entry.getKey(), - wrapInReference(entry.getValue(), entry.getKey())); - } - } - contextStore.remove(context); - } - //House-keeping (remove cleared references) - checkReferenceQueue(); - } - - /** - * Checks the reference queue if any references have been cleared and removes them from the - * cache. - */ - private void checkReferenceQueue() { - SoftReferenceWithKey ref; - while ((ref = (SoftReferenceWithKey)refQueue.poll()) != null) { - refStore.remove(ref.key); - } - } - - class Context { - private Map images = Collections.synchronizedMap(new java.util.HashMap()); - private Set invalid = null; - private FOUserAgent userAgent; - - public Context(FOUserAgent ua, boolean inv) { - userAgent = ua; - if (inv) { - invalid = Collections.synchronizedSet(new java.util.HashSet()); - } - } - - public ImageLoader getImage(String url, ImageCache c) { - if (images.containsKey(url)) { - return (ImageLoader) images.get(url); - } - ImageLoader loader = new ImageLoader(url, c, userAgent); - images.put(url, loader); - return loader; - } - - public void putImage(String url, ImageLoader image) { - images.put(url, image); - } - - public ImageLoader getImage(String url) { - return (ImageLoader) images.get(url); - } - - public void releaseImage(String url) { - images.remove(url); - } - - public Map getImages() { - return images; - } - - public void invalidateImage(String url) { - invalid.add(url); - } - - public boolean invalid(String url) { - return invalid.contains(url); - } - - } - - /** {@inheritDoc} */ - public void clearAll() { - this.refStore.clear(); - this.invalid.clear(); - //The context-sensitive caches are not cleared so there are no negative side-effects - //in a multi-threaded environment. Not that it's a good idea to use this method at - //all except in testing environments. If such a calls is necessary in normal environments - //we need to check on memory leaks! - } - -} - -/** - * Encapsulates a class of type FopImage by holding its class name. - * This allows dynamic loading of the class at runtime. - */ -class ImageProvider { - - private String name = null; - - private String className = null; - - private boolean checked = false; - - private Class clazz = null; - - /** - * Creates an ImageProvider with a given name and implementing class. - * The class name should refer to a class of type {@link FopImage}. - * However, this is not checked on construction. - * @param name The name of the provider - * @param className The full class name of the class implementing this provider - */ - public ImageProvider(String name, String className) { - setName(name); - setClassName(className); - } - - /** - * Returns the provider name. - * @return The provider name - */ - public String getName() { - return name; - } - - private void setName(String name) { - this.name = name; - } - - /** - * Returns the implementing class name. - * @return The implementing class name - */ - public String getClassName() { - return className; - } - - private void setClassName(String className) { - this.className = className; - } - - /** - * Returns the implementing class as a {@link Class} object. - * @return The implementing class or null if it couldn't be loaded. - */ - public Class getImplementingClass() { - if (!checked) { - try { - clazz = Class.forName(getClassName()); - } catch (ClassNotFoundException cnfe) { - //nop - } catch (LinkageError le) { - // This can happen if fop was build with support for a - // particular provider (e.g. a binary fop distribution) - // but the required support files (e.g. jai, jimi) are not - // available in the current runtime environment. - ImageFactory.log.debug("Image support provider " + getName() - + " could not be loaded. If " + getName() + " should be" - + " available please make sure all required external libraries" - + " are on the classpath."); - } - checked = true; - } - return clazz; - } -} - -/** - * Holds a mime type for a particular image format plus a list of - * {@link ImageProvider} objects which support the particular image format. - */ -class ImageMimeType { - - private String mimeType = null; - - private List providers = null; - - /** - * Constructor for a particular mime type. - * @param mimeType The mime type - */ - public ImageMimeType(String mimeType) { - setMimeType(mimeType); - } - - /** - * Returns the mime type. - * @return The mime type - */ - public String getMimeType() { - return mimeType; - } - - private void setMimeType(String mimeType) { - this.mimeType = mimeType; - } - - /** - * Returns the class from the first available provider. - * @return The first available class or null if none can be found - */ - public Class getFirstImplementingClass() { - if (providers == null) { - return null; - } - for (Iterator it = providers.iterator(); it.hasNext();) { - ImageProvider ip = (ImageProvider)it.next(); - Class clazz = ip.getImplementingClass(); - if (clazz != null) { - return clazz; - } - } - return null; - } - - /** - * Adds a new provider. - * The provider is added to the end of the current provider list. - * @param The new provider to add - */ - public void addProvider(ImageProvider provider) { - if (providers == null) { - providers = new ArrayList(4); // Assume we only have a few providers - } - if (!providers.contains(provider)) { - providers.add(provider); - } - } -} \ No newline at end of file diff --git a/src/java/org/apache/fop/image/ImageLoader.java b/src/java/org/apache/fop/image/ImageLoader.java deleted file mode 100644 index 111ef919f..000000000 --- a/src/java/org/apache/fop/image/ImageLoader.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -import org.apache.fop.apps.FOUserAgent; - -/** - * Class to load images. - */ -class ImageLoader { - - private String url; - private ImageCache cache; - private boolean valid = true; - private FOUserAgent userAgent; - private FopImage image = null; - - /** - * Main constructor. - * @param url URL to the image - * @param cache Image cache - * @param ua User agent - */ - public ImageLoader(String url, ImageCache cache, FOUserAgent ua) { - this.url = url; - this.cache = cache; - this.userAgent = ua; - } - - /** - * Loads the image. - * @return the loaded image - */ - public synchronized FopImage loadImage() { - if (!valid || image != null) { - return image; - } - ImageFactory imageFactory = userAgent.getFactory().getImageFactory(); - image = imageFactory.loadImage(url, userAgent); - if (image == null) { - cache.invalidateImage(url, userAgent); - valid = false; - } - return image; - } - -} diff --git a/src/java/org/apache/fop/image/JAIImage.java b/src/java/org/apache/fop/image/JAIImage.java deleted file mode 100644 index 8b3074052..000000000 --- a/src/java/org/apache/fop/image/JAIImage.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// AWT -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.BufferedImage; -import java.awt.Color; - -// JAI -import javax.media.jai.JAI; -import javax.media.jai.RenderedOp; - -import org.apache.commons.io.IOUtils; -// Sun codec -import com.sun.media.jai.codec.FileCacheSeekableStream; - -/** - * FopImage object using JAI. - * - * @see AbstractFopImage - * @see FopImage - */ -public class JAIImage extends AbstractFopImage { - - /** - * Create a new JAI image. - * - * @param imgInfo the image info for this JAI image - */ - public JAIImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * {@inheritDoc} - */ - protected boolean loadDimensions() { - if (this.bitmaps == null) { - loadImage(); - } - return this.bitmaps != null; - } - - /** - * {@inheritDoc} - */ - protected boolean loadBitmap() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.bitmaps != null; - } - - /** - * Loads the image from the inputstream - */ - protected void loadImage() { - com.sun.media.jai.codec.FileCacheSeekableStream seekableInput = null; - RenderedOp imageOp = null; - try { - seekableInput = new FileCacheSeekableStream(inputStream); - imageOp = JAI.create("stream", seekableInput); - - this.height = imageOp.getHeight(); - this.width = imageOp.getWidth(); - - ColorModel cm = imageOp.getColorModel(); - //this.bitsPerPixel = 8; - this.bitsPerPixel = cm.getPixelSize(); - - // TODO: the getRGB() function converts the image into the RGB - // colorspace. However, here we assume the image colorspace is kept. - // It should be either one of them, but not both. Unfortunately - // there are other hacks for images in the CMYK colorspace (e.g. in - // the PDF output) that would need to be changed as well. - - //this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); - this.colorSpace = cm.getColorSpace(); - - BufferedImage imageData = imageOp.getAsBufferedImage(); - int[] tmpMap = imageData.getRGB(0, 0, this.width, - this.height, null, 0, this.width); - - if (cm.hasAlpha()) { - // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT - int transparencyType = cm.getTransparency(); - - if (transparencyType == java.awt.Transparency.OPAQUE) { - this.isTransparent = false; - } else if (transparencyType == java.awt.Transparency.BITMASK) { - if (cm instanceof IndexColorModel) { - this.isTransparent = false; - byte[] alphas = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] reds = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] greens = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] blues = new byte[ - ((IndexColorModel) cm).getMapSize()]; - ((IndexColorModel) cm).getAlphas(alphas); - ((IndexColorModel) cm).getReds(reds); - ((IndexColorModel) cm).getGreens(greens); - ((IndexColorModel) cm).getBlues(blues); - for (int i = 0; - i < ((IndexColorModel) cm).getMapSize(); - i++) { - if ((alphas[i] & 0xFF) == 0) { - this.isTransparent = true; - this.transparentColor = new Color( - (int)(reds[i] & 0xFF), - (int)(greens[i] & 0xFF), - (int)(blues[i] & 0xFF)); - break; - } - } - } else { - // TRANSLUCENT - /* - * this.isTransparent = false; - * for (int i = 0; i < this.width * this.height; i++) { - * if (cm.getAlpha(tmpMap[i]) == 0) { - * this.isTransparent = true; - * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]), - * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i])); - * break; - * } - * } - * // or use special API... - */ - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - for (int i = 0; i < this.height; i++) { - for (int j = 0; j < this.width; j++) { - int p = tmpMap[i * this.width + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF); - } - } - - } catch (Exception ex) { - log.error("Error while loading image (JAI): " + ex.getMessage(), ex); - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - if (imageOp != null) { - imageOp.dispose(); - } - if (seekableInput != null) { - IOUtils.closeQuietly(seekableInput); - } - } - } - - /** {@inheritDoc} */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } - -} - diff --git a/src/java/org/apache/fop/image/JimiImage.java b/src/java/org/apache/fop/image/JimiImage.java deleted file mode 100644 index 49fb0b2e0..000000000 --- a/src/java/org/apache/fop/image/JimiImage.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// Java -import java.awt.image.ImageProducer; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.color.ColorSpace; -import java.awt.Color; - -import org.apache.commons.io.IOUtils; - -// Jimi -import com.sun.jimi.core.Jimi; - -/** - * FopImage object for several images types, using Jimi. - * See Jimi documentation for supported image types. - * - * @see AbstractFopImage - * @see FopImage - */ -public class JimiImage extends AbstractFopImage { - - /** - * Create a new Jimi image. - * - * @param imgInfo the image info for this Jimi image - */ - public JimiImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * {@inheritDoc} - */ - protected boolean loadDimensions() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.bitmaps != null; - } - - /** - * {@inheritDoc} - */ - protected boolean loadBitmap() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.bitmaps != null; - } - - /** - * Loads the image from the inputstream - */ - protected void loadImage() { - int[] tmpMap = null; - try { - ImageProducer ip = Jimi.getImageProducer(inputStream, - Jimi.SYNCHRONOUS | Jimi.IN_MEMORY); - FopImageConsumer consumer = new FopImageConsumer(ip); - ip.startProduction(consumer); - - while (!consumer.isImageReady()) { - Thread.sleep(500); - } - this.height = consumer.getHeight(); - this.width = consumer.getWidth(); - - try { - tmpMap = consumer.getImage(); - } catch (Exception ex) { - log.error("Image grabbing interrupted", ex); - return; - } - - ColorModel cm = consumer.getColorModel(); - this.bitsPerPixel = 8; - // this.bitsPerPixel = cm.getPixelSize(); - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); - if (cm.hasAlpha()) { - // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT - int transparencyType = cm.getTransparency(); - if (transparencyType == java.awt.Transparency.OPAQUE) { - this.isTransparent = false; - } else if (transparencyType == java.awt.Transparency.BITMASK) { - if (cm instanceof IndexColorModel) { - this.isTransparent = false; - byte[] alphas = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] reds = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] greens = new byte[ - ((IndexColorModel) cm).getMapSize()]; - byte[] blues = new byte[ - ((IndexColorModel) cm).getMapSize()]; - ((IndexColorModel) cm).getAlphas(alphas); - ((IndexColorModel) cm).getReds(reds); - ((IndexColorModel) cm).getGreens(greens); - ((IndexColorModel) cm).getBlues(blues); - for (int i = 0; - i < ((IndexColorModel) cm).getMapSize(); - i++) { - if ((alphas[i] & 0xFF) == 0) { - this.isTransparent = true; - this.transparentColor = new Color( - (int)(reds[i] & 0xFF), - (int)(greens[i] & 0xFF), - (int)(blues[i] & 0xFF)); - break; - } - } - } else { - // TRANSLUCENT - /* - * this.isTransparent = false; - * for (int i = 0; i < this.width * this.height; i++) { - * if (cm.getAlpha(tmpMap[i]) == 0) { - * this.isTransparent = true; - * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]), - * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i])); - * break; - * } - * } - */ - // use special API... - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } else { - this.isTransparent = false; - } - } catch (Throwable ex) { - log.error("Error while loading image (Jimi): " + ex.getMessage(), ex); - return; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - - // Should take care of the ColorSpace and bitsPerPixel - this.bitmaps = new byte[this.width * this.height * 3]; - for (int i = 0; i < this.height; i++) { - for (int j = 0; j < this.width; j++) { - int p = tmpMap[i * this.width + j]; - int r = (p >> 16) & 0xFF; - int g = (p >> 8) & 0xFF; - int b = (p) & 0xFF; - this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF); - this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF); - } - } - } - - /** {@inheritDoc} */ - protected boolean loadOriginalData() { - return loadDefaultOriginalData(); - } - -} - diff --git a/src/java/org/apache/fop/image/JpegImage.java b/src/java/org/apache/fop/image/JpegImage.java deleted file mode 100644 index 1de6b0d48..000000000 --- a/src/java/org/apache/fop/image/JpegImage.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -import java.awt.color.ColorSpace; -import java.awt.color.ICC_Profile; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.fop.util.CMYKColorSpace; - -/** - * FopImage object for JPEG images, Using Java native classes. - * - * @see AbstractFopImage - * @see FopImage - */ -public class JpegImage extends AbstractFopImage { - private ICC_Profile iccProfile = null; - private boolean foundICCProfile = false; - private boolean hasAPPEMarker = false; - - /** - * Create a jpeg image with the info. - * - * @param imgInfo the image info for this jpeg - */ - public JpegImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - } - - /** - * Load the original jpeg data. - * This loads the original jpeg data and reads the color space, - * and icc profile if any. - * - * @return true if loaded false for any error - */ - protected boolean loadOriginalData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ByteArrayOutputStream iccStream = null; - int index = 0; - boolean cont = true; - - try { - byte[] readBuf = new byte[4096]; - int bytesRead; - while ((bytesRead = inputStream.read(readBuf)) != -1) { - baos.write(readBuf, 0, bytesRead); - } - } catch (java.io.IOException ex) { - log.error("Error while loading image (Jpeg): " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - this.raw = baos.toByteArray(); - this.bitsPerPixel = 8; - this.isTransparent = false; - - //Check for SOI (Start of image) marker (FFD8) - if (this.raw.length > (index + 2) - && uByte(this.raw[index]) == 255 /*0xFF*/ - && uByte(this.raw[index + 1]) == 216 /*0xD8*/) { - index += 2; - - while (index < this.raw.length && cont) { - //check to be sure this is the begining of a header - if (this.raw.length > (index + 2) - && uByte(this.raw[index]) == 255 /*0xFF*/) { - - //192 or 194 are the header bytes that contain - // the jpeg width height and color depth. - if (uByte(this.raw[index + 1]) == 192 /*0xC0*/ - || uByte(this.raw[index + 1]) == 194 /*0xC2*/) { - - this.height = calcBytes(this.raw[index + 5], - this.raw[index + 6]); - this.width = calcBytes(this.raw[index + 7], - this.raw[index + 8]); - - int numComponents = this.raw[index + 9]; - if (numComponents == 1) { - this.colorSpace = ColorSpace.getInstance( - ColorSpace.CS_GRAY); - } else if (numComponents == 3) { - this.colorSpace = ColorSpace.getInstance( - ColorSpace.CS_LINEAR_RGB); - } else if (numComponents == 4) { - // howto create CMYK color space - /* - this.colorSpace = ColorSpace.getInstance( - ColorSpace.CS_CIEXYZ); - */ - this.colorSpace = CMYKColorSpace.getInstance(); - } else { - log.error("Unknown ColorSpace for image: " - + ""); - return false; - } - - if (foundICCProfile) { - cont = false; - break; - } - index += calcBytes(this.raw[index + 2], - this.raw[index + 3]) + 2; - - } else if (uByte(this.raw[index + 1]) == 226 /*0xE2*/ - && this.raw.length > (index + 60)) { - // Check if ICC profile - byte[] iccString = new byte[11]; - System.arraycopy(this.raw, index + 4, - iccString, 0, 11); - - if ("ICC_PROFILE".equals(new String(iccString))) { - int chunkSize = calcBytes( - this.raw[index + 2], - this.raw[index + 3]) + 2; - - if (iccStream == null) { - iccStream = new ByteArrayOutputStream(); - } - iccStream.write(this.raw, - index + 18, chunkSize - 18); - - } - - index += calcBytes(this.raw[index + 2], - this.raw[index + 3]) + 2; - // Check for Adobe APPE Marker - } else if ((uByte(this.raw[index]) == 0xff - && uByte(this.raw[index + 1]) == 0xee - && uByte(this.raw[index + 2]) == 0 - && uByte(this.raw[index + 3]) == 14 - && "Adobe".equals(new String(this.raw, index + 4, 5)))) { - // The reason for reading the APPE marker is that Adobe Photoshop - // generates CMYK JPEGs with inverted values. The correct thing - // to do would be to interpret the values in the marker, but for now - // only assume that if APPE marker is present and colorspace is CMYK, - // the image is inverted. - hasAPPEMarker = true; - - index += calcBytes(this.raw[index + 2], - this.raw[index + 3]) + 2; - } else { - index += calcBytes(this.raw[index + 2], - this.raw[index + 3]) + 2; - } - - } else { - cont = false; - } - } - } else { - log.error("Error while loading " - + "JpegImage - Invalid JPEG Header."); - return false; - } - if (iccStream != null && iccStream.size() > 0) { - int padding = (8 - (iccStream.size() % 8)) % 8; - if (padding != 0) { - try { - iccStream.write(new byte[padding]); - } catch (Exception ex) { - log.error("Error while aligning ICC stream: " + ex.getMessage(), ex); - return false; - } - } - try { - iccProfile = ICC_Profile.getInstance(iccStream.toByteArray()); - } catch (IllegalArgumentException iae) { - log.warn("An ICC profile is present but it is invalid (" - + iae.getMessage() + "). The color profile will be ignored. (" - + this.getOriginalURI() + ")"); - } - if (iccProfile.getNumComponents() != this.colorSpace.getNumComponents()) { - log.warn("The number of components of the ICC profile (" - + iccProfile.getNumComponents() - + ") doesn't match the image (" - + this.colorSpace.getNumComponents() - + "). Ignoring the ICC color profile."); - this.iccProfile = null; - } - } else if (this.colorSpace == null) { - log.error("ColorSpace not specified for JPEG image"); - return false; - } - if (hasAPPEMarker && this.colorSpace.getType() == ColorSpace.TYPE_CMYK) { - if (log.isDebugEnabled()) { - log.debug("JPEG has an Adobe APPE marker. Note: CMYK Image will be inverted. (" - + this.getOriginalURI() + ")"); - } - this.invertImage = true; - } - return true; - } - - /** - * Get the ICC profile for this Jpeg image. - * - * @return the icc profile or null if not found - */ - public ICC_Profile getICCProfile() { - return iccProfile; - } - - private int calcBytes(byte bOne, byte bTwo) { - return (uByte(bOne) * 256) + uByte(bTwo); - } - - private int uByte(byte bIn) { - if (bIn < 0) { - return 256 + bIn; - } else { - return bIn; - } - } -} - diff --git a/src/java/org/apache/fop/image/PNGImage.java b/src/java/org/apache/fop/image/PNGImage.java deleted file mode 100644 index c83d491f0..000000000 --- a/src/java/org/apache/fop/image/PNGImage.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -import java.io.IOException; - -import org.apache.xmlgraphics.image.codec.png.PNGRed; -import org.apache.xmlgraphics.image.codec.png.PNGDecodeParam; -import org.apache.xmlgraphics.image.codec.util.SeekableStream; -import org.apache.xmlgraphics.image.rendered.CachableRed; -import org.apache.commons.io.IOUtils; - -/** - * FopImage object using PNG - * - * @see AbstractFopImage - * @see FopImage - */ -public class PNGImage extends XmlGraphicsCommonsImage { - - /** - * Constructs a new PNGImage instance. - * @param imgReader basic metadata for the image - */ - public PNGImage(FopImage.ImageInfo imgReader) { - super(imgReader); - this.loaded = 0; //TODO The PNGReader cannot read the resolution, yet. - } - - /** - * {@inheritDoc} - */ - protected CachableRed decodeImage(SeekableStream stream) throws IOException { - PNGDecodeParam param = new PNGDecodeParam(); - param.setPerformGammaCorrection(true); - param.setDisplayExponent(2.2f); // sRGB gamma - PNGRed red = new PNGRed(stream, param); - String unit = (String)red.getProperty("pixel_units"); - if ("Meters".equals(unit)) { - this.dpiHorizontal = ((Integer)red.getProperty("x_pixels_per_unit")).intValue() - * 25.4f / 1000f; - this.dpiVertical = ((Integer)red.getProperty("y_pixels_per_unit")).intValue() - * 25.4f / 1000f; - } - return red; - } - - /** - * Load the original PNG data. - * This loads the original PNG data as is into memory. - * - * @return true if loaded false for any error - */ - protected boolean loadOriginalData() { - try { - seekableInput.seek(0); - this.raw = IOUtils.toByteArray(seekableInput); - - } catch (java.io.IOException ex) { - log.error("Error while loading raw image: " + ex.getMessage(), ex); - return false; - } finally { - IOUtils.closeQuietly(inputStream); - inputStream = null; - } - - return true; - } - -} diff --git a/src/java/org/apache/fop/image/RegisterableImageProvider.java b/src/java/org/apache/fop/image/RegisterableImageProvider.java deleted file mode 100644 index fd79ebd91..000000000 --- a/src/java/org/apache/fop/image/RegisterableImageProvider.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -/** - * This interface is used to dynamically register FopImage implementations. - *

                                                                                                - * NOTE: Please don't rely on this interface too much. It is a temporary measure - * until the whole image package can be redesigned. The redesign will likely - * provide a different mechanism to dynamically register new implementations. - */ -public interface RegisterableImageProvider { - - /** - * Returns the MIME type the implementation supports. - * @return the MIME type - */ - String getSupportedMimeType(); - - /** - * Returns the name of the implementation. - * @return the name - */ - String getName(); - - /** - * Returns the fully qualified class name for the implementing class. - * @return the class name - */ - String getClassName(); - -} diff --git a/src/java/org/apache/fop/image/TIFFImage.java b/src/java/org/apache/fop/image/TIFFImage.java deleted file mode 100644 index d9a9fc022..000000000 --- a/src/java/org/apache/fop/image/TIFFImage.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -import java.awt.color.ColorSpace; -import java.io.IOException; - -import org.apache.xmlgraphics.image.codec.util.SeekableStream; -import org.apache.xmlgraphics.image.codec.tiff.TIFFDirectory; -import org.apache.xmlgraphics.image.codec.tiff.TIFFField; -import org.apache.xmlgraphics.image.codec.tiff.TIFFImageDecoder; -import org.apache.xmlgraphics.image.rendered.CachableRed; -import org.apache.commons.io.IOUtils; - -/** - * TIFF implementation using the Batik codecs. - */ -public class TIFFImage extends XmlGraphicsCommonsImage { - - private int compression = 0; - private int stripCount = 0; - private long stripOffset = 0; - private long stripLength = 0; - private int fillOrder = 1; - - /** - * Constructs a new BatikImage instance. - * @param imgReader basic metadata for the image - */ - public TIFFImage(FopImage.ImageInfo imgReader) { - super(imgReader); - } - - /** - * The compression type set in the TIFF directory - * @return the TIFF compression type - */ - public int getCompression() { - return compression; - } - - /** - * The number of strips in the image - * @return the number of strips in the image - */ - public int getStripCount() { - return stripCount; - } - - /** - * {@inheritDoc} - * org.apache.xmlgraphics.image.codec.util.SeekableStream) - */ - protected CachableRed decodeImage(SeekableStream stream) throws IOException { - org.apache.xmlgraphics.image.codec.tiff.TIFFImage img - = new org.apache.xmlgraphics.image.codec.tiff.TIFFImage - (stream, null, 0); - TIFFDirectory dir = (TIFFDirectory)img.getProperty("tiff_directory"); - TIFFField fld = dir.getField(TIFFImageDecoder.TIFF_RESOLUTION_UNIT); - int resUnit = fld.getAsInt(0); - fld = dir.getField(TIFFImageDecoder.TIFF_X_RESOLUTION); - double xRes = fld.getAsDouble(0); - fld = dir.getField(TIFFImageDecoder.TIFF_Y_RESOLUTION); - double yRes = fld.getAsDouble(0); - switch (resUnit) { - case 2: //inch - this.dpiHorizontal = xRes; - this.dpiVertical = yRes; - break; - case 3: //cm - this.dpiHorizontal = xRes * 2.54f; - this.dpiVertical = yRes * 2.54f; - break; - default: - //ignored - log.warn("Cannot determine bitmap resolution." - + " Unimplemented resolution unit: " + resUnit); - } - fld = dir.getField(TIFFImageDecoder.TIFF_COMPRESSION); - if (fld != null) { - compression = fld.getAsInt(0); - } - fld = dir.getField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE); - if (fld != null) { - bitsPerPixel = fld.getAsInt(0); - } - fld = dir.getField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP); - if (fld == null) { - stripCount = 1; - } else { - stripCount = (int)(dir.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_LENGTH) - / fld.getAsLong(0)); - } - - fld = dir.getField(TIFFImageDecoder.TIFF_FILL_ORDER); - if (fld != null) { - fillOrder = fld.getAsInt(0); - } - - stripOffset = dir.getField(TIFFImageDecoder.TIFF_STRIP_OFFSETS).getAsLong(0); - stripLength = dir.getField(TIFFImageDecoder.TIFF_STRIP_BYTE_COUNTS).getAsLong(0); - - if (this.bitsPerPixel == 1) { - this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY); - } - return img; - } - - /** - * Load the original TIFF data. - * This loads only strip 1 of the original TIFF data. - * - * @return true if loaded false for any error - * {@inheritDoc} - */ - protected boolean loadOriginalData() { - if (loadDimensions()) { - byte[] readBuf = new byte[(int)stripLength]; - int bytesRead; - - try { - this.seekableInput.reset(); - this.seekableInput.skip(stripOffset); - bytesRead = seekableInput.read(readBuf); - if (bytesRead != stripLength) { - log.error("Error while loading image: length mismatch on read"); - return false; - } - - // need to invert bytes if fill order = 2 - if (fillOrder == 2) { - for (int i = 0; i < (int)stripLength; i++) { - readBuf[i] = flipTable[readBuf[i] & 0xff]; - } - } - this.raw = readBuf; - - return true; - } catch (IOException ioe) { - log.error("Error while loading image strip 1 (TIFF): ", ioe); - return false; - } finally { - IOUtils.closeQuietly(seekableInput); - IOUtils.closeQuietly(inputStream); - this.seekableInput = null; - this.inputStream = null; - this.cr = null; - } - } - return false; - } - - // Table to be used when fillOrder = 2, for flipping bytes. - // Copied from XML Graphics Commons' TIFFFaxDecoder class - private static byte[] flipTable = { - 0, -128, 64, -64, 32, -96, 96, -32, - 16, -112, 80, -48, 48, -80, 112, -16, - 8, -120, 72, -56, 40, -88, 104, -24, - 24, -104, 88, -40, 56, -72, 120, -8, - 4, -124, 68, -60, 36, -92, 100, -28, - 20, -108, 84, -44, 52, -76, 116, -12, - 12, -116, 76, -52, 44, -84, 108, -20, - 28, -100, 92, -36, 60, -68, 124, -4, - 2, -126, 66, -62, 34, -94, 98, -30, - 18, -110, 82, -46, 50, -78, 114, -14, - 10, -118, 74, -54, 42, -86, 106, -22, - 26, -102, 90, -38, 58, -70, 122, -6, - 6, -122, 70, -58, 38, -90, 102, -26, - 22, -106, 86, -42, 54, -74, 118, -10, - 14, -114, 78, -50, 46, -82, 110, -18, - 30, -98, 94, -34, 62, -66, 126, -2, - 1, -127, 65, -63, 33, -95, 97, -31, - 17, -111, 81, -47, 49, -79, 113, -15, - 9, -119, 73, -55, 41, -87, 105, -23, - 25, -103, 89, -39, 57, -71, 121, -7, - 5, -123, 69, -59, 37, -91, 101, -27, - 21, -107, 85, -43, 53, -75, 117, -11, - 13, -115, 77, -51, 45, -83, 109, -19, - 29, -99, 93, -35, 61, -67, 125, -3, - 3, -125, 67, -61, 35, -93, 99, -29, - 19, -109, 83, -45, 51, -77, 115, -13, - 11, -117, 75, -53, 43, -85, 107, -21, - 27, -101, 91, -37, 59, -69, 123, -5, - 7, -121, 71, -57, 39, -89, 103, -25, - 23, -105, 87, -41, 55, -73, 119, -9, - 15, -113, 79, -49, 47, -81, 111, -17, - 31, -97, 95, -33, 63, -65, 127, -1, - }; - // end -} diff --git a/src/java/org/apache/fop/image/XMLImage.java b/src/java/org/apache/fop/image/XMLImage.java deleted file mode 100644 index 261dc8494..000000000 --- a/src/java/org/apache/fop/image/XMLImage.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -// Java -import org.w3c.dom.Document; -import javax.xml.parsers.SAXParserFactory; - -/** - * This is an implementation for XML-based images such as SVG. - * - * @see AbstractFopImage - * @see FopImage - */ -public class XMLImage extends AbstractFopImage { - - private Document doc; - private String namespace = ""; - - /** - * @see org.apache.fop.image.AbstractFopImage#AbstractFopImage(FopImage.ImageInfo) - */ - public XMLImage(FopImage.ImageInfo imgInfo) { - super(imgInfo); - if (imgInfo.data instanceof Document) { - doc = (Document)imgInfo.data; - loaded = loaded | ORIGINAL_DATA; - } - namespace = imgInfo.str; - } - - /** - * Returns the fully qualified classname of an XML parser for - * Batik classes that apparently need it (error messages, perhaps) - * @return an XML parser classname - */ - public static String getParserName() { - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - return factory.newSAXParser().getXMLReader().getClass().getName(); - } catch (Exception e) { - return null; - } - } - - /** - * Returns the XML document as a DOM document. - * @return the DOM document - */ - public Document getDocument() { - return this.doc; - } - - /** - * Returns the namespace of the XML document. - * @return the namespace - */ - public String getNameSpace() { - return this.namespace; - } -} diff --git a/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java b/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java deleted file mode 100644 index 662673726..000000000 --- a/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image; - -import java.awt.Color; -import java.awt.Transparency; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.RenderedImage; -import java.awt.image.WritableRaster; -import java.awt.image.BufferedImage; -import java.io.IOException; - -import org.apache.xmlgraphics.image.GraphicsUtil; -import org.apache.xmlgraphics.image.codec.util.SeekableStream; -import org.apache.xmlgraphics.image.codec.util.MemoryCacheSeekableStream; -import org.apache.xmlgraphics.image.codec.util.FileCacheSeekableStream; -import org.apache.xmlgraphics.image.rendered.CachableRed; - -import org.apache.commons.io.IOUtils; - -/** - * Abstract FopImage implementation which uses the internal codecs from XML Graphics Commons. - * - * @see AbstractFopImage - * @see FopImage - */ -public abstract class XmlGraphicsCommonsImage extends AbstractFopImage { - - private byte[] softMask = null; - - /** - * The InputStream wrapped into a SeekableStream for decoding. - */ - protected SeekableStream seekableInput = null; - - /** - * The Batik representation of the image - */ - protected CachableRed cr = null; - - /** - * Constructs a new BatikImage instance. - * @param imgReader basic metadata for the image - */ - public XmlGraphicsCommonsImage(FopImage.ImageInfo imgReader) { - super(imgReader); - } - - /** - * {@inheritDoc} - */ - protected boolean loadDimensions() { - if (seekableInput == null && inputStream != null) { - try { - seekableInput = new FileCacheSeekableStream(inputStream); - } catch (IOException ioe) { - seekableInput = new MemoryCacheSeekableStream(inputStream); - } - try { - this.bitsPerPixel = 8; - cr = decodeImage(seekableInput); - this.height = cr.getHeight(); - this.width = cr.getWidth(); - this.isTransparent = false; - this.softMask = null; - ColorModel cm = cr.getColorModel(); - - this.height = cr.getHeight(); - this.width = cr.getWidth(); - this.isTransparent = false; - this.softMask = null; - - int transparencyType = cm.getTransparency(); - if (cm instanceof IndexColorModel) { - if (transparencyType == Transparency.BITMASK) { - // Use 'transparent color'. - IndexColorModel icm = (IndexColorModel)cm; - int numColor = icm.getMapSize(); - byte [] alpha = new byte[numColor]; - icm.getAlphas(alpha); - for (int i = 0; i < numColor; i++) { - if ((alpha[i] & 0xFF) == 0) { - this.isTransparent = true; - int red = (icm.getRed (i)) & 0xFF; - int grn = (icm.getGreen(i)) & 0xFF; - int blu = (icm.getBlue (i)) & 0xFF; - this.transparentColor = new Color(red, grn, blu); - break; - } - } - } - } else { - cr = GraphicsUtil.convertTosRGB(cr); - } - - // Get our current ColorModel - cm = cr.getColorModel(); - if (this.colorSpace == null) { - this.colorSpace = cm.getColorSpace(); - } - } catch (IOException ioe) { - log.error("Error while loading image (Batik): " + ioe.getMessage(), ioe); - IOUtils.closeQuietly(seekableInput); - IOUtils.closeQuietly(inputStream); - seekableInput = null; - inputStream = null; - return false; - } - } - return this.height != -1; - } - - /** - * {@inheritDoc} - */ - protected boolean loadBitmap() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.bitmaps != null; - } - - /** - * {@inheritDoc} - */ - public boolean hasSoftMask() { - if (this.bitmaps == null && this.raw == null) { - loadImage(); - } - - return (this.softMask != null); - } - - /** - * {@inheritDoc} - */ - public byte[] getSoftMask() { - if (this.bitmaps == null) { - loadImage(); - } - - return this.softMask; - } - - /** - * Decodes the image from the stream. - * @param stream the stream to read the image from - * @return the decoded image - * @throws IOException in case an I/O problem occurs - */ - protected abstract CachableRed decodeImage(SeekableStream stream) throws IOException; - - /** - * Loads the image from the InputStream. - */ - protected void loadImage() { - if (loadDimensions()) { - try { - if (cr == null) { - throw new IllegalStateException( - "Can't load the bitmaps data without the CachableRed instance"); - } - - // Get our current ColorModel - ColorModel cm = cr.getColorModel(); - - // It has an alpha channel so generate a soft mask. - if (!this.isTransparent && cm.hasAlpha()) { - this.softMask = new byte[this.width * this.height]; - } - - this.bitmaps = new byte[this.width * this.height * 3]; - - constructBitmaps(cr, this.bitmaps, this.softMask); - } catch (Exception ex) { - log.error("Error while loading image (Batik): " + ex.getMessage(), ex); - } finally { - // Make sure we clean up - IOUtils.closeQuietly(seekableInput); - IOUtils.closeQuietly(inputStream); - seekableInput = null; - inputStream = null; - cr = null; - } - } - } - - private static void constructBitmaps(RenderedImage red, byte[] bitmaps, byte[] softMask) { - WritableRaster wr = (WritableRaster)red.getData(); - ColorModel cm = red.getColorModel(); - BufferedImage bi = new BufferedImage - (cm, wr.createWritableTranslatedChild(0, 0), - cm.isAlphaPremultiplied(), null); - int width = red.getWidth(); - int height = red.getHeight(); - int [] tmpMap = new int[width]; - int idx = 0; - int sfIdx = 0; - for (int y = 0; y < height; y++) { - tmpMap = bi.getRGB(0, y, width, 1, tmpMap, 0, width); - if (softMask != null) { - for (int x = 0; x < width; x++) { - int pix = tmpMap[x]; - softMask[sfIdx++] = (byte)(pix >>> 24); - bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF); - bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF); - bitmaps[idx++] = (byte)((pix) & 0xFF); - } - } else { - for (int x = 0; x < width; x++) { - int pix = tmpMap[x]; - bitmaps[idx++] = (byte)((pix >> 16) & 0xFF); - bitmaps[idx++] = (byte)((pix >> 8) & 0xFF); - bitmaps[idx++] = (byte)((pix) & 0xFF); - } - } - } - } - -} \ No newline at end of file diff --git a/src/java/org/apache/fop/image/analyser/BMPReader.java b/src/java/org/apache/fop/image/analyser/BMPReader.java deleted file mode 100644 index caca6f3dd..000000000 --- a/src/java/org/apache/fop/image/analyser/BMPReader.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for BMP image type. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class BMPReader implements ImageReader { - - /** Length of the BMP header */ - protected static final int BMP_SIG_LENGTH = 46; - - /** offset to width */ - private static final int WIDTH_OFFSET = 18; - /** offset to height */ - private static final int HEIGHT_OFFSET = 22; - /** offset to horizontal res */ - private static final int HRES_OFFSET = 38; - /** offset to vertical res */ - private static final int VRES_OFFSET = 42; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported = ((header[0] == (byte) 0x42) - && (header[1] == (byte) 0x4d)); - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(header, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/bmp"; - } - - private void getDimension(byte[] header, FopImage.ImageInfo info) { - // little endian notation - int byte1 = header[WIDTH_OFFSET] & 0xff; - int byte2 = header[WIDTH_OFFSET + 1] & 0xff; - int byte3 = header[WIDTH_OFFSET + 2] & 0xff; - int byte4 = header[WIDTH_OFFSET + 3] & 0xff; - long l = (long) ((byte4 << 24) | (byte3 << 16) - | (byte2 << 8) | byte1); - info.width = (int) (l & 0xffffffff); - - byte1 = header[HEIGHT_OFFSET] & 0xff; - byte2 = header[HEIGHT_OFFSET + 1] & 0xff; - byte3 = header[HEIGHT_OFFSET + 2] & 0xff; - byte4 = header[HEIGHT_OFFSET + 3] & 0xff; - l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - info.height = (int) (l & 0xffffffff); - - byte1 = header[HRES_OFFSET] & 0xff; - byte2 = header[HRES_OFFSET + 1] & 0xff; - byte3 = header[HRES_OFFSET + 2] & 0xff; - byte4 = header[HRES_OFFSET + 3] & 0xff; - l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - if (l > 0) { - info.dpiHorizontal = l / 39.37d; - } - - byte1 = header[VRES_OFFSET] & 0xff; - byte2 = header[VRES_OFFSET + 1] & 0xff; - byte3 = header[VRES_OFFSET + 2] & 0xff; - byte4 = header[VRES_OFFSET + 3] & 0xff; - l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - if (l > 0) { - info.dpiVertical = l / 39.37d; - } - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[BMP_SIG_LENGTH]; - try { - imageStream.mark(BMP_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - -} diff --git a/src/java/org/apache/fop/image/analyser/EMFReader.java b/src/java/org/apache/fop/image/analyser/EMFReader.java deleted file mode 100644 index d6e2f2975..000000000 --- a/src/java/org/apache/fop/image/analyser/EMFReader.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for EMF image type. - * - * @author Peter Herweg - */ -public class EMFReader implements ImageReader { - - /** Length of the EMF header */ - protected static final int EMF_SIG_LENGTH = 88; - - /** offset to signature */ - private static final int SIGNATURE_OFFSET = 40; - /** offset to width */ - private static final int WIDTH_OFFSET = 32; - /** offset to height */ - private static final int HEIGHT_OFFSET = 36; - /** offset to horizontal resolution in pixel */ - private static final int HRES_PIXEL_OFFSET = 72; - /** offset to vertical resolution in pixel */ - private static final int VRES_PIXEL_OFFSET = 76; - /** offset to horizontal resolution in mm */ - private static final int HRES_MM_OFFSET = 80; - /** offset to vertical resolution in mm */ - private static final int VRES_MM_OFFSET = 84; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported - = ( (header[SIGNATURE_OFFSET + 0] == (byte) 0x20) - && (header[SIGNATURE_OFFSET + 1] == (byte) 0x45) - && (header[SIGNATURE_OFFSET + 2] == (byte) 0x4D) - && (header[SIGNATURE_OFFSET + 3] == (byte) 0x46) ); - - if (supported) { - FopImage.ImageInfo info = getDimension(header); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/emf"; - } - - private FopImage.ImageInfo getDimension(byte[] header) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - long value = 0; - int byte1; - int byte2; - int byte3; - int byte4; - - // little endian notation - - //resolution - byte1 = header[HRES_MM_OFFSET] & 0xff; - byte2 = header[HRES_MM_OFFSET + 1] & 0xff; - byte3 = header[HRES_MM_OFFSET + 2] & 0xff; - byte4 = header[HRES_MM_OFFSET + 3] & 0xff; - long hresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[VRES_MM_OFFSET] & 0xff; - byte2 = header[VRES_MM_OFFSET + 1] & 0xff; - byte3 = header[VRES_MM_OFFSET + 2] & 0xff; - byte4 = header[VRES_MM_OFFSET + 3] & 0xff; - long vresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[HRES_PIXEL_OFFSET] & 0xff; - byte2 = header[HRES_PIXEL_OFFSET + 1] & 0xff; - byte3 = header[HRES_PIXEL_OFFSET + 2] & 0xff; - byte4 = header[HRES_PIXEL_OFFSET + 3] & 0xff; - long hresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - byte1 = header[VRES_PIXEL_OFFSET] & 0xff; - byte2 = header[VRES_PIXEL_OFFSET + 1] & 0xff; - byte3 = header[VRES_PIXEL_OFFSET + 2] & 0xff; - byte4 = header[VRES_PIXEL_OFFSET + 3] & 0xff; - long vresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - - info.dpiHorizontal = hresPixel / (hresMM / 25.4f); - info.dpiVertical = vresPixel / (vresMM / 25.4f); - - //width - byte1 = header[WIDTH_OFFSET] & 0xff; - byte2 = header[WIDTH_OFFSET + 1] & 0xff; - byte3 = header[WIDTH_OFFSET + 2] & 0xff; - byte4 = header[WIDTH_OFFSET + 3] & 0xff; - value = (long) ((byte4 << 24) | (byte3 << 16) - | (byte2 << 8) | byte1); - value = Math.round(value / 100f / 25.4f * info.dpiHorizontal); - info.width = (int) (value & 0xffffffff); - - //height - byte1 = header[HEIGHT_OFFSET] & 0xff; - byte2 = header[HEIGHT_OFFSET + 1] & 0xff; - byte3 = header[HEIGHT_OFFSET + 2] & 0xff; - byte4 = header[HEIGHT_OFFSET + 3] & 0xff; - value = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); - value = Math.round(value / 100f / 25.4f * info.dpiVertical); - info.height = (int) (value & 0xffffffff); - - return info; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[EMF_SIG_LENGTH]; - try { - imageStream.mark(EMF_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } -} diff --git a/src/java/org/apache/fop/image/analyser/EPSReader.java b/src/java/org/apache/fop/image/analyser/EPSReader.java deleted file mode 100644 index 92260d1ab..000000000 --- a/src/java/org/apache/fop/image/analyser/EPSReader.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -// FOP -import org.apache.commons.io.IOUtils; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.EPSImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for EPS document image type. - * - * @version $Id$ - */ -public class EPSReader implements ImageReader { - - private static final byte[] EPS_HEADER_ASCII = "%!PS".getBytes(); - private static final byte[] BOUNDINGBOX = "%%BoundingBox: ".getBytes(); - //private static final byte[] HIRESBOUNDINGBOX = "%%HiResBoundingBox: ".getBytes(); - //TODO Implement HiResBoundingBox, ImageInfo probably needs some changes for that - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - - boolean isEPS = false; - - bis.mark(32); - byte[] header = new byte[30]; - bis.read(header, 0, 30); - bis.reset(); - - EPSImage.EPSData data = new EPSImage.EPSData(); - - // Check if binary header - if (getLong(header, 0) == 0xC6D3D0C5) { - data.isAscii = false; - isEPS = true; - - data.psStart = getLong(header, 4); - data.psLength = getLong(header, 8); - data.wmfStart = getLong(header, 12); - data.wmfLength = getLong(header, 16); - data.tiffStart = getLong(header, 20); - data.tiffLength = getLong(header, 24); - - } else { - // Check if plain ascii - byte[] epsh = "%!PS".getBytes(); - if (EPS_HEADER_ASCII[0] == header[0] - && EPS_HEADER_ASCII[1] == header[1] - && EPS_HEADER_ASCII[2] == header[2] - && EPS_HEADER_ASCII[3] == header[3]) { - data.isAscii = true; - isEPS = true; - } - } - - if (isEPS) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.data = data; - readEPSImage(bis, data); - data.bbox = readBBox(data); - - if (data.bbox != null) { - info.width = (int) (data.bbox[2] - data.bbox[0]); - info.height = (int) (data.bbox[3] - data.bbox[1]); - - // image data read - IOUtils.closeQuietly(bis); - info.inputStream = null; - - return info; - } else { - // Ain't eps if no BoundingBox - isEPS = false; - } - } - - return null; - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/eps"; - } - - private long getLong(byte[] buf, int idx) { - int b1 = buf[idx] & 0xff; - int b2 = buf[idx + 1] & 0xff; - int b3 = buf[idx + 2] & 0xff; - int b4 = buf[idx + 3] & 0xff; - - return (long) ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); - } - - /** - * Read the eps file and extract eps part. - * - * @param bis The InputStream - * @param data EPSData object to write the results to - * @exception IOException If an I/O error occurs - */ - private void readEPSImage(InputStream bis, EPSImage.EPSData data) - throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] file; - byte[] readBuf = new byte[20480]; - int bytesRead; - int index = 0; - boolean cont = true; - - try { - while ((bytesRead = bis.read(readBuf)) != -1) { - baos.write(readBuf, 0, bytesRead); - } - } catch (java.io.IOException ex) { - throw new IOException("Error while loading EPS image: " - + ex.getMessage()); - } - - file = baos.toByteArray(); - - if (data.isAscii) { - data.rawEps = null; - data.epsFile = new byte[file.length]; - System.arraycopy(file, 0, data.epsFile, 0, data.epsFile.length); - } else { - data.rawEps = new byte[file.length]; - data.epsFile = new byte[(int) data.psLength]; - System.arraycopy(file, 0, data.rawEps, 0, data.rawEps.length); - System.arraycopy(data.rawEps, (int) data.psStart, data.epsFile, 0, - (int) data.psLength); - } - } - - /** - * Get embedded TIFF preview or null. - * - * @param data The EPS payload - * @return The embedded preview - */ - public byte[] getPreview(EPSImage.EPSData data) { - if (data.preview == null) { - if (data.tiffLength > 0) { - data.preview = new byte[(int) data.tiffLength]; - System.arraycopy(data.rawEps, (int) data.tiffStart, data.preview, 0, - (int) data.tiffLength); - } - } - return data.preview; - } - - /** - * Extract bounding box from eps part. - * - * @param data The EPS payload - * @return An Array of four coordinates making up the bounding box - */ - private long[] readBBox(EPSImage.EPSData data) { - long[] mbbox = null; - int idx = 0; - boolean found = false; - - while (!found && (data.epsFile.length > (idx + BOUNDINGBOX.length))) { - boolean sfound = true; - int i = idx; - for (i = idx; sfound && (i - idx) < BOUNDINGBOX.length; i++) { - if (BOUNDINGBOX[i - idx] != data.epsFile[i]) { - sfound = false; - } - } - if (sfound) { - found = true; - idx = i; - } else { - idx++; - } - } - - if (!found) { - return mbbox; - } - - mbbox = new long[4]; - idx += readLongString(data, mbbox, 0, idx); - idx += readLongString(data, mbbox, 1, idx); - idx += readLongString(data, mbbox, 2, idx); - idx += readLongString(data, mbbox, 3, idx); - - return mbbox; - } - - private int readLongString(EPSImage.EPSData data, long[] mbbox, int i, int idx) { - while (idx < data.epsFile.length && (data.epsFile[idx] == 32)) { - idx++; - } - - int nidx = idx; - - // check also for ANSI46(".") to identify floating point values - while (nidx < data.epsFile.length - && ((data.epsFile[nidx] >= 48 && data.epsFile[nidx] <= 57) - || (data.epsFile[nidx] == 45) - || (data.epsFile[nidx] == 46))) { - nidx++; - } - - byte[] num = new byte[nidx - idx]; - System.arraycopy(data.epsFile, idx, num, 0, nidx - idx); - String ns = new String(num); - - //if( ns.indexOf(".") != -1 ) { - // do something like logging a warning - //} - - // then parse the double and round off to the next math. Integer - mbbox[i] = (long) Math.ceil(Double.parseDouble(ns)); - - return (1 + nidx - idx); - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/GIFReader.java b/src/java/org/apache/fop/image/analyser/GIFReader.java deleted file mode 100644 index d8da89607..000000000 --- a/src/java/org/apache/fop/image/analyser/GIFReader.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for GIF image type. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class GIFReader implements ImageReader { - - private static final int GIF_SIG_LENGTH = 10; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported = ((header[0] == 'G') - && (header[1] == 'I') - && (header[2] == 'F') - && (header[3] == '8') - && (header[4] == '7' || header[4] == '9') - && (header[5] == 'a')); - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(header, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/gif"; - } - - private void getDimension(byte[] header, FopImage.ImageInfo info) { - // little endian notation - int byte1 = header[6] & 0xff; - int byte2 = header[7] & 0xff; - info.width = ((byte2 << 8) | byte1) & 0xffff; - - byte1 = header[8] & 0xff; - byte2 = header[9] & 0xff; - info.height = ((byte2 << 8) | byte1) & 0xffff; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[GIF_SIG_LENGTH]; - try { - imageStream.mark(GIF_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/ImageReader.java b/src/java/org/apache/fop/image/analyser/ImageReader.java deleted file mode 100644 index 980d1e489..000000000 --- a/src/java/org/apache/fop/image/analyser/ImageReader.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader objects read image headers to determine the image size. - * - * @author Pankaj Narula - * @version $Id$ - */ -public interface ImageReader { - - /** - * Verify image type. If the stream does not contain image data expected by - * the reader it must reset the stream to the start. This is so that the - * next reader can start reading from the start. The reader must not close - * the stream unless it can handle the image and it has read the - * information. - * - * @param bis Image buffered input stream - * @param uri URI to the image - * @param ua The user agent - * @return true if image type is the handled one - * @exception IOException if an I/O error occurs - */ - FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) - throws IOException; - -} - diff --git a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java b/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java deleted file mode 100644 index c07d68d39..000000000 --- a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.image.FopImage; -import org.apache.xmlgraphics.util.Service; - -/** - * Factory for ImageReader objects. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class ImageReaderFactory { - - private static List formats = new java.util.ArrayList(); - - /** logger */ - protected static Log log = LogFactory.getLog(ImageReaderFactory.class); - - static { - registerFormat(new JPEGReader()); - registerFormat(new BMPReader()); - registerFormat(new GIFReader()); - registerFormat(new PNGReader()); - registerFormat(new TIFFReader()); - registerFormat(new EPSReader()); - registerFormat(new EMFReader()); - - //Dynamic registration of ImageReaders - Iterator iter = Service.providers(ImageReader.class, true); - while (iter.hasNext()) { - registerFormat((ImageReader)iter.next()); - } - - // the xml parser through batik closes the stream when finished - // so there is a workaround in the SVGReader - registerFormat(new SVGReader()); - registerFormat(new SVGZReader()); - registerFormat(new XMLReader()); - } - - /** - * Registers a new ImageReader. - * - * @param reader An ImageReader instance - */ - public static void registerFormat(ImageReader reader) { - formats.add(reader); - } - - /** - * ImageReader maker. - * - * @param uri URI to the image - * @param in image input stream - * @param ua user agent - * @return An ImageInfo object describing the image - */ - public static FopImage.ImageInfo make(String uri, InputStream in, - FOUserAgent ua) { - - ImageReader reader; - try { - for (int count = 0; count < formats.size(); count++) { - reader = (ImageReader) formats.get(count); - FopImage.ImageInfo info = reader.verifySignature(uri, in, ua); - if (info != null) { - return info; - } - } - log.warn("No ImageReader found for " + uri); - in.close(); - } catch (IOException ex) { - log.error("Error while recovering Image Informations (" - + uri + ")", ex); - } - return null; - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/JPEGReader.java b/src/java/org/apache/fop/image/analyser/JPEGReader.java deleted file mode 100644 index c90f6b000..000000000 --- a/src/java/org/apache/fop/image/analyser/JPEGReader.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for JPEG image type. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class JPEGReader implements ImageReader { - - /** - * Only SOFn and APPn markers are defined as SOFn is needed for the height and - * width search. APPn is also defined because if the JPEG contains thumbnails - * the dimensions of the thumnail would also be after the SOFn marker enclosed - * inside the APPn marker. And we don't want to confuse those dimensions with - * the image dimensions. - */ - private static final int MARK = 0xff; // Beginning of a Marker - private static final int NULL = 0x00; // Special case for 0xff00 - private static final int SOF1 = 0xc0; // Baseline DCT - private static final int SOF2 = 0xc1; // Extended Sequential DCT - private static final int SOF3 = 0xc2; // Progrssive DCT only PDF 1.3 - private static final int SOFA = 0xca; // Progressice DCT only PDF 1.3 - private static final int APP0 = 0xe0; // Application marker, JFIF - private static final int APPF = 0xef; // Application marker - private static final int SOS = 0xda; // Start of Scan - private static final int SOI = 0xd8; // start of Image - private static final int JPG_SIG_LENGTH = 2; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream fis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(fis); - boolean supported = ((header[0] == (byte) 0xff) - && (header[1] == (byte) 0xd8)); - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(fis, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = fis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/jpeg"; - } - - private byte[] getDefaultHeader(InputStream imageStream) throws IOException { - byte[] header = new byte[JPG_SIG_LENGTH]; - try { - imageStream.mark(JPG_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - - private void getDimension(InputStream imageStream, - FopImage.ImageInfo info) - throws IOException { - try { - int pos=0, avail = imageStream.available(); - imageStream.mark(avail); - int marker = NULL; - long length, skipped; -outer: - while (true) { - do { - if (avail == 0) { - imageStream.reset(); - avail = 2*pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - //Marker first byte (FF) - marker = imageStream.read(); - pos++; avail--; - } while (marker != MARK); - - do { - if (avail == 0) { - imageStream.reset(); - avail = 2*pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - //Marker second byte - marker = imageStream.read(); - pos++; avail--; - } while (marker == MARK); - - switch (marker) { - case SOI: - break; - case NULL: - break; - case APP0: - if (avail < 14) { - imageStream.reset(); - avail = 2 * pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - int reclen = this.read2bytes(imageStream); - pos += 2; avail -= 2; - this.skip(imageStream, 7); - pos += 7; avail -= 7; - int densityUnits = imageStream.read(); - pos++; avail--; - int xdensity = this.read2bytes(imageStream); - pos += 2; avail -= 2; - int ydensity = this.read2bytes(imageStream); - pos += 2; avail -= 2; - - if (densityUnits == 2) { - info.dpiHorizontal = xdensity * 28.3464567 / 72; //dpi - info.dpiVertical = ydensity * 28.3464567 / 72; //dpi - } else if (densityUnits == 1) { - info.dpiHorizontal = xdensity; - info.dpiVertical = ydensity; - } else { - // Use resolution specified in - // FOUserAgent.getFactory() (default 72dpi). - } - - int restlen = reclen - 12; - if (avail < restlen) { - imageStream.reset(); - avail = 2 * pos; - if (avail < pos + restlen + 10) { - avail = (int)(pos + restlen + 10); - } - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - skipped = this.skip(imageStream, restlen - 2); - pos += skipped; avail -= skipped; - if (skipped != restlen - 2) { - throw new IOException("Skipping Error"); - } - break; - case SOF1: - case SOF2: - case SOF3: // SOF3 and SOFA are only supported by PDF 1.3 - case SOFA: - while (avail < 7) { - imageStream.reset(); - avail = 2*pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - this.skip(imageStream, 3); - pos+=3; avail-=3; - info.height = this.read2bytes(imageStream); - pos+=2; avail-=2; - info.width = this.read2bytes(imageStream); - pos+=2; avail-=2; - break outer; - default: - while (avail < 2) { - imageStream.reset(); - avail = 2*pos; - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - length = this.read2bytes(imageStream); - pos+=2; avail-=2; - if (avail < length) { - imageStream.reset(); - avail = 2*pos; - if (avail < pos+length+10) { - avail = (int)(pos+length+10); - } - imageStream.mark(avail); - pos = (int)this.skip(imageStream, pos); - avail -= pos; - } - skipped = this.skip(imageStream, length - 2); - pos += skipped; avail -= skipped; - if (skipped != length - 2) { - throw new IOException("Skipping Error"); - } - } - } - imageStream.reset(); - } catch (IOException ioe) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ioe; - } - } - - private int read2bytes(InputStream imageStream) throws IOException { - int byte1 = imageStream.read(); - int byte2 = imageStream.read(); - return (int) ((byte1 << 8) | byte2); - } - - private long skip(InputStream imageStream, long n) throws IOException { - long discarded = 0; - while (discarded != n) { - imageStream.read(); - discarded++; - } - return discarded; // scope for exception - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/PNGReader.java b/src/java/org/apache/fop/image/analyser/PNGReader.java deleted file mode 100644 index ab6c64775..000000000 --- a/src/java/org/apache/fop/image/analyser/PNGReader.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for PNG image type. - * - * @author Pankaj Narula - * @version $Id$ - */ -public class PNGReader implements ImageReader { - - private static final int PNG_SIG_LENGTH = 24; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported = ((header[0] == (byte) 0x89) - && (header[1] == (byte) 0x50) - && (header[2] == (byte) 0x4e) - && (header[3] == (byte) 0x47) - && (header[4] == (byte) 0x0d) - && (header[5] == (byte) 0x0a) - && (header[6] == (byte) 0x1a) - && (header[7] == (byte) 0x0a)); - - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(header, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/png"; - } - - private void getDimension(byte[] header, FopImage.ImageInfo info) { - // png is always big endian - int byte1 = header[16] & 0xff; - int byte2 = header[17] & 0xff; - int byte3 = header[18] & 0xff; - int byte4 = header[19] & 0xff; - long l = (long) ((byte1 << 24) - | (byte2 << 16) - | (byte3 << 8) - | (byte4)); - info.width = (int) l; - - byte1 = header[20] & 0xff; - byte2 = header[21] & 0xff; - byte3 = header[22] & 0xff; - byte4 = header[23] & 0xff; - l = (long) ((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4); - info.height = (int) l; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[PNG_SIG_LENGTH]; - try { - imageStream.mark(PNG_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - -} diff --git a/src/java/org/apache/fop/image/analyser/SVGReader.java b/src/java/org/apache/fop/image/analyser/SVGReader.java deleted file mode 100644 index cffaa365c..000000000 --- a/src/java/org/apache/fop/image/analyser/SVGReader.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; -import java.awt.geom.AffineTransform; - -// XML -import org.w3c.dom.Element; -import org.w3c.dom.svg.SVGDocument; - -// Batik -import org.apache.batik.dom.svg.SAXSVGDocumentFactory; -import org.apache.batik.dom.svg.SVGOMDocument; -import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.bridge.UnitProcessor; -import org.apache.batik.dom.svg.SVGDOMImplementation; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -// FOP -import org.apache.fop.image.XMLImage; -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.svg.SVGUserAgent; -import org.apache.fop.util.UnclosableInputStream; - -/** - * ImageReader object for SVG document image type. - */ -public class SVGReader implements ImageReader { - - /** Logger instance */ - protected static Log log = LogFactory.getLog(SVGReader.class); - - /** SVG's MIME type */ - public static final String SVG_MIME_TYPE = "image/svg+xml"; - - private boolean batik = true; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream fis, - FOUserAgent ua) throws IOException { - FopImage.ImageInfo info = loadImage(uri, fis, ua); - if (info != null) { - IOUtils.closeQuietly(fis); - } - return info; - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return SVG_MIME_TYPE; - } - - /** - * This means the external svg document will be loaded twice. Possibly need - * a slightly different design for the image stuff. - * - * @param uri @todo Description of the Parameter - * @param fis @todo Description of the Parameter - * @param ua @todo Description of the Parameter - * @return @todo Description of the Return Value - */ - private FopImage.ImageInfo loadImage(String uri, InputStream bis, - FOUserAgent ua) { - if (batik) { - try { - Loader loader = new Loader(); - return loader.getImage(uri, bis, - ua.getSourcePixelUnitToMillimeter()); - } catch (NoClassDefFoundError e) { - batik = false; - log.warn("Batik not in class path", e); - return null; - } - } - return null; - } - - /** - * This method is put in another class so that the classloader does not - * attempt to load batik related classes when constructing the SVGReader - * class. - */ - class Loader { - private FopImage.ImageInfo getImage(String uri, InputStream fis, - float pixelUnitToMM) { - // parse document and get the size attributes of the svg element - - try { - fis = new UnclosableInputStream(fis); - - FopImage.ImageInfo info = new FopImage.ImageInfo(); - - //Set the resolution to that of the FOUserAgent - info.dpiHorizontal = 25.4f / pixelUnitToMM; - info.dpiVertical = info.dpiHorizontal; - - info.originalURI = uri; - info.mimeType = getMimeType(); - info.str = SVGDOMImplementation.SVG_NAMESPACE_URI; - - int length = fis.available(); - fis.mark(length + 1); - SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( - XMLImage.getParserName()); - SVGDocument doc = (SVGDocument) factory.createSVGDocument(uri, fis); - info.data = doc; - - Element e = doc.getRootElement(); - String s; - SVGUserAgent userAg = new SVGUserAgent(pixelUnitToMM, - new AffineTransform()); - BridgeContext ctx = new BridgeContext(userAg); - UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); - - // 'width' attribute - default is 100% - s = e.getAttributeNS(null, - SVGOMDocument.SVG_WIDTH_ATTRIBUTE); - if (s.length() == 0) { - s = SVGOMDocument.SVG_SVG_WIDTH_DEFAULT_VALUE; - } - info.width = Math.round(UnitProcessor.svgHorizontalLengthToUserSpace( - s, SVGOMDocument.SVG_WIDTH_ATTRIBUTE, uctx)); - - // 'height' attribute - default is 100% - s = e.getAttributeNS(null, - SVGOMDocument.SVG_HEIGHT_ATTRIBUTE); - if (s.length() == 0) { - s = SVGOMDocument.SVG_SVG_HEIGHT_DEFAULT_VALUE; - } - info.height = Math.round(UnitProcessor.svgVerticalLengthToUserSpace( - s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx)); - - return info; - } catch (NoClassDefFoundError ncdfe) { - try { - fis.reset(); - } catch (IOException ioe) { - // we're more interested in the original exception - } - batik = false; - log.warn("Batik not in class path", ncdfe); - return null; - } catch (IOException e) { - // If the svg is invalid then it throws an IOException - // so there is no way of knowing if it is an svg document - - log.debug("Error while trying to load stream as an SVG file: " - + e.getMessage()); - // assuming any exception means this document is not svg - // or could not be loaded for some reason - try { - fis.reset(); - } catch (IOException ioe) { - // we're more interested in the original exception - } - return null; - } - } - } - -} diff --git a/src/java/org/apache/fop/image/analyser/SVGZReader.java b/src/java/org/apache/fop/image/analyser/SVGZReader.java deleted file mode 100644 index 14fde1cb6..000000000 --- a/src/java/org/apache/fop/image/analyser/SVGZReader.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.GZIPInputStream; - -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.image.FopImage; - -/** - * Implements a reader for gzipped XMLFiles. - * - *

                                                                                                - * The current implementation is limited to SVG files only. - */ -public class SVGZReader extends XMLReader { - /** - * Default constructor. - */ - public SVGZReader() { - } - - /** {@inheritDoc} */ - protected FopImage.ImageInfo loadImage(final String uri, - final InputStream bis, final FOUserAgent ua) { - try { - return new SVGReader().verifySignature(uri, - new GZIPInputStream(bis), ua); - } catch (final IOException e) { - // ignore - } - return null; - } -} diff --git a/src/java/org/apache/fop/image/analyser/TIFFReader.java b/src/java/org/apache/fop/image/analyser/TIFFReader.java deleted file mode 100644 index 08d702780..000000000 --- a/src/java/org/apache/fop/image/analyser/TIFFReader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.apps.FOUserAgent; - -/** - * ImageReader object for TIFF image type. - * - * @author Pankaj Narula, Michael Lee - * @version $Id$ - */ -public class TIFFReader implements ImageReader { - - private static final int TIFF_SIG_LENGTH = 8; - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream bis, - FOUserAgent ua) throws IOException { - byte[] header = getDefaultHeader(bis); - boolean supported = false; - - // first 2 bytes = II (little endian encoding) - if (header[0] == (byte) 0x49 && header[1] == (byte) 0x49) { - - // look for '42' in byte 3 and '0' in byte 4 - if (header[2] == 42 && header[3] == 0) { - supported = true; - } - } - - // first 2 bytes == MM (big endian encoding) - if (header[0] == (byte) 0x4D && header[1] == (byte) 0x4D) { - - // look for '42' in byte 4 and '0' in byte 3 - if (header[2] == 0 && header[3] == 42) { - supported = true; - } - } - - if (supported) { - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.dpiHorizontal = ua.getFactory().getSourceResolution(); - info.dpiVertical = info.dpiHorizontal; - - getDimension(header, info); - info.originalURI = uri; - info.mimeType = getMimeType(); - info.inputStream = bis; - return info; - } else { - return null; - } - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "image/tiff"; - } - - private void getDimension(byte[] header, FopImage.ImageInfo info) { - // currently not setting the width and height - // these are set again by the Jimi image reader. - // I suppose I'll do it one day to be complete. Or - // someone else will. - // Note: bytes 4,5,6,7 contain the byte offset in the stream of the first IFD block - info.width = -1; - info.height = -1; - } - - private byte[] getDefaultHeader(InputStream imageStream) - throws IOException { - byte[] header = new byte[TIFF_SIG_LENGTH]; - try { - imageStream.mark(TIFF_SIG_LENGTH + 1); - imageStream.read(header); - imageStream.reset(); - } catch (IOException ex) { - try { - imageStream.reset(); - } catch (IOException exbis) { - // throw the original exception, not this one - } - throw ex; - } - return header; - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/XMLReader.java b/src/java/org/apache/fop/image/analyser/XMLReader.java deleted file mode 100644 index 4d0145eed..000000000 --- a/src/java/org/apache/fop/image/analyser/XMLReader.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.image.analyser; - -// Java -import java.io.InputStream; -import java.io.IOException; -import java.util.Map; - -// XML -import javax.xml.parsers.DocumentBuilderFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -// FOP -import org.apache.fop.image.FopImage; -import org.apache.fop.util.UnclosableInputStream; -import org.apache.fop.apps.FOUserAgent; - -// Commons-Logging -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** ImageReader object for XML document image type. */ -public class XMLReader implements ImageReader { - - /** - * logging instance - */ - private Log log = LogFactory.getLog(XMLReader.class); - - private static Map converters = new java.util.HashMap(); - - /** - * Registers a Converter implementation with XMLReader. - * - * @param ns The namespace to associate with this converter - * @param conv The actual Converter implementation - */ - public static void setConverter(String ns, Converter conv) { - converters.put(ns, conv); - } - - /** {@inheritDoc} */ - public FopImage.ImageInfo verifySignature(String uri, InputStream fis, - FOUserAgent ua) - throws IOException { - FopImage.ImageInfo info = loadImage(uri, fis, ua); - if (info != null) { - info.originalURI = uri; - IOUtils.closeQuietly(fis); - } - return info; - } - - /** - * Returns the MIME type supported by this implementation. - * - * @return The MIME type - */ - public String getMimeType() { - return "text/xml"; - } - - /** - * Creates an ImageInfo object from an XML image read from a stream. - * - * (todo) This means the external svg document will be loaded twice. Possibly need - * a slightly different design for the image stuff. - * - * @param uri The URI to the image - * @param bis The InputStream - * @param ua The user agent - * @return An ImageInfo object describing the image - */ - protected FopImage.ImageInfo loadImage(String uri, InputStream bis, - FOUserAgent ua) { - return createDocument(bis, ua); - } - - /** - * Creates an ImageInfo object from an XML image read from a stream. - * - * @param input The InputStream - * @param ua The user agent - * @return An ImageInfo object describing the image - */ - public FopImage.ImageInfo createDocument(final InputStream input, final FOUserAgent ua) { - Document doc = null; - FopImage.ImageInfo info = new FopImage.ImageInfo(); - info.mimeType = getMimeType(); - - try { - final InputStream is = new UnclosableInputStream(input); - int length = is.available(); - is.mark(length); - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - doc = dbf.newDocumentBuilder().parse(is); - info.data = doc; - - Element root = doc.getDocumentElement(); - log.debug("XML image namespace: " + root.getAttribute("xmlns")); - String ns = root.getAttribute("xmlns"); - info.str = ns; - - Converter conv = (Converter) converters.get(ns); - if (conv != null) { - FopImage.ImageInfo i = conv.convert(doc); - if (i != null) { - info = i; - } - } - } catch (Exception e) { - log.debug("Error while constructing image from XML", e); - try { - input.reset(); - } catch (IOException ioe) { - // throw the original exception, not this one - } - return null; - } - if (info != null) { - try { - input.close(); - } catch (IOException io) { - // ignore - } - } - return info; - } - - /** - * This interface is to be implemented for XML to image converters. - */ - public static interface Converter { - - /** - * This method is called for a DOM document to be converted into an - * ImageInfo object. - * - * @param doc The DOM document to convert - * @return An ImageInfo object describing the image - */ - FopImage.ImageInfo convert(Document doc); - } - -} - diff --git a/src/java/org/apache/fop/image/analyser/package.html b/src/java/org/apache/fop/image/analyser/package.html deleted file mode 100644 index 677a625b2..000000000 --- a/src/java/org/apache/fop/image/analyser/package.html +++ /dev/null @@ -1,23 +0,0 @@ - - - -org.apache.fop.image.analyser Package - -

                                                                                                Image analyzers for determining the format of an image and to preload its intrinsic size.

                                                                                                - - \ No newline at end of file diff --git a/src/java/org/apache/fop/image/package.html b/src/java/org/apache/fop/image/package.html index 0145864b2..cbd2d7c5e 100644 --- a/src/java/org/apache/fop/image/package.html +++ b/src/java/org/apache/fop/image/package.html @@ -18,6 +18,6 @@ org.apache.fop.image Package -

                                                                                                Contains image loading adapters for various image sources and the image cache.

                                                                                                +

                                                                                                Contains image loading adapters for various image sources.

                                                                                                \ No newline at end of file diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 435f25b48..5e5613898 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -386,6 +386,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); + + //All child content is processed. Only break-after can occur now, so... + context.clearPendingMarks(); addKnuthElementsForBreakAfter(returnList, context); setFinished(true); diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 541912a08..67ed1de9f 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -294,15 +294,22 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (returnedList != null && returnedList.size() == 1 && ((ListElement) returnedList.getFirst()).isForcedBreak()) { - // a descendant of this block has break-before - contentList.addAll(returnedList); if (curLM.isFinished() && !hasNextChildLM()) { - forcedBreakAfterLast = (BreakElement)contentList.removeLast(); + // a descendant of this block has break-before + forcedBreakAfterLast = (BreakElement) returnedList.getFirst(); context.clearPendingMarks(); break; } + if (contentList.size() == 0) { + // Empty fo:block, zero-length box makes sure the IDs and/or markers + // are registered and borders/padding are painted. + returnList.add(new KnuthBox(0, notifyPos(new Position(this)), false)); + } + // a descendant of this block has break-before + contentList.addAll(returnedList); + /* extension: conversione di tutta la sequenza fin'ora ottenuta */ if (bpUnit > 0) { storedList = contentList; @@ -393,6 +400,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); + + //All child content is processed. Only break-after can occur now, so... + context.clearPendingMarks(); if (forcedBreakAfterLast == null) { addKnuthElementsForBreakAfter(returnList, context); } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index a72fca9af..79b5e232f 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -285,12 +285,8 @@ public class LayoutContext { * Clears all pending marks on the LayoutContext. */ public void clearPendingMarks() { - if (this.pendingBeforeMarks != null) { - this.pendingBeforeMarks.clear(); - } - if (this.pendingAfterMarks != null) { - this.pendingAfterMarks.clear(); - } + this.pendingBeforeMarks = null; + this.pendingAfterMarks = null; } /** diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 4e41e909f..ab65a1d28 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -337,14 +337,22 @@ class ActiveCell { } /** - * Returns the last step for this cell. + * Returns the last step for this cell. This includes the normal border- and + * padding-before, the whole content, the normal padding-after, and the + * trailing after border. Indeed, if the normal border is taken instead, + * and appears to be smaller than the trailing one, the last step may be smaller than + * the current step (see TableStepper#considerRowLastStep). This will produce a wrong + * infinite penalty, plus the cell's content won't be taken into account since the + * final step will be smaller than the current one (see {@link #signalNextStep(int)}). + * This actually means that the content will be swallowed. * - * @return the step including all of the cell's content plus the normal borders and paddings + * @return the length of last step */ int getLastStep() { assert nextStep.end == elementList.size() - 1; assert nextStep.contentLength == totalLength && nextStep.penaltyLength == 0; - int lastStep = bpBeforeNormal + totalLength + bpAfterNormal; + int lastStep = bpBeforeNormal + totalLength + paddingAfterNormal + + pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING); log.debug(this + ": last step = " + lastStep); return lastStep; } @@ -466,8 +474,12 @@ class ActiveCell { */ void endRow(int rowIndex) { if (endsOnRow(rowIndex)) { + // Subtract the old value of bpAfterTrailing... + nextStep.totalLength -= bpAfterTrailing; bpAfterTrailing = paddingAfterNormal + pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING); + // ... and add the new one + nextStep.totalLength += bpAfterTrailing; lastCellPart = true; } else { bpBeforeLeading = paddingBeforeLeading diff --git a/src/java/org/apache/fop/render/ps/PSImageUtils.java b/src/java/org/apache/fop/render/ps/PSImageUtils.java deleted file mode 100644 index 004d5a22a..000000000 --- a/src/java/org/apache/fop/render/ps/PSImageUtils.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.ps; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.xmlgraphics.ps.PSGenerator; - -import org.apache.fop.image.EPSImage; -import org.apache.fop.image.FopImage; - -/** - * Utility code for rendering images in PostScript. - */ -public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils { - - /** logging instance */ - protected static Log log = LogFactory.getLog(PSImageUtils.class); - - /** - * Renders an EPS image to PostScript. - * @param img EPS image to render - * @param x x position - * @param y y position - * @param w width - * @param h height - * @param gen PS generator - * @deprecated Use {@link #renderEPS(java.io.InputStream, String, java.awt.geom.Rectangle2D, - * java.awt.geom.Rectangle2D, PSGenerator)} instead - */ - public static void renderEPS(EPSImage img, - float x, float y, float w, float h, - PSGenerator gen) { - try { - if (!img.load(FopImage.ORIGINAL_DATA)) { - gen.commentln("%EPS image could not be processed: " + img); - return; - } - int[] bbox = img.getBBox(); - int bboxw = bbox[2] - bbox[0]; - int bboxh = bbox[3] - bbox[1]; - String name = img.getDocName(); - if (name == null || name.length() == 0) { - name = img.getOriginalURI(); - } - renderEPS(img.getEPSImage(), name, - x, y, w, h, - bbox[0], bbox[1], bboxw, bboxh, gen); - - } catch (Exception e) { - log.error("PSRenderer.renderImageArea(): Error rendering bitmap (" - + e.getMessage() + ")", e); - } - } - -} diff --git a/src/java/org/apache/fop/render/rtf/SVGConverter.java b/src/java/org/apache/fop/render/rtf/SVGConverter.java deleted file mode 100644 index 11ba8dc82..000000000 --- a/src/java/org/apache/fop/render/rtf/SVGConverter.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.rtf; - -import org.apache.batik.transcoder.TranscoderException; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.TranscoderOutput; -import org.apache.batik.transcoder.image.JPEGTranscoder; -import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.image.XMLImage; - -/** - * Helper class for converting SVG to bitmap images. - */ -public final class SVGConverter { - - /** logger instance */ - private static Log log = LogFactory.getLog(SVGConverter.class); - - /** - * Constructor is private, because it's just a utility class. - */ - private SVGConverter() { - } - - /** - * Converts a SVG image to a JPEG bitmap. - * @param image the SVG image - * @return a byte array containing the JPEG image - */ - public static byte[] convertToJPEG(XMLImage image) { - JPEGTranscoder transcoder = new JPEGTranscoder(); - /* TODO Disabled to avoid side-effect due to the mixing of source and target resolutions - * This should be reenabled when it has been determined how exactly to handle this - transcoder.addTranscodingHint(ImageTranscoder.KEY_PIXEL_UNIT_TO_MILLIMETER, - new Float(25.4f / 300)); //300dpi should be enough for now. - */ - transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(0.9f)); - TranscoderInput input = new TranscoderInput(image.getDocument()); - ByteArrayOutputStream baout = new ByteArrayOutputStream(16384); - TranscoderOutput output = new TranscoderOutput(baout); - try { - transcoder.transcode(input, output); - return baout.toByteArray(); - } catch (TranscoderException e) { - log.error(e); - return null; - } - } - -} diff --git a/src/java/org/apache/fop/svg/GraphicsConfiguration.java b/src/java/org/apache/fop/svg/GraphicsConfiguration.java new file mode 100644 index 000000000..a92baed27 --- /dev/null +++ b/src/java/org/apache/fop/svg/GraphicsConfiguration.java @@ -0,0 +1,51 @@ +/* + * 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.svg; + +import java.awt.image.VolatileImage; + +/** + * Adapter to allow subclassing java.awt.GraphicsConfiguration without + * compilation errors. + * The version for JDK 1.4 needs to add an override for the abstract + * createCompatibleVolatileImage() method. It can't be overidden + * for JDK 1.3 because there is no VolatileImage there. + * + */ +abstract public class GraphicsConfiguration extends java.awt.GraphicsConfiguration { + + /** + * @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int) + * @since JDK 1.4 + */ + public VolatileImage createCompatibleVolatileImage(int width, int height) { + return null; + } + + /** + * @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int, int) + * @since JDK 1.5 + */ + public VolatileImage createCompatibleVolatileImage(int width, int height, int transparency) { + return null; + } + +} diff --git a/status.xml b/status.xml index 8a4fc3da9..11b719678 100644 --- a/status.xml +++ b/status.xml @@ -59,7 +59,7 @@ --> - +
                                                                                                Notes @@ -108,14 +108,24 @@

                                                                                              - The image libraries Jimi and JAI are no longer needed (and used). Instead we rely - completely on the Image I/O API that has been introduced with Java 1.4. If you still - need support for bitmap image formats that do not work out-of-the-box, we recommend - adding JAI Image I/O Tools - (an Image I/O compatible image codec package) to the classpath. + The image libraries Jimi and JAI are no longer needed (and used) for image loading. + Instead we rely completely on the Image I/O API that has been introduced with + Java 1.4. If you still need support for bitmap image formats that do not work + out-of-the-box, we recommend adding + JAI Image I/O Tools + (an Image I/O compatible image codec package) to the classpath. JAI is still required + for building the FOP distribution but it is optional for normal builds and at run-time.

                                                                                        + + Bugfix: The before border of a block is no longer swallowed if its first child issues + a break-before. + + + Bugfix: When there was a forced break after a block with (conditional) borders the + border-after wasn't painted. + Bugfix: a forced break inside a cell was ignored when occurring before the minimum height set on the enclosing row was set. diff --git a/test/java/org/apache/fop/URIResolutionTestCase.java b/test/java/org/apache/fop/URIResolutionTestCase.java index 1277126bc..106ec0a2c 100644 --- a/test/java/org/apache/fop/URIResolutionTestCase.java +++ b/test/java/org/apache/fop/URIResolutionTestCase.java @@ -36,17 +36,19 @@ import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.w3c.dom.Document; + import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.xpath.XPathAPI; +import org.apache.xpath.objects.XObject; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import org.apache.fop.render.xml.XMLRenderer; -import org.apache.xpath.XPathAPI; -import org.apache.xpath.objects.XObject; -import org.w3c.dom.Document; /** * Tests URI resolution facilities. @@ -85,9 +87,6 @@ public class URIResolutionTestCase extends AbstractFOPTestCase { private void innerTestFO1(boolean withStream) throws Exception { FOUserAgent ua = fopFactory.newFOUserAgent(); - //Reset the image caches to force URI resolution! - ua.getFactory().getImageFactory().clearCaches(); - File foFile = new File(getBaseDir(), "test/xml/uri-resolution1.fo"); MyURIResolver resolver = new MyURIResolver(withStream); diff --git a/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml b/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml new file mode 100644 index 000000000..523d22c6f --- /dev/null +++ b/test/layoutengine/standard-testcases/block-level_break-after_bug44412.xml @@ -0,0 +1,112 @@ + + + + + +

                                                                                        + This test checks Bugzilla #44412 where the border-after of an fo:block wasn't painted in + case break-after is present. +

                                                                                        +
                                                                                        + + + + + + + + + + Before the block + A block with + borders and break-before and break-after. + After the block + + + + + + A block-container with borders and break-after. + + After the block-container + + + + + + + + + + + Blaaaaaah + + + + After the list-block + + + + + + + + + + + Blaaaaaah + + + + After the list-item + + + + + + + + + + Blaaaaah + + + + + After the table + + + + + + + + + + + + + + + + + + + + +
                                                                                        diff --git a/test/layoutengine/standard-testcases/block_break-before_bug44412.xml b/test/layoutengine/standard-testcases/block_break-before_bug44412.xml new file mode 100644 index 000000000..9ef4150b5 --- /dev/null +++ b/test/layoutengine/standard-testcases/block_break-before_bug44412.xml @@ -0,0 +1,64 @@ + + + + + +

                                                                                        + This test checks Bugzilla #44412 where a break-before on the first child of an otherwise + empty block is set. It is expected that the parent block creates two areas, the first with + only border-before on the first page and zero bpd. +

                                                                                        +
                                                                                        + + + + + + + + + + Before the block + + The break-before set on this block causes the parent + block to produce an empty block area with only a border before on the + first page. + + + + + + + + + + + + + + + + + + + + + 3 + + +
                                                                                        diff --git a/test/layoutengine/standard-testcases/table_bug44621.xml b/test/layoutengine/standard-testcases/table_bug44621.xml new file mode 100644 index 000000000..b4b9edbd0 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_bug44621.xml @@ -0,0 +1,105 @@ + + + + + +

                                                                                        + This is a testcase for bug #44621: when the width of the after border of a cell, in the + trailing case, is bigger than in the normal case, a wrong sequence of Knuth elements was + generated, leading to some content being swallowed. +

                                                                                        +
                                                                                        + + + + + + + + + + The after borders of the body’s cells, in the trailing case, + are thicker than in the normal case. + + + + + Footer 1.1 + + + Footer 1.2 + + + + + + Cell 1.1 + + + Cell 1.2 + + + + + Cell 2.1 + + + Cell 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + + + 3 + + +
                                                                                        diff --git a/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml b/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml index 7b50996cc..0c6ed10eb 100644 --- a/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml +++ b/test/layoutengine/standard-testcases/table_row-delay_fixed-row-height.xml @@ -145,7 +145,7 @@ 3 - + -- cgit v1.2.3 From 486aaffb5c0357779f252775db5d6aa51ab020a9 Mon Sep 17 00:00:00 2001 From: Clay Leeds Date: Sat, 22 Mar 2008 21:54:27 +0000 Subject: updates to Forrest web site (expand menu structure). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@640089 13f79535-47bb-0310-9956-ffa450edef68 --- forrest.properties | 2 +- src/documentation/skinconf.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/forrest.properties b/forrest.properties index 95260e665..add080783 100644 --- a/forrest.properties +++ b/forrest.properties @@ -56,7 +56,7 @@ project.skin=pelt #project.images-dir=${project.resources-dir}/images #project.schema-dir=${project.resources-dir}/schema #project.skins-dir=${project.content-dir}/skins -#project.skinconf=${project.content-dir}/skinconf.xml +project.skinconf=${project.content-dir}/skinconf.xml #project.lib-dir=${project.content-dir}/lib #project.classes-dir=${project.content-dir}/classes #project.translations-dir=${project.content-dir}/translations diff --git a/src/documentation/skinconf.xml b/src/documentation/skinconf.xml index 47c8d5e55..e87baab34 100644 --- a/src/documentation/skinconf.xml +++ b/src/documentation/skinconf.xml @@ -164,6 +164,7 @@ which will be used to configure the chosen Forrest skin. .ForrestTable td.partial { background-color: #FFFFCC; text-align: center; } .ForrestTable td.category { /*background-color: #CFDCED;*/ font-size: 1.2em } + .menuitemgroup{ display: block;} -- cgit v1.2.3 From 40cdce2da150ea5b0061d0ed2250d30ce0e5584c Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 23 Mar 2008 19:36:36 +0000 Subject: Cleanup and minor refactoring: * consolidate addId() in AbstractLayoutManager * replace getPSLM().addIdToPage(getXXX().getId()) in various LMs Smaller changes/cleanup in the affected LMs include: * removal of some redundant casts * simplified conditionals * avoid duplicating the reference to the FObj as much as possible: the reference is already stored in AbstractLM, yet every subclass seems to add another reference... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@640242 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/AbstractLayoutManager.java | 16 +++++++++++-- .../fop/layoutmgr/BlockContainerLayoutManager.java | 16 +++++-------- .../apache/fop/layoutmgr/BlockLayoutManager.java | 8 +++---- .../inline/AbstractGraphicsLayoutManager.java | 7 ------ .../AbstractPageNumberCitationLayoutManager.java | 17 +++++++------- .../layoutmgr/inline/CharacterLayoutManager.java | 23 +++++-------------- .../fop/layoutmgr/inline/ICLayoutManager.java | 5 ----- .../fop/layoutmgr/inline/InlineLayoutManager.java | 9 ++------ .../inline/InlineStackingLayoutManager.java | 26 +++++----------------- .../fop/layoutmgr/inline/LeaderLayoutManager.java | 5 ----- .../layoutmgr/inline/LeafNodeLayoutManager.java | 10 --------- .../layoutmgr/inline/PageNumberLayoutManager.java | 6 +---- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 12 +++++----- .../list/ListItemContentLayoutManager.java | 10 ++++----- .../fop/layoutmgr/list/ListItemLayoutManager.java | 20 ++++++++--------- .../table/TableAndCaptionLayoutManager.java | 7 ++---- .../layoutmgr/table/TableCaptionLayoutManager.java | 5 +---- .../layoutmgr/table/TableCellLayoutManager.java | 10 ++++----- .../fop/layoutmgr/table/TableLayoutManager.java | 6 ++--- 19 files changed, 79 insertions(+), 139 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index f75fffc0d..656b5e2df 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -113,7 +113,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager if (curChildLM != null && !curChildLM.isFinished()) { return curChildLM; } - while (childLMiter.hasNext()) { + if (childLMiter.hasNext()) { curChildLM = (LayoutManager) childLMiter.next(); curChildLM.initialize(); return curChildLM; @@ -350,6 +350,10 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** * Registers the FO's markers on the current PageViewport + * + * @param isStarting boolean indicating whether the markers qualify as 'starting' + * @param isFirst boolean indicating whether the markers qualify as 'first' + * @param isLast boolean indicating whether the markers qualify as 'last' */ protected void addMarkersToPage(boolean isStarting, boolean isFirst, boolean isLast) { if (this.markers != null) { @@ -361,10 +365,18 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } } + /** + * Registers the FO's id on the current PageViewport + */ + protected void addId() { + if (fobj != null) { + getPSLM().addIDToPage(fobj.getId()); + } + } + /** {@inheritDoc} */ public String toString() { return (super.toString() + (fobj != null ? "[fobj=" + fobj.toString() + "]" : "")); } - } diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 5e5613898..e8ca88c1c 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -248,7 +248,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager MinOptMax stackLimit = new MinOptMax(relDims.bpd); - LinkedList returnedList = null; + LinkedList returnedList; LinkedList contentList = new LinkedList(); LinkedList returnList = new LinkedList(); @@ -602,11 +602,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } public boolean isOverflow() { - if (isEmpty()) { - return false; - } else { - return (deferredAlg.getPageBreaks().size() > 1); - } + return !isEmpty() && (deferredAlg.getPageBreaks().size() > 1); } protected LayoutManager getTopLevelLM() { @@ -708,7 +704,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); } - LayoutManager childLM = null; + LayoutManager childLM; LayoutManager lastLM = null; LayoutContext lc = new LayoutContext(0); lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); @@ -737,7 +733,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } Position innerPosition = pos; if (pos instanceof NonLeafPosition) { - innerPosition = ((NonLeafPosition)pos).getPosition(); + innerPosition = pos.getPosition(); } if (pos instanceof BlockContainerPosition) { if (bcpos != null) { @@ -773,7 +769,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } - getPSLM().addIDToPage(getBlockContainerFO().getId()); + addId(); addMarkersToPage(true, isFirst(firstPos), isLast(lastPos)); @@ -874,7 +870,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager referenceArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(((BlockContainer)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index a65c0ed9b..f5270107c 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -147,7 +147,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager * @return true if there are more child lms */ public boolean hasNext() { - return (curPos < listLMs.size()) ? true : createNextChildLMs(curPos); + return (curPos < listLMs.size()) || createNextChildLMs(curPos); } /** @@ -250,7 +250,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); } - LayoutManager childLM = null; + LayoutManager childLM; LayoutManager lastLM = null; LayoutContext lc = new LayoutContext(0); lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); @@ -280,7 +280,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager Position innerPosition = pos; if (pos instanceof NonLeafPosition) { //Not all elements are wrapped - innerPosition = ((NonLeafPosition) pos).getPosition(); + innerPosition = pos.getPosition(); } if (innerPosition == null) { // pos was created by this BlockLM and was inside an element @@ -309,7 +309,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } } - getPSLM().addIDToPage(getBlockFO().getId()); + addId(); addMarkersToPage(true, isFirst(firstPos), isLast(lastPos)); diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index 6426f15db..38e0c35bc 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -123,13 +123,6 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage ); } - /** - * {@inheritDoc} - */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - /** * Returns the image of foreign object area to be put into * the viewport. diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java index 41d4af1c1..c92bdb6fc 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java @@ -51,7 +51,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa * Constructor * * @param node the formatting object that creates this area - * @todo better retrieval of font info + * TODO better retrieval of font info */ public AbstractPageNumberCitationLayoutManager(AbstractPageNumberCitation node) { super(node); @@ -83,7 +83,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa /** {@inheritDoc} */ public InlineArea get(LayoutContext context) { - curArea = getPageNumberCitationInlineArea(parentLM); + curArea = getPageNumberCitationInlineArea(); return curArea; } @@ -99,12 +99,15 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa } /** - * if id can be resolved then simply return a word, otherwise + * If id can be resolved then simply return a word, otherwise * return a resolvable area + * + * @param parentLM the parent LayoutManager + * @return a corresponding InlineArea */ - private InlineArea getPageNumberCitationInlineArea(LayoutManager parentLM) { + private InlineArea getPageNumberCitationInlineArea() { PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId()); - TextArea text = null; + TextArea text; if (page != null) { String str = page.getPageNumberString(); // get page string from parent, build area @@ -150,9 +153,5 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa return width; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index 0430eef0c..b53e442d4 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -45,7 +45,6 @@ import org.apache.fop.util.CharUtilities; * LayoutManager for the fo:character formatting object */ public class CharacterLayoutManager extends LeafNodeLayoutManager { - private Character fobj; private MinOptMax letterSpaceIPD; private int hyphIPD; private Font font; @@ -57,13 +56,13 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { * @param node the fo:character formatting object */ public CharacterLayoutManager(Character node) { - // @todo better null checking of node super(node); - fobj = node; } /** {@inheritDoc} */ public void initialize() { + Character fobj = (Character)this.fobj; + FontInfo fi = fobj.getFOEventHandler().getFontInfo(); FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this)); @@ -90,7 +89,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { text.addWord(String.valueOf(ch), 0); } TraitSetter.setProducerID(text, node.getId()); - TraitSetter.addTextDecoration(text, fobj.getTextDecoration()); + TraitSetter.addTextDecoration(text, node.getTextDecoration()); return text; } @@ -105,6 +104,8 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { return null; } + Character fobj = (Character)this.fobj; + ipd = new MinOptMax(font.getCharWidth(fobj.getCharacter())); curArea.setIPD(ipd.opt); @@ -178,14 +179,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public boolean applyChanges(List oldList) { setFinished(false); - if (isSomethingChanged) { - // there is nothing to do, - // possible changes have already been applied - // in the hyphenate() method - return true; - } else { - return false; - } + return isSomethingChanged; } /** {@inheritDoc} */ @@ -238,10 +232,5 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { return returnList; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java index 4ffafb061..7ca9e0d5e 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java @@ -31,12 +31,10 @@ import org.apache.fop.fo.flow.InlineContainer; * and id areas are maintained for later retrieval. */ public class ICLayoutManager extends LeafNodeLayoutManager { - private InlineContainer fobj; private List childrenLM; public ICLayoutManager(InlineContainer node, List childLM) { super(node); - fobj = node; childrenLM = childLM; } @@ -44,7 +42,4 @@ public class ICLayoutManager extends LeafNodeLayoutManager { return null; } - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 1f53e792e..e9919e02f 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -297,7 +297,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { ); } - while ((curLM = (LayoutManager) getChildLM()) != null) { + while ((curLM = getChildLM()) != null) { if (!(curLM instanceof InlineLevelLayoutManager)) { // A block LM @@ -436,7 +436,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // layout context given to lastLM, but must be cleared in the // layout context given to the other LMs. LinkedList positionList = new LinkedList(); - NonLeafPosition pos = null; + NonLeafPosition pos; LayoutManager lastLM = null;// last child LM in this iterator Position lastPos = null; while (parentIter.hasNext()) { @@ -600,9 +600,4 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { return this.auxiliaryPosition; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index 4d0872a6d..bf1538a7c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -75,15 +75,9 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager private Area currentArea; // LineArea or InlineParent - //private BreakPoss prevBP; - /** The child layout context */ protected LayoutContext childLC; - private boolean bAreaCreated = false; - - //private LayoutManager currentLM = null; - /** Used to store previous content IPD for each child LM. */ private HashMap hmPrevIPD = new HashMap(); @@ -170,14 +164,6 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager hmPrevIPD.clear(); } - /** - * This method is called by addAreas() so IDs can be added to a page for FOs that - * support the 'id' property. - */ - protected void addId() { - // Do nothing here, overriden in subclasses that have an 'id' property. - } - /** * Returns the current area. * @return the current area @@ -255,7 +241,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager // "unwrap" the Position stored in each element of oldList while (oldListIterator.hasNext()) { element = (KnuthElement) oldListIterator.next(); - element.setPosition(((NonLeafPosition)element.getPosition()).getPosition()); + element.setPosition(element.getPosition().getPosition()); } // The last element may not have a layout manager (its position == null); @@ -288,7 +274,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager // "unwrap" the Position stored in each element of oldList while (oldListIterator.hasNext()) { element = (KnuthElement) oldListIterator.next(); - element.setPosition(((NonLeafPosition)element.getPosition()).getPosition()); + element.setPosition(element.getPosition().getPosition()); } ((InlineLevelLayoutManager) @@ -298,14 +284,14 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager /** {@inheritDoc} */ public void getWordChars(StringBuffer sbChars, Position pos) { - Position newPos = ((NonLeafPosition) pos).getPosition(); + Position newPos = pos.getPosition(); ((InlineLevelLayoutManager) newPos.getLM()).getWordChars(sbChars, newPos); } /** {@inheritDoc} */ public void hyphenate(Position pos, HyphContext hc) { - Position newPos = ((NonLeafPosition) pos).getPosition(); + Position newPos = pos.getPosition(); ((InlineLevelLayoutManager) newPos.getLM()).hyphenate(newPos, hc); } @@ -318,7 +304,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager while (oldListIterator.hasNext()) { oldElement = (KnuthElement) oldListIterator.next(); oldElement.setPosition - (((NonLeafPosition) oldElement.getPosition()).getPosition()); + (oldElement.getPosition().getPosition()); } // reset the iterator oldListIterator = oldList.listIterator(); @@ -385,7 +371,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager while (oldListIterator.hasNext()) { oldElement = (KnuthElement) oldListIterator.next(); oldElement.setPosition - (((NonLeafPosition) oldElement.getPosition()).getPosition()); + (oldElement.getPosition().getPosition()); } // reset the iterator oldListIterator = oldList.listIterator(); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index 5f93ab98c..f4bcde96f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -339,11 +339,6 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { return returnList; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } - /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index 78d126194..fb5e9ee4d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -65,8 +65,6 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager /** The alignment context applying to this area */ protected AlignmentContext alignmentContext = null; - private MinOptMax ipd; - /** Flag to indicate if something was changed as part of the getChangeKnuthElements sequence */ protected boolean isSomethingChanged = false; /** Our area info for the Knuth elements */ @@ -204,14 +202,6 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager return curArea; } - /** - * This method is called by addAreas() so IDs can be added to a page for FOs that - * support the 'id' property. - */ - protected void addId() { - // Do nothing here, overriden in subclasses that have an 'id' property. - } - /** * Offset this area. * Offset the inline area in the bpd direction when adding the diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java index 88f1d283c..1aaaaf527 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java @@ -42,7 +42,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { * Constructor * * @param node the fo:page-number formatting object that creates the area - * @todo better null checking of node, font + * TODO better null checking of node, font */ public PageNumberLayoutManager(PageNumber node) { super(node); @@ -131,9 +131,5 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { return width; } - /** {@inheritDoc} */ - protected void addId() { - getPSLM().addIDToPage(fobj.getId()); - } } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index e17880e59..c17ddc711 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -156,11 +156,11 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); } - getPSLM().addIDToPage(getListBlockFO().getId()); + addId(); // the list block contains areas stacked from each list item - LayoutManager childLM = null; + LayoutManager childLM; LayoutContext lc = new LayoutContext(0); LayoutManager firstLM = null; LayoutManager lastLM = null; @@ -181,10 +181,10 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } if (pos instanceof NonLeafPosition && (pos.getPosition() != null) - && ((NonLeafPosition) pos).getPosition().getLM() != this) { + && pos.getPosition().getLM() != this) { // pos was created by a child of this ListBlockLM - positionList.add(((NonLeafPosition) pos).getPosition()); - lastLM = ((NonLeafPosition) pos).getPosition().getLM(); + positionList.add(pos.getPosition()); + lastLM = pos.getPosition().getLM(); if (firstLM == null) { firstLM = lastLM; } @@ -218,7 +218,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(((ListBlock)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 363f6493f..8b0028a8f 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -115,9 +115,9 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(getPartFO().getId()); + addId(); - LayoutManager childLM = null; + LayoutManager childLM; LayoutContext lc = new LayoutContext(0); LayoutManager firstLM = null; LayoutManager lastLM = null; @@ -141,8 +141,8 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { } if (pos instanceof NonLeafPosition) { // pos was created by a child of this ListBlockLM - positionList.add(((NonLeafPosition) pos).getPosition()); - lastLM = ((NonLeafPosition) pos).getPosition().getLM(); + positionList.add(pos.getPosition()); + lastLM = pos.getPosition().getLM(); if (firstLM == null) { firstLM = lastLM; } @@ -172,7 +172,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { curBlockArea = null; - getPSLM().notifyEndOfLayout(((AbstractListItemPart)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 5c6e9aeb1..c6b5b8cf9 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -73,8 +73,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager private LinkedList labelList = null; private LinkedList bodyList = null; - private int listItemHeight; - private boolean discardBorderBefore; private boolean discardBorderAfter; private boolean discardPaddingBefore; @@ -84,7 +82,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager private boolean keepWithNextPendingOnLabel; private boolean keepWithNextPendingOnBody; - + + private int listItemHeight; + private class ListItemPosition extends Position { private int iLabelFirstIndex; private int iLabelLastIndex; @@ -307,12 +307,12 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int additionalPenaltyHeight = 0; KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]); if (endEl instanceof KnuthPenalty) { - additionalPenaltyHeight = ((KnuthPenalty)endEl).getW(); + additionalPenaltyHeight = endEl.getW(); } endEl = (KnuthElement)elementLists[1].get(end[1]); if (endEl instanceof KnuthPenalty) { additionalPenaltyHeight = Math.max( - additionalPenaltyHeight, ((KnuthPenalty)endEl).getW()); + additionalPenaltyHeight, endEl.getW()); } int boxHeight = step - addedBoxHeight - penaltyHeight; @@ -419,10 +419,10 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager // body // "unwrap" the Positions stored in the elements ListIterator oldListIterator = oldList.listIterator(); - KnuthElement oldElement = null; + KnuthElement oldElement; while (oldListIterator.hasNext()) { oldElement = (KnuthElement)oldListIterator.next(); - Position innerPosition = ((NonLeafPosition) oldElement.getPosition()).getPosition(); + Position innerPosition = oldElement.getPosition().getPosition(); //log.debug(" BLM> unwrapping: " + (oldElement.isBox() // ? "box " : (oldElement.isGlue() ? "glue " : "penalty")) // + " creato da " + oldElement.getLayoutManager().getClass().getName()); @@ -465,7 +465,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(getListItemFO().getId()); + addId(); LayoutContext lc = new LayoutContext(0); Position firstPos = null; @@ -484,7 +484,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } if (pos instanceof NonLeafPosition && pos.getPosition() != null) { // pos contains a ListItemPosition created by this ListBlockLM - positionList.add(((NonLeafPosition) pos).getPosition()); + positionList.add(pos.getPosition()); } } @@ -560,7 +560,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(((ListItem)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index 6d2e49e96..2e5bbdf1f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -23,7 +23,6 @@ import org.apache.fop.fo.flow.table.TableAndCaption; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -36,8 +35,7 @@ import org.apache.fop.area.Block; * @todo Implement getNextKnuthElements() */ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { - private TableAndCaption fobj; - + private Block curBlockArea; //private List childBreaks = new java.util.ArrayList(); @@ -48,7 +46,6 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { */ public TableAndCaptionLayoutManager(TableAndCaption node) { super(node); - fobj = node; } /** @@ -134,7 +131,7 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(fobj.getId()); + addId(); /* TODO: Reimplement using Knuth approach LayoutManager childLM; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 4c21df937..674fd9a90 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -23,7 +23,6 @@ import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.Position; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -34,7 +33,6 @@ import org.apache.fop.area.Block; * @todo Implement getNextKnuthElements() */ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { - private TableCaption fobj; private Block curBlockArea; @@ -46,7 +44,6 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { */ public TableCaptionLayoutManager(TableCaption node) { super(node); - fobj = node; } /** @@ -133,7 +130,7 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(fobj.getId()); + addId(); /* TODO: Reimplement using Knuth approach LayoutManager childLM; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index df23838f9..8acfebca0 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -136,7 +136,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager cellIPD = referenceIPD; cellIPD -= getIPIndents(); - LinkedList returnedList = null; + LinkedList returnedList; LinkedList contentList = new LinkedList(); LinkedList returnList = new LinkedList(); @@ -242,7 +242,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager p.setP(0); } - getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); setFinished(true); return returnList; @@ -330,7 +330,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager int firstRowHeight) { getParentArea(null); - getPSLM().addIDToPage(getTableCell().getId()); + addId(); int borderBeforeWidth = primaryGridUnit.getBeforeBorderWidth(startRow, borderBeforeWhich); int borderAfterWidth = primaryGridUnit.getAfterBorderWidth(endRow, borderAfterWhich); @@ -419,7 +419,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager int dx = xoffset; for (int x = 0; x < gridUnits.length; x++) { int ipd = getTable().getColumn(primaryGridUnit.getColIndex() + x) - .getColumnWidth().getValue((PercentBaseContext) getParent()); + .getColumnWidth().getValue(getParent()); if (blocks[y][x] != null) { Block block = blocks[y][x]; adjustYOffset(block, dy); @@ -491,7 +491,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager Block rowBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); ((TableLayoutManager) parentLM).addBackgroundArea(rowBackgroundArea); TraitSetter.addBackground(rowBackgroundArea, row.getCommonBorderPaddingBackground(), - (TableLayoutManager) parentLM, + parentLM, -xoffset - startIndent, -borderBeforeWidth, parentLM.getContentAreaIPD(), firstRowHeight); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 0b3967643..d6bba5cb5 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -233,7 +233,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager // Elements for the table-header/footer/body - LinkedList contentKnuthElements = null; + LinkedList contentKnuthElements; contentLM = new TableContentLayoutManager(this); LayoutContext childLC = new LayoutContext(0); /* @@ -319,7 +319,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(getTable().getId()); + addId(); // add space before, in order to implement display-align = "center" or "after" if (layoutContext.getSpaceBefore() != 0) { @@ -379,7 +379,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager resetSpaces(); curBlockArea = null; - getPSLM().notifyEndOfLayout(((Table)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** -- cgit v1.2.3 From a32194e7187ef54492d5918e624114b18e35ac5b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 27 Mar 2008 08:49:41 +0000 Subject: Added support for addressing all glyphs available in a Type 1 font, not just the ones in the font's primary encoding. Typeface: getEncoding() changed to getEncodingName() to make clearer what is held here. Some cleanup in the font classes to put the various things in more appropriate places. Created a common base class for all Base 14 fonts (makes the hierarchy clearer). Made PDFTextUtil more universally useful and made use of it in PDFRenderer, too. Made PDFStream.add(String) more efficient. The encoding converter is not called for each invocation anymore as the whole thing get buffered by a BufferedWriter (as suggested by the javadoc of OutputStreamWriter). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@641742 13f79535-47bb-0310-9956-ffa450edef68 --- fop.bat | 2 +- lib/xmlgraphics-commons-1.3.jar | Bin 509244 -> 0 bytes lib/xmlgraphics-commons-1.4svn.jar | Bin 0 -> 511830 bytes src/codegen/fonts/font-file.xsl | 6 +- .../fop/fo/properties/CommonHyphenation.java | 5 +- .../apache/fop/fonts/AbstractCodePointMapping.java | 23 +- src/java/org/apache/fop/fonts/Base14Font.java | 27 ++ src/java/org/apache/fop/fonts/CIDFont.java | 31 +-- src/java/org/apache/fop/fonts/CIDSubset.java | 177 +++++++++++++ src/java/org/apache/fop/fonts/Font.java | 2 +- src/java/org/apache/fop/fonts/LazyFont.java | 24 +- src/java/org/apache/fop/fonts/MultiByteFont.java | 156 +++-------- src/java/org/apache/fop/fonts/NamedCharacter.java | 142 ++++++++++ .../apache/fop/fonts/SimpleSingleByteEncoding.java | 145 ++++++++++ .../org/apache/fop/fonts/SingleByteEncoding.java | 50 ++++ src/java/org/apache/fop/fonts/SingleByteFont.java | 214 +++++++++++++-- src/java/org/apache/fop/fonts/Typeface.java | 7 +- .../apache/fop/fonts/truetype/TTFSubSetFile.java | 19 +- .../org/apache/fop/fonts/type1/AFMCharMetrics.java | 46 ++-- src/java/org/apache/fop/fonts/type1/AFMFile.java | 12 +- src/java/org/apache/fop/fonts/type1/AFMParser.java | 17 +- .../apache/fop/fonts/type1/Type1FontLoader.java | 33 ++- src/java/org/apache/fop/pdf/PDFCMap.java | 5 +- src/java/org/apache/fop/pdf/PDFEncoding.java | 8 + src/java/org/apache/fop/pdf/PDFFactory.java | 133 +++++++--- src/java/org/apache/fop/pdf/PDFResources.java | 2 +- src/java/org/apache/fop/pdf/PDFStream.java | 38 ++- src/java/org/apache/fop/pdf/PDFTTFStream.java | 2 +- src/java/org/apache/fop/pdf/PDFTextUtil.java | 295 +++++++++++++++++++++ .../apache/fop/render/afp/fonts/OutlineFont.java | 7 +- .../apache/fop/render/afp/fonts/RasterFont.java | 8 +- .../fop/render/java2d/CustomFontMetricsMapper.java | 2 +- .../fop/render/java2d/SystemFontMetricsMapper.java | 2 +- .../fop/render/pdf/PDFGraphics2DAdapter.java | 4 +- .../org/apache/fop/render/pdf/PDFRenderer.java | 258 +++++++----------- src/java/org/apache/fop/render/ps/PSFontUtils.java | 128 ++++++++- src/java/org/apache/fop/render/ps/PSRenderer.java | 91 +++++-- src/java/org/apache/fop/svg/PDFGraphics2D.java | 11 +- src/java/org/apache/fop/svg/PDFTextPainter.java | 11 +- src/java/org/apache/fop/svg/PDFTextUtil.java | 231 ++-------------- status.xml | 8 +- .../apache/fop/render/pdf/PDFEncodingTestCase.java | 6 +- 42 files changed, 1640 insertions(+), 748 deletions(-) delete mode 100644 lib/xmlgraphics-commons-1.3.jar create mode 100644 lib/xmlgraphics-commons-1.4svn.jar create mode 100644 src/java/org/apache/fop/fonts/Base14Font.java create mode 100644 src/java/org/apache/fop/fonts/CIDSubset.java create mode 100644 src/java/org/apache/fop/fonts/NamedCharacter.java create mode 100644 src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java create mode 100644 src/java/org/apache/fop/fonts/SingleByteEncoding.java create mode 100644 src/java/org/apache/fop/pdf/PDFTextUtil.java (limited to 'src') diff --git a/fop.bat b/fop.bat index 119b2e2f8..c2444a083 100644 --- a/fop.bat +++ b/fop.bat @@ -61,7 +61,7 @@ set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xercesImpl-2.7.1.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xalan-2.7.0.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\serializer-2.7.0.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\batik-all-1.7.jar -set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xmlgraphics-commons-1.3.jar +set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xmlgraphics-commons-1.4svn.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\avalon-framework-4.2.0.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-io-1.3.1.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-logging-1.0.4.jar diff --git a/lib/xmlgraphics-commons-1.3.jar b/lib/xmlgraphics-commons-1.3.jar deleted file mode 100644 index df8773460..000000000 Binary files a/lib/xmlgraphics-commons-1.3.jar and /dev/null differ diff --git a/lib/xmlgraphics-commons-1.4svn.jar b/lib/xmlgraphics-commons-1.4svn.jar new file mode 100644 index 000000000..cb386bd59 Binary files /dev/null and b/lib/xmlgraphics-commons-1.4svn.jar differ diff --git a/src/codegen/fonts/font-file.xsl b/src/codegen/fonts/font-file.xsl index dbca3eba5..21a6507b8 100644 --- a/src/codegen/fonts/font-file.xsl +++ b/src/codegen/fonts/font-file.xsl @@ -40,10 +40,10 @@ import java.util.Map; import java.util.Set; import org.apache.fop.fonts.FontType; -import org.apache.fop.fonts.Typeface; +import org.apache.fop.fonts.Base14Font; import org.apache.fop.fonts.CodePointMapping; -public class extends Typeface { +public class extends Base14Font { private final static String fontName = ""; private final static String fullName = ""; private final static Set familyNames; @@ -84,7 +84,7 @@ public class extends Typeface { this.enableKerning = enableKerning; } - public String getEncoding() { + public String getEncodingName() { return encoding; } diff --git a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java index 26747c24d..f47ddbe0c 100644 --- a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java +++ b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java @@ -21,6 +21,7 @@ package org.apache.fop.fo.properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.Constants; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; @@ -142,7 +143,7 @@ public final class CommonHyphenation { FontMetrics metrics = font.getFontMetrics(); if (metrics instanceof Typeface) { Typeface typeface = (Typeface)metrics; - if ("SymbolEncoding".equals(typeface.getEncoding())) { + if ("SymbolEncoding".equals(typeface.getEncodingName())) { //SymbolEncoding doesn't have HYPHEN_MINUS, so replace by MINUS_SIGN } else { //only warn if the encoding is not SymbolEncoding @@ -154,7 +155,7 @@ public final class CommonHyphenation { FontMetrics metrics = font.getFontMetrics(); if (metrics instanceof Typeface) { Typeface typeface = (Typeface)metrics; - if ("ZapfDingbatsEncoding".equals(typeface.getEncoding())) { + if ("ZapfDingbatsEncoding".equals(typeface.getEncodingName())) { //ZapfDingbatsEncoding doesn't have HYPHEN_MINUS, so replace by ' ' } else { //only warn if the encoding is not ZapfDingbatsEncoding diff --git a/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java b/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java index 91d13da85..3a2ac5022 100644 --- a/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java +++ b/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java @@ -29,7 +29,7 @@ import org.apache.fop.util.CharUtilities; /** * Abstract base class for code point mapping classes (1-byte character encodings). */ -public class AbstractCodePointMapping { +public class AbstractCodePointMapping implements SingleByteEncoding { private String name; private char[] latin1Map; @@ -114,19 +114,12 @@ public class AbstractCodePointMapping { } } - /** - * Returns the encoding's name. - * @return the name of the encoding - */ + /** {@inheritDoc} */ public String getName() { return this.name; } - /** - * Maps a Unicode character to a code point in the encoding. - * @param c the Unicode character to map - * @return the coid point in the encoding or 0 (=.notdef) if not found - */ + /** {@inheritDoc} */ public final char mapChar(char c) { if (c < 256) { char latin1 = latin1Map[c]; @@ -172,8 +165,8 @@ public class AbstractCodePointMapping { } } - putFallbackCharacter(c, '\0'); - return 0; + putFallbackCharacter(c, NOT_FOUND_CODE_POINT); + return NOT_FOUND_CODE_POINT; } private void putFallbackCharacter(char c, char mapTo) { @@ -227,11 +220,7 @@ public class AbstractCodePointMapping { return -1; } - /** - * Returns the array of character names for this encoding. - * @return the array of character names - * (unmapped code points are represented by a ".notdef" value) - */ + /** {@inheritDoc} */ public String[] getCharNameMap() { if (this.charNameMap != null) { String[] copy = new String[this.charNameMap.length]; diff --git a/src/java/org/apache/fop/fonts/Base14Font.java b/src/java/org/apache/fop/fonts/Base14Font.java new file mode 100644 index 000000000..26c11e72b --- /dev/null +++ b/src/java/org/apache/fop/fonts/Base14Font.java @@ -0,0 +1,27 @@ +/* + * 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.fonts; + +/** + * Base class for all Base 14 fonts. + */ +public abstract class Base14Font extends Typeface { + +} diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java index c554d2165..1a7e1b0e3 100644 --- a/src/java/org/apache/fop/fonts/CIDFont.java +++ b/src/java/org/apache/fop/fonts/CIDFont.java @@ -20,31 +20,14 @@ package org.apache.fop.fonts; //Java -import java.util.Map; /** * Abstract base class for CID fonts. */ public abstract class CIDFont extends CustomFont { - /** - * usedGlyphs contains orginal, new glyph index - */ - public Map usedGlyphs = new java.util.HashMap(); - - /** - * usedGlyphsIndex contains new glyph, original index - */ - public Map usedGlyphsIndex = new java.util.HashMap(); - public int usedGlyphsCount = 0; - - /** - * usedCharsIndex contains new glyph, original char - */ - public Map usedCharsIndex = new java.util.HashMap(); - - //private PDFWArray warray = new PDFWArray(); - public int width[] = null; + /** Contains the character widths for all characters in the font */ + protected int[] width = null; // ---- Required ---- /** @@ -73,6 +56,11 @@ public abstract class CIDFont extends CustomFont { */ public abstract int getSupplement(); + /** + * Returns the subset information for this font. + * @return the subset information + */ + public abstract CIDSubset getCIDSubset(); // ---- Optional ---- /** @@ -88,9 +76,4 @@ public abstract class CIDFont extends CustomFont { return true; } - /** - * Returns a char array containing all Unicode characters that have been accessed. - * @return a char array with all used Unicode characters - */ - public abstract char[] getCharsUsed(); } \ No newline at end of file diff --git a/src/java/org/apache/fop/fonts/CIDSubset.java b/src/java/org/apache/fop/fonts/CIDSubset.java new file mode 100644 index 000000000..6bcfc0b71 --- /dev/null +++ b/src/java/org/apache/fop/fonts/CIDSubset.java @@ -0,0 +1,177 @@ +/* + * 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.fonts; + +import java.util.BitSet; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; + +import org.apache.fop.util.CharUtilities; + +//Naming: +//glyph index: original index of the glyph in the non-subset font (!= unicode index) +//character selector: index into a set of glyphs. For subset CID fonts, this starts at 0. For +// non-subset fonts, this is the same as the glyph index. +//Unicode index: The Unicode codepoint of a character. +//Glyph name: the Adobe glyph name (as found in Glyphs.java) + +/** + * Keeps track of the glyphs used in a document. This information is later used to build + * a subset of a font. + */ +public class CIDSubset { + + /** + * usedGlyphs contains orginal, new glyph index (glyph index -> char selector) + */ + private Map/**/ usedGlyphs = new java.util.HashMap(); + + /** + * usedGlyphsIndex contains new glyph, original index (char selector -> glyph index) + */ + private Map/**/ usedGlyphsIndex = new java.util.HashMap(); + private int usedGlyphsCount = 0; + + /** + * usedCharsIndex contains new glyph, original char (char selector -> Unicode) + */ + private Map/**/ usedCharsIndex = new java.util.HashMap(); + + public CIDSubset() { + } + + /** + * Adds the initial 3 glyphs which are the same for all CID subsets. + */ + public void setupFirstThreeGlyphs() { + // Make sure that the 3 first glyphs are included + usedGlyphs.put(new Integer(0), new Integer(0)); + usedGlyphsIndex.put(new Integer(0), new Integer(0)); + usedGlyphsCount++; + usedGlyphs.put(new Integer(1), new Integer(1)); + usedGlyphsIndex.put(new Integer(1), new Integer(1)); + usedGlyphsCount++; + usedGlyphs.put(new Integer(2), new Integer(2)); + usedGlyphsIndex.put(new Integer(2), new Integer(2)); + usedGlyphsCount++; + } + + /** + * Returns the original index of the glyph inside the (non-subset) font's glyph list. This + * index can be used to access the character width information, for example. + * @param subsetIndex the subset index (character selector) to access the glyph + * @return the original index (or -1 if no glyph index is available for the subset index) + */ + public int getGlyphIndexForSubsetIndex(int subsetIndex) { + Integer glyphIndex = (Integer)usedGlyphsIndex.get(new Integer(subsetIndex)); + if (glyphIndex != null) { + return glyphIndex.intValue(); + } else { + return -1; + } + } + + /** + * Returns the Unicode value for a subset index (character selector). If there's no such + * Unicode value, the "NOT A CHARACTER" (0xFFFF) is returned. + * @param subsetIndex the subset index (character selector) + * @return the Unicode value or "NOT A CHARACTER" (0xFFFF) + */ + public char getUnicodeForSubsetIndex(int subsetIndex) { + Character mapValue = (Character)usedCharsIndex.get(new Integer(subsetIndex)); + if (mapValue != null) { + return mapValue.charValue(); + } else { + return CharUtilities.NOT_A_CHARACTER; + } + } + + /** + * Maps a character to a character selector for a font subset. If the character isn't in the + * subset, yet, it is added and a new character selector returned. Otherwise, the already + * allocated character selector is returned from the existing map/subset. + * @param glyphIndex the glyph index of the character + * @param unicode the Unicode index of the character + * @return the subset index + */ + public int mapSubsetChar(int glyphIndex, char unicode) { + // Reencode to a new subset font or get the reencoded value + // IOW, accumulate the accessed characters and build a character map for them + Integer subsetCharSelector = (Integer)usedGlyphs.get(new Integer(glyphIndex)); + if (subsetCharSelector == null) { + int selector = usedGlyphsCount; + usedGlyphs.put(new Integer(glyphIndex), + new Integer(selector)); + usedGlyphsIndex.put(new Integer(selector), + new Integer(glyphIndex)); + usedCharsIndex.put(new Integer(selector), + new Character(unicode)); + usedGlyphsCount++; + return selector; + } else { + return subsetCharSelector.intValue(); + } + } + + /** + * Returns an unmodifiable Map of the font subset. It maps from glyph index to + * character selector (i.e. the subset index in this case). + * @return Map Map<Integer, Integer> of the font subset + */ + public Map/**/ getSubsetGlyphs() { + return Collections.unmodifiableMap(this.usedGlyphs); + } + + /** + * Returns a char array containing all Unicode characters that are in the subset. + * @return a char array with all used Unicode characters + */ + public char[] getSubsetChars() { + char[] charArray = new char[usedGlyphsCount]; + for (int i = 0; i < usedGlyphsCount; i++) { + charArray[i] = getUnicodeForSubsetIndex(i); + } + return charArray; + } + + /** + * Returns the number of glyphs in the subset. + * @return the number of glyphs in the subset + */ + public int getSubsetSize() { + return this.usedGlyphsCount; + } + + /** + * Returns a BitSet with bits set for each available glyph index. + * @return a BitSet indicating available glyph indices + */ + public BitSet getGlyphIndexBitSet() { + BitSet bitset = new BitSet(); + Iterator iter = usedGlyphs.keySet().iterator(); + while (iter.hasNext()) { + Integer cid = (Integer)iter.next(); + bitset.set(cid.intValue()); + } + return bitset; + } + +} diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index e123513c2..ff71434c6 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -199,7 +199,7 @@ public class Font { // Use default CodePointMapping char d = CodePointMapping.getMapping("WinAnsiEncoding").mapChar(c); - if (d != 0) { + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { c = d; } else { log.warn("Glyph " + (int) c + " not available in font " + fontName); diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index e6ed7e881..8997069d4 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -64,11 +64,10 @@ public class LazyFont extends Typeface implements FontDescriptor { this.resolver = resolver; } - /** - * String representation of LazyFont - */ + /** {@inheritDoc} */ public String toString() { - return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath + ", kerning=" + useKerning ); + return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath + + ", kerning=" + useKerning ); } private void load(boolean fail) { @@ -80,8 +79,9 @@ public class LazyFont extends Typeface implements FontDescriptor { if (resolver != null) { Source source = resolver.resolve(metricsFileName); if (source == null) { - String err = "Cannot load font: failed to create Source from metrics file " - + metricsFileName; + String err + = "Cannot load font: failed to create Source from metrics file " + + metricsFileName; if (fail) { throw new RuntimeException(err); } else { @@ -112,8 +112,8 @@ public class LazyFont extends Typeface implements FontDescriptor { src.setSystemId(source.getSystemId()); reader = new FontReader(src); } else { - reader - = new FontReader(new InputSource(new URL(metricsFileName).openStream())); + reader = new FontReader(new InputSource( + new URL(metricsFileName).openStream())); } reader.setKerningEnabled(useKerning); reader.setFontEmbedPath(fontEmbedPath); @@ -153,12 +153,10 @@ public class LazyFont extends Typeface implements FontDescriptor { } // ---- Font ---- - /** - * {@inheritDoc} - */ - public String getEncoding() { + /** {@inheritDoc} */ + public String getEncodingName() { load(true); - return realFont.getEncoding(); + return realFont.getEncodingName(); } /** diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index e40c40985..5849379bd 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -39,6 +39,9 @@ public class MultiByteFont extends CIDFont { private String namePrefix = null; // Quasi unique prefix + private CIDSubset subset = new CIDSubset(); + + /** A map from Unicode indices to glyph indices */ private BFEntry[] bfentries = null; /** @@ -46,15 +49,7 @@ public class MultiByteFont extends CIDFont { */ public MultiByteFont() { // Make sure that the 3 first glyphs are included - usedGlyphs.put(new Integer(0), new Integer(0)); - usedGlyphsIndex.put(new Integer(0), new Integer(0)); - usedGlyphsCount++; - usedGlyphs.put(new Integer(1), new Integer(1)); - usedGlyphsIndex.put(new Integer(1), new Integer(1)); - usedGlyphsCount++; - usedGlyphs.put(new Integer(2), new Integer(2)); - usedGlyphsIndex.put(new Integer(2), new Integer(2)); - usedGlyphsCount++; + subset.setupFirstThreeGlyphs(); // Create a quasiunique prefix for fontname synchronized (this.getClass()) { @@ -77,37 +72,27 @@ public class MultiByteFont extends CIDFont { setFontType(FontType.TYPE0); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getDefaultWidth() { return defaultWidth; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getRegistry() { return "Adobe"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getOrdering() { return "UCS"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getSupplement() { return 0; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public CIDFontType getCIDType() { return cidType; } @@ -133,68 +118,47 @@ public class MultiByteFont extends CIDFont { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean isEmbeddable() { return !(getEmbedFileName() == null && getEmbedResourceName() == null); } - /** - * {@inheritDoc} - */ - public String getEncoding() { + /** {@inheritDoc} */ + public CIDSubset getCIDSubset() { + return this.subset; + } + + /** {@inheritDoc} */ + public String getEncodingName() { return encoding; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getWidth(int i, int size) { if (isEmbeddable()) { - Integer idx = (Integer)usedGlyphsIndex.get(new Integer(i)); - return size * width[idx.intValue()]; + int glyphIndex = subset.getGlyphIndexForSubsetIndex(i); + return size * width[glyphIndex]; } else { return size * width[i]; } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int[] getWidths() { int[] arr = new int[width.length]; System.arraycopy(width, 0, arr, 0, width.length - 1); - /* - for (int i = 0; i < arr.length; i++) - arr[i] *= size; - */ return arr; } /** - * Remaps a codepoint based. - * @param i codepoint to remap - * @return new codepoint + * Returns the glyph index for a Unicode character. The method returns 0 if there's no + * such glyph in the character map. + * @param c the Unicode character index + * @return the glyph index (or 0 if the glyph is not available) */ -/* unused - public Integer reMap(Integer i) { - if (isEmbeddable()) { - Integer ret = (Integer)usedGlyphsIndex.get(i); - if (ret == null) { - ret = i; - } - return ret; - } else { - return i; - } - - } -*/ - private int findGlyphIndex(char c) { int idx = (int)c; - int retIdx = 0; + int retIdx = 0; //.notdef for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) { if (bfentries[i].getUnicodeStart() <= idx @@ -208,48 +172,30 @@ public class MultiByteFont extends CIDFont { return retIdx; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public char mapChar(char c) { notifyMapOperation(); - int retIdx = findGlyphIndex(c); + int glyphIndex = findGlyphIndex(c); if (isEmbeddable()) { - // Reencode to a new subset font or get - // the reencoded value - Integer newIdx = (Integer)usedGlyphs.get(new Integer(retIdx)); - if (newIdx == null) { - usedGlyphs.put(new Integer(retIdx), - new Integer(usedGlyphsCount)); - usedGlyphsIndex.put(new Integer(usedGlyphsCount), - new Integer(retIdx)); - usedCharsIndex.put(new Integer(usedGlyphsCount), - new Integer((int) c)); - retIdx = usedGlyphsCount; - usedGlyphsCount++; - } else { - retIdx = newIdx.intValue(); - } + glyphIndex = subset.mapSubsetChar(glyphIndex, c); } - return (char)retIdx; + return (char)glyphIndex; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean hasChar(char c) { return (findGlyphIndex(c) > 0); } - /** - * Sets the bfentries. - * @param bfentries The bfentries to set + * Sets the array of BFEntry instances which constitutes the Unicode to glyph index map for + * a font. ("BF" means "base font") + * @param entries the Unicode to glyph index map */ - public void setBFEntries(BFEntry[] bfentries) { - this.bfentries = bfentries; + public void setBFEntries(BFEntry[] entries) { + this.bfentries = entries; } /** @@ -276,17 +222,6 @@ public class MultiByteFont extends CIDFont { this.ttcName = ttcName; } - /** - * Adds a new CID width entry to the font. - * @param cidWidthIndex index - * @param wds array of widths - */ - /* - public void addCIDWidthEntry(int cidWidthIndex, int[] wds) { - this.warray.addEntry(cidWidthIndex, wds); - }*/ - - /** * Sets the width array. * @param wds array of widths. @@ -300,30 +235,15 @@ public class MultiByteFont extends CIDFont { * @return Map Map of used Glyphs */ public Map getUsedGlyphs() { - return usedGlyphs; + return subset.getSubsetGlyphs(); } - /** The invalid Unicode character, suitable as a return value in methods - * that need to return an invalid character. */ - public static final char INVALID_UNICODE_CHAR = 0xFFFF; - /** {@inheritDoc} */ public char[] getCharsUsed() { if (!isEmbeddable()) { return null; } - char[] charArray = new char[usedGlyphsCount]; - for (int i = 0; i < usedGlyphsCount; i++) { - Integer mapValue = (Integer)usedCharsIndex.get(new Integer(i)); - if (mapValue != null) { - char arrayItem = (char) mapValue.intValue(); - charArray[i] = arrayItem; - } - else { - charArray[i] = INVALID_UNICODE_CHAR; - } - } - return charArray; + return subset.getSubsetChars(); } } diff --git a/src/java/org/apache/fop/fonts/NamedCharacter.java b/src/java/org/apache/fop/fonts/NamedCharacter.java new file mode 100644 index 000000000..2c8007ba1 --- /dev/null +++ b/src/java/org/apache/fop/fonts/NamedCharacter.java @@ -0,0 +1,142 @@ +/* + * 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.fonts; + +import org.apache.xmlgraphics.fonts.Glyphs; + +import org.apache.fop.util.CharUtilities; + +/** + * Represents an named character with character name (from the Adobe glyph list) and a Unicode + * sequence that this character represents. + */ +public class NamedCharacter { + + private String charName; + private String unicodeSequence; + + /** + * Main constructor. + * @param charName the character name + * @param unicodeSequence the Unicode sequence associated with this character + */ + public NamedCharacter(String charName, String unicodeSequence) { + if (charName == null) { + throw new NullPointerException("charName must not be null"); + } + this.charName = charName; + if (unicodeSequence != null) { + this.unicodeSequence = unicodeSequence; + } else { + this.unicodeSequence = Glyphs.getUnicodeSequenceForGlyphName(charName); + } + } + + /** + * Simple constructor. + * @param charName the character name + */ + public NamedCharacter(String charName) { + this(charName, null); + } + + /** {@inheritDoc} */ + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((charName == null) ? 0 : charName.hashCode()); + return result; + } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final NamedCharacter other = (NamedCharacter)obj; + return charName.equals(other.charName); + } + + /** + * Returns the character name (as defined by the Adobe glyph list). + * @return the character name + */ + public String getName() { + return this.charName; + } + + /** + * Returns the Unicode sequence associated with this character. + * @return the Unicode sequence (or null if no Unicode sequence is associated) + */ + public String getUnicodeSequence() { + return this.unicodeSequence; + } + + /** + * Indicates whether a single Unicode value is associated with this character. + * @return true if exactly one Unicode value is associated with this character, false otherwise + */ + public boolean hasSingleUnicodeValue() { + return (this.unicodeSequence != null && this.unicodeSequence.length() == 1); + } + + /** + * Returns the single Unicode value associated with this named character. Check + * {@link #hasSingleUnicodeValue()} before you call this method because an + * IllegalStateException is thrown is a Unicode sequence with more than one character is + * associated with this character. + * @return the single Unicode value (or FFFF ("NOT A CHARACTER") if no Unicode value is + * available) + * @throws IllegalStateException if a Unicode sequence with more than one value is associated + * with the named character + */ + public char getSingleUnicodeValue() throws IllegalStateException { + if (this.unicodeSequence == null) { + return CharUtilities.NOT_A_CHARACTER; + } + if (this.unicodeSequence.length() > 1) { + throw new IllegalStateException("getSingleUnicodeValue() may not be called for a" + + " named character that has more than one Unicode value (a sequence)" + + " associated with the named character!"); + } + return this.unicodeSequence.charAt(0); + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(this.unicodeSequence); + sb.append(" ("); + if (this.unicodeSequence != null) { + for (int i = 0, c = this.unicodeSequence.length(); i < c; i++) { + sb.append("0x").append(Integer.toHexString(this.unicodeSequence.charAt(0))); + } + sb.append(", "); + } + sb.append(getName()).append(')'); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java b/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java new file mode 100644 index 000000000..a5ba1a33b --- /dev/null +++ b/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java @@ -0,0 +1,145 @@ +/* + * 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.fonts; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.xmlgraphics.fonts.Glyphs; + +/** + * A simple implementation of the OneByteEncoding mostly used for encodings that are constructed + * on-the-fly. + */ +public class SimpleSingleByteEncoding implements SingleByteEncoding { + + private String name; + private List mapping = new java.util.ArrayList(); + //List + private Map charMap = new java.util.HashMap(); + //Map + + /** + * Main constructor. + * @param name the encoding's name + */ + public SimpleSingleByteEncoding(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + public String getName() { + return this.name; + } + + /** {@inheritDoc} */ + public char mapChar(char c) { + Character nc = (Character)charMap.get(new Character(c)); + if (nc != null) { + return nc.charValue(); + } + return NOT_FOUND_CODE_POINT; + } + + /** {@inheritDoc} */ + public String[] getCharNameMap() { + String[] map = new String[getSize()]; + Arrays.fill(map, Glyphs.NOTDEF); + for (int i = getFirstChar(); i <= getLastChar(); i++) { + NamedCharacter ch = (NamedCharacter)this.mapping.get(i - 1); + map[i] = ch.getName(); + } + return map; + } + + /** + * Returns the index of the first defined character. + * @return the index of the first defined character (always 1 for this class) + */ + public int getFirstChar() { + return 1; + } + + /** + * Returns the index of the last defined character. + * @return the index of the last defined character + */ + public int getLastChar() { + return this.mapping.size(); + } + + /** + * Returns the number of characters defined by this encoding. + * @return the number of characters + */ + public int getSize() { + return this.mapping.size() + 1; + } + + /** + * Indicates whether the encoding is full (with 256 code points). + * @return true if the encoding is full + */ + public boolean isFull() { + return (getSize() == 256); + } + + /** + * Adds a new character to the encoding. + * @param ch the named character + * @return the code point assigned to the character + */ + public char addCharacter(NamedCharacter ch) { + if (!ch.hasSingleUnicodeValue()) { + throw new IllegalArgumentException("Only NamedCharacters with a single Unicode value" + + " are currently supported!"); + } + if (isFull()) { + throw new IllegalStateException("Encoding is full!"); + } + char newSlot = (char)(getLastChar() + 1); + this.mapping.add(ch); + this.charMap.put(new Character(ch.getSingleUnicodeValue()), new Character(newSlot)); + return newSlot; + } + + /** + * Returns the named character at a given code point in the encoding. + * @param codePoint the code point of the character + * @return the NamedCharacter (or null if no character is at this position) + */ + public NamedCharacter getCharacterForIndex(int codePoint) { + if (codePoint < 0 || codePoint > 255) { + throw new IllegalArgumentException("codePoint must be between 0 and 255"); + } + if (codePoint <= getLastChar()) { + return (NamedCharacter)this.mapping.get(codePoint - 1); + } else { + return null; + } + } + + /** {@inheritDoc} */ + public String toString() { + return getName() + " (" + getSize() + " chars)"; + } + +} diff --git a/src/java/org/apache/fop/fonts/SingleByteEncoding.java b/src/java/org/apache/fop/fonts/SingleByteEncoding.java new file mode 100644 index 000000000..ac7241e24 --- /dev/null +++ b/src/java/org/apache/fop/fonts/SingleByteEncoding.java @@ -0,0 +1,50 @@ +/* + * 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.fonts; + +/** + * The interface defines a 1-byte character encoding (with 256 characters). + */ +public interface SingleByteEncoding { + + /** Code point that is used if no code point for a specific character has been found. */ + char NOT_FOUND_CODE_POINT = '\0'; + + /** + * Returns the encoding's name. + * @return the name of the encoding + */ + String getName(); + + /** + * Maps a Unicode character to a code point in the encoding. + * @param c the Unicode character to map + * @return the code point in the encoding or 0 (=.notdef) if not found + */ + char mapChar(char c); + + /** + * Returns the array of character names for this encoding. + * @return the array of character names + * (unmapped code points are represented by a ".notdef" value) + */ + String[] getCharNameMap(); + +} diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index 814d05a2c..ac12b7615 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -19,6 +19,8 @@ package org.apache.fop.fonts; +import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; @@ -31,14 +33,21 @@ import org.apache.xmlgraphics.fonts.Glyphs; */ public class SingleByteFont extends CustomFont { + /** Code point that is used if no code point for a specific character has been found. */ + public static final char NOT_FOUND = '#'; + /** logger */ private static Log log = LogFactory.getLog(SingleByteFont.class); - private CodePointMapping mapping; + private SingleByteEncoding mapping; private int[] width = null; private Set warnedChars; + + private Map unencodedCharacters; + //Map + private List additionalEncodings; /** * Main constructor. @@ -54,7 +63,7 @@ public class SingleByteFont extends CustomFont { } /** {@inheritDoc} */ - public String getEncoding() { + public String getEncodingName() { return this.mapping.getName(); } @@ -62,18 +71,28 @@ public class SingleByteFont extends CustomFont { * Returns the code point mapping (encoding) of this font. * @return the code point mapping */ - public CodePointMapping getCodePointMapping() { + public SingleByteEncoding getEncoding() { return this.mapping; } /** {@inheritDoc} */ public int getWidth(int i, int size) { - int idx = i - getFirstChar(); - if (idx >= 0 && idx < width.length) { - return size * width[i - getFirstChar()]; - } else { - return 0; + if (i < 256) { + int idx = i - getFirstChar(); + if (idx >= 0 && idx < width.length) { + return size * width[i - getFirstChar()]; + } + } else if (this.additionalEncodings != null) { + int encodingIndex = (i / 256) - 1; + SimpleSingleByteEncoding encoding = getAdditionalEncoding(encodingIndex); + int codePoint = i % 256; + NamedCharacter nc = encoding.getCharacterForIndex(codePoint); + UnencodedCharacter uc + = (UnencodedCharacter)this.unencodedCharacters.get( + new Character(nc.getSingleUnicodeValue())); + return size * uc.getWidth(); } + return 0; } /** {@inheritDoc} */ @@ -87,30 +106,80 @@ public class SingleByteFont extends CustomFont { public char mapChar(char c) { notifyMapOperation(); char d = mapping.mapChar(c); - if (d != 0) { + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { return d; - } else { - Character ch = new Character(c); - if (warnedChars == null) { - warnedChars = new java.util.HashSet(); + } + + //Check unencoded characters which are available in the font by character name + d = mapUnencodedChar(c); + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { + return d; + } + + //Give up, character is not available + Character ch = new Character(c); + if (warnedChars == null) { + warnedChars = new java.util.HashSet(); + } + if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { + warnedChars.add(ch); + if (warnedChars.size() == 8) { + log.warn("Many requested glyphs are not available in font " + getFontName()); + } else { + log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) + + ", " + Glyphs.charToGlyphName(c) + + ") not available in font " + getFontName()); } - if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { - warnedChars.add(ch); - if (warnedChars.size() == 8) { - log.warn("Many requested glyphs are not available in font " + getFontName()); - } else { - log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) - + ", " + Glyphs.charToGlyphName(c) - + ") not available in font " + getFontName()); + } + return NOT_FOUND; + } + + private char mapUnencodedChar(char ch) { + if (this.unencodedCharacters != null) { + UnencodedCharacter unencoded + = (UnencodedCharacter)this.unencodedCharacters.get(new Character(ch)); + if (unencoded != null) { + if (this.additionalEncodings == null) { + this.additionalEncodings = new java.util.ArrayList(); + } + SimpleSingleByteEncoding encoding = null; + char mappedStart = 0; + int additionalsCount = this.additionalEncodings.size(); + for (int i = 0; i < additionalsCount; i++) { + mappedStart += 256; + encoding = getAdditionalEncoding(i); + char alt = encoding.mapChar(ch); + if (alt != 0) { + return (char)(mappedStart + alt); + } + } + if (encoding != null && encoding.isFull()) { + encoding = null; } + if (encoding == null) { + encoding = new SimpleSingleByteEncoding( + getFontName() + "EncodingSupp" + (additionalsCount + 1)); + this.additionalEncodings.add(encoding); + mappedStart += 256; + } + return (char)(mappedStart + encoding.addCharacter(unencoded.getCharacter())); } - return '#'; } + return 0; } /** {@inheritDoc} */ public boolean hasChar(char c) { - return (mapping.mapChar(c) > 0); + char d = mapping.mapChar(c); + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { + return true; + } + //Check unencoded characters which are available in the font by character name + d = mapUnencodedChar(c); + if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { + return true; + } + return false; } /* ---- single byte font specific setters --- */ @@ -146,13 +215,106 @@ public class SingleByteFont extends CustomFont { /** * Sets a width for a character. * @param index index of the character - * @param width the width of the character + * @param w the width of the character */ - public void setWidth(int index, int width) { + public void setWidth(int index, int w) { if (this.width == null) { this.width = new int[getLastChar() - getFirstChar() + 1]; } - this.width[index - getFirstChar()] = width; + this.width[index - getFirstChar()] = w; + } + + /** + * Adds an unencoded character (one that is not supported by the primary encoding). + * @param ch the named character + * @param width the width of the character + */ + public void addUnencodedCharacter(NamedCharacter ch, int width) { + if (this.unencodedCharacters == null) { + this.unencodedCharacters = new java.util.HashMap(); + } + if (ch.hasSingleUnicodeValue()) { + UnencodedCharacter uc = new UnencodedCharacter(ch, width); + this.unencodedCharacters.put(new Character(ch.getSingleUnicodeValue()), uc); + } else { + //Cannot deal with unicode sequences, so ignore this character + } + } + + /** + * Indicates whether the encoding has additional encodings besides the primary encoding. + * @return true if there are additional encodings. + */ + public boolean hasAdditionalEncodings() { + return (this.additionalEncodings != null) && (this.additionalEncodings.size() > 0); + } + + /** + * Returns the number of additional encodings this single-byte font maintains. + * @return the number of additional encodings + */ + public int getAdditionalEncodingCount() { + if (hasAdditionalEncodings()) { + return this.additionalEncodings.size(); + } else { + return 0; + } + } + + /** + * Returns an additional encoding. + * @param index the index of the additional encoding + * @return the additional encoding + * @throws IndexOutOfBoundsException if the index is out of bounds + */ + public SimpleSingleByteEncoding getAdditionalEncoding(int index) + throws IndexOutOfBoundsException { + if (hasAdditionalEncodings()) { + return (SimpleSingleByteEncoding)this.additionalEncodings.get(index); + } else { + throw new IndexOutOfBoundsException("No additional encodings available"); + } + } + + /** + * Returns an array with the widths for an additional encoding. + * @param index the index of the additional encoding + * @return the width array + */ + public int[] getAdditionalWidths(int index) { + SimpleSingleByteEncoding enc = getAdditionalEncoding(index); + int[] arr = new int[enc.getLastChar() - enc.getFirstChar() + 1]; + for (int i = 0, c = arr.length; i < c; i++) { + NamedCharacter nc = enc.getCharacterForIndex(enc.getFirstChar() + i); + UnencodedCharacter uc = (UnencodedCharacter)this.unencodedCharacters.get( + new Character(nc.getSingleUnicodeValue())); + arr[i] = uc.getWidth(); + } + return arr; + } + + private static final class UnencodedCharacter { + + private NamedCharacter character; + private int width; + + public UnencodedCharacter(NamedCharacter character, int width) { + this.character = character; + this.width = width; + } + + public NamedCharacter getCharacter() { + return this.character; + } + + public int getWidth() { + return this.width; + } + + /** {@inheritDoc} */ + public String toString() { + return getCharacter().toString(); + } } } diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java index 3bc3be772..173d2e8a3 100644 --- a/src/java/org/apache/fop/fonts/Typeface.java +++ b/src/java/org/apache/fop/fonts/Typeface.java @@ -19,11 +19,8 @@ package org.apache.fop.fonts; -// FOP - - /** - * Base class for PDF font classes + * Base class for font classes */ public abstract class Typeface implements FontMetrics { @@ -37,7 +34,7 @@ public abstract class Typeface implements FontMetrics { * Get the encoding of the font. * @return the encoding */ - public abstract String getEncoding(); + public abstract String getEncodingName(); /** * Map a Unicode character to a code point in the font. diff --git a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java index 99fd10315..d593c4544 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java @@ -592,8 +592,8 @@ public class TTFSubSetFile extends TTFFile { + mtxTab[origIndex.intValue()].getOffset()) < 0) { // origIndex is a composite glyph allComposites.put(origIndex, glyphs.get(origIndex)); - List composites = - getIncludedGlyphs(in, (int)entry.getOffset(), + List composites + = getIncludedGlyphs(in, (int)entry.getOffset(), origIndex); // Iterate through all composites pointed to @@ -651,6 +651,9 @@ public class TTFSubSetFile extends TTFFile { if (!checkTTC(in, name)) { throw new IOException("Failed to read font"); } + + //Copy the Map as we're going to modify it + Map subsetGlyphs = new java.util.HashMap(glyphs); output = new byte[in.getFileSize()]; @@ -661,14 +664,14 @@ public class TTFSubSetFile extends TTFFile { readHorizontalMetrics(in); readIndexToLocation(in); - scanGlyphs(in, glyphs); + scanGlyphs(in, subsetGlyphs); createDirectory(); // Create the TrueType header and directory createHead(in); - createHhea(in, glyphs.size()); // Create the hhea table - createHmtx(in, glyphs); // Create hmtx table - createMaxp(in, glyphs.size()); // copy the maxp table + createHhea(in, subsetGlyphs.size()); // Create the hhea table + createHmtx(in, subsetGlyphs); // Create hmtx table + createMaxp(in, subsetGlyphs.size()); // copy the maxp table boolean optionalTableFound; optionalTableFound = createCvt(in); // copy the cvt table @@ -689,8 +692,8 @@ public class TTFSubSetFile extends TTFFile { log.debug("TrueType: prep table not present. Skipped."); } - createLoca(glyphs.size()); // create empty loca table - createGlyf(in, glyphs); //create glyf table and update loca table + createLoca(subsetGlyphs.size()); // create empty loca table + createGlyf(in, subsetGlyphs); //create glyf table and update loca table pad4(); createCheckSumAdjustment(); diff --git a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java index 1b7f814b8..758078af4 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java +++ b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java @@ -21,6 +21,8 @@ package org.apache.fop.fonts.type1; import java.awt.geom.RectangularShape; +import org.apache.fop.fonts.NamedCharacter; + /** * Holds the metrics of a single character from an AFM file. @@ -28,8 +30,7 @@ import java.awt.geom.RectangularShape; public class AFMCharMetrics { private int charCode = -1; - private String unicodeSequence; - private String charName; + private NamedCharacter character; private double widthX; private double widthY; private RectangularShape bBox; @@ -59,36 +60,45 @@ public class AFMCharMetrics { } /** - * Returns the Unicode sequence for this character. - * @return the Unicode characters - * (or null if no such Unicode sequence exists for this character) + * Returns the named character represented by this instance. + * @return the named character (or null if no named character is associated) */ - public String getUnicodeSequence() { - return this.unicodeSequence; + public NamedCharacter getCharacter() { + return this.character; + } + + /** + * Sets the named character represented by this instance. + * @param ch the named character + */ + public void setCharacter(NamedCharacter ch) { + this.character = ch; } /** - * Sets the Unicode sequence for this character. + * Sets the named character represented by this instance. + * @param charName the character name (as defined in the Adobe glyph list) * @param unicodeSequence the Unicode sequence */ - public void setUnicodeSequence(String unicodeSequence) { - this.unicodeSequence = unicodeSequence; + public void setCharacter(String charName, String unicodeSequence) { + setCharacter(new NamedCharacter(charName, unicodeSequence)); } /** - * Returns the PostScript character name. - * @return the charName + * Returns the Unicode sequence for this character. + * @return the Unicode characters + * (or null if no such Unicode sequence exists for this character) */ - public String getCharName() { - return charName; + public String getUnicodeSequence() { + return (getCharacter() != null ? getCharacter().getUnicodeSequence() : null); } /** - * Sets the PostScript character name. - * @param charName the charName to set + * Returns the PostScript character name. + * @return the charName (or null if no character name is associated) */ - public void setCharName(String charName) { - this.charName = charName; + public String getCharName() { + return (getCharacter() != null ? getCharacter().getName() : null); } /** diff --git a/src/java/org/apache/fop/fonts/type1/AFMFile.java b/src/java/org/apache/fop/fonts/type1/AFMFile.java index b51485485..6a1973843 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMFile.java +++ b/src/java/org/apache/fop/fonts/type1/AFMFile.java @@ -26,7 +26,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.xmlgraphics.fonts.Glyphs; import org.apache.xmlgraphics.java2d.Dimension2DDouble; /** @@ -315,15 +314,8 @@ public class AFMFile { public void addCharMetrics(AFMCharMetrics metrics) { String name = metrics.getCharName(); if (metrics.getUnicodeSequence() == null) { - if (name != null) { - String u = Glyphs.getUnicodeSequenceForGlyphName(metrics.getCharName()); - if (u != null) { - metrics.setUnicodeSequence(u); - } - } else { - //Ignore as no Unicode assignment is possible - return; - } + //Ignore as no Unicode assignment is possible + return; } this.charMetrics.add(metrics); if (name != null) { diff --git a/src/java/org/apache/fop/fonts/type1/AFMParser.java b/src/java/org/apache/fop/fonts/type1/AFMParser.java index bb7ea3d30..2e63ea729 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMParser.java +++ b/src/java/org/apache/fop/fonts/type1/AFMParser.java @@ -31,6 +31,8 @@ import java.util.Stack; import org.apache.commons.io.IOUtils; +import org.apache.fop.fonts.NamedCharacter; + /** * Parses the contents of a Type 1 AFM font metrics file into an object structure ({@link AFMFile}). */ @@ -126,7 +128,7 @@ public class AFMParser { VALUE_PARSERS.put(W, new NotImplementedYet(W)); VALUE_PARSERS.put(W0, new NotImplementedYet(W0)); VALUE_PARSERS.put(W1, new NotImplementedYet(W1)); - VALUE_PARSERS.put(N, new StringSetter("CharName")); + VALUE_PARSERS.put(N, new NamedCharacterSetter("Character")); VALUE_PARSERS.put(B, new CharBBox()); VALUE_PARSERS.put(START_TRACK_KERN, new NotImplementedYet(START_TRACK_KERN)); VALUE_PARSERS.put(END_TRACK_KERN, new NotImplementedYet(END_TRACK_KERN)); @@ -379,6 +381,19 @@ public class AFMParser { } } + private static class NamedCharacterSetter extends BeanSetter { + + public NamedCharacterSetter(String variable) { + super(variable); + } + + public void parse(String line, int startpos, Stack stack) throws IOException { + NamedCharacter ch = new NamedCharacter(getStringValue(line, startpos)); + Object obj = stack.peek(); + setValue(obj, ch); + } + } + private static class NumberSetter extends BeanSetter { public NumberSetter(String variable) { super(variable); diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 473ee9a08..8cf6f2371 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -127,12 +127,17 @@ public class Type1FontLoader extends FontLoader { singleFont.setEmbedFileName(this.fontFileURI); returnFont = singleFont; + handleEncoding(afm, pfm); + handleFontName(afm, pfm); + handleMetrics(afm, pfm); + } + + private void handleEncoding(AFMFile afm, PFMFile pfm) { //Encoding if (afm != null) { String encoding = afm.getEncodingScheme(); if ("AdobeStandardEncoding".equals(encoding)) { - //Use WinAnsi in this case as it better fits the usual character set people need - singleFont.setEncoding(CodePointMapping.WIN_ANSI_ENCODING); + singleFont.setEncoding(CodePointMapping.STANDARD_ENCODING); } else { String effEncodingName; if ("FontSpecific".equals(encoding)) { @@ -147,6 +152,14 @@ public class Type1FontLoader extends FontLoader { CodePointMapping mapping = buildCustomEncoding(effEncodingName, afm); singleFont.setEncoding(mapping); } + List charMetrics = afm.getCharMetrics(); + for (int i = 0, c = afm.getCharCount(); i < c; i++) { + AFMCharMetrics metrics = (AFMCharMetrics)charMetrics.get(i); + if (!metrics.hasCharCode() && metrics.getCharacter() != null) { + singleFont.addUnencodedCharacter(metrics.getCharacter(), + (int)Math.round(metrics.getWidthX())); + } + } } else { if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) { singleFont.setEncoding(pfm.getCharSetName() + "Encoding"); @@ -156,7 +169,9 @@ public class Type1FontLoader extends FontLoader { singleFont.setEncoding("WinAnsiEncoding"); //Try fallback, no guarantees! } } - + } + + private void handleFontName(AFMFile afm, PFMFile pfm) { //Font name if (afm != null) { returnFont.setFontName(afm.getFontName()); //PostScript font name @@ -173,7 +188,9 @@ public class Type1FontLoader extends FontLoader { names.add(pfm.getWindowsName()); //emulate afm.getFamilyName() returnFont.setFamilyNames(names); } - + } + + private void handleMetrics(AFMFile afm, PFMFile pfm) { //Basic metrics if (afm != null) { if (afm.getCapHeight() != null) { @@ -271,8 +288,6 @@ public class Type1FontLoader extends FontLoader { returnFont.setCapHeight(returnFont.getAscender()); } - /* DISABLED because of mismatch with our using WinAnsiEncoding and the AFM - delivering the font's default encoding. if (afm != null) { //TODO returnFont.setFlags(flags); @@ -286,15 +301,15 @@ public class Type1FontLoader extends FontLoader { } } returnFont.replaceKerningMap(afm.createXKerningMapEncoded()); - } else {*/ - returnFont.setFlags(pfm.getFlags()); + } else { returnFont.setFirstChar(pfm.getFirstChar()); returnFont.setLastChar(pfm.getLastChar()); for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { singleFont.setWidth(i, pfm.getCharWidth(i)); } returnFont.replaceKerningMap(pfm.getKerning()); - //} + } + returnFont.setFlags(pfm.getFlags()); } private CodePointMapping buildCustomEncoding(String encodingName, AFMFile afm) { diff --git a/src/java/org/apache/fop/pdf/PDFCMap.java b/src/java/org/apache/fop/pdf/PDFCMap.java index bdf8108c2..1be5e9dc4 100644 --- a/src/java/org/apache/fop/pdf/PDFCMap.java +++ b/src/java/org/apache/fop/pdf/PDFCMap.java @@ -21,7 +21,6 @@ package org.apache.fop.pdf; import java.io.IOException; import java.io.OutputStream; -import java.io.StringWriter; import java.io.Writer; /** @@ -425,10 +424,8 @@ public class PDFCMap extends PDFStream { /** {@inheritDoc} */ protected int output(OutputStream stream) throws IOException { - StringWriter writer = new StringWriter(); - CMapBuilder builder = createCMapBuilder(writer); + CMapBuilder builder = createCMapBuilder(getBufferWriter()); builder.writeCMap(); - add(writer.getBuffer().toString()); //TODO Could be optimized by not buffering return super.output(stream); } } diff --git a/src/java/org/apache/fop/pdf/PDFEncoding.java b/src/java/org/apache/fop/pdf/PDFEncoding.java index b2fba6e53..6dc448b40 100644 --- a/src/java/org/apache/fop/pdf/PDFEncoding.java +++ b/src/java/org/apache/fop/pdf/PDFEncoding.java @@ -131,6 +131,14 @@ public class PDFEncoding extends PDFDictionary { return this; } + /** + * Indicates whether any differences have been recorded. + * @return true if there are differences. + */ + public boolean hasDifferences() { + return (this.differences.length() > 0); + } + /** * Creates and returns the PDFArray representing the Differences entry. * @return the Differences entry diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index 687b32016..f4474331f 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -43,6 +43,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.xmlgraphics.xmp.Metadata; import org.apache.fop.fonts.CIDFont; +import org.apache.fop.fonts.CIDSubset; import org.apache.fop.fonts.CodePointMapping; import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.FontDescriptor; @@ -50,6 +51,8 @@ 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.SimpleSingleByteEncoding; +import org.apache.fop.fonts.SingleByteEncoding; import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; import org.apache.fop.fonts.truetype.FontFileReader; @@ -1166,7 +1169,7 @@ public class PDFFactory { } /** - * make a Type1 /Font object + * Make a Type1 /Font object. * * @param fontname internal name to use for this font (eg "F1") * @param basefont name of the base font (eg "Helvetica") @@ -1217,10 +1220,12 @@ public class PDFFactory { (PDFCIDFontDescriptor)pdfdesc); getDocument().registerObject(cidFont); - PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics.getCharsUsed(), "fop-ucs-H", - new PDFCIDSystemInfo("Adobe", - "Identity", - 0)); + PDFCMap cmap = new PDFToUnicodeCMap( + cidMetrics.getCIDSubset().getSubsetChars(), + "fop-ucs-H", + new PDFCIDSystemInfo("Adobe", + "Identity", + 0)); getDocument().registerObject(cmap); ((PDFFontType0)font).setCMAP(cmap); ((PDFFontType0)font).setDescendantFonts(cidFont); @@ -1238,35 +1243,20 @@ public class PDFFactory { int lastChar = singleByteFont.getLastChar(); nonBase14.setWidthMetrics(firstChar, lastChar, - makeArray(metrics.getWidths())); + new PDFArray(null, metrics.getWidths())); //Handle encoding - CodePointMapping mapping = singleByteFont.getCodePointMapping(); + SingleByteEncoding mapping = singleByteFont.getEncoding(); 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++; - } + Object pdfEncoding = createPDFEncoding(mapping, + singleByteFont.getFontName()); + if (pdfEncoding instanceof PDFEncoding) { + font.setEncoding((PDFEncoding)pdfEncoding); + } else { + font.setEncoding((String)pdfEncoding); } - 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 @@ -1278,21 +1268,88 @@ public class PDFFactory { nonBase14.setToUnicode(cmap); */ } + + //Handle additional encodings (characters outside the primary encoding) + if (singleByteFont.hasAdditionalEncodings()) { + for (int i = 0, c = singleByteFont.getAdditionalEncodingCount(); i < c; i++) { + SimpleSingleByteEncoding addEncoding + = singleByteFont.getAdditionalEncoding(i); + String name = fontname + "_" + (i + 1); + Object pdfenc = createPDFEncoding(addEncoding, + singleByteFont.getFontName()); + PDFFontNonBase14 addFont = (PDFFontNonBase14)PDFFont.createFont( + name, fonttype, + basefont, pdfenc); + addFont.setDescriptor(pdfdesc); + addFont.setWidthMetrics( + addEncoding.getFirstChar(), + addEncoding.getLastChar(), + new PDFArray(null, singleByteFont.getAdditionalWidths(i))); + getDocument().registerObject(addFont); + getDocument().getResources().addFont(addFont); + } + } } return font; } } + /** + * Creates a PDFEncoding instance from a CodePointMapping instance. + * @param encoding the code point mapping (encoding) + * @return the PDF Encoding dictionary (or a String with the predefined encoding) + */ + public Object createPDFEncoding(SingleByteEncoding encoding, String fontNameHint) { + SingleByteEncoding baseEncoding; + if (fontNameHint.indexOf("Symbol") >= 0) { + baseEncoding = CodePointMapping.getMapping( + CodePointMapping.SYMBOL_ENCODING); + } else { + baseEncoding = CodePointMapping.getMapping( + CodePointMapping.STANDARD_ENCODING); + } + PDFEncoding pdfEncoding = new PDFEncoding(baseEncoding.getName()); + PDFEncoding.DifferencesBuilder builder + = pdfEncoding.createDifferencesBuilder(); + int start = -1; + String[] baseNames = baseEncoding.getCharNameMap(); + String[] charNameMap = encoding.getCharNameMap(); + for (int i = 0, ci = charNameMap.length; i < ci; i++) { + String basec = baseNames[i]; + String c = charNameMap[i]; + if (!basec.equals(c)) { + if (start != i) { + builder.addDifference(i); + start = i; + } + builder.addName(c); + start++; + } + } + if (builder.hasDifferences()) { + pdfEncoding.setDifferences(builder.toPDFArray()); + return pdfEncoding; + } else { + return baseEncoding.getName(); + } + } + + /** + * Creates and returns a width array with the widths of all the characters in the subset. + * @param cidFont the font + * @return the width array + */ public PDFWArray getSubsetWidths(CIDFont cidFont) { // Create widths for reencoded chars PDFWArray warray = new PDFWArray(); - int[] tmpWidth = new int[cidFont.usedGlyphsCount]; + int[] widths = cidFont.getWidths(); + CIDSubset subset = cidFont.getCIDSubset(); + int[] tmpWidth = new int[subset.getSubsetSize()]; - for (int i = 0; i < cidFont.usedGlyphsCount; i++) { - Integer nw = (Integer)cidFont.usedGlyphsIndex.get(new Integer(i)); - int nwx = (nw == null) ? 0 : nw.intValue(); - tmpWidth[i] = cidFont.width[nwx]; + for (int i = 0, c = subset.getSubsetSize(); i < c; i++) { + int nwx = Math.max(0, subset.getGlyphIndexForSubsetIndex(i)); + tmpWidth[i] = widths[nwx]; } warray.addEntry(0, tmpWidth); return warray; @@ -1345,12 +1402,7 @@ public class PDFFactory { } private void buildCIDSet(PDFFontDescriptor descriptor, CIDFont cidFont) { - BitSet cidSubset = new BitSet(); - Iterator iter = cidFont.usedGlyphs.keySet().iterator(); - while (iter.hasNext()) { - Integer cid = (Integer)iter.next(); - cidSubset.set(cid.intValue()); - } + BitSet cidSubset = cidFont.getCIDSubset().getGlyphIndexBitSet(); PDFStream cidSet = makeStream(null, true); ByteArrayOutputStream baout = new ByteArrayOutputStream(cidSubset.length() / 8 + 1); int value = 0; @@ -1548,14 +1600,13 @@ public class PDFFactory { } /** - * make an Array object (ex. Widths array for a font) + * Make an Array object (ex. Widths array for a font). * * @param values the int array values * @return the PDF Array with the int values */ public PDFArray makeArray(int[] values) { PDFArray array = new PDFArray(null, values); - getDocument().registerObject(array); return array; } diff --git a/src/java/org/apache/fop/pdf/PDFResources.java b/src/java/org/apache/fop/pdf/PDFResources.java index 66ccdc78b..b0c0128e1 100644 --- a/src/java/org/apache/fop/pdf/PDFResources.java +++ b/src/java/org/apache/fop/pdf/PDFResources.java @@ -110,7 +110,7 @@ public class PDFResources extends PDFObject { desc = (FontDescriptor)font; } addFont(doc.getFactory().makeFont( - f, font.getEmbedFontName(), font.getEncoding(), font, desc)); + f, font.getEmbedFontName(), font.getEncodingName(), font, desc)); } } } diff --git a/src/java/org/apache/fop/pdf/PDFStream.java b/src/java/org/apache/fop/pdf/PDFStream.java index 59a8336c5..a213340e3 100644 --- a/src/java/org/apache/fop/pdf/PDFStream.java +++ b/src/java/org/apache/fop/pdf/PDFStream.java @@ -19,8 +19,9 @@ package org.apache.fop.pdf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; /** * Class representing a PDF stream. @@ -37,6 +38,8 @@ public class PDFStream extends AbstractPDFStream { */ protected StreamCache data; + private transient Writer streamWriter; + /** * Create an empty stream object */ @@ -44,6 +47,10 @@ public class PDFStream extends AbstractPDFStream { super(); try { data = StreamCacheFactory.getInstance().createStreamCache(); + this.streamWriter = new java.io.OutputStreamWriter( + getBufferOutputStream(), PDFDocument.ENCODING); + //Buffer to minimize calls to the converter + this.streamWriter = new java.io.BufferedWriter(this.streamWriter); } catch (IOException ex) { //TODO throw the exception and catch it elsewhere ex.printStackTrace(); @@ -57,14 +64,25 @@ public class PDFStream extends AbstractPDFStream { */ public void add(String s) { try { - data.getOutputStream().write(PDFDocument.encode(s)); + this.streamWriter.write(s); } catch (IOException ex) { //TODO throw the exception and catch it elsewhere ex.printStackTrace(); } - + } + + private void flush() throws IOException { + this.streamWriter.flush(); } + /** + * Returns a Writer that writes to the OutputStream of the buffer. + * @return the Writer + */ + public Writer getBufferWriter() { + return this.streamWriter; + } + /** * Returns an OutputStream that can be used to write to the buffer which is used * to build up the PDF stream. @@ -72,6 +90,9 @@ public class PDFStream extends AbstractPDFStream { * @throws IOException In case of an I/O problem */ public OutputStream getBufferOutputStream() throws IOException { + if (this.streamWriter != null) { + flush(); //Just to be sure + } return this.data.getOutputStream(); } @@ -91,6 +112,7 @@ public class PDFStream extends AbstractPDFStream { */ public int getDataLength() { try { + flush(); return data.getSize(); } catch (Exception e) { //TODO throw the exception and catch it elsewhere @@ -99,17 +121,15 @@ public class PDFStream extends AbstractPDFStream { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected int getSizeHint() throws IOException { + flush(); return data.getSize(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void outputRawStreamData(OutputStream out) throws IOException { + flush(); data.outputContents(out); } diff --git a/src/java/org/apache/fop/pdf/PDFTTFStream.java b/src/java/org/apache/fop/pdf/PDFTTFStream.java index b3488f6a1..5570c62f3 100644 --- a/src/java/org/apache/fop/pdf/PDFTTFStream.java +++ b/src/java/org/apache/fop/pdf/PDFTTFStream.java @@ -67,7 +67,7 @@ public class PDFTTFStream extends PDFStream { */ public void setData(byte[] data, int size) throws IOException { this.data.clear(); - this.data.getOutputStream().write(data, 0, size); + getBufferOutputStream().write(data, 0, size); } } diff --git a/src/java/org/apache/fop/pdf/PDFTextUtil.java b/src/java/org/apache/fop/pdf/PDFTextUtil.java new file mode 100644 index 000000000..224bb6a1d --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFTextUtil.java @@ -0,0 +1,295 @@ +/* + * 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.pdf; + +import java.awt.geom.AffineTransform; + +/** + * Utility class for generating PDF text objects. It needs to be subclassed to add writing + * functionality (see {@link #write(String)}). + */ +public abstract class PDFTextUtil { + + /** The number of decimal places. */ + private static final int DEC = 8; + + /** PDF text rendering mode: Fill text */ + public static final int TR_FILL = 0; + /** PDF text rendering mode: Stroke text */ + public static final int TR_STROKE = 1; + /** PDF text rendering mode: Fill, then stroke text */ + public static final int TR_FILL_STROKE = 2; + /** PDF text rendering mode: Neither fill nor stroke text (invisible) */ + public static final int TR_INVISIBLE = 3; + /** PDF text rendering mode: Fill text and add to path for clipping */ + public static final int TR_FILL_CLIP = 4; + /** PDF text rendering mode: Stroke text and add to path for clipping */ + public static final int TR_STROKE_CLIP = 5; + /** PDF text rendering mode: Fill, then stroke text and add to path for clipping */ + public static final int TR_FILL_STROKE_CLIP = 6; + /** PDF text rendering mode: Add text to path for clipping */ + public static final int TR_CLIP = 7; + + private boolean inTextObject = false; + private String startText; + private String endText; + private boolean useMultiByte; + private StringBuffer bufTJ; + private int textRenderingMode = TR_FILL; + + private String currentFontName; + private double currentFontSize; + + /** + * Main constructor. + */ + public PDFTextUtil() { + //nop + } + + /** + * Writes PDF code. + * @param code the PDF code to write + */ + protected abstract void write(String code); + + private void writeAffineTransform(AffineTransform at, StringBuffer sb) { + double[] lt = new double[6]; + at.getMatrix(lt); + sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" "); + sb.append(PDFNumber.doubleOut(lt[5], DEC)); + } + + private void writeChar(char ch, StringBuffer sb) { + if (!useMultiByte) { + if (ch < 32 || ch > 127) { + sb.append("\\").append(Integer.toOctalString((int)ch)); + } else { + switch (ch) { + case '(': + case ')': + case '\\': + sb.append("\\"); + break; + default: + } + sb.append(ch); + } + } else { + sb.append(PDFText.toUnicodeHex(ch)); + } + } + + private void checkInTextObject() { + if (!inTextObject) { + throw new IllegalStateException("Not in text object"); + } + } + + /** + * Indicates whether we are in a text object or not. + * @return true if we are in a text object + */ + public boolean isInTextObject() { + return inTextObject; + } + + /** + * Called when a new text object should be started. Be sure to call setFont() before + * issuing any text painting commands. + */ + public void beginTextObject() { + if (inTextObject) { + throw new IllegalStateException("Already in text object"); + } + write("BT\n"); + this.inTextObject = true; + } + + /** + * Called when a text object should be ended. + */ + public void endTextObject() { + checkInTextObject(); + write("ET\n"); + this.inTextObject = false; + initValues(); + } + + /** + * Resets the state fields. + */ + protected void initValues() { + this.currentFontName = null; + this.currentFontSize = 0.0; + this.textRenderingMode = TR_FILL; + } + + /** + * Creates a "q" command, pushing a copy of the entire graphics state onto the stack. + */ + public void saveGraphicsState() { + write("q\n"); + } + + /** + * Creates a "Q" command, restoring the entire graphics state to its former value by popping + * it from the stack. + */ + public void restoreGraphicsState() { + write("Q\n"); + } + + /** + * Creates a "cm" command. + * @param at the transformation matrix + */ + public void concatMatrix(AffineTransform at) { + if (!at.isIdentity()) { + writeTJ(); + StringBuffer sb = new StringBuffer(); + writeAffineTransform(at, sb); + sb.append(" cm\n"); + write(sb.toString()); + } + } + + /** + * Writes a "Tf" command, setting a new current font. + * @param fontName the name of the font to select + * @param fontSize the font size (in points) + */ + public void writeTf(String fontName, double fontSize) { + checkInTextObject(); + write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n"); + + this.startText = useMultiByte ? "<" : "("; + this.endText = useMultiByte ? ">" : ")"; + } + + /** + * Updates the current font. This method only writes a "Tf" if the current font changes. + * @param fontName the name of the font to select + * @param fontSize the font size (in points) + * @param multiByte true indicates the font is a multi-byte font, false means single-byte + */ + public void updateTf(String fontName, double fontSize, boolean multiByte) { + checkInTextObject(); + if (!fontName.equals(this.currentFontName) || (fontSize != this.currentFontSize)) { + writeTJ(); + this.currentFontName = fontName; + this.currentFontSize = fontSize; + this.useMultiByte = multiByte; + writeTf(fontName, fontSize); + } + } + + /** + * Sets the text rendering mode. + * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*) + */ + public void setTextRenderingMode(int mode) { + if (mode < 0 || mode > 7) { + throw new IllegalArgumentException( + "Illegal value for text rendering mode. Expected: 0-7"); + } + if (mode != this.textRenderingMode) { + writeTJ(); + this.textRenderingMode = mode; + write(this.textRenderingMode + " Tr\n"); + } + } + + /** + * Sets the text rendering mode. + * @param fill true if the text should be filled + * @param stroke true if the text should be stroked + * @param addToClip true if the path should be added for clipping + */ + public void setTextRenderingMode(boolean fill, boolean stroke, boolean addToClip) { + int mode; + if (fill) { + mode = (stroke ? 2 : 0); + } else { + mode = (stroke ? 1 : 3); + } + if (addToClip) { + mode += 4; + } + setTextRenderingMode(mode); + } + + /** + * Writes a "Tm" command, setting a new text transformation matrix. + * @param localTransform the new text transformation matrix + */ + public void writeTextMatrix(AffineTransform localTransform) { + StringBuffer sb = new StringBuffer(); + writeAffineTransform(localTransform, sb); + sb.append(" Tm "); + write(sb.toString()); + } + + /** + * Writes a char to the "TJ-Buffer". + * @param codepoint the mapped character (code point/character code) + */ + public void writeTJMappedChar(char codepoint) { + if (bufTJ == null) { + bufTJ = new StringBuffer(); + } + if (bufTJ.length() == 0) { + bufTJ.append("[").append(startText); + } + writeChar(codepoint, bufTJ); + } + + /** + * Writes a glyph adjust value to the "TJ-Buffer". + * @param adjust the glyph adjust value in thousands of text unit space. + */ + public void adjustGlyphTJ(double adjust) { + bufTJ.append(endText).append(" "); + bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4)); + bufTJ.append(" "); + bufTJ.append(startText); + } + + /** + * Writes a "TJ" command, writing out the accumulated buffer with the characters and glyph + * positioning values. The buffer is reset afterwards. + */ + public void writeTJ() { + if (isInString()) { + bufTJ.append(endText).append("] TJ\n"); + write(bufTJ.toString()); + bufTJ.setLength(0); + } + } + + private boolean isInString() { + return bufTJ != null && bufTJ.length() > 0; + } + +} diff --git a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java index 57886f89c..f8dd9a1ed 100644 --- a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java @@ -174,11 +174,8 @@ public class OutlineFont extends AFPFont { return charSet.mapChar(c); } - /** - * Get the encoding of the font. - * @return the encoding - */ - public String getEncoding() { + /** {@inheritDoc} */ + public String getEncodingName() { return charSet.getEncoding(); } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java index a61f97ab5..8312dca72 100644 --- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.render.afp.exceptions.FontRuntimeException; @@ -229,11 +230,8 @@ public class RasterFont extends AFPFont { return charSet.mapChar(c); } - /** - * Get the encoding of the font. - * @return the encoding - */ - public String getEncoding() { + /** {@inheritDoc} */ + public String getEncodingName() { return charSet.getEncoding(); } diff --git a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java index 208bc303a..3a773a2db 100644 --- a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java @@ -112,7 +112,7 @@ public class CustomFontMetricsMapper extends Typeface implements FontMetricsMapp } /** {@inheritDoc} */ - public final String getEncoding() { + public final String getEncodingName() { return null; //Not applicable to Java2D rendering } diff --git a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java index ed7391383..19e9a4d1d 100644 --- a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java @@ -172,7 +172,7 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp } /** {@inheritDoc} */ - public String getEncoding() { + public String getEncodingName() { return null; //Not applicable to Java2D rendering } diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java index 1a121e294..c47b944d0 100644 --- a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java @@ -89,8 +89,8 @@ public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter { PDFGraphics2D graphics = new PDFGraphics2D(textAsShapes, pdfInfo.fi, pdfInfo.pdfDoc, pdfInfo.pdfContext, pdfInfo.pdfPage.referencePDF(), - renderer.currentFontName, - renderer.currentFontSize); + pdfInfo.currentFontName, + pdfInfo.currentFontSize); graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); AffineTransform transform = new AffineTransform(); diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 5b7dd840e..268791ac2 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -63,7 +63,6 @@ import org.apache.fop.area.OffDocumentExtensionAttachment; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageSequence; import org.apache.fop.area.PageViewport; -import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.AbstractTextArea; import org.apache.fop.area.inline.Image; @@ -78,6 +77,8 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.extensions.xmp.XMPMetadata; import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.LazyFont; +import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; import org.apache.fop.pdf.PDFAMode; import org.apache.fop.pdf.PDFAction; @@ -106,7 +107,7 @@ import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFStream; -import org.apache.fop.pdf.PDFText; +import org.apache.fop.pdf.PDFTextUtil; import org.apache.fop.pdf.PDFXMode; import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.AbstractPathOrientedRenderer; @@ -250,21 +251,14 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** drawing state */ protected PDFState currentState = null; - /** Name of currently selected font */ - protected String currentFontName = ""; - /** Size of currently selected font */ - protected int currentFontSize = 0; + /** Text generation utility holding the current font status */ + protected PDFTextUtil textutil; /** page height */ protected int pageHeight; /** Registry of PDF filters */ protected Map filterMap; - /** - * true if a BT command has been written. - */ - protected boolean inTextMode = false; - /** Image handler registry */ private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry(); @@ -527,7 +521,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { currentContext = null; currentPage = null; currentState = null; - currentFontName = ""; + this.textutil = null; idPositions.clear(); idGoTos.clear(); @@ -665,19 +659,15 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** Indicates the beginning of a text object. */ protected void beginTextObject() { - if (!inTextMode) { - currentStream.add("BT\n"); - currentFontName = ""; - inTextMode = true; + if (!textutil.isInTextObject()) { + textutil.beginTextObject(); } } /** Indicates the end of a text object. */ protected void endTextObject() { - closeText(); - if (inTextMode) { - currentStream.add("ET\n"); - inTextMode = false; + if (textutil.isInTextObject()) { + textutil.endTextObject(); } } @@ -787,6 +777,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { currentStream = this.pdfDoc.getFactory() .makeStream(PDFFilterList.CONTENT_FILTER, false); + this.textutil = new PDFTextUtil() { + protected void write(String code) { + currentStream.add(code); + } + }; currentState = new PDFState(); // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's @@ -795,9 +790,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { currentState.concatenate(basicPageTransform); currentStream.add(CTMHelper.toPDFString(basicPageTransform, false) + " cm\n"); - - currentFontName = ""; - super.renderPage(page); this.pdfDoc.registerObject(currentStream); @@ -808,6 +800,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } this.pdfDoc.addObject(currentPage); this.pdfDoc.output(ostream); + this.textutil = null; } /** {@inheritDoc} */ @@ -840,17 +833,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } } - /** - * Handle the traits for a region - * This is used to draw the traits for the given page region. - * (See Sect. 6.4.1.2 of XSL-FO spec.) - * @param region the RegionViewport whose region is to be drawn - */ - protected void handleRegionTraits(RegionViewport region) { - currentFontName = ""; - super.handleRegionTraits(region); - } - /** * Formats a float value (normally coordinates) as Strings. * @param value the value @@ -866,7 +848,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { float w = x2 - x1; float h = y2 - y1; if ((w < 0) || (h < 0)) { - log.error("Negative extent received (w=" + w + ", h=" + h + "). Border won't be painted."); + log.error("Negative extent received (w=" + w + ", h=" + h + + "). Border won't be painted."); return; } switch (style) { @@ -1329,12 +1312,9 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { super.renderBlock(block); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void renderLineArea(LineArea line) { super.renderLineArea(line); - closeText(); } /** @@ -1423,11 +1403,20 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } } - /** - * {@inheritDoc} - */ + private Typeface getTypeface(String fontName) { + Typeface tf = (Typeface) fontInfo.getFonts().get(fontName); + if (tf instanceof LazyFont) { + tf = ((LazyFont)tf).getRealFont(); + } + return tf; + } + + /** {@inheritDoc} */ public void renderText(TextArea text) { renderInlineAreaBackAndBorders(text); + Color ct = (Color) text.getTrait(Trait.COLOR); + updateColor(ct, true); + beginTextObject(); StringBuffer pdf = new StringBuffer(); @@ -1435,12 +1424,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); // This assumes that *all* CIDFonts use a /ToUnicode mapping - Typeface tf = (Typeface) fontInfo.getFonts().get(fontName); - boolean useMultiByte = tf.isMultiByte(); + Typeface tf = getTypeface(fontName); + + textutil.updateTf(fontName, size / 1000f, tf.isMultiByte()); - updateFont(fontName, size, pdf); - Color ct = (Color) text.getTrait(Trait.COLOR); - updateColor(ct, true, pdf); // word.getOffset() = only height of text itself // currentBlockIPPosition: 0 for beginning of line; nonzero @@ -1448,66 +1435,46 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); - pdf.append("1 0 0 -1 " + format(rx / 1000f) + " " + format(bl / 1000f) + " Tm " - /*+ format(text.getTextLetterSpaceAdjust() / 1000f) + " Tc\n"*/ - /*+ format(text.getTextWordSpaceAdjust() / 1000f) + " Tw ["*/); + textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, rx / 1000f, bl / 1000f)); - pdf.append("["); currentStream.add(pdf.toString()); super.renderText(text); - currentStream.add("] TJ\n"); + textutil.writeTJ(); renderTextDecoration(tf, size, text, bl, rx); } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ public void renderWord(WordArea word) { Font font = getFontFromArea(word.getParentArea()); - Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName()); - boolean useMultiByte = tf.isMultiByte(); - - StringBuffer pdf = new StringBuffer(); - String s = word.getWord(); - escapeText(s, word.getLetterAdjustArray(), - font, (AbstractTextArea)word.getParentArea(), useMultiByte, pdf); - currentStream.add(pdf.toString()); + escapeText(s, word.getLetterAdjustArray(), + font, (AbstractTextArea)word.getParentArea()); super.renderWord(word); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderSpace(SpaceArea space) { Font font = getFontFromArea(space.getParentArea()); - Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName()); - boolean useMultiByte = tf.isMultiByte(); - String s = space.getSpace(); - StringBuffer pdf = new StringBuffer(); - AbstractTextArea textArea = (AbstractTextArea)space.getParentArea(); - escapeText(s, null, font, textArea, useMultiByte, pdf); + escapeText(s, null, font, textArea); if (space.isAdjustable()) { int tws = -((TextArea) space.getParentArea()).getTextWordSpaceAdjust() - 2 * textArea.getTextLetterSpaceAdjust(); if (tws != 0) { - pdf.append(format(tws / (font.getFontSize() / 1000f))); - pdf.append(" "); + float adjust = tws / (font.getFontSize() / 1000f); + textutil.adjustGlyphTJ(adjust); } } - currentStream.add(pdf.toString()); - super.renderSpace(space); } @@ -1515,101 +1482,77 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * Escapes text according to PDF rules. * @param s Text to escape * @param letterAdjust an array of widths for letter adjustment (may be null) - * @param fs Font state + * @param font to font in use + * @param parentArea the parent text area to retrieve certain traits from + */ + protected void escapeText(String s, + int[] letterAdjust, + Font font, AbstractTextArea parentArea) { + escapeText(s, 0, s.length(), letterAdjust, font, parentArea); + } + + /** + * Escapes text according to PDF rules. + * @param s Text to escape + * @param start the start position in the text + * @param end the end position in the text + * @param letterAdjust an array of widths for letter adjustment (may be null) + * @param font to font in use * @param parentArea the parent text area to retrieve certain traits from - * @param useMultiByte Indicates the use of multi byte convention - * @param pdf target buffer for the escaped text */ - public void escapeText(String s, int[] letterAdjust, - Font fs, AbstractTextArea parentArea, - boolean useMultiByte, StringBuffer pdf) { - String startText = useMultiByte ? "<" : "("; - String endText = useMultiByte ? "> " : ") "; - - /* - boolean kerningAvailable = false; - Map kerning = fs.getKerning(); - if (kerning != null && !kerning.isEmpty()) { - //kerningAvailable = true; - //TODO Reenable me when the layout engine supports kerning, too - log.warn("Kerning support is disabled until it is supported by the layout engine!"); - } - */ + protected void escapeText(String s, int start, int end, + int[] letterAdjust, + Font font, AbstractTextArea parentArea) { + String fontName = font.getFontName(); + float fontSize = font.getFontSize() / 1000f; + Typeface tf = getTypeface(fontName); + SingleByteFont singleByteFont = null; + if (tf instanceof SingleByteFont) { + singleByteFont = (SingleByteFont)tf; + } int l = s.length(); - - float fontSize = fs.getFontSize() / 1000f; - boolean startPending = true; - for (int i = 0; i < l; i++) { + + for (int i = start; i < end; i++) { char orgChar = s.charAt(i); char ch; float glyphAdjust = 0; - if (fs.hasChar(orgChar)) { - ch = fs.mapChar(orgChar); + if (font.hasChar(orgChar)) { + ch = font.mapChar(orgChar); + if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) { + int encoding = ch / 256; + if (encoding == 0) { + textutil.updateTf(fontName, fontSize, tf.isMultiByte()); + } else { + textutil.updateTf(fontName + "_" + Integer.toString(encoding), + fontSize, tf.isMultiByte()); + ch = (char)(ch % 256); + } + } int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0); glyphAdjust -= tls; } else { if (CharUtilities.isFixedWidthSpace(orgChar)) { //Fixed width space are rendered as spaces so copy/paste works in a reader - ch = fs.mapChar(CharUtilities.SPACE); - glyphAdjust = fs.getCharWidth(ch) - fs.getCharWidth(orgChar); + ch = font.mapChar(CharUtilities.SPACE); + glyphAdjust = font.getCharWidth(ch) - font.getCharWidth(orgChar); } else { - ch = fs.mapChar(orgChar); + ch = font.mapChar(orgChar); } } if (letterAdjust != null && i < l - 1) { glyphAdjust -= letterAdjust[i + 1]; } - if (startPending) { - pdf.append(startText); - startPending = false; - } - if (!useMultiByte) { - if (ch < 32 || ch > 127) { - pdf.append("\\"); - pdf.append(Integer.toOctalString((int) ch)); - } else { - switch (ch) { - case '(': - case ')': - case '\\': - pdf.append("\\"); - break; - default: - } - pdf.append(ch); - } - } else { - pdf.append(PDFText.toUnicodeHex(ch)); - } + textutil.writeTJMappedChar(ch); float adjust = glyphAdjust / fontSize; if (adjust != 0) { - pdf.append(endText).append(format(adjust)).append(' '); - startPending = true; + textutil.adjustGlyphTJ(adjust); } } - if (!startPending) { - pdf.append(endText); - } - } - - /** - * Checks to see if we have some text rendering commands open - * still and writes out the TJ command to the stream if we do - */ - protected void closeText() { - /* - if (textOpen) { - currentStream.add("] TJ\n"); - textOpen = false; - prevWordX = 0; - prevWordY = 0; - currentFontName = ""; - }*/ } /** @@ -1623,8 +1566,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { protected void setColor(Color col, boolean fill, StringBuffer pdf) { PDFColor color = new PDFColor(this.pdfDoc, col); - closeText(); - if (pdf != null) { pdf.append(color.getColorSpaceOut(fill)); } else { @@ -1656,22 +1597,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } /** {@inheritDoc} */ - protected void updateColor(Color col, boolean fill) { + protected void updateColor(Color col, boolean fill) { updateColor(col, fill, null); } - private void updateFont(String name, int size, StringBuffer pdf) { - if ((!name.equals(this.currentFontName)) - || (size != this.currentFontSize)) { - closeText(); - - this.currentFontName = name; - this.currentFontSize = size; - pdf = pdf.append("/" + name + " " + format((float) size / 1000f) - + " Tf\n"); - } - } - /** {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { endTextObject(); @@ -1727,8 +1656,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); - - Map hints = ImageUtil.getDefaultHints(sessionContext); org.apache.xmlgraphics.image.loader.Image img = manager.getImage( info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext); @@ -1802,9 +1729,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { context.setProperty(PDFRendererContextConstants.PDF_CONTEXT, currentContext); context.setProperty(PDFRendererContextConstants.PDF_STREAM, currentStream); context.setProperty(PDFRendererContextConstants.PDF_FONT_INFO, fontInfo); - context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, currentFontName); - context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE, - new Integer(currentFontSize)); + context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, ""); + context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE, new Integer(0)); return context; } diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java index bbc811b4e..1566ef799 100644 --- a/src/java/org/apache/fop/render/ps/PSFontUtils.java +++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java @@ -32,16 +32,20 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.fonts.Glyphs; import org.apache.xmlgraphics.ps.DSCConstants; import org.apache.xmlgraphics.ps.PSGenerator; import org.apache.xmlgraphics.ps.PSResource; import org.apache.xmlgraphics.ps.dsc.ResourceTracker; +import org.apache.fop.fonts.Base14Font; import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.LazyFont; +import org.apache.fop.fonts.SingleByteEncoding; +import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; /** @@ -81,9 +85,21 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { while (iter.hasNext()) { String key = (String)iter.next(); Typeface tf = getTypeFace(fontInfo, fonts, key); - PSResource fontRes = new PSResource("font", tf.getFontName()); + PSResource fontRes = new PSResource(PSResource.TYPE_FONT, tf.getFontName()); fontResources.put(key, fontRes); embedFont(gen, tf, fontRes); + + if (tf instanceof SingleByteFont) { + SingleByteFont sbf = (SingleByteFont)tf; + for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) { + SingleByteEncoding encoding = sbf.getAdditionalEncoding(i); + defineEncoding(gen, encoding); + String postFix = "_" + (i + 1); + PSResource derivedFontRes = defineDerivedFont(gen, tf.getFontName(), + tf.getFontName() + postFix, encoding.getName()); + fontResources.put(key + postFix, derivedFontRes); + } + } } gen.commentln("%FOPEndFontDict"); reencodeFonts(gen, fonts); @@ -91,29 +107,35 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { } private static void reencodeFonts(PSGenerator gen, Map fonts) throws IOException { + ResourceTracker tracker = gen.getResourceTracker(); + + if (!tracker.isResourceSupplied(WINANSI_ENCODING_RESOURCE)) { + defineWinAnsiEncoding(gen); + } gen.commentln("%FOPBeginFontReencode"); - defineWinAnsiEncoding(gen); //Rewrite font encodings Iterator iter = fonts.keySet().iterator(); while (iter.hasNext()) { String key = (String)iter.next(); - Typeface fm = (Typeface)fonts.get(key); - if (fm instanceof LazyFont && ((LazyFont)fm).getRealFont() == null) { - continue; - } else if (null == fm.getEncoding()) { + Typeface tf = (Typeface)fonts.get(key); + if (tf instanceof LazyFont) { + tf = ((LazyFont)tf).getRealFont(); + if (tf == null) { + continue; + } + } + if (null == tf.getEncodingName()) { //ignore (ZapfDingbats and Symbol used to run through here, kept for safety reasons) - } else if ("SymbolEncoding".equals(fm.getEncoding())) { + } else if ("SymbolEncoding".equals(tf.getEncodingName())) { //ignore (no encoding redefinition) - } else if ("ZapfDingbatsEncoding".equals(fm.getEncoding())) { + } else if ("ZapfDingbatsEncoding".equals(tf.getEncodingName())) { //ignore (no encoding redefinition) - } else if ("WinAnsiEncoding".equals(fm.getEncoding())) { - redefineFontEncoding(gen, fm.getFontName(), fm.getEncoding()); } else { - /* Don't complain anymore, just use the font's default encoding. - gen.commentln("%WARNING: Only WinAnsiEncoding is supported. Font '" - + fm.getFontName() + "' asks for: " + fm.getEncoding()); - */ + if (tf instanceof Base14Font) { + //Our Base 14 fonts don't use the default encoding + redefineFontEncoding(gen, tf.getFontName(), tf.getEncodingName()); + } } } gen.commentln("%FOPEndFontReencode"); @@ -233,10 +255,88 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { if (isEmbeddable(cf)) { resTracker.registerSuppliedResource(fontRes); } + if (tf instanceof SingleByteFont) { + SingleByteFont sbf = (SingleByteFont)tf; + for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) { + SingleByteEncoding encoding = sbf.getAdditionalEncoding(i); + PSResource encodingRes = new PSResource( + PSResource.TYPE_ENCODING, encoding.getName()); + resTracker.registerSuppliedResource(encodingRes); + PSResource derivedFontRes = new PSResource( + PSResource.TYPE_FONT, tf.getFontName() + "_" + (i + 1)); + resTracker.registerSuppliedResource(derivedFontRes); + } + } } } } return fontResources; } + /** + * Defines the single-byte encoding for use in PostScript files. + * @param gen the PostScript generator + * @param encoding the single-byte encoding + * @return the PSResource instance that represents the encoding + * @throws IOException In case of an I/O problem + */ + public static PSResource defineEncoding(PSGenerator gen, SingleByteEncoding encoding) + throws IOException { + PSResource res = new PSResource(PSResource.TYPE_ENCODING, encoding.getName()); + gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res); + gen.writeln("/" + encoding.getName() + " ["); + String[] charNames = encoding.getCharNameMap(); + for (int i = 0; i < 256; i++) { + if (i > 0) { + if ((i % 5) == 0) { + gen.newLine(); + } else { + gen.write(" "); + } + } + String glyphname = null; + if (i < charNames.length) { + glyphname = charNames[i]; + } + if (glyphname == null || "".equals(glyphname)) { + glyphname = Glyphs.NOTDEF; + } + gen.write("/"); + gen.write(glyphname); + } + gen.newLine(); + gen.writeln("] def"); + gen.writeDSCComment(DSCConstants.END_RESOURCE); + gen.getResourceTracker().registerSuppliedResource(res); + return res; + } + + /** + * Derives a new font based on an existing font with a given encoding. The encoding must + * have been registered before. + * @param gen the PostScript generator + * @param baseFontName the font name of the font to derive from + * @param fontName the font name of the new font to be define + * @param encoding the new encoding (must be predefined in the PS file) + * @return the PSResource representing the derived font + * @throws IOException In case of an I/O problem + */ + public static PSResource defineDerivedFont(PSGenerator gen, String baseFontName, String fontName, + String encoding) throws IOException { + PSResource res = new PSResource(PSResource.TYPE_FONT, fontName); + gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res); + gen.commentln("%XGCDependencies: font " + baseFontName); + gen.commentln("%XGC+ encoding " + encoding); + gen.writeln("/" + baseFontName + " findfont"); + gen.writeln("dup length dict begin"); + gen.writeln(" {1 index /FID ne {def} {pop pop} ifelse} forall"); + gen.writeln(" /Encoding " + encoding + " def"); + gen.writeln(" currentdict"); + gen.writeln("end"); + gen.writeln("/" + fontName + " exch definefont pop"); + gen.writeDSCComment(DSCConstants.END_RESOURCE); + gen.getResourceTracker().registerSuppliedResource(res); + return res; + } + } diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index ecd403749..7e32977e6 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -89,6 +89,7 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.LazyFont; +import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; @@ -660,6 +661,12 @@ public class PSRenderer extends AbstractPathOrientedRenderer } private String getPostScriptNameForFontKey(String key) { + int pos = key.indexOf('_'); + String postFix = null; + if (pos > 0) { + postFix = key.substring(pos); + key = key.substring(0, pos); + } Map fonts = fontInfo.getFonts(); Typeface tf = (Typeface)fonts.get(key); if (tf instanceof LazyFont) { @@ -668,7 +675,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer if (tf == null) { throw new IllegalStateException("Font not available: " + key); } - return tf.getFontName(); + if (postFix == null) { + return tf.getFontName(); + } else { + return tf.getFontName() + postFix; + } } /** @@ -698,7 +709,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer protected void useFont(String key, int size) { try { PSResource res = getPSResourceForFontKey(key); - //gen.useFont(key, size / 1000f); gen.useFont("/" + res.getName(), size / 1000f); gen.getResourceTracker().notifyResourceUsageOnPage(res); } catch (IOException ioe) { @@ -951,7 +961,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer if (!isOptimizeResources()) { this.fontResources = PSFontUtils.writeFontDict(gen, fontInfo); } else { - gen.commentln("%FOPFontSetup"); + gen.commentln("%FOPFontSetup"); //Place-holder, will be replaced in the second pass } gen.writeDSCComment(DSCConstants.END_SETUP); } @@ -1292,17 +1302,16 @@ public class PSRenderer extends AbstractPathOrientedRenderer */ public void renderText(TextArea area) { renderInlineAreaBackAndBorders(area); - String fontname = getInternalFontNameForArea(area); + String fontkey = getInternalFontNameForArea(area); int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE); // This assumes that *all* CIDFonts use a /ToUnicode mapping - Typeface tf = (Typeface) fontInfo.getFonts().get(fontname); + Typeface tf = (Typeface) fontInfo.getFonts().get(fontkey); //Determine position int rx = currentIPPosition + area.getBorderAndPaddingWidthStart(); int bl = currentBPPosition + area.getOffset() + area.getBaselineOffset(); - useFont(fontname, fontsize); Color ct = (Color)area.getTrait(Trait.COLOR); if (ct != null) { try { @@ -1347,30 +1356,75 @@ public class PSRenderer extends AbstractPathOrientedRenderer super.renderSpace(space); } + private Typeface getTypeface(String fontName) { + Typeface tf = (Typeface)fontInfo.getFonts().get(fontName); + if (tf instanceof LazyFont) { + tf = ((LazyFont)tf).getRealFont(); + } + return tf; + } + private void renderText(AbstractTextArea area, String text, int[] letterAdjust) { + String fontkey = getInternalFontNameForArea(area); + int fontSize = area.getTraitAsInteger(Trait.FONT_SIZE); Font font = getFontFromArea(area); - Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName()); + Typeface tf = getTypeface(font.getFontName()); + SingleByteFont singleByteFont = null; + if (tf instanceof SingleByteFont) { + singleByteFont = (SingleByteFont)tf; + } + int textLen = text.length(); + if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) { + int start = 0; + int currentEncoding = -1; + for (int i = 0; i < textLen; i++) { + char c = text.charAt(i); + char mapped = tf.mapChar(c); + int encoding = mapped / 256; + if (currentEncoding != encoding) { + if (i > 0) { + writeText(area, text, start, i - start, letterAdjust, fontSize, tf); + } + if (encoding == 0) { + useFont(fontkey, fontSize); + } else { + useFont(fontkey + "_" + Integer.toString(encoding), fontSize); + } + currentEncoding = encoding; + start = i; + } + } + writeText(area, text, start, textLen - start, letterAdjust, fontSize, tf); + } else { + useFont(fontkey, fontSize); + writeText(area, text, 0, textLen, letterAdjust, fontSize, tf); + } + } + + private void writeText(AbstractTextArea area, String text, int start, int len, + int[] letterAdjust, int fontsize, Typeface tf) { + int end = start + len; int initialSize = text.length(); initialSize += initialSize / 2; StringBuffer sb = new StringBuffer(initialSize); - int textLen = text.length(); if (letterAdjust == null && area.getTextLetterSpaceAdjust() == 0 && area.getTextWordSpaceAdjust() == 0) { sb.append("("); - for (int i = 0; i < textLen; i++) { + for (int i = start; i < end; i++) { final char c = text.charAt(i); - final char mapped = tf.mapChar(c); + final char mapped = (char)(tf.mapChar(c) % 256); PSGenerator.escapeChar(mapped, sb); } sb.append(") t"); } else { sb.append("("); - int[] offsets = new int[textLen]; - for (int i = 0; i < textLen; i++) { + int[] offsets = new int[len]; + for (int i = start; i < end; i++) { final char c = text.charAt(i); final char mapped = tf.mapChar(c); + char codepoint = (char)(mapped % 256); int wordSpace; if (CharUtilities.isAdjustableSpace(mapped)) { @@ -1378,14 +1432,14 @@ public class PSRenderer extends AbstractPathOrientedRenderer } else { wordSpace = 0; } - int cw = tf.getWidth(mapped, font.getFontSize()) / 1000; - int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0); - int tls = (i < textLen - 1 ? area.getTextLetterSpaceAdjust() : 0); - offsets[i] = cw + ladj + tls + wordSpace; - PSGenerator.escapeChar(mapped, sb); + int cw = tf.getWidth(mapped, fontsize) / 1000; + int ladj = (letterAdjust != null && i < end - 1 ? letterAdjust[i + 1] : 0); + int tls = (i < end - 1 ? area.getTextLetterSpaceAdjust() : 0); + offsets[i - start] = cw + ladj + tls + wordSpace; + PSGenerator.escapeChar(codepoint, sb); } sb.append(")" + PSGenerator.LF + "["); - for (int i = 0; i < textLen; i++) { + for (int i = 0; i < len; i++) { if (i > 0) { if (i % 8 == 0) { sb.append(PSGenerator.LF); @@ -1398,7 +1452,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer sb.append("]" + PSGenerator.LF + "xshow"); } writeln(sb.toString()); - } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 864809ebe..f6a7cbc3b 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -70,12 +70,10 @@ import org.apache.xmlgraphics.image.loader.impl.ImageRendered; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; -import org.apache.fop.fonts.CIDFont; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontTriplet; -import org.apache.fop.fonts.LazyFont; import org.apache.fop.pdf.BitmapImage; import org.apache.fop.pdf.PDFAnnotList; import org.apache.fop.pdf.PDFColor; @@ -1473,14 +1471,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { // This assumes that *all* CIDFonts use a /ToUnicode mapping org.apache.fop.fonts.Typeface f = (org.apache.fop.fonts.Typeface)fontInfo.getFonts().get(name); - if (f instanceof LazyFont) { - if (((LazyFont) f).getRealFont() instanceof CIDFont) { - return true; - } - } else if (f instanceof CIDFont) { - return true; - } - return false; + return f.isMultiByte(); } private void addKerning(StringWriter buf, Integer ch1, Integer ch2, diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java index 7154c68a9..754b0794b 100644 --- a/src/java/org/apache/fop/svg/PDFTextPainter.java +++ b/src/java/org/apache/fop/svg/PDFTextPainter.java @@ -43,6 +43,7 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter; import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; import org.apache.batik.gvt.text.TextPaintInfo; import org.apache.batik.gvt.text.TextSpanLayout; + import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; @@ -83,8 +84,12 @@ public class PDFTextPainter extends StrokingTextPainter { super.paintTextRuns(textRuns, g2d); return; } - PDFGraphics2D pdf = (PDFGraphics2D)g2d; - PDFTextUtil textUtil = new PDFTextUtil(pdf); + final PDFGraphics2D pdf = (PDFGraphics2D)g2d; + PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) { + protected void write(String code) { + pdf.currentStream.write(code); + } + }; for (int i = 0; i < textRuns.size(); i++) { TextRun textRun = (TextRun)textRuns.get(i); AttributedCharacterIterator runaci = textRun.getACI(); @@ -134,7 +139,7 @@ public class PDFTextPainter extends StrokingTextPainter { } textUtil.saveGraphicsState(); - textUtil.concatMatrixCurrentTransform(); + textUtil.concatMatrix(g2d.getTransform()); Shape imclip = g2d.getClip(); pdf.writeClip(imclip); diff --git a/src/java/org/apache/fop/svg/PDFTextUtil.java b/src/java/org/apache/fop/svg/PDFTextUtil.java index 0fb552026..f3c7f31a2 100644 --- a/src/java/org/apache/fop/svg/PDFTextUtil.java +++ b/src/java/org/apache/fop/svg/PDFTextUtil.java @@ -19,145 +19,33 @@ package org.apache.fop.svg; -import java.awt.geom.AffineTransform; - import org.apache.fop.fonts.Font; -import org.apache.fop.pdf.PDFNumber; -import org.apache.fop.pdf.PDFText; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.Typeface; /** - * Utility class for generating PDF text objects. + * Utility class for generating PDF text objects. It needs to be subclassed to add writing + * functionality (see {@link #write(String)}). */ -public class PDFTextUtil { +public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil { - /** The number of decimal places. */ - private static final int DEC = 8; - - /** PDF text rendering mode: Fill text */ - public static final int TR_FILL = 0; - /** PDF text rendering mode: Stroke text */ - public static final int TR_STROKE = 1; - /** PDF text rendering mode: Fill, then stroke text */ - public static final int TR_FILL_STROKE = 2; - /** PDF text rendering mode: Neither fill nor stroke text (invisible) */ - public static final int TR_INVISIBLE = 3; - /** PDF text rendering mode: Fill text and add to path for clipping */ - public static final int TR_FILL_CLIP = 4; - /** PDF text rendering mode: Stroke text and add to path for clipping */ - public static final int TR_STROKE_CLIP = 5; - /** PDF text rendering mode: Fill, then stroke text and add to path for clipping */ - public static final int TR_FILL_STROKE_CLIP = 6; - /** PDF text rendering mode: Add text to path for clipping */ - public static final int TR_CLIP = 7; - - - private PDFGraphics2D g2d; - private boolean inTextObject = false; + private FontInfo fontInfo; private Font[] fonts; private Font font; - private String startText; - private String endText; - private boolean useMultiByte; - private StringBuffer bufTJ; - private int textRenderingMode = 0; /** * Main constructor. - * @param g2d the PDFGraphics2D instance to work with + * @param fontInfo the font catalog */ - public PDFTextUtil(PDFGraphics2D g2d) { - this.g2d = g2d; + public PDFTextUtil(FontInfo fontInfo) { + super(); + this.fontInfo = fontInfo; } - private void writeAffineTransform(AffineTransform at, StringBuffer sb) { - double[] lt = new double[6]; - at.getMatrix(lt); - sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" "); - sb.append(PDFNumber.doubleOut(lt[5], DEC)); - } - - private void writeChar(char ch, StringBuffer sb) { - if (!useMultiByte) { - if (ch > 127) { - sb.append("\\").append(Integer.toOctalString((int)ch)); - } else { - switch (ch) { - case '(': - case ')': - case '\\': - sb.append("\\"); - break; - default: - } - sb.append(ch); - } - } else { - sb.append(PDFText.toUnicodeHex(ch)); - } - } - - private void checkInTextObject() { - if (!inTextObject) { - throw new IllegalStateException("Not in text object"); - } - } - - /** - * Called when a new text object should be started. Be sure to call setFont() before - * issuing any text painting commands. - */ - public void beginTextObject() { - if (inTextObject) { - throw new IllegalStateException("Already in text object"); - } - g2d.currentStream.write("BT\n"); - this.inTextObject = true; - } - - /** - * Called when a text object should be ended. - */ - public void endTextObject() { - checkInTextObject(); - g2d.currentStream.write("ET\n"); - this.inTextObject = false; - initValues(); - } - - private void initValues() { + /** {@inheritDoc} */ + protected void initValues() { + super.initValues(); this.font = null; - this.textRenderingMode = TR_FILL; - } - - /** - * Creates a "q" command, pushing a copy of the entire graphics state onto the stack. - */ - public void saveGraphicsState() { - g2d.currentStream.write("q\n"); - } - - /** - * Creates a "Q" command, restoring the entire graphics state to its former value by popping - * it from the stack. - */ - public void restoreGraphicsState() { - g2d.currentStream.write("Q\n"); - } - - /** - * Creates a "cm" command using the current transformation as the matrix. - */ - public void concatMatrixCurrentTransform() { - StringBuffer sb = new StringBuffer(); - if (!g2d.getTransform().isIdentity()) { - writeAffineTransform(g2d.getTransform(), sb); - sb.append(" cm\n"); - } - g2d.currentStream.write(sb.toString()); } /** @@ -193,64 +81,24 @@ public class PDFTextUtil { this.font = f; } + /** + * Determines whether the font with the given name is a multi-byte font. + * @param name the name of the font + * @return true if it's a multi-byte font + */ + protected boolean isMultiByteFont(String name) { + Typeface f = (Typeface)fontInfo.getFonts().get(name); + return f.isMultiByte(); + } + /** * Writes a "Tf" command, setting a new current font. * @param f the font to select */ public void writeTf(Font f) { - checkInTextObject(); String fontName = f.getFontName(); float fontSize = (float)f.getFontSize() / 1000f; - g2d.currentStream.write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n"); - - this.useMultiByte = g2d.isMultiByteFont(fontName); - this.startText = useMultiByte ? "<" : "("; - this.endText = useMultiByte ? ">" : ")"; - } - - /** - * Sets the text rendering mode. - * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*) - */ - public void setTextRenderingMode(int mode) { - if (mode < 0 || mode > 7) { - throw new IllegalArgumentException( - "Illegal value for text rendering mode. Expected: 0-7"); - } - if (mode != this.textRenderingMode) { - this.textRenderingMode = mode; - g2d.currentStream.write(this.textRenderingMode + " Tr\n"); - } - } - - /** - * Sets the text rendering mode. - * @param fill true if the text should be filled - * @param stroke true if the text should be stroked - * @param addToClip true if the path should be added for clipping - */ - public void setTextRenderingMode(boolean fill, boolean stroke, boolean addToClip) { - int mode; - if (fill) { - mode = (stroke ? 2 : 0); - } else { - mode = (stroke ? 1 : 3); - } - if (addToClip) { - mode += 4; - } - setTextRenderingMode(mode); - } - - /** - * Writes a "Tm" command, setting a new text transformation matrix. - * @param localTransform the new text transformation matrix - */ - public void writeTextMatrix(AffineTransform localTransform) { - StringBuffer sb = new StringBuffer(); - writeAffineTransform(localTransform, sb); - sb.append(" Tm\n"); - g2d.currentStream.write(sb.toString()); + updateTf(fontName, fontSize, isMultiByteFont(fontName)); } /** @@ -272,37 +120,8 @@ public class PDFTextUtil { * @param ch the unmapped character */ public void writeTJChar(char ch) { - if (bufTJ == null) { - bufTJ = new StringBuffer(); - } - if (bufTJ.length() == 0) { - bufTJ.append("[").append(startText); - } char mappedChar = font.mapChar(ch); - writeChar(mappedChar, bufTJ); - } - - /** - * Writes a glyph adjust value to the "TJ-Buffer". - * @param adjust the glyph adjust value in thousands of text unit space. - */ - public void adjustGlyphTJ(double adjust) { - bufTJ.append(endText).append(" "); - bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4)); - bufTJ.append(" "); - bufTJ.append(startText); - } - - /** - * Writes a "TJ" command, writing out the accumulated buffer with the characters and glyph - * positioning values. The buffer is reset afterwards. - */ - public void writeTJ() { - if (bufTJ != null && bufTJ.length() > 0) { - bufTJ.append(endText).append("] TJ\n"); - g2d.currentStream.write(bufTJ.toString()); - bufTJ.setLength(0); - } + writeTJMappedChar(mappedChar); } } diff --git a/status.xml b/status.xml index 11b719678..9e9430de0 100644 --- a/status.xml +++ b/status.xml @@ -52,13 +52,17 @@ - + - + + Added support for addressing all glyphs available in a Type 1 font, not just the ones + in the font's primary encoding. + +
                                                                                        diff --git a/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java b/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java index b29249f00..c9fba08c7 100644 --- a/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java +++ b/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java @@ -65,7 +65,7 @@ public class PDFEncodingTestCase extends BasePDFTestCase { * The following array is used to look for these patterns */ final String[] testPatterns = { - TEST_MARKER + "1", "(Standard)", + TEST_MARKER + "1", "Standard", TEST_MARKER + "2", "XX_\\351_XX", TEST_MARKER + "3", "XX_\\342\\352\\356\\364\\373_XX" }; @@ -75,7 +75,9 @@ public class PDFEncodingTestCase extends BasePDFTestCase { /** * TODO test disabled for now, fails due (probably) do different PDF - * encoding when custom font is used + * encoding when custom font is used. + * TODO This should be tested using PDFBox. If PDFBox can extract the text correctly, + * everything is fine. The tests here are too unstable. * * @throws Exception * checkstyle wants a comment here, even a silly one -- cgit v1.2.3 From f1e20bb4e5ed277795329e5b05cf1f2485b9387a Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 27 Mar 2008 14:29:44 +0000 Subject: When a JPEG image is embedded, an optionally embedded color profile is filtered out as it's already embedded separately in the PDF file. Worked around a problem (PDF renderer) with JPEG image containing RGB color profiles which are not sRGB. The images drifted into yellow. The color profile is simply disabled in this case. Please let us know if you know what the problem could be. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@641827 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/render/pdf/AbstractImageAdapter.java | 10 +- .../apache/fop/render/pdf/ImageRawJPEGAdapter.java | 101 ++++++++++++++++++++- status.xml | 9 ++ 3 files changed, 118 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java index b676ad6d5..caf8928ac 100644 --- a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java +++ b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java @@ -81,7 +81,7 @@ public abstract class AbstractImageAdapter implements PDFImage { /** {@inheritDoc} */ public void setup(PDFDocument doc) { - ICC_Profile prof = image.getICCProfile(); + ICC_Profile prof = getEffectiveICCProfile(); PDFDeviceColorSpace pdfCS = toPDFColorSpace(getImageColorSpace()); if (prof != null) { pdfICCStream = setupColorProfile(doc, prof, pdfCS); @@ -100,6 +100,14 @@ public abstract class AbstractImageAdapter implements PDFImage { } } + /** + * Returns the effective ICC profile for the image. + * @return an ICC profile or null + */ + protected ICC_Profile getEffectiveICCProfile() { + return image.getICCProfile(); + } + private static PDFICCStream setupColorProfile(PDFDocument doc, ICC_Profile prof, PDFDeviceColorSpace pdfCS) { boolean defaultsRGB = ColorProfileUtil.isDefaultsRGB(prof); diff --git a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java index 4b0ce4a85..1c8fceb50 100644 --- a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java +++ b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java @@ -18,19 +18,33 @@ /* $Id$ */ package org.apache.fop.render.pdf; +import java.awt.color.ICC_Profile; +import java.io.DataInput; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +import org.apache.commons.io.IOUtils; + import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.JPEGConstants; +import org.apache.xmlgraphics.image.loader.impl.JPEGFile; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.fop.pdf.DCTFilter; import org.apache.fop.pdf.PDFDeviceColorSpace; import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFFilter; import org.apache.fop.pdf.PDFFilterList; +import org.apache.fop.util.ColorProfileUtil; /** * PDFImage implementation for the PDF renderer which handles raw JPEG images. + *

                                                                                        + * The JPEG is copied to the XObject's stream as-is but some elements (marker segments) are + * filtered. For example, an embedded color profile is filtered since it is already added as + * a PDF object and associated with the XObject. This way, the PDF file size is kept as small + * as possible. */ public class ImageRawJPEGAdapter extends AbstractImageAdapter { @@ -67,6 +81,21 @@ public class ImageRawJPEGAdapter extends AbstractImageAdapter { return toPDFColorSpace(getImageColorSpace()); } + /** {@inheritDoc} */ + protected ICC_Profile getEffectiveICCProfile() { + ICC_Profile profile = super.getEffectiveICCProfile(); + if (profile != null + && profile.getNumComponents() == 3 + && !ColorProfileUtil.isDefaultsRGB(profile)) { + //RGB profiles which are not sRGB don't seem to work. + //Without this override, the image drifts into yellow for an unknown reason. + //TODO Find out why this happens. + //Test using a JPEG images with, for example, "Adobe RGB 1998" color profile. + profile = null; + } + return profile; + } + /** {@inheritDoc} */ public int getBitsPerComponent() { return 8; @@ -84,7 +113,77 @@ public class ImageRawJPEGAdapter extends AbstractImageAdapter { /** {@inheritDoc} */ public void outputContents(OutputStream out) throws IOException { - getImage().writeTo(out); + InputStream in = getImage().createInputStream(); + in = ImageUtil.decorateMarkSupported(in); + try { + JPEGFile jpeg = new JPEGFile(in); + DataInput din = jpeg.getDataInput(); + + //Copy the whole JPEG file except: + // - the ICC profile + //TODO Thumbnails could safely be skipped, too. + //TODO Metadata (XMP, IPTC, EXIF) could safely be skipped, too. + while (true) { + int reclen; + int segID = jpeg.readMarkerSegment(); + switch (segID) { + case JPEGConstants.SOI: + out.write(0xFF); + out.write(segID); + break; + case JPEGConstants.EOI: + case JPEGConstants.SOS: + out.write(0xFF); + out.write(segID); + IOUtils.copy(in, out); //Just copy the rest! + return; + /* + case JPEGConstants.APP1: //Metadata + case JPEGConstants.APPD: + jpeg.skipCurrentMarkerSegment(); + break;*/ + case JPEGConstants.APP2: //ICC (see ICC1V42.pdf) + boolean skipICCProfile = false; + in.mark(16); + try { + reclen = jpeg.readSegmentLength(); + // Check for ICC profile + byte[] iccString = new byte[11]; + din.readFully(iccString); + din.skipBytes(1); //string terminator (null byte) + + if ("ICC_PROFILE".equals(new String(iccString, "US-ASCII"))) { + skipICCProfile = (this.image.getICCProfile() != null); + } + } finally { + in.reset(); + } + if (skipICCProfile) { + //ICC profile is skipped as it is already embedded as a PDF object + jpeg.skipCurrentMarkerSegment(); + break; + } + default: + out.write(0xFF); + out.write(segID); + + reclen = jpeg.readSegmentLength(); + //write short + out.write((reclen >>> 8) & 0xFF); + out.write((reclen >>> 0) & 0xFF); + int left = reclen - 2; + byte[] buf = new byte[2048]; + while (left > 0) { + int part = Math.min(buf.length, left); + din.readFully(buf, 0, part); + out.write(buf, 0, part); + left -= part; + } + } + } + } finally { + IOUtils.closeQuietly(in); + } } /** {@inheritDoc} */ diff --git a/status.xml b/status.xml index 9e9430de0..6d245a3d2 100644 --- a/status.xml +++ b/status.xml @@ -58,6 +58,15 @@ Added SVG support for AFP (GOCA). --> + + When a JPEG image is embedded, an optionally embedded color profile is filtered out + as it's already embedded separately in the PDF file. + + + Worked around a problem (PDF renderer) with JPEG image containing RGB color profiles which + are not sRGB. The images drifted into yellow. The color profile is simply disabled in this + case. Please let us know if you know what the problem could be. + Added support for addressing all glyphs available in a Type 1 font, not just the ones in the font's primary encoding. -- cgit v1.2.3 From 3e8128c8d05a7f08258913a81a438d0666bdf220 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 31 Mar 2008 08:39:49 +0000 Subject: Fixed possible NullPointerException in AFM kerning table build code. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@642923 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/type1/AFMFile.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/type1/AFMFile.java b/src/java/org/apache/fop/fonts/type1/AFMFile.java index 6a1973843..3cb4b3343 100644 --- a/src/java/org/apache/fop/fonts/type1/AFMFile.java +++ b/src/java/org/apache/fop/fonts/type1/AFMFile.java @@ -413,7 +413,7 @@ public class AFMFile { Map.Entry entryFrom = (Map.Entry)iterFrom.next(); String name1 = (String)entryFrom.getKey(); AFMCharMetrics chm1 = getChar(name1); - if (!chm1.hasCharCode()) { + if (chm1 == null || !chm1.hasCharCode()) { continue; } Map container = null; @@ -423,7 +423,7 @@ public class AFMFile { Map.Entry entryTo = (Map.Entry)iterTo.next(); String name2 = (String)entryTo.getKey(); AFMCharMetrics chm2 = getChar(name2); - if (!chm2.hasCharCode()) { + if (chm2 == null || !chm2.hasCharCode()) { continue; } if (container == null) { -- cgit v1.2.3 From 0f7b92411a4aceb705dfd1aea211b180ed90a95b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 31 Mar 2008 08:40:48 +0000 Subject: Added missing code for determining the PDF Flags. The removes the need to have a PFM if you have an AFM file for a Type 1 font. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@642924 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fonts/type1/Type1FontLoader.java | 27 ++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 8cf6f2371..3187379d5 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -108,11 +108,6 @@ public class Type1FontLoader extends FontLoader { throw new java.io.FileNotFoundException( "Neither an AFM nor a PFM file was found for " + this.fontFileURI); } - if (pfm == null) { - //Cannot do without the PFM for now - throw new java.io.FileNotFoundException( - "No PFM file was found for " + this.fontFileURI); - } buildFont(afm, pfm); this.loaded = true; } @@ -289,7 +284,25 @@ public class Type1FontLoader extends FontLoader { } if (afm != null) { - //TODO returnFont.setFlags(flags); + String charSet = afm.getCharacterSet(); + int flags = 0; + if ("Special".equals(charSet)) { + flags |= 4; //bit 3: Symbolic + } else { + if (singleFont.getEncoding().mapChar('A') == 'A') { + //High likelyhood that the font is non-symbolic + flags |= 32; //bit 6: Nonsymbolic + } else { + flags |= 4; //bit 3: Symbolic + } + } + if (afm.getWritingDirectionMetrics(0).isFixedPitch()) { + flags |= 1; //bit 1: FixedPitch + } + if (afm.getWritingDirectionMetrics(0).getItalicAngle() != 0.0) { + flags |= 64; //bit 7: Italic + } + returnFont.setFlags(flags); returnFont.setFirstChar(afm.getFirstChar()); returnFont.setLastChar(afm.getLastChar()); @@ -302,6 +315,7 @@ public class Type1FontLoader extends FontLoader { } returnFont.replaceKerningMap(afm.createXKerningMapEncoded()); } else { + returnFont.setFlags(pfm.getFlags()); returnFont.setFirstChar(pfm.getFirstChar()); returnFont.setLastChar(pfm.getLastChar()); for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { @@ -309,7 +323,6 @@ public class Type1FontLoader extends FontLoader { } returnFont.replaceKerningMap(pfm.getKerning()); } - returnFont.setFlags(pfm.getFlags()); } private CodePointMapping buildCustomEncoding(String encodingName, AFMFile afm) { -- cgit v1.2.3 From 1f0ed2013cfcc24f8071b09ad17c3dd4eec5633f Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 3 Apr 2008 08:05:14 +0000 Subject: Bugzilla #44737: Added support for auto-configuring TrueType Collections. XML font metrics files for *.ttc fonts are not required anymore. Submitted by: Jason Harrop Changes to patch or in addition to the patch: - Tab chars removed and Checkstyle issues fixed - Some simplifications in the cache handling (CachedFontInfo is obsolete and less cache-private information is exposed to the outside). - TTCs are fully detected and registered with FOP. - TTCs can also be registered using a "font" element. The new "sub-font" attribute selected the sub-font in the TTC. - Bug fixed in TTFFile: Font names were not decoded correctly (ex. font names in Chinese) - Minimal docs. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@644208 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/fonts.xml | 5 + src/foschema/fop-configuration.xsd | 1 + src/java/org/apache/fop/fonts/CachedFontInfo.java | 120 -------------- src/java/org/apache/fop/fonts/EmbedFontInfo.java | 41 ++++- src/java/org/apache/fop/fonts/FontCache.java | 174 ++++++++++++++++++--- src/java/org/apache/fop/fonts/FontLoader.java | 17 +- src/java/org/apache/fop/fonts/LazyFont.java | 4 +- .../fop/fonts/autodetect/FontFileFinder.java | 7 +- .../fop/fonts/autodetect/FontInfoFinder.java | 124 ++++++++++----- .../apache/fop/fonts/truetype/FontFileReader.java | 22 ++- .../org/apache/fop/fonts/truetype/TTFFile.java | 69 +++++++- .../apache/fop/fonts/truetype/TTFFontLoader.java | 38 ++++- .../fop/render/PrintRendererConfigurator.java | 31 ++-- .../org/apache/fop/render/java2d/FontSetup.java | 2 +- status.xml | 4 + 15 files changed, 449 insertions(+), 210 deletions(-) delete mode 100644 src/java/org/apache/fop/fonts/CachedFontInfo.java (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml index 423eaad11..070ca8203 100644 --- a/src/documentation/content/xdocs/trunk/fonts.xml +++ b/src/documentation/content/xdocs/trunk/fonts.xml @@ -308,6 +308,11 @@ java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar org.apache.fop.fonts.apps.TTFReader -ttcname "MS Mincho" msmincho.ttc msminch.xml +

                                                                                        + Alternatively, the individual sub-fonts of a TrueType Collections can be selected + using the "sub-font" attribute on the "font" element. That means that generating + an XML font metrics file for TrueType collections is not necessary anymore. +

                                                                                        Register Fonts with FOP diff --git a/src/foschema/fop-configuration.xsd b/src/foschema/fop-configuration.xsd index c4d9ac47f..94f690342 100644 --- a/src/foschema/fop-configuration.xsd +++ b/src/foschema/fop-configuration.xsd @@ -210,6 +210,7 @@ + diff --git a/src/java/org/apache/fop/fonts/CachedFontInfo.java b/src/java/org/apache/fop/fonts/CachedFontInfo.java deleted file mode 100644 index 3de3cfd4e..000000000 --- a/src/java/org/apache/fop/fonts/CachedFontInfo.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.fonts; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; - -import org.apache.commons.io.FileUtils; - -/** - * Font info stored in the cache - */ -public class CachedFontInfo extends EmbedFontInfo { - - /** Serialization Version UID */ - private static final long serialVersionUID = 240028291961081894L; - - /** file modify date (if available) */ - private long lastModified = -1; - - /** - * Returns a file given a list of urls - * @param urls array of possible font urls - * @return file font file - */ - public static File getFileFromUrls(String[] urls) { - for (int i = 0; i < urls.length; i++) { - String urlStr = urls[i]; - if (urlStr != null) { - File fontFile = null; - if (urlStr.startsWith("file:")) { - try { - URL url = new URL(urlStr); - fontFile = FileUtils.toFile(url); - } catch (MalformedURLException mfue) { - // do nothing - } - } - if (fontFile == null) { - fontFile = new File(urlStr); - } - if (fontFile.exists() && fontFile.canRead()) { - return fontFile; - } - } - } - return null; - } - - /** - * Default constructor - * @param metricsFile metrics file - * @param kerning kerning - * @param fontTriplets font triplets - * @param embedFile embed file - * @param lastModified timestamp that this font was last modified - */ - public CachedFontInfo(String metricsFile, boolean kerning, List fontTriplets, - String embedFile, long lastModified) { - super(metricsFile, kerning, fontTriplets, embedFile); - this.lastModified = lastModified; - } - - /** - * Constructor - * @param fontInfo an existing embed font info - */ - public CachedFontInfo(EmbedFontInfo fontInfo) { - super(fontInfo.metricsFile, fontInfo.kerning, fontInfo.fontTriplets, fontInfo.embedFile); - // try and determine modified date - File fontFile = getFileFromUrls(new String[] {embedFile, metricsFile}); - if (fontFile != null ) { - this.lastModified = fontFile.lastModified(); - } - } - - /** - * Gets the modified timestamp for font file (not always available) - * @return modified timestamp - */ - public long lastModified() { - return this.lastModified; - } - - /** - * Gets the modified timestamp for font file - * (used for the purposes of font info caching) - * @param lastModified modified font file timestamp - */ - public void setLastModified(long lastModified) { - this.lastModified = lastModified; - } - - /** - * @return string representation of this object - * {@inheritDoc} - */ - public String toString() { - return super.toString() + ", lastModified=" + lastModified; - } -} diff --git a/src/java/org/apache/fop/fonts/EmbedFontInfo.java b/src/java/org/apache/fop/fonts/EmbedFontInfo.java index 58dcbf142..8bda40532 100644 --- a/src/java/org/apache/fop/fonts/EmbedFontInfo.java +++ b/src/java/org/apache/fop/fonts/EmbedFontInfo.java @@ -28,7 +28,7 @@ import java.util.List; public class EmbedFontInfo implements Serializable { /** Serialization Version UID */ - private static final long serialVersionUID = -9075848379822693399L; + private static final long serialVersionUID = 8755432068669997367L; /** filename of the metrics file */ protected String metricsFile; @@ -38,20 +38,27 @@ public class EmbedFontInfo implements Serializable { protected boolean kerning; /** the list of associated font triplets */ protected List fontTriplets; - + + /** the PostScript name of the font */ + protected String postScriptName = null; + /** the sub-fontname of the font (used for TrueType Collections, null otherwise) */ + protected String subFontName = null; + /** * Main constructor * @param metricsFile Path to the xml file containing font metrics * @param kerning True if kerning should be enabled * @param fontTriplets List of font triplets to associate with this font * @param embedFile Path to the embeddable font file (may be null) + * @param subFontName the sub-fontname used for TrueType Collections (null otherwise) */ public EmbedFontInfo(String metricsFile, boolean kerning, - List fontTriplets, String embedFile) { + List fontTriplets, String embedFile, String subFontName) { this.metricsFile = metricsFile; this.embedFile = embedFile; this.kerning = kerning; this.fontTriplets = fontTriplets; + this.subFontName = subFontName; } /** @@ -86,9 +93,35 @@ public class EmbedFontInfo implements Serializable { return fontTriplets; } + /** + * Returns the sub-fontname name of the font. This is primarily used for TrueType Collections + * to select one of the sub-fonts. For all other fonts, this is always null. + * @return the sub-fontname (or null) + */ + public String getSubFontName() { + return this.subFontName; + } + + /** + * Returns the PostScript name of the font. + * @return the PostScript name + */ + public String getPostScriptName() { + return postScriptName; + } + + /** + * Sets the PostScript name of the font + * @param postScriptName the PostScript name + */ + public void setPostScriptName(String postScriptName) { + this.postScriptName = postScriptName; + } + /** {@inheritDoc} */ public String toString() { return "metrics-url=" + metricsFile + ",embed-url=" + embedFile - + ", kerning=" + kerning + ", font-triplet=" + fontTriplets; + + ", kerning=" + kerning + ", font-triplet=" + fontTriplets + + (getSubFontName() != null ? ", sub-font=" + getSubFontName() : ""); } } diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index 13afa5a65..fcf26dafb 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -26,8 +26,12 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; import java.util.Map; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -61,10 +65,11 @@ public final class FontCache implements Serializable { /** change lock */ private transient Object changeLock = new Object(); - /** master mapping of font url -> font info */ - private Map fontMap = new java.util.HashMap(); + /** master mapping of font url -> font info. This needs to be + * a list, since a TTC file may contain more than 1 font. */ + private Map fontfileMap = new java.util.HashMap(); //Map - /** mapping of font url -> file modified date */ + /** mapping of font url -> file modified date (for all fonts that have failed to load) */ private Map failedFontMap = new java.util.HashMap(); /** @@ -216,7 +221,7 @@ public final class FontCache implements Serializable { */ public boolean containsFont(String embedUrl) { if (embedUrl != null) { - return fontMap.containsKey(embedUrl); + return fontfileMap.containsKey(embedUrl); } return false; } @@ -228,44 +233,99 @@ public final class FontCache implements Serializable { */ public boolean containsFont(EmbedFontInfo fontInfo) { if (fontInfo != null) { - return fontMap.containsKey(getCacheKey(fontInfo)); + return fontfileMap.containsKey(getCacheKey(fontInfo)); } return false; } /** - * adds a font info to cache + * Tries to identify a File instance from an array of URLs. If there's no file URL in the + * array, the method returns null. + * @param urls array of possible font urls + * @return file font file + */ + public static File getFileFromUrls(String[] urls) { + for (int i = 0; i < urls.length; i++) { + String urlStr = urls[i]; + if (urlStr != null) { + File fontFile = null; + if (urlStr.startsWith("file:")) { + try { + URL url = new URL(urlStr); + fontFile = FileUtils.toFile(url); + } catch (MalformedURLException mfue) { + // do nothing + } + } + if (fontFile == null) { + fontFile = new File(urlStr); + } + if (fontFile.exists() && fontFile.canRead()) { + return fontFile; + } + } + } + return null; + } + + /** + * Adds a font info to cache * @param fontInfo font info */ public void addFont(EmbedFontInfo fontInfo) { String cacheKey = getCacheKey(fontInfo); synchronized (changeLock) { - if (!containsFont(cacheKey)) { + CachedFontFile cachedFontFile; + if (containsFont(cacheKey)) { + cachedFontFile = (CachedFontFile)fontfileMap.get(cacheKey); + if (!cachedFontFile.containsFont(fontInfo)) { + cachedFontFile.put(fontInfo); + } + } else { + // try and determine modified date + File fontFile = getFileFromUrls(new String[] + {fontInfo.getEmbedFile(), fontInfo.getMetricsFile()}); + long lastModified = (fontFile != null ? fontFile.lastModified() : -1); + cachedFontFile = new CachedFontFile(lastModified); if (log.isTraceEnabled()) { log.trace("Font added to cache: " + cacheKey); } - if (fontInfo instanceof CachedFontInfo) { - fontMap.put(cacheKey, fontInfo); - } else { - fontMap.put(cacheKey, new CachedFontInfo(fontInfo)); - } + cachedFontFile.put(fontInfo); + fontfileMap.put(cacheKey, cachedFontFile); changed = true; } } } /** - * returns a font from the cache + * Returns a font from the cache. * @param embedUrl font info - * @return boolean + * @return CachedFontFile object */ - public CachedFontInfo getFont(String embedUrl) { + public CachedFontFile getFontFile(String embedUrl) { if (containsFont(embedUrl)) { - return (CachedFontInfo)fontMap.get(embedUrl); + return (CachedFontFile)fontfileMap.get(embedUrl); } return null; } + /** + * Returns the EmbedFontInfo instances belonging to a font file. If the font file was + * modified since it was cached the entry is removed and null is returned. + * @param embedUrl the font URL + * @param lastModified the last modified date/time of the font file + * @return the EmbedFontInfo instances or null if there's no cached entry or if it is outdated + */ + public EmbedFontInfo[] getFontInfos(String embedUrl, long lastModified) { + CachedFontFile cff = getFontFile(embedUrl); + if (cff.lastModified() == lastModified) { + return cff.getEmbedFontInfos(); + } else { + removeFont(embedUrl); + return null; + } + } + /** * removes font from cache * @param embedUrl embed url @@ -276,7 +336,7 @@ public final class FontCache implements Serializable { if (log.isTraceEnabled()) { log.trace("Font removed from cache: " + embedUrl); } - fontMap.remove(embedUrl); + fontfileMap.remove(embedUrl); changed = true; } } @@ -326,9 +386,87 @@ public final class FontCache implements Serializable { if (log.isTraceEnabled()) { log.trace("Font cache cleared."); } - fontMap.clear(); + fontfileMap.clear(); failedFontMap.clear(); changed = true; } } + + /** + * Retrieve the last modified date/time of a URL. + * @param url the URL + * @return the last modified date/time + */ + public static long getLastModified(URL url) { + try { + URLConnection conn = url.openConnection(); + try { + return conn.getLastModified(); + } finally { + //An InputStream is created even if it's not accessed, but we need to close it. + IOUtils.closeQuietly(conn.getInputStream()); + } + } catch (IOException e) { + // Should never happen, because URL must be local + log.debug("IOError: " + e.getMessage()); + return 0; + } + } + + private static class CachedFontFile implements Serializable { + /** file modify date (if available) */ + private long lastModified = -1; + + private Map filefontsMap = new java.util.HashMap(); //Map + + public CachedFontFile(long lastModified) { + setLastModified(lastModified); + } + + void put(EmbedFontInfo efi) { + filefontsMap.put(efi.getPostScriptName(), efi); + } + + public boolean containsFont(EmbedFontInfo efi) { + if (efi.getPostScriptName() != null) { + return filefontsMap.containsKey(efi.getPostScriptName()); + } + return false; + } + + public Map getFilefontsMap() { + return filefontsMap; + } + + public EmbedFontInfo[] getEmbedFontInfos() { + return (EmbedFontInfo[])this.filefontsMap.values().toArray( + new EmbedFontInfo[this.filefontsMap.size()]); + } + + /** + * Gets the modified timestamp for font file (not always available) + * @return modified timestamp + */ + public long lastModified() { + return this.lastModified; + } + + /** + * Gets the modified timestamp for font file + * (used for the purposes of font info caching) + * @param lastModified modified font file timestamp + */ + public void setLastModified(long lastModified) { + this.lastModified = lastModified; + } + + /** + * @return string representation of this object + * {@inheritDoc} + */ + public String toString() { + return super.toString() + ", lastModified=" + lastModified; + } + + } } diff --git a/src/java/org/apache/fop/fonts/FontLoader.java b/src/java/org/apache/fop/fonts/FontLoader.java index 1fa328a0a..69c55ceae 100644 --- a/src/java/org/apache/fop/fonts/FontLoader.java +++ b/src/java/org/apache/fop/fonts/FontLoader.java @@ -71,36 +71,39 @@ public abstract class FontLoader { /** * Loads a custom font from a File. In the case of Type 1 fonts, the PFB file must be specified. * @param fontFile the File representation of the font + * @param subFontName the sub-fontname of a font (for TrueType Collections, null otherwise) * @param resolver the font resolver to use when resolving URIs * @return the newly loaded font * @throws IOException In case of an I/O error */ - public static CustomFont loadFont(File fontFile, FontResolver resolver) + public static CustomFont loadFont(File fontFile, String subFontName, FontResolver resolver) throws IOException { - return loadFont(fontFile.getAbsolutePath(), resolver); + return loadFont(fontFile.getAbsolutePath(), subFontName, resolver); } /** * Loads a custom font from an URL. In the case of Type 1 fonts, the PFB file must be specified. * @param fontUrl the URL representation of the font + * @param subFontName the sub-fontname of a font (for TrueType Collections, null otherwise) * @param resolver the font resolver to use when resolving URIs * @return the newly loaded font * @throws IOException In case of an I/O error */ - public static CustomFont loadFont(URL fontUrl, FontResolver resolver) + public static CustomFont loadFont(URL fontUrl, String subFontName, FontResolver resolver) throws IOException { - return loadFont(fontUrl.toExternalForm(), resolver); + return loadFont(fontUrl.toExternalForm(), subFontName, resolver); } /** * Loads a custom font from a URI. In the case of Type 1 fonts, the PFB file must be specified. * @param fontFileURI the URI to the font + * @param subFontName the sub-fontname of a font (for TrueType Collections, null otherwise) * @param resolver the font resolver to use when resolving URIs * @return the newly loaded font * @throws IOException In case of an I/O error */ - public static CustomFont loadFont(String fontFileURI, FontResolver resolver) + public static CustomFont loadFont(String fontFileURI, String subFontName, FontResolver resolver) throws IOException { fontFileURI = fontFileURI.trim(); boolean type1 = isType1(fontFileURI); @@ -108,7 +111,7 @@ public abstract class FontLoader { if (type1) { loader = new Type1FontLoader(fontFileURI, resolver); } else { - loader = new TTFFontLoader(fontFileURI, resolver); + loader = new TTFFontLoader(fontFileURI, subFontName, resolver); } return loader.getFont(); } @@ -121,7 +124,7 @@ public abstract class FontLoader { * @throws IOException In case of an I/O error * @throws MalformedURLException If an invalid URL is built */ - protected static InputStream openFontUri(FontResolver resolver, String uri) + public static InputStream openFontUri(FontResolver resolver, String uri) throws IOException, MalformedURLException { InputStream in = null; if (resolver != null) { diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index 8997069d4..07b5be305 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -44,6 +44,7 @@ public class LazyFont extends Typeface implements FontDescriptor { private String metricsFileName = null; private String fontEmbedPath = null; private boolean useKerning = false; + private String subFontName = null; private boolean isMetricsLoaded = false; private Typeface realFont = null; @@ -61,6 +62,7 @@ public class LazyFont extends Typeface implements FontDescriptor { this.metricsFileName = fontInfo.getMetricsFile(); this.fontEmbedPath = fontInfo.getEmbedFile(); this.useKerning = fontInfo.getKerning(); + this.subFontName = fontInfo.getSubFontName(); this.resolver = resolver; } @@ -123,7 +125,7 @@ public class LazyFont extends Typeface implements FontDescriptor { if (fontEmbedPath == null) { throw new RuntimeException("Cannot load font. No font URIs available."); } - realFont = FontLoader.loadFont(fontEmbedPath, resolver); + realFont = FontLoader.loadFont(fontEmbedPath, this.subFontName, resolver); } if (realFont instanceof FontDescriptor) { realFontDescriptor = (FontDescriptor) realFont; diff --git a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java index c35faf65d..d0f7b4f14 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java @@ -72,14 +72,15 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { } /** - * Font file filter. Currently searches for files with .ttf and .pfb extensions. + * Font file filter. Currently searches for files with .ttf, .ttc, .otf, and .pfb extensions. * @return IOFileFilter font file filter */ protected static IOFileFilter getFileFilter() { return FileFilterUtils.andFileFilter( FileFilterUtils.fileFileFilter(), - new WildcardFileFilter(new String[] {"*.ttf", "*.otf", "*.pfb"}, IOCase.INSENSITIVE) - //TODO Add *.ttc when support for it has been added to the auto-detection mech. + new WildcardFileFilter( + new String[] {"*.ttf", "*.otf", "*.pfb", "*.ttc"}, + IOCase.INSENSITIVE) ); } diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index 5fc0525c3..8207eb140 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -19,9 +19,8 @@ package org.apache.fop.fonts.autodetect; -import java.io.IOException; +import java.io.InputStream; import java.net.URL; -import java.net.URLConnection; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -32,7 +31,6 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.fonts.CachedFontInfo; import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.EmbedFontInfo; import org.apache.fop.fonts.Font; @@ -41,6 +39,10 @@ import org.apache.fop.fonts.FontLoader; import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.FontUtil; +import org.apache.fop.fonts.MultiByteFont; +import org.apache.fop.fonts.truetype.FontFileReader; +import org.apache.fop.fonts.truetype.TTFFile; +import org.apache.fop.fonts.truetype.TTFFontLoader; /** * Attempts to determine correct FontInfo @@ -131,8 +133,13 @@ public class FontInfoFinder { generateTripletsFromFont(customFont, fontTripletList); String embedUrl; embedUrl = fontUrl.toExternalForm(); + String subFontName = null; + if (customFont instanceof MultiByteFont) { + subFontName = ((MultiByteFont)customFont).getTTCName(); + } EmbedFontInfo fontInfo = new EmbedFontInfo(null, customFont.isKerningEnabled(), - fontTripletList, embedUrl); + fontTripletList, embedUrl, subFontName); + fontInfo.setPostScriptName(customFont.getFontName()); if (fontCache != null) { fontCache.addFont(fontInfo); } @@ -145,35 +152,21 @@ public class FontInfoFinder { * @param fontUrl font URL. Assumed to be local. * @param resolver font resolver used to resolve font * @param fontCache font cache (may be null) - * @return newly created embed font info + * @return an array of newly created embed font info. Generally, this array + * will have only one entry, unless the fontUrl is a TrueType Collection */ - public EmbedFontInfo find(URL fontUrl, FontResolver resolver, FontCache fontCache) { + public EmbedFontInfo[] find(URL fontUrl, FontResolver resolver, FontCache fontCache) { String embedUrl = null; embedUrl = fontUrl.toExternalForm(); long fileLastModified = -1; if (fontCache != null) { - try { - URLConnection conn = fontUrl.openConnection(); - try { - fileLastModified = conn.getLastModified(); - } finally { - //An InputStream is created even if it's not accessed, but we need to close it. - IOUtils.closeQuietly(conn.getInputStream()); - } - } catch (IOException e) { - // Should never happen, because URL must be local - log.debug("IOError: " + e.getMessage()); - fileLastModified = 0; - } + fileLastModified = FontCache.getLastModified(fontUrl); // firstly try and fetch it from cache before loading/parsing the font file if (fontCache.containsFont(embedUrl)) { - CachedFontInfo fontInfo = fontCache.getFont(embedUrl); - if (fontInfo.lastModified() == fileLastModified) { - return fontInfo; - } else { - // out of date cache item - fontCache.removeFont(embedUrl); + EmbedFontInfo[] fontInfos = fontCache.getFontInfos(embedUrl, fileLastModified); + if (fontInfos != null) { + return fontInfos; } // is this a previously failed parsed font? } else if (fontCache.isFailedFont(embedUrl, fileLastModified)) { @@ -184,20 +177,81 @@ public class FontInfoFinder { } } + // try to determine triplet information from font file CustomFont customFont = null; - try { - customFont = FontLoader.loadFont(fontUrl, resolver); - } catch (Exception e) { - //TODO Too verbose (it's an error but we don't care if some fonts can't be loaded) - if (log.isErrorEnabled()) { - log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage()); + + if (fontUrl.toExternalForm().endsWith(".ttc")) { + // Get a list of the TTC Font names + List ttcNames = null; //List + String fontFileURI = fontUrl.toExternalForm().trim(); + TTFFontLoader ttfLoader = new TTFFontLoader(fontFileURI, resolver); + InputStream in = null; + try { + in = FontLoader.openFontUri(resolver, fontFileURI); + TTFFile ttf = new TTFFile(); + FontFileReader reader = new FontFileReader(in); + ttcNames = ttf.getTTCnames(reader); + } catch (Exception e) { + log.error(e); + } finally { + IOUtils.closeQuietly(in); } - if (fontCache != null) { - fontCache.registerFailedFont(embedUrl, fileLastModified); + + List embedFontInfoList = new java.util.ArrayList(); //List + + // For each font name ... + //for (String fontName : ttcNames) { + Iterator ttcNamesIterator = ttcNames.iterator(); + while (ttcNamesIterator.hasNext()) { + String fontName = (String)ttcNamesIterator.next(); + + if (log.isDebugEnabled()) { + log.debug("Loading " + fontName); + } + try { + ttfLoader = new TTFFontLoader(fontFileURI, fontName, resolver); + customFont = ttfLoader.getFont(); + } catch (Exception e) { + //TODO Too verbose (it's an error but we don't care if some fonts can't be loaded) + //if (log.isErrorEnabled()) { + log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage()); + //} + if (fontCache != null) { + fontCache.registerFailedFont(embedUrl, fileLastModified); + } + continue; + } + EmbedFontInfo fi = fontInfoFromCustomFont(fontUrl, customFont, fontCache); + if (fi != null) { + embedFontInfoList.add(fi); + } + } + return (EmbedFontInfo[])embedFontInfoList.toArray( + new EmbedFontInfo[embedFontInfoList.size()]); + } else { + // The normal case + try { + customFont = FontLoader.loadFont(fontUrl, null, resolver); + } catch (Exception e) { + //TODO Too verbose (it's an error but we don't care if some fonts can't be loaded) + //if (log.isErrorEnabled()) { + log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage()); + //} + if (fontCache != null) { + fontCache.registerFailedFont(embedUrl, fileLastModified); + } + return null; + } + EmbedFontInfo fi = fontInfoFromCustomFont(fontUrl, customFont, fontCache); + if (fi != null) { + return new EmbedFontInfo[] {fi}; + } else { + return null; } - return null; } - return fontInfoFromCustomFont(fontUrl, customFont, fontCache); + + } + } diff --git a/src/java/org/apache/fop/fonts/truetype/FontFileReader.java b/src/java/org/apache/fop/fonts/truetype/FontFileReader.java index 18ac7ad0f..0d1af4785 100644 --- a/src/java/org/apache/fop/fonts/truetype/FontFileReader.java +++ b/src/java/org/apache/fop/fonts/truetype/FontFileReader.java @@ -19,9 +19,9 @@ package org.apache.fop.fonts.truetype; -import java.io.InputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import org.apache.commons.io.IOUtils; @@ -313,6 +313,26 @@ public class FontFileReader { return new String(tmp, encoding); } + /** + * Read an ISO-8859-1 string of len bytes. + * + * @param len The length of the string to read + * @return A String + * @throws IOException If EOF is reached + */ + public final String readTTFString(int len, int encodingID) throws IOException { + if ((len + current) > fsize) { + throw new java.io.EOFException("Reached EOF, file size=" + fsize); + } + + byte[] tmp = new byte[len]; + System.arraycopy(file, current, tmp, 0, len); + current += len; + final String encoding; + encoding = "UTF-16BE"; //Use this for all known encoding IDs for now + return new String(tmp, encoding); + } + /** * Return a copy of the internal array * diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index e60722331..8c5211e67 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -988,7 +988,10 @@ public class TTFFile { if (dirTabs.get("OS/2") != null) { seekTab(in, "OS/2", 2 * 2); this.usWeightClass = in.readTTFUShort(); + + // usWidthClass in.skip(2); + int fsType = in.readTTFUShort(); if (fsType == 2) { isEmbeddable = false; @@ -1123,7 +1126,12 @@ public class TTFFile { if (((platformID == 1 || platformID == 3) && (encodingID == 0 || encodingID == 1))) { in.seekSet(j + in.readTTFUShort()); - String txt = in.readTTFString(l); + String txt; + if (platformID == 3) { + txt = in.readTTFString(l, encodingID); + } else { + txt = in.readTTFString(l); + } if (log.isDebugEnabled()) { log.debug(platformID + " " @@ -1147,7 +1155,7 @@ public class TTFFile { } break; case 4: - if (fullName.length() == 0) { + if (fullName.length() == 0 || (platformID == 3 && languageID == 1033)) { fullName = txt; } break; @@ -1474,6 +1482,59 @@ public class TTFFile { } } + /** + * Return TTC font names + * @param in FontFileReader to read from + * @return True if not collection or font name present, false otherwise + * @throws IOException In case of an I/O problem + */ + public final List getTTCnames(FontFileReader in) throws IOException { + List fontNames = new java.util.ArrayList(); + + String tag = in.readTTFString(4); + + if ("ttcf".equals(tag)) { + // This is a TrueType Collection + in.skip(4); + + // Read directory offsets + int numDirectories = (int)in.readTTFULong(); + long[] dirOffsets = new long[numDirectories]; + for (int i = 0; i < numDirectories; i++) { + dirOffsets[i] = in.readTTFULong(); + } + + if (log.isDebugEnabled()) { + log.debug("This is a TrueType collection file with " + + numDirectories + " fonts"); + log.debug("Containing the following fonts: "); + } + + for (int i = 0; (i < numDirectories); i++) { + in.seekSet(dirOffsets[i]); + readDirTabs(in); + + readName(in); + + log.debug(fullName); + fontNames.add(fullName); + + // Reset names + notice = ""; + fullName = ""; + familyNames.clear(); + postScriptName = ""; + subFamilyName = ""; + } + + in.seekSet(0); + return fontNames; + } else { + log.error("Not a TTC!"); + return null; + } + } + /* * Helper classes, they are not very efficient, but that really * doesn't matter... @@ -1536,8 +1597,8 @@ public class TTFFile { * @throws IOException if unicodeIndex not found */ private Integer unicodeToGlyph(int unicodeIndex) throws IOException { - final Integer result = - (Integer) unicodeToGlyphMap.get(new Integer(unicodeIndex)); + final Integer result + = (Integer) unicodeToGlyphMap.get(new Integer(unicodeIndex)); if (result == null) { throw new IOException( "Glyph index not found for unicode value " + unicodeIndex); diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index 60a6948fc..9cd59b5b3 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -34,11 +34,12 @@ import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.MultiByteFont; /** - * Loads a font into memory directly from the original font file. + * Loads a TrueType font into memory directly from the original font file. */ public class TTFFontLoader extends FontLoader { private MultiByteFont multiFont; + private String subFontName; /** * Default constructor @@ -46,27 +47,50 @@ public class TTFFontLoader extends FontLoader { * @param resolver the FontResolver for font URI resolution */ public TTFFontLoader(String fontFileURI, FontResolver resolver) { + this(fontFileURI, null, resolver); + } + + /** + * Additional constructor for TrueType Collections. + * @param fontFileURI the URI representing the font file + * @param subFontName the sub-fontname of a font in a TrueType Collection (or null for normal + * TrueType fonts) + * @param resolver the FontResolver for font URI resolution + */ + public TTFFontLoader(String fontFileURI, String subFontName, FontResolver resolver) { super(fontFileURI, resolver); + this.subFontName = subFontName; } /** {@inheritDoc} */ protected void read() throws IOException { + read(this.subFontName); + } + + /** + * Reads a TrueType font. + * @param ttcFontName the TrueType sub-font name of TrueType Collection (may be null for + * normal TrueType fonts) + * @throws IOException if an I/O error occurs + */ + private void read(String ttcFontName) throws IOException { InputStream in = openFontUri(resolver, this.fontFileURI); try { TTFFile ttf = new TTFFile(); FontFileReader reader = new FontFileReader(in); - boolean supported = ttf.readFont(reader, null); + boolean supported = ttf.readFont(reader, ttcFontName); if (!supported) { throw new IOException("TrueType font is not supported: " + fontFileURI); } - buildFont(ttf); + buildFont(ttf, ttcFontName); loaded = true; } finally { IOUtils.closeQuietly(in); } } - - private void buildFont(TTFFile ttf) { + + + private void buildFont(TTFFile ttf, String ttcFontName) { if (ttf.isCFF()) { throw new UnsupportedOperationException( "OpenType fonts with CFF data are not supported, yet"); @@ -79,7 +103,7 @@ public class TTFFontLoader extends FontLoader { returnFont.setFullName(ttf.getFullName()); returnFont.setFamilyNames(ttf.getFamilyNames()); returnFont.setFontSubFamilyName(ttf.getSubFamilyName()); - //multiFont.setTTCName(ttcName) + multiFont.setTTCName(ttcFontName); returnFont.setCapHeight(ttf.getCapHeight()); returnFont.setXHeight(ttf.getXHeight()); returnFont.setAscender(ttf.getLowerCaseAscent()); @@ -91,7 +115,7 @@ public class TTFFontLoader extends FontLoader { returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle())); returnFont.setMissingWidth(0); returnFont.setWeight(ttf.getWeightClass()); - + multiFont.setCIDType(CIDFontType.CIDTYPE2); int[] wx = ttf.getWidths(); multiFont.setWidthArray(wx); diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index 0f0acd60d..2dbb88be1 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -36,10 +36,11 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.util.ClasspathResource; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FopFactory; -import org.apache.fop.fonts.CachedFontInfo; import org.apache.fop.fonts.EmbedFontInfo; import org.apache.fop.fonts.FontCache; import org.apache.fop.fonts.FontInfo; @@ -50,7 +51,6 @@ import org.apache.fop.fonts.FontUtil; import org.apache.fop.fonts.autodetect.FontFileFinder; import org.apache.fop.fonts.autodetect.FontInfoFinder; import org.apache.fop.util.LogUtil; -import org.apache.xmlgraphics.util.ClasspathResource; /** * Base Print renderer configurator (mostly handles font configuration) @@ -230,9 +230,20 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator URL fontUrl = (URL)iter.next(); // parse font to ascertain font info FontInfoFinder finder = new FontInfoFinder(); - EmbedFontInfo fontInfo = finder.find(fontUrl, resolver, fontCache); - if (fontInfo != null) { - fontInfoList.add(fontInfo); + //EmbedFontInfo fontInfo = finder.find(fontUrl, resolver, fontCache); + + //List embedFontInfoList = finder.find(fontUrl, resolver, fontCache); + EmbedFontInfo[] embedFontInfos = finder.find(fontUrl, resolver, fontCache); + + if (embedFontInfos == null) { + return; + } + + for (int i = 0, c = embedFontInfos.length; i < c; i++) { + EmbedFontInfo fontInfo = embedFontInfos[i]; + if (fontInfo != null) { + fontInfoList.add(fontInfo); + } } } } @@ -257,9 +268,10 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator */ public static EmbedFontInfo getFontInfoFromConfiguration( Configuration fontCfg, FontResolver fontResolver, boolean strict, FontCache fontCache) - throws FOPException { + throws FOPException { String metricsUrl = fontCfg.getAttribute("metrics-url", null); String embedUrl = fontCfg.getAttribute("embed-url", null); + String subFont = fontCfg.getAttribute("sub-font", null); if (metricsUrl == null && embedUrl == null) { LogUtil.handleError(log, "Font configuration without metric-url or embed-url", strict); @@ -296,7 +308,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator LogUtil.handleError(log, "font without font-triplet", strict); // if not strict try to determine font info from the embed/metrics url - File fontFile = CachedFontInfo.getFileFromUrls(new String[] {embedUrl, metricsUrl}); + File fontFile = FontCache.getFileFromUrls(new String[] {embedUrl, metricsUrl}); URL fontUrl; try { fontUrl = fontFile.toURI().toURL(); @@ -307,7 +319,8 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator } if (fontFile != null) { FontInfoFinder finder = new FontInfoFinder(); - return finder.find(fontUrl, fontResolver, fontCache); + EmbedFontInfo[] infos = finder.find(fontUrl, subFont, fontResolver, fontCache); + return infos[0]; //When subFont is set, only one font is returned } else { return null; } @@ -337,7 +350,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator } } - fontInfo = new EmbedFontInfo(metricsUrl, useKerning, tripleList, embedUrl); + fontInfo = new EmbedFontInfo(metricsUrl, useKerning, tripleList, embedUrl, subFont); if (fontCache != null) { if (!fontCache.containsFont(fontInfo)) { diff --git a/src/java/org/apache/fop/render/java2d/FontSetup.java b/src/java/org/apache/fop/render/java2d/FontSetup.java index 752335521..ade457d95 100644 --- a/src/java/org/apache/fop/render/java2d/FontSetup.java +++ b/src/java/org/apache/fop/render/java2d/FontSetup.java @@ -304,7 +304,7 @@ public class FontSetup { Source fontSource = resolver.resolve(configFontInfo.getEmbedFile()); font = new CustomFontMetricsMapper(fontMetrics, fontSource); } else { - CustomFont fontMetrics = FontLoader.loadFont(fontFile, resolver); + CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, resolver); font = new CustomFontMetricsMapper(fontMetrics); } diff --git a/status.xml b/status.xml index 6d245a3d2..4bd080975 100644 --- a/status.xml +++ b/status.xml @@ -58,6 +58,10 @@ Added SVG support for AFP (GOCA). --> + + Added support for auto-configuring TrueType Collections. XML font metrics files for + *.ttc fonts are not required anymore. + When a JPEG image is embedded, an optionally embedded color profile is filtered out as it's already embedded separately in the PDF file. -- cgit v1.2.3 From 9bccefa52425d4ce58d9230e60c2ea2ee11540d7 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 3 Apr 2008 08:13:50 +0000 Subject: Oops. Fixed a last-minute change that broke the build. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@644213 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/PrintRendererConfigurator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index 2dbb88be1..ccff3baa1 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -319,7 +319,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator } if (fontFile != null) { FontInfoFinder finder = new FontInfoFinder(); - EmbedFontInfo[] infos = finder.find(fontUrl, subFont, fontResolver, fontCache); + EmbedFontInfo[] infos = finder.find(fontUrl, fontResolver, fontCache); return infos[0]; //When subFont is set, only one font is returned } else { return null; -- cgit v1.2.3 From 3465436b86cf3153adfd9e275f9da72c6847086c Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 4 Apr 2008 12:19:50 +0000 Subject: Bugzilla #44743: Added a public accessor for reference to the current page to PDFGraphics2D. Submitted by: Yegor Kozlov git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@644691 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/svg/PDFGraphics2D.java | 14 +++++++++++--- status.xml | 3 +++ 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index f6a7cbc3b..1e23a6f20 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -304,7 +304,15 @@ public class PDFGraphics2D extends AbstractGraphics2D { } /** - * Set the Grpahics context. + * Gets the PDF reference of the current page. + * @return the PDF reference of the current page + */ + public String getPageReference() { + return this.pageRef; + } + + /** + * Set the Graphics context. * @param c the graphics context to use */ public void setGraphicContext(GraphicContext c) { @@ -390,7 +398,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { if (linkType != PDFLink.EXTERNAL) { String pdfdest = "/FitR " + dest; resourceContext.addAnnotation( - pdfDoc.getFactory().makeLink(rect, pageRef, pdfdest)); + pdfDoc.getFactory().makeLink(rect, getPageReference(), pdfdest)); } else { resourceContext.addAnnotation( pdfDoc.getFactory().makeLink(rect, dest, linkType, 0)); @@ -958,7 +966,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { PDFResources res = pdfDoc.getFactory().makeResources(); PDFResourceContext context = new PDFResourceContext(res); PDFGraphics2D pattGraphic = new PDFGraphics2D(textAsShapes, specialFontInfo, - pdfDoc, context, pageRef, + pdfDoc, context, getPageReference(), "", 0); pattGraphic.setGraphicContext(new GraphicContext()); pattGraphic.gc.validateTransformStack(); diff --git a/status.xml b/status.xml index 4bd080975..a70aebb4d 100644 --- a/status.xml +++ b/status.xml @@ -58,6 +58,9 @@ Added SVG support for AFP (GOCA). --> + + Added a public accessor for reference to the current page to PDFGraphics2D. + Added support for auto-configuring TrueType Collections. XML font metrics files for *.ttc fonts are not required anymore. -- cgit v1.2.3 From c8398fb8fb8998f534daee7e4ff42600792898a6 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 4 Apr 2008 12:40:22 +0000 Subject: Bugzilla #44744: Disable drawString(AttributedCharacterIterator, float, float) as it contains bugs and rely on the fallback implementation from AbstractGraphics2D. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@644697 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/svg/PDFGraphics2D.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 1e23a6f20..05c30ef50 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -50,8 +50,6 @@ import java.awt.image.renderable.RenderableImage; import java.io.IOException; import java.io.OutputStream; import java.io.StringWriter; -import java.text.AttributedCharacterIterator; -import java.text.CharacterIterator; import java.util.List; import java.util.Map; @@ -1520,7 +1518,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { * @see #setTransform * @see #setComposite * @see #setClip - */ + *//* TODO Reimplement for higher efficiency similar to the way it was done in PDFTextPainter public void drawString(AttributedCharacterIterator iterator, float x, float y) { preparePainting(); @@ -1585,7 +1583,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { } currentStream.write("ET\n"); - } + }*/ /** * Fills the interior of a Shape using the settings of the -- cgit v1.2.3 From 81b2489b3492093b197d99da83dc517001bc0ecc Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Sat, 5 Apr 2008 14:11:50 +0000 Subject: Fixed broken links. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@645104 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/0.94/upgrading.xml | 2 +- src/documentation/content/xdocs/0.95/upgrading.xml | 2 +- src/documentation/content/xdocs/trunk/upgrading.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/0.94/upgrading.xml b/src/documentation/content/xdocs/0.94/upgrading.xml index b9bec0d66..3446dcab3 100644 --- a/src/documentation/content/xdocs/0.94/upgrading.xml +++ b/src/documentation/content/xdocs/0.94/upgrading.xml @@ -77,7 +77,7 @@
                                                                                      • Extensions and Renderers written for version 0.20.5 will not work with the new code! The new FOP - extension for Barcode4J is available since + extension for Barcode4J is available since January 2007.
                                                                                      • diff --git a/src/documentation/content/xdocs/0.95/upgrading.xml b/src/documentation/content/xdocs/0.95/upgrading.xml index 77925fbf8..d2f808c57 100644 --- a/src/documentation/content/xdocs/0.95/upgrading.xml +++ b/src/documentation/content/xdocs/0.95/upgrading.xml @@ -78,7 +78,7 @@
                                                                                      • Extensions and Renderers written for version 0.20.5 will not work with the new code! The new FOP - extension for Barcode4J is available since + extension for Barcode4J is available since January 2007.
                                                                                      • diff --git a/src/documentation/content/xdocs/trunk/upgrading.xml b/src/documentation/content/xdocs/trunk/upgrading.xml index 25e63ace8..8b4f109a3 100644 --- a/src/documentation/content/xdocs/trunk/upgrading.xml +++ b/src/documentation/content/xdocs/trunk/upgrading.xml @@ -79,7 +79,7 @@
                                                                                      • Extensions and Renderers written for version 0.20.5 will not work with the new code! The new FOP - extension for Barcode4J is available since + extension for Barcode4J is available since January 2007.
                                                                                      • -- cgit v1.2.3 From 53a32144019d2158cd14336ff83d131337a1cb84 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 14 Apr 2008 11:53:29 +0000 Subject: Merged branch https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ProcessingFeedback into Trunk. Changes on branch: ........ r615153 | jeremias | 2008-01-25 10:07:21 +0100 (Fr, 25 Jan 2008) | 1 line Created temporary branch for processing feedback. ........ r615155 | jeremias | 2008-01-25 10:11:59 +0100 (Fr, 25 Jan 2008) | 1 line Initial commit of what I've built already for those who prefer code to minimalistic design docs. ........ r615278 | jeremias | 2008-01-25 18:25:00 +0100 (Fr, 25 Jan 2008) | 1 line EventProducer interfaces now operational. ........ r615773 | jeremias | 2008-01-28 10:06:16 +0100 (Mo, 28 Jan 2008) | 1 line No casting in client code when creating EventProducer instances. ........ r616242 | vhennebert | 2008-01-29 11:34:45 +0100 (Di, 29 Jan 2008) | 3 lines Trick to avoid hard-coding the class name of EventProducer in the source file. Feel free to revert if it's not ok. ........ r616900 | jeremias | 2008-01-30 21:59:31 +0100 (Mi, 30 Jan 2008) | 1 line Generate event model XMLs in to the build directory: build/gensrc and build/test-gensrc (the latter is new and needs to be setup as source folder in your IDE!) ........ r616907 | jeremias | 2008-01-30 22:12:59 +0100 (Mi, 30 Jan 2008) | 1 line Added an XMLResourceBundle that uses an XML file instead of a properties file to load the translations. The XML format is the same as for Cocoon's XMLResourceBundle. ........ r617097 | vhennebert | 2008-01-31 11:53:21 +0100 (Do, 31 Jan 2008) | 2 lines Minor typo + slight improvement of Javadoc ........ r617176 | jeremias | 2008-01-31 19:14:19 +0100 (Do, 31 Jan 2008) | 5 lines Renamed FopEvent to Event as suggested by Simon. EventProducerCollectorTask.java now reads the EventSeverity from a doclet tag. Added generation of EventProducer translations (including simple merging, no validation, yet) EventFormatter introduced (only basic functionality, yet). Added a simple EventListener implementation that uses EventFormatter to convert the events to human-readable, localized messages that are sent to the log via Commons Logging. ........ r617362 | jeremias | 2008-02-01 08:18:07 +0100 (Fr, 01 Feb 2008) | 1 line Some remaining rename operations based on an earlier discussion. ........ r617413 | jeremias | 2008-02-01 10:46:26 +0100 (Fr, 01 Feb 2008) | 2 lines Extracted formatting functionality into utility class AdvancedMessageFormat.java. AdvancedMessageFormat.java now supports conditional sub-groups (delimited by []). ........ r618682 | jeremias | 2008-02-05 17:07:08 +0100 (Di, 05 Feb 2008) | 1 line Add support for special object formatters (where toString() isn't good enough). ATM, it's hard-coded but could later be hooked into dynamic discovery if we have multiple such formatters. The SAX Locator is the only example for now. ........ r618686 | jeremias | 2008-02-05 17:12:56 +0100 (Di, 05 Feb 2008) | 3 lines Hooked most of FONode into the new event mechanism. The FOUserAgent provides a DefaultEventBroadcaster instance. If a producer method declares throwing an exception, the event is automatically marked FATAL and the dynamic proxy throws an exception right after notifying the listeners. The exceptions are created through the EventExceptionManager. It currently contains only one exception factory for ValidationException. If we need more such factories it's better to register them dynamically. Right now, they're hard-coded. ........ r619313 | jeremias | 2008-02-07 10:14:15 +0100 (Do, 07 Feb 2008) | 1 line Make sure no events are now just silently swallowed because after upgrading a user doesn't know about the event system. ........ r619314 | jeremias | 2008-02-07 10:14:46 +0100 (Do, 07 Feb 2008) | 1 line Log what translation file is being written. ........ r619320 | jeremias | 2008-02-07 10:31:00 +0100 (Do, 07 Feb 2008) | 2 lines FObj hooked into the event system. Code reduction using a protected method on FONode to acquire a FOValidationEventProducer. ........ r619359 | jeremias | 2008-02-07 11:59:19 +0100 (Do, 07 Feb 2008) | 2 lines Fop's QName now extends XGCommons' QName to initiate a transition. Hooked PropertyList into the event mechanism. ........ r631252 | jeremias | 2008-02-26 16:24:33 +0100 (Di, 26 Feb 2008) | 1 line Removed superfluous warning. ........ r631268 | jeremias | 2008-02-26 17:08:11 +0100 (Di, 26 Feb 2008) | 1 line Deprecated two methods which are a problem for localization. Also helps finding additional spots to switch over to the event mechanism. ........ r633852 | jeremias | 2008-03-05 15:20:24 +0100 (Mi, 05 Mrz 2008) | 1 line Add severity to formatting parameters. ........ r633855 | jeremias | 2008-03-05 15:21:57 +0100 (Mi, 05 Mrz 2008) | 4 lines Added support for additional field styles: {,if,,} {,equals,,,} ........ r633856 | jeremias | 2008-03-05 15:24:04 +0100 (Mi, 05 Mrz 2008) | 2 lines Javadocs and TODOs. EventListeners can change the event severity. ........ r633857 | jeremias | 2008-03-05 15:27:08 +0100 (Mi, 05 Mrz 2008) | 4 lines Javadocs. Moved out event listener registration into a CompositeEventListener. Event broadcaster uses the events effective severity, not the initial value (for the case where listeners override the initial value). Set up a special EventBroadCaster in the FOUserAgent that filters events through a class (FOValidationEventListenerProxy) that adjusts the event severity for relaxed validation. ........ r633858 | jeremias | 2008-03-05 15:32:07 +0100 (Mi, 05 Mrz 2008) | 2 lines Instead of always decentrally checking whether strict validation is enabled or not, this is now done in a special event listener. The event producer method caller simply indicates whether it can recover from the error condition and continue. Started switching to event production in table FOs. ........ r634027 | jeremias | 2008-03-05 21:58:35 +0100 (Mi, 05 Mrz 2008) | 7 lines Moved AdvancedMessageFormat into its own package. AdvancedMessageFormat got the following added functionality: - Alternative conditional regions [ bla {field}] -> [ bla {field1}| even more bla {field2}] - Functions: functions get access to the parameters and they can produce an object that is then formatted ({#gatherContextInfo}) - "if" and "equals" format moved to top-level classes and added by dynamic registration. EventFormatter now supports includes in the form {{includeName}} so you can include other entries from the resource bundle for better reuse. Some more events in table code. ........ r634031 | jeremias | 2008-03-05 22:05:22 +0100 (Mi, 05 Mrz 2008) | 1 line SVN Props ........ r634208 | jeremias | 2008-03-06 11:26:52 +0100 (Do, 06 Mrz 2008) | 2 lines Improved context gathering. Moved GatherContextInfoFunction to an inner class of FONode to reduce visibilities. ........ r634209 | jeremias | 2008-03-06 11:28:14 +0100 (Do, 06 Mrz 2008) | 1 line Made FOPException localizable. ........ r634280 | jeremias | 2008-03-06 15:38:30 +0100 (Do, 06 Mrz 2008) | 2 lines ExceptionFactory is now dynamically registered. More table warnings and errors switch to events. ........ r634326 | jeremias | 2008-03-06 17:08:16 +0100 (Do, 06 Mrz 2008) | 1 line Remaining table FOs switched to events. ........ r634328 | jeremias | 2008-03-06 17:09:21 +0100 (Do, 06 Mrz 2008) | 1 line Deprecated FOP's QName. Mixing with Commons' variant only produces problems. ........ r634381 | jeremias | 2008-03-06 20:12:57 +0100 (Do, 06 Mrz 2008) | 2 lines Made the "invalidChild" event fully localizable by adding a "lookup" field for the optional rule to be displayed. And a few switches to the event system. ........ r634692 | jeremias | 2008-03-07 15:31:43 +0100 (Fr, 07 Mrz 2008) | 1 line More FO tree stuff switched to events. ........ r634712 | jeremias | 2008-03-07 16:19:21 +0100 (Fr, 07 Mrz 2008) | 1 line Avoid an NPE that says nothing (ex. could happen if the message template is wrong). ........ r634738 | jeremias | 2008-03-07 17:38:21 +0100 (Fr, 07 Mrz 2008) | 2 lines Non-FO children were not properly run through validation by FOTreeBuilder. Unified the way that non-FO elements are validated. Some FOs were already fixed. I now fixed the rest, so foreign elements can occur everywhere. ........ r637833 | jeremias | 2008-03-17 12:01:41 +0100 (Mo, 17 Mrz 2008) | 1 line Exception while cloning for RetrieveMarker to be handled by user as suggested by Andreas. ........ r637835 | jeremias | 2008-03-17 12:03:31 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a RuntimeException of no other Exception class is specified for an event as a fallback if someone just sets the event severity to FATAL. ........ r637838 | jeremias | 2008-03-17 12:06:10 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a meaningful exception when the property name is wrong. Otherwise, there will be an ArrayIndexOutOfBoundsException. ........ r637859 | jeremias | 2008-03-17 13:35:26 +0100 (Mo, 17 Mrz 2008) | 1 line Throw a meaningful exception when the property name is wrong. Otherwise, there will be an ArrayIndexOutOfBoundsException. ........ r637938 | jeremias | 2008-03-17 16:19:51 +0100 (Mo, 17 Mrz 2008) | 1 line Switched pagination package to events. ........ r637947 | jeremias | 2008-03-17 16:45:16 +0100 (Mo, 17 Mrz 2008) | 1 line Removed unlocalizable validation helper methods. ........ r637952 | jeremias | 2008-03-17 16:59:02 +0100 (Mo, 17 Mrz 2008) | 1 line Events on FOTreeBuilder. ........ r638299 | jeremias | 2008-03-18 11:09:30 +0100 (Di, 18 Mrz 2008) | 2 lines Added support for java.util.text's ChoiceFormat to AdvancedMessageFormat. Reuse the regexes as constants. ........ r638302 | jeremias | 2008-03-18 11:17:06 +0100 (Di, 18 Mrz 2008) | 1 line Events for inline-level layout managers. ........ r638774 | jeremias | 2008-03-19 11:17:36 +0100 (Mi, 19 Mrz 2008) | 1 line Added DEBUG level. ........ r638777 | jeremias | 2008-03-19 11:23:40 +0100 (Mi, 19 Mrz 2008) | 3 lines Generalized FOValidationEventListenerProxy into FOPEventListenerProxy, the main proxy for FOP's own event manipulation proxy. Done because of support for overflow="hidden" vs. overflow="error-if-overflow". Switched block-level layout managers to events. Some cleanup along the way. ........ r639222 | jeremias | 2008-03-20 10:27:34 +0100 (Do, 20 Mrz 2008) | 2 lines Some initial work for event forwarding from Batik. Missing errors/exceptions converted to events in PageSequenceMaster. ........ r639270 | jeremias | 2008-03-20 13:50:35 +0100 (Do, 20 Mrz 2008) | 1 line Removed DEBUG event severity again. Promoted constrained geometry adjustment event to INFO level as per discussion. ........ r640395 | jeremias | 2008-03-24 13:39:13 +0100 (Mo, 24 Mrz 2008) | 3 lines Moved the creation of the fallback LoggingEventListener to FOUserAgent so event before the startDocument() SAX event arrive in the log. Dynamic discovery of event models. Renderers and extensions can register renderer-specific event models. Switched the most important parts of the renderers to events (maybe not everything is converted). ........ r640397 | jeremias | 2008-03-24 13:43:04 +0100 (Mo, 24 Mrz 2008) | 1 line Remaining fixcrlfs. Xalan likes to mix CRLF and LF on Windows. ........ r640398 | jeremias | 2008-03-24 13:43:54 +0100 (Mo, 24 Mrz 2008) | 1 line Ignore namespace declarations for property handling. ........ r640463 | jeremias | 2008-03-24 17:59:52 +0100 (Mo, 24 Mrz 2008) | 2 lines Event in area package. Exposed getUserAgent() in Renderer interface (was already public in AbstractRenderer). ........ r642972 | jeremias | 2008-03-31 14:18:39 +0200 (Mo, 31 Mrz 2008) | 1 line Code restructured a bit. ........ r642975 | jeremias | 2008-03-31 14:24:07 +0200 (Mo, 31 Mrz 2008) | 2 lines Plugged fonts package into the event subsystem. Note: I did not follow the same pattern as for the rest as the font package is to be considered FOP-external, so I just added a manual adapter for the FontEventListener. This demonstrates how an external library can be integrated with the event system. Missing warning for unknown formatting objects added. Warning is not issued by the ElementMappingRegistry anymore but by FOTreeBuilder which has access to more context information. ........ r642997 | jeremias | 2008-03-31 16:10:08 +0200 (Mo, 31 Mrz 2008) | 1 line Added an example to demonstrate how to write your own event listener and how to deal with the exceptions thrown in the process. ........ r642998 | jeremias | 2008-03-31 16:13:40 +0200 (Mo, 31 Mrz 2008) | 1 line Removed unused method. Event formatting should not be part of the Event class. Use EventFormatter.format(Event) instead. ........ r643066 | jeremias | 2008-03-31 19:18:54 +0200 (Mo, 31 Mrz 2008) | 1 line First part of the event subsystem documentation (DRAFT). ........ r643784 | jeremias | 2008-04-02 10:05:33 +0200 (Mi, 02 Apr 2008) | 1 line More documentation. ........ r643785 | jeremias | 2008-04-02 10:06:38 +0200 (Mi, 02 Apr 2008) | 1 line Some nits. ........ r643787 | jeremias | 2008-04-02 10:24:41 +0200 (Mi, 02 Apr 2008) | 1 line Completed javadocs ........ r643824 | jeremias | 2008-04-02 12:00:30 +0200 (Mi, 02 Apr 2008) | 1 line Javadocs. ........ r645847 | vhennebert | 2008-04-08 12:54:16 +0200 (Di, 08 Apr 2008) | 2 lines Minor typo fixes ........ r645848 | vhennebert | 2008-04-08 12:58:30 +0200 (Di, 08 Apr 2008) | 2 lines Another small typo fix ........ r647678 | jeremias | 2008-04-14 09:20:26 +0200 (Mo, 14 Apr 2008) | 1 line Renamed *EventProducer.Factory.create() to *EventProducer.Provider.get() to better reflect what the method does (instances may be cached and reused). ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@647742 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 168 +++++-- .../java/embedding/events/ExampleEvents.java | 227 ++++++++++ .../java/embedding/events/missing-image.fo | 33 ++ lib/build/qdox-1.6.3.jar | Bin 0 -> 104078 bytes lib/build/qdox.LICENSE.txt | 201 +++++++++ .../apache/fop/tools/EventConventionException.java | 28 ++ .../apache/fop/tools/EventProducerCollector.java | 183 ++++++++ .../fop/tools/EventProducerCollectorTask.java | 200 +++++++++ .../org/apache/fop/tools/merge-translation.xsl | 55 +++ .../org/apache/fop/tools/model2translation.xsl | 35 ++ src/documentation/content/xdocs/site.xml | 1 + src/documentation/content/xdocs/trunk/events.xml | 422 ++++++++++++++++++ ...p.events.EventExceptionManager$ExceptionFactory | 4 + .../org.apache.fop.events.model.EventModelFactory | 7 + ...he.fop.util.text.AdvancedMessageFormat$Function | 1 + ...util.text.AdvancedMessageFormat$ObjectFormatter | 1 + ...fop.util.text.AdvancedMessageFormat$PartFactory | 6 + src/java/org/apache/fop/apps/FOPException.java | 21 + src/java/org/apache/fop/apps/FOUserAgent.java | 45 ++ .../org/apache/fop/area/AreaEventProducer.java | 91 ++++ src/java/org/apache/fop/area/AreaTreeHandler.java | 5 +- src/java/org/apache/fop/area/AreaTreeObject.java | 10 +- src/java/org/apache/fop/area/AreaTreeParser.java | 2 +- .../apache/fop/area/CachedRenderPagesModel.java | 77 ++-- src/java/org/apache/fop/area/PageViewport.java | 16 +- src/java/org/apache/fop/area/RenderPagesModel.java | 45 +- .../apache/fop/events/CompositeEventListener.java | 69 +++ .../apache/fop/events/DefaultEventBroadcaster.java | 160 +++++++ src/java/org/apache/fop/events/Event.java | 150 +++++++ .../org/apache/fop/events/EventBroadcaster.java | 61 +++ .../apache/fop/events/EventExceptionManager.java | 84 ++++ src/java/org/apache/fop/events/EventFormatter.java | 196 +++++++++ src/java/org/apache/fop/events/EventFormatter.xml | 101 +++++ .../org/apache/fop/events/EventFormatter_de.xml | 23 + src/java/org/apache/fop/events/EventListener.java | 37 ++ src/java/org/apache/fop/events/EventProducer.java | 31 ++ .../apache/fop/events/FOPEventListenerProxy.java | 73 +++ .../apache/fop/events/FOPEventModelFactory.java | 37 ++ .../apache/fop/events/LoggingEventListener.java | 92 ++++ .../fop/events/PropertyExceptionFactory.java | 47 ++ .../apache/fop/events/ResourceEventProducer.java | 136 ++++++ .../UnsupportedOperationExceptionFactory.java | 43 ++ .../fop/events/ValidationExceptionFactory.java | 51 +++ .../events/model/AbstractEventModelFactory.java | 61 +++ .../apache/fop/events/model/EventMethodModel.java | 198 +++++++++ .../org/apache/fop/events/model/EventModel.java | 135 ++++++ .../apache/fop/events/model/EventModelFactory.java | 33 ++ .../apache/fop/events/model/EventModelParser.java | 140 ++++++ .../fop/events/model/EventProducerModel.java | 105 +++++ .../org/apache/fop/events/model/EventSeverity.java | 82 ++++ src/java/org/apache/fop/fo/ElementMapping.java | 3 +- .../org/apache/fop/fo/ElementMappingRegistry.java | 2 +- src/java/org/apache/fop/fo/FOElementMapping.java | 2 +- src/java/org/apache/fop/fo/FOEventHandler.java | 2 + src/java/org/apache/fop/fo/FONode.java | 172 ++++++-- src/java/org/apache/fop/fo/FOText.java | 9 +- src/java/org/apache/fop/fo/FOTreeBuilder.java | 67 +-- .../apache/fop/fo/FOValidationEventProducer.java | 348 +++++++++++++++ src/java/org/apache/fop/fo/FObj.java | 77 ++-- src/java/org/apache/fop/fo/PropertyList.java | 67 ++- .../org/apache/fop/fo/expr/FromParentFunction.java | 8 +- .../apache/fop/fo/expr/InheritedPropFunction.java | 5 + .../fop/fo/expr/NearestSpecPropFunction.java | 5 + .../fop/fo/extensions/ExtensionElementMapping.java | 9 +- .../fop/fo/extensions/destination/Destination.java | 14 +- .../apache/fop/fo/flow/AbstractListItemPart.java | 29 +- .../fop/fo/flow/AbstractPageNumberCitation.java | 4 +- src/java/org/apache/fop/fo/flow/BasicLink.java | 21 +- src/java/org/apache/fop/fo/flow/BidiOverride.java | 32 +- .../org/apache/fop/fo/flow/BlockContainer.java | 18 +- src/java/org/apache/fop/fo/flow/Character.java | 7 +- .../org/apache/fop/fo/flow/ExternalGraphic.java | 18 +- src/java/org/apache/fop/fo/flow/Float.java | 7 +- src/java/org/apache/fop/fo/flow/Footnote.java | 8 +- src/java/org/apache/fop/fo/flow/FootnoteBody.java | 4 +- .../org/apache/fop/fo/flow/InitialPropertySet.java | 4 +- src/java/org/apache/fop/fo/flow/Inline.java | 33 +- .../org/apache/fop/fo/flow/InlineContainer.java | 18 +- .../apache/fop/fo/flow/InstreamForeignObject.java | 43 +- src/java/org/apache/fop/fo/flow/ListBlock.java | 18 +- src/java/org/apache/fop/fo/flow/ListItem.java | 32 +- src/java/org/apache/fop/fo/flow/Marker.java | 13 +- src/java/org/apache/fop/fo/flow/MultiCase.java | 3 +- .../org/apache/fop/fo/flow/MultiProperties.java | 9 +- .../org/apache/fop/fo/flow/MultiPropertySet.java | 7 +- src/java/org/apache/fop/fo/flow/MultiSwitch.java | 11 +- src/java/org/apache/fop/fo/flow/MultiToggle.java | 11 +- src/java/org/apache/fop/fo/flow/PageNumber.java | 4 +- .../org/apache/fop/fo/flow/RetrieveMarker.java | 31 +- src/java/org/apache/fop/fo/flow/Wrapper.java | 25 +- .../fop/fo/flow/table/FixedColRowGroupBuilder.java | 12 +- src/java/org/apache/fop/fo/flow/table/Table.java | 39 +- .../apache/fop/fo/flow/table/TableAndCaption.java | 47 +- .../org/apache/fop/fo/flow/table/TableBody.java | 29 +- .../org/apache/fop/fo/flow/table/TableCaption.java | 21 +- .../org/apache/fop/fo/flow/table/TableCell.java | 28 +- .../fop/fo/flow/table/TableCellContainer.java | 7 +- .../org/apache/fop/fo/flow/table/TableColumn.java | 21 +- .../fop/fo/flow/table/TableEventProducer.java | 159 +++++++ .../org/apache/fop/fo/flow/table/TableFObj.java | 29 +- .../org/apache/fop/fo/flow/table/TableRow.java | 13 +- .../fop/fo/pagination/AbstractPageSequence.java | 13 +- .../org/apache/fop/fo/pagination/ColorProfile.java | 21 +- .../pagination/ConditionalPageMasterReference.java | 16 +- .../org/apache/fop/fo/pagination/Declarations.java | 21 +- src/java/org/apache/fop/fo/pagination/Flow.java | 39 +- .../apache/fop/fo/pagination/LayoutMasterSet.java | 63 +-- .../fop/fo/pagination/PageNumberGenerator.java | 6 +- .../org/apache/fop/fo/pagination/PageSequence.java | 28 +- .../fop/fo/pagination/PageSequenceMaster.java | 38 +- .../fop/fo/pagination/PageSequenceWrapper.java | 19 +- src/java/org/apache/fop/fo/pagination/Region.java | 29 +- .../org/apache/fop/fo/pagination/RegionAfter.java | 14 +- .../org/apache/fop/fo/pagination/RegionBA.java | 6 +- .../org/apache/fop/fo/pagination/RegionBefore.java | 15 +- .../org/apache/fop/fo/pagination/RegionBody.java | 24 +- .../org/apache/fop/fo/pagination/RegionEnd.java | 18 +- .../org/apache/fop/fo/pagination/RegionSE.java | 6 +- .../org/apache/fop/fo/pagination/RegionStart.java | 15 +- .../RepeatablePageMasterAlternatives.java | 43 +- .../pagination/RepeatablePageMasterReference.java | 20 +- src/java/org/apache/fop/fo/pagination/Root.java | 20 +- .../org/apache/fop/fo/pagination/SideRegion.java | 6 +- .../apache/fop/fo/pagination/SimplePageMaster.java | 130 +++--- .../fo/pagination/SinglePageMasterReference.java | 16 +- .../apache/fop/fo/pagination/StaticContent.java | 18 +- src/java/org/apache/fop/fo/pagination/Title.java | 19 +- .../fop/fo/pagination/bookmarks/Bookmark.java | 37 +- .../fop/fo/pagination/bookmarks/BookmarkTitle.java | 17 +- .../fop/fo/pagination/bookmarks/BookmarkTree.java | 24 +- .../fop/fo/properties/XMLLangShorthandParser.java | 2 +- .../org/apache/fop/fonts/FontEventAdapter.java | 82 ++++ .../org/apache/fop/fonts/FontEventListener.java | 52 +++ src/java/org/apache/fop/fonts/FontInfo.java | 22 +- src/java/org/apache/fop/fonts/LazyFont.java | 1 + src/java/org/apache/fop/fonts/SingleByteFont.java | 28 +- src/java/org/apache/fop/fonts/Typeface.java | 12 + .../fop/fonts/autodetect/FontInfoFinder.java | 38 +- .../image/loader/batik/ImageConverterSVG2G2D.java | 31 +- .../fop/image/loader/batik/PreloaderSVG.java | 14 +- .../org/apache/fop/layoutmgr/AbstractBreaker.java | 8 +- .../fop/layoutmgr/BlockContainerLayoutManager.java | 44 +- .../fop/layoutmgr/BlockLevelEventProducer.java | 168 +++++++ .../fop/layoutmgr/BlockStackingLayoutManager.java | 10 +- .../layoutmgr/ExternalDocumentLayoutManager.java | 19 +- .../org/apache/fop/layoutmgr/LayoutException.java | 105 +++++ src/java/org/apache/fop/layoutmgr/PageBreaker.java | 33 +- .../fop/layoutmgr/PageBreakingAlgorithm.java | 43 +- .../org/apache/fop/layoutmgr/PageProvider.java | 10 +- .../fop/layoutmgr/StaticContentLayoutManager.java | 43 +- .../fop/layoutmgr/inline/ContentLayoutManager.java | 1 - .../layoutmgr/inline/InlineLevelEventProducer.java | 66 +++ .../fop/layoutmgr/inline/LeaderLayoutManager.java | 16 +- .../fop/layoutmgr/inline/LineLayoutManager.java | 14 +- .../apache/fop/layoutmgr/table/ColumnSetup.java | 15 +- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 12 +- .../fop/layoutmgr/table/TableLayoutManager.java | 18 +- .../fop/render/AbstractGenericSVGHandler.java | 29 +- .../fop/render/AbstractPathOrientedRenderer.java | 2 +- .../org/apache/fop/render/AbstractRenderer.java | 25 +- src/java/org/apache/fop/render/Renderer.java | 6 + .../apache/fop/render/RendererEventProducer.java | 53 +++ .../apache/fop/render/afp/AFPEventProducer.java | 63 +++ .../org/apache/fop/render/afp/AFPEventProducer.xml | 4 + .../org/apache/fop/render/afp/AFPRenderer.java | 30 +- .../render/bitmap/BitmapRendererEventProducer.java | 80 ++++ .../render/bitmap/BitmapRendererEventProducer.xml | 6 + .../org/apache/fop/render/bitmap/PNGRenderer.java | 17 +- .../org/apache/fop/render/bitmap/TIFFRenderer.java | 11 +- .../apache/fop/render/java2d/Java2DRenderer.java | 17 +- .../apache/fop/render/java2d/Java2DSVGHandler.java | 63 +-- .../apache/fop/render/pcl/PCLEventProducer.java | 66 +++ .../org/apache/fop/render/pcl/PCLEventProducer.xml | 4 + .../org/apache/fop/render/pcl/PCLGenerator.java | 12 +- .../org/apache/fop/render/pcl/PCLRenderer.java | 33 +- .../apache/fop/render/pcl/PCLRendererContext.java | 3 +- .../apache/fop/render/pdf/PDFEventProducer.java | 64 +++ .../org/apache/fop/render/pdf/PDFEventProducer.xml | 4 + .../org/apache/fop/render/pdf/PDFRenderer.java | 100 +++-- .../org/apache/fop/render/pdf/PDFSVGHandler.java | 29 +- .../org/apache/fop/render/ps/PSEventProducer.java | 65 +++ .../org/apache/fop/render/ps/PSEventProducer.xml | 4 + src/java/org/apache/fop/render/ps/PSRenderer.java | 29 +- .../org/apache/fop/render/ps/PSSVGHandler.java | 68 +-- .../org/apache/fop/render/ps/ResourceHandler.java | 8 +- .../ps/extensions/AbstractPSCommentElement.java | 5 +- .../ps/extensions/AbstractPSExtensionElement.java | 6 +- .../ps/extensions/AbstractPSExtensionObject.java | 13 +- .../ps/extensions/PSCommentAfterElement.java | 1 + .../ps/extensions/PSCommentBeforeElement.java | 1 + .../render/ps/extensions/PSExtensionHandler.java | 20 +- .../ps/extensions/PSPageSetupCodeElement.java | 5 +- .../ps/extensions/PSSetPageDeviceElement.java | 11 +- .../render/ps/extensions/PSSetupCodeElement.java | 5 +- .../apache/fop/render/rtf/RTFEventProducer.java | 94 ++++ .../org/apache/fop/render/rtf/RTFEventProducer.xml | 8 + src/java/org/apache/fop/render/rtf/RTFHandler.java | 153 ++++--- .../org/apache/fop/render/xml/XMLRenderer.java | 2 +- src/java/org/apache/fop/svg/SVGEventProducer.java | 89 ++++ src/java/org/apache/fop/svg/SVGUserAgent.java | 131 ++---- .../org/apache/fop/svg/SimpleSVGUserAgent.java | 126 ++++++ src/java/org/apache/fop/util/QName.java | 94 +--- .../org/apache/fop/util/XMLResourceBundle.java | 398 +++++++++++++++++ .../fop/util/text/AdvancedMessageFormat.java | 487 +++++++++++++++++++++ .../org/apache/fop/util/text/ChoiceFieldPart.java | 91 ++++ .../org/apache/fop/util/text/EqualsFieldPart.java | 92 ++++ .../apache/fop/util/text/GlyphNameFieldPart.java | 89 ++++ .../org/apache/fop/util/text/HexFieldPart.java | 84 ++++ src/java/org/apache/fop/util/text/IfFieldPart.java | 116 +++++ .../org/apache/fop/util/text/LocatorFormatter.java | 42 ++ .../org.apache.fop.events.model.EventModelFactory | 1 + test/java/org/apache/fop/UtilityCodeTestSuite.java | 4 + .../org/apache/fop/events/BasicEventTestCase.java | 95 ++++ .../fop/events/FOPTestEventModelFactory.java | 37 ++ .../org/apache/fop/events/TestEventProducer.java | 48 ++ .../fop/util/AdvancedMessageFormatTestCase.java | 183 ++++++++ .../apache/fop/util/XMLResourceBundleTestCase.java | 60 +++ .../apache/fop/util/XMLResourceBundleTestCase.xml | 5 + .../fop/util/XMLResourceBundleTestCase_de.xml | 4 + .../apache/fop/util/invalid-translation-file.xml | 5 + 220 files changed, 9154 insertions(+), 1628 deletions(-) create mode 100644 examples/embedding/java/embedding/events/ExampleEvents.java create mode 100644 examples/embedding/java/embedding/events/missing-image.fo create mode 100644 lib/build/qdox-1.6.3.jar create mode 100644 lib/build/qdox.LICENSE.txt create mode 100644 src/codegen/java/org/apache/fop/tools/EventConventionException.java create mode 100644 src/codegen/java/org/apache/fop/tools/EventProducerCollector.java create mode 100644 src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java create mode 100644 src/codegen/java/org/apache/fop/tools/merge-translation.xsl create mode 100644 src/codegen/java/org/apache/fop/tools/model2translation.xsl create mode 100644 src/documentation/content/xdocs/trunk/events.xml create mode 100644 src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory create mode 100644 src/java/META-INF/services/org.apache.fop.events.model.EventModelFactory create mode 100644 src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$Function create mode 100644 src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$ObjectFormatter create mode 100644 src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$PartFactory create mode 100644 src/java/org/apache/fop/area/AreaEventProducer.java create mode 100644 src/java/org/apache/fop/events/CompositeEventListener.java create mode 100644 src/java/org/apache/fop/events/DefaultEventBroadcaster.java create mode 100644 src/java/org/apache/fop/events/Event.java create mode 100644 src/java/org/apache/fop/events/EventBroadcaster.java create mode 100644 src/java/org/apache/fop/events/EventExceptionManager.java create mode 100644 src/java/org/apache/fop/events/EventFormatter.java create mode 100644 src/java/org/apache/fop/events/EventFormatter.xml create mode 100644 src/java/org/apache/fop/events/EventFormatter_de.xml create mode 100644 src/java/org/apache/fop/events/EventListener.java create mode 100644 src/java/org/apache/fop/events/EventProducer.java create mode 100644 src/java/org/apache/fop/events/FOPEventListenerProxy.java create mode 100644 src/java/org/apache/fop/events/FOPEventModelFactory.java create mode 100644 src/java/org/apache/fop/events/LoggingEventListener.java create mode 100644 src/java/org/apache/fop/events/PropertyExceptionFactory.java create mode 100644 src/java/org/apache/fop/events/ResourceEventProducer.java create mode 100644 src/java/org/apache/fop/events/UnsupportedOperationExceptionFactory.java create mode 100644 src/java/org/apache/fop/events/ValidationExceptionFactory.java create mode 100644 src/java/org/apache/fop/events/model/AbstractEventModelFactory.java create mode 100644 src/java/org/apache/fop/events/model/EventMethodModel.java create mode 100644 src/java/org/apache/fop/events/model/EventModel.java create mode 100644 src/java/org/apache/fop/events/model/EventModelFactory.java create mode 100644 src/java/org/apache/fop/events/model/EventModelParser.java create mode 100644 src/java/org/apache/fop/events/model/EventProducerModel.java create mode 100644 src/java/org/apache/fop/events/model/EventSeverity.java create mode 100644 src/java/org/apache/fop/fo/FOValidationEventProducer.java create mode 100644 src/java/org/apache/fop/fo/flow/table/TableEventProducer.java create mode 100644 src/java/org/apache/fop/fonts/FontEventAdapter.java create mode 100644 src/java/org/apache/fop/fonts/FontEventListener.java create mode 100644 src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java create mode 100644 src/java/org/apache/fop/layoutmgr/LayoutException.java create mode 100644 src/java/org/apache/fop/layoutmgr/inline/InlineLevelEventProducer.java create mode 100644 src/java/org/apache/fop/render/RendererEventProducer.java create mode 100644 src/java/org/apache/fop/render/afp/AFPEventProducer.java create mode 100644 src/java/org/apache/fop/render/afp/AFPEventProducer.xml create mode 100644 src/java/org/apache/fop/render/bitmap/BitmapRendererEventProducer.java create mode 100644 src/java/org/apache/fop/render/bitmap/BitmapRendererEventProducer.xml create mode 100644 src/java/org/apache/fop/render/pcl/PCLEventProducer.java create mode 100644 src/java/org/apache/fop/render/pcl/PCLEventProducer.xml create mode 100644 src/java/org/apache/fop/render/pdf/PDFEventProducer.java create mode 100644 src/java/org/apache/fop/render/pdf/PDFEventProducer.xml create mode 100644 src/java/org/apache/fop/render/ps/PSEventProducer.java create mode 100644 src/java/org/apache/fop/render/ps/PSEventProducer.xml create mode 100644 src/java/org/apache/fop/render/rtf/RTFEventProducer.java create mode 100644 src/java/org/apache/fop/render/rtf/RTFEventProducer.xml create mode 100644 src/java/org/apache/fop/svg/SVGEventProducer.java create mode 100644 src/java/org/apache/fop/svg/SimpleSVGUserAgent.java create mode 100644 src/java/org/apache/fop/util/XMLResourceBundle.java create mode 100644 src/java/org/apache/fop/util/text/AdvancedMessageFormat.java create mode 100644 src/java/org/apache/fop/util/text/ChoiceFieldPart.java create mode 100644 src/java/org/apache/fop/util/text/EqualsFieldPart.java create mode 100644 src/java/org/apache/fop/util/text/GlyphNameFieldPart.java create mode 100644 src/java/org/apache/fop/util/text/HexFieldPart.java create mode 100644 src/java/org/apache/fop/util/text/IfFieldPart.java create mode 100644 src/java/org/apache/fop/util/text/LocatorFormatter.java create mode 100644 test/java/META-INF/services/org.apache.fop.events.model.EventModelFactory create mode 100644 test/java/org/apache/fop/events/BasicEventTestCase.java create mode 100644 test/java/org/apache/fop/events/FOPTestEventModelFactory.java create mode 100644 test/java/org/apache/fop/events/TestEventProducer.java create mode 100644 test/java/org/apache/fop/util/AdvancedMessageFormatTestCase.java create mode 100644 test/java/org/apache/fop/util/XMLResourceBundleTestCase.java create mode 100644 test/java/org/apache/fop/util/XMLResourceBundleTestCase.xml create mode 100644 test/java/org/apache/fop/util/XMLResourceBundleTestCase_de.xml create mode 100644 test/java/org/apache/fop/util/invalid-translation-file.xml (limited to 'src') diff --git a/build.xml b/build.xml index 2169003f8..5a72154f7 100644 --- a/build.xml +++ b/build.xml @@ -118,13 +118,15 @@ list of possible build targets. - - - - - + + + + + + + @@ -362,7 +364,7 @@ list of possible build targets. - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -390,31 +498,22 @@ list of possible build targets. - - - - - - - - - - - + + + - + + - + @@ -452,13 +551,13 @@ list of possible build targets. - + - + @@ -487,13 +586,13 @@ list of possible build targets. - + - + @@ -608,14 +707,14 @@ list of possible build targets. - + - + @@ -693,6 +792,7 @@ list of possible build targets. + + + + + + + + + + + + + + + diff --git a/examples/embedding/java/embedding/events/ExampleEvents.java b/examples/embedding/java/embedding/events/ExampleEvents.java new file mode 100644 index 000000000..9c52e4ba1 --- /dev/null +++ b/examples/embedding/java/embedding/events/ExampleEvents.java @@ -0,0 +1,227 @@ +/* + * 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 embedding.events; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamSource; + +import org.xml.sax.SAXException; + +import org.apache.commons.io.IOUtils; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.events.Event; +import org.apache.fop.events.EventFormatter; +import org.apache.fop.events.EventListener; +import org.apache.fop.events.model.EventSeverity; + +/** + * This class demonstrates how to register an event listener with FOP so you can customize + * FOP's error behaviour. + */ +public class ExampleEvents { + + // configure fopFactory as desired + private FopFactory fopFactory = FopFactory.newInstance(); + + /** + * Converts an FO file to a PDF file using FOP + * @param fo the FO file + * @param pdf the target PDF file + * @throws IOException In case of an I/O problem + * @throws FOPException In case of a FOP problem + * @throws TransformerException In case of a problem with XSLT + */ + public void convertFO2PDF(URL fo, File pdf) + throws IOException, FOPException, TransformerException { + + OutputStream out = null; + + try { + //Create the user agent for this processing run + FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); + + //Adding a simple logging listener that writes to stdout and stderr + foUserAgent.getEventBroadcaster().addEventListener(new SysOutEventListener()); + + // Add your own event listener + foUserAgent.getEventBroadcaster().addEventListener(new MyEventListener()); + + // configure foUserAgent further as desired + + // Setup output stream. Note: Using BufferedOutputStream + // for performance reasons (helpful with FileOutputStreams). + out = new FileOutputStream(pdf); + out = new BufferedOutputStream(out); + + // Construct fop with desired output format + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out); + + // Setup JAXP using identity transformer + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(); // identity transformer + + // Setup input stream + Source src = new StreamSource(fo.toExternalForm()); + + // Resulting SAX events (the generated FO) must be piped through to FOP + Result res = new SAXResult(fop.getDefaultHandler()); + + // Start XSLT transformation and FOP processing + transformer.transform(src, res); + + } finally { + IOUtils.closeQuietly(out); + } + } + + private static class MyEventListener implements EventListener { + + public void processEvent(Event event) { + if ("org.apache.fop.events.ResourceEventProducer.imageNotFound" + .equals(event.getEventID())) { + + //Get the FileNotFoundException that's part of the event's parameters + FileNotFoundException fnfe = (FileNotFoundException)event.getParam("fnfe"); + + System.out.println("---=== imageNotFound Event for " + event.getParam("uri") + + "!!! ===---"); + //Stop processing when an image could not be found. Otherwise, FOP would just + //continue without the image! + + System.out.println("Throwing a RuntimeException..."); + throw new RuntimeException(EventFormatter.format(event), fnfe); + } else { + //ignore all other events + } + } + + } + + /** A simple event listener that writes the events to stdout and sterr. */ + private static class SysOutEventListener implements EventListener { + + /** {@inheritDoc} */ + public void processEvent(Event event) { + String msg = EventFormatter.format(event); + EventSeverity severity = event.getSeverity(); + if (severity == EventSeverity.INFO) { + System.out.println("[INFO ] " + msg); + } else if (severity == EventSeverity.WARN) { + System.out.println("[WARN ] " + msg); + } else if (severity == EventSeverity.ERROR) { + System.err.println("[ERROR] " + msg); + } else if (severity == EventSeverity.FATAL) { + System.err.println("[FATAL] " + msg); + } else { + assert false; + } + } + } + + + /** + * This method extracts the original exception from some exception. The exception + * might be nested multiple levels deep. + * @param t the Throwable to inspect + * @return the original Throwable or the method parameter t if there are no nested Throwables. + */ + private static Throwable getOriginalThrowable(Throwable t) { + if (t instanceof SAXException) { + SAXException saxe = (SAXException)t; + if (saxe.getException() != null) { + return getOriginalThrowable(saxe.getException()); + } else { + return saxe; + } + } else { + if (t.getCause() != null) { + return getOriginalThrowable(t.getCause()); + } else { + return t; + } + } + } + + /** + * Main method. + * @param args command-line arguments + */ + public static void main(String[] args) { + try { + System.out.println("FOP ExampleEvents\n"); + System.out.println("Preparing..."); + + //Setup directories + File baseDir = new File("."); + File outDir = new File(baseDir, "out"); + outDir.mkdirs(); + + //Setup input and output files + URL fo = ExampleEvents.class.getResource("missing-image.fo"); + File pdffile = new File(outDir, "out.pdf"); + + System.out.println("Input: XSL-FO (" + fo.toExternalForm() + ")"); + System.out.println("Output: PDF (" + pdffile + ")"); + System.out.println(); + System.out.println("Transforming..."); + + ExampleEvents app = new ExampleEvents(); + + try { + app.convertFO2PDF(fo, pdffile); + } catch (TransformerException te) { + //Note: We don't get the original exception here! + //FOP needs to embed the exception in a SAXException and the TraX transformer + //again wraps the SAXException in a TransformerException. Even our own + //RuntimeException just wraps the original FileNotFoundException. + //So we need to unpack to get the original exception (about three layers deep). + Throwable originalThrowable = getOriginalThrowable(te); + originalThrowable.printStackTrace(System.err); + System.out.println("Aborted!"); + System.exit(-1); + } + + System.out.println("Success!"); + } catch (Exception e) { + //Some other error (shouldn't happen in this example) + e.printStackTrace(System.err); + System.exit(-1); + } + } + +} diff --git a/examples/embedding/java/embedding/events/missing-image.fo b/examples/embedding/java/embedding/events/missing-image.fo new file mode 100644 index 000000000..2c55f66ce --- /dev/null +++ b/examples/embedding/java/embedding/events/missing-image.fo @@ -0,0 +1,33 @@ + + + + + + + + + + + + + The following image is not available: + + + + + diff --git a/lib/build/qdox-1.6.3.jar b/lib/build/qdox-1.6.3.jar new file mode 100644 index 000000000..3e99cb064 Binary files /dev/null and b/lib/build/qdox-1.6.3.jar differ diff --git a/lib/build/qdox.LICENSE.txt b/lib/build/qdox.LICENSE.txt new file mode 100644 index 000000000..3e4e3d004 --- /dev/null +++ b/lib/build/qdox.LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/src/codegen/java/org/apache/fop/tools/EventConventionException.java b/src/codegen/java/org/apache/fop/tools/EventConventionException.java new file mode 100644 index 000000000..675f4a0ca --- /dev/null +++ b/src/codegen/java/org/apache/fop/tools/EventConventionException.java @@ -0,0 +1,28 @@ +/* + * 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.tools; + +public class EventConventionException extends Exception { + + public EventConventionException(String message) { + super(message); + } + +} diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java new file mode 100644 index 000000000..e42395ae7 --- /dev/null +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java @@ -0,0 +1,183 @@ +/* + * 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.tools; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.Map; + +import org.apache.fop.events.EventProducer; +import org.apache.fop.events.model.EventMethodModel; +import org.apache.fop.events.model.EventModel; +import org.apache.fop.events.model.EventProducerModel; +import org.apache.fop.events.model.EventSeverity; + +import com.thoughtworks.qdox.JavaDocBuilder; +import com.thoughtworks.qdox.model.DefaultDocletTagFactory; +import com.thoughtworks.qdox.model.DocletTag; +import com.thoughtworks.qdox.model.DocletTagFactory; +import com.thoughtworks.qdox.model.JavaClass; +import com.thoughtworks.qdox.model.JavaMethod; +import com.thoughtworks.qdox.model.JavaParameter; +import com.thoughtworks.qdox.model.Type; + +/** + * Finds EventProducer interfaces and builds the event model for them. + */ +public class EventProducerCollector { + + private static final String CLASSNAME_EVENT_PRODUCER = EventProducer.class.getName(); + private static final Map PRIMITIVE_MAP; + + static { + Map m = new java.util.HashMap(); + m.put("boolean", Boolean.class); + m.put("byte", Byte.class); + m.put("char", Character.class); + m.put("short", Short.class); + m.put("int", Integer.class); + m.put("long", Long.class); + m.put("float", Float.class); + m.put("double", Double.class); + PRIMITIVE_MAP = Collections.unmodifiableMap(m); + } + + private DocletTagFactory tagFactory; + private EventModel model = new EventModel(); + + public EventProducerCollector() { + this.tagFactory = createDocletTagFactory(); + } + + protected DocletTagFactory createDocletTagFactory() { + return new DefaultDocletTagFactory(); + } + + public void scanFile(File src, String filename) + throws IOException, EventConventionException, ClassNotFoundException { + JavaDocBuilder builder = new JavaDocBuilder(this.tagFactory); + builder.addSource(src); + JavaClass[] classes = builder.getClasses(); + for (int i = 0, c = classes.length; i < c; i++) { + JavaClass clazz = classes[i]; + if (clazz.isInterface() && implementsInterface(clazz, CLASSNAME_EVENT_PRODUCER)) { + processEventProducerInterface(clazz, filename); + } + } + } + + private boolean implementsInterface(JavaClass clazz, String intf) { + JavaClass[] classes = clazz.getImplementedInterfaces(); + for (int i = 0, c = classes.length; i < c; i++) { + JavaClass cl = classes[i]; + if (cl.getFullyQualifiedName().equals(intf)) { + return true; + } + } + return false; + } + + /** + * Processes an EventProducer interface and creates an EventProducerModel from it. + * @param clazz the EventProducer interface + * @param javaFilename the filename of the Java source of the interface + * @throws EventConventionException if the event producer conventions are violated + * @throws ClassNotFoundException if a required class cannot be found + */ + protected void processEventProducerInterface(JavaClass clazz, String javaFilename) + throws EventConventionException, ClassNotFoundException { + EventProducerModel prodMeta = new EventProducerModel(clazz.getFullyQualifiedName()); + JavaMethod[] methods = clazz.getMethods(true); + for (int i = 0, c = methods.length; i < c; i++) { + JavaMethod method = methods[i]; + EventMethodModel methodMeta = createMethodModel(method); + prodMeta.addMethod(methodMeta); + } + this.model.addProducer(prodMeta); + } + + private EventMethodModel createMethodModel(JavaMethod method) + throws EventConventionException, ClassNotFoundException { + JavaClass clazz = method.getParentClass(); + //Check EventProducer conventions + if (!method.getReturns().isVoid()) { + throw new EventConventionException("All methods of interface " + + clazz.getFullyQualifiedName() + " must have return type 'void'!"); + } + String methodSig = clazz.getFullyQualifiedName() + "." + method.getCallSignature(); + JavaParameter[] params = method.getParameters(); + if (params.length < 1) { + throw new EventConventionException("The method " + methodSig + + " must have at least one parameter: 'Object source'!"); + } + Type firstType = params[0].getType(); + if (firstType.isPrimitive() || !"source".equals(params[0].getName())) { + throw new EventConventionException("The first parameter of the method " + methodSig + + " must be: 'Object source'!"); + } + + //build method model + DocletTag tag = method.getTagByName("event.severity"); + EventSeverity severity; + if (tag != null) { + severity = EventSeverity.valueOf(tag.getValue()); + } else { + severity = EventSeverity.INFO; + } + EventMethodModel methodMeta = new EventMethodModel( + method.getName(), severity); + if (params.length > 1) { + for (int j = 1, cj = params.length; j < cj; j++) { + JavaParameter p = params[j]; + Class type; + JavaClass pClass = p.getType().getJavaClass(); + if (p.getType().isPrimitive()) { + type = (Class)PRIMITIVE_MAP.get(pClass.getName()); + if (type == null) { + throw new UnsupportedOperationException( + "Primitive datatype not supported: " + pClass.getName()); + } + } else { + String className = pClass.getFullyQualifiedName(); + type = Class.forName(className); + } + methodMeta.addParameter(type, p.getName()); + } + } + Type[] exceptions = method.getExceptions(); + if (exceptions != null && exceptions.length > 0) { + //We only use the first declared exception because that is always thrown + JavaClass cl = exceptions[0].getJavaClass(); + methodMeta.setExceptionClass(cl.getFullyQualifiedName()); + methodMeta.setSeverity(EventSeverity.FATAL); //In case it's not set in the comments + } + return methodMeta; + } + + public EventModel getModel() { + return this.model; + } + + public void saveModelToXML(File modelFile) throws IOException { + getModel().saveToXML(modelFile); + } + +} diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java new file mode 100644 index 000000000..755e3da0b --- /dev/null +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java @@ -0,0 +1,200 @@ +/* + * 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.tools; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Iterator; +import java.util.List; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.URIResolver; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.w3c.dom.Node; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.selectors.FilenameSelector; + +public class EventProducerCollectorTask extends Task { + + private List filesets = new java.util.ArrayList(); + private File modelFile; + private File translationFile; + + /** {@inheritDoc} */ + public void execute() throws BuildException { + try { + EventProducerCollector collector = new EventProducerCollector(); + processFileSets(collector); + getModelFile().getParentFile().mkdirs(); + collector.saveModelToXML(getModelFile()); + log("Event model written to " + getModelFile()); + if (getTranslationFile() != null) { + updateTranslationFile(); + } + } catch (ClassNotFoundException e) { + throw new BuildException(e); + } catch (EventConventionException ece) { + throw new BuildException(ece); + } catch (IOException ioe) { + throw new BuildException(ioe); + } + } + + private static final String MODEL2TRANSLATION = "model2translation.xsl"; + private static final String MERGETRANSLATION = "merge-translation.xsl"; + + protected void updateTranslationFile() throws IOException { + try { + boolean resultExists = getTranslationFile().exists(); + SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + + //Generate fresh generated translation file as template + Source src = new StreamSource(getModelFile()); + StreamSource xslt1 = new StreamSource( + getClass().getResourceAsStream(MODEL2TRANSLATION)); + if (xslt1.getInputStream() == null) { + throw new FileNotFoundException(MODEL2TRANSLATION + " not found"); + } + DOMResult domres = new DOMResult(); + Transformer transformer = tFactory.newTransformer(xslt1); + transformer.transform(src, domres); + final Node generated = domres.getNode(); + + Node sourceDocument; + if (resultExists) { + //Load existing translation file into memory (because we overwrite it later) + src = new StreamSource(getTranslationFile()); + domres = new DOMResult(); + transformer = tFactory.newTransformer(); + transformer.transform(src, domres); + sourceDocument = domres.getNode(); + } else { + //Simply use generated as source document + sourceDocument = generated; + } + + //Generate translation file (with potentially new translations) + src = new DOMSource(sourceDocument); + Result res = new StreamResult(getTranslationFile()); + StreamSource xslt2 = new StreamSource( + getClass().getResourceAsStream(MERGETRANSLATION)); + if (xslt2.getInputStream() == null) { + throw new FileNotFoundException(MERGETRANSLATION + " not found"); + } + transformer = tFactory.newTransformer(xslt2); + transformer.setURIResolver(new URIResolver() { + public Source resolve(String href, String base) throws TransformerException { + if ("my:dom".equals(href)) { + return new DOMSource(generated); + } + return null; + } + }); + if (resultExists) { + transformer.setParameter("generated-url", "my:dom"); + } + transformer.transform(src, res); + if (resultExists) { + log("Translation file updated: " + getTranslationFile()); + } else { + log("Translation file generated: " + getTranslationFile()); + } + } catch (TransformerException te) { + throw new IOException(te.getMessage()); + } + } + + protected void processFileSets(EventProducerCollector collector) + throws IOException, EventConventionException, ClassNotFoundException { + Iterator iter = filesets.iterator(); + while (iter.hasNext()) { + FileSet fs = (FileSet)iter.next(); + DirectoryScanner ds = fs.getDirectoryScanner(getProject()); + String[] srcFiles = ds.getIncludedFiles(); + File directory = fs.getDir(getProject()); + for (int i = 0, c = srcFiles.length; i < c; i++) { + String filename = srcFiles[i]; + File src = new File(directory, filename); + collector.scanFile(src, filename); + } + } + } + + public void addFileset(FileSet set) { + filesets.add(set); + } + + public void setModelFile(File f) { + this.modelFile = f; + } + + public File getModelFile() { + return this.modelFile; + } + + public void setTranslationFile(File f) { + this.translationFile = f; + } + + public File getTranslationFile() { + return this.translationFile; + } + + public static void main(String[] args) { + try { + Project project = new Project(); + + EventProducerCollectorTask generator = new EventProducerCollectorTask(); + generator.setProject(project); + project.setName("Test"); + FileSet fileset = new FileSet(); + fileset.setDir(new File("test/java")); + + FilenameSelector selector = new FilenameSelector(); + selector.setName("**/*.java"); + fileset.add(selector); + generator.addFileset(fileset); + + File targetDir = new File("build/codegen1"); + targetDir.mkdirs(); + + generator.setModelFile(new File("D:/out.xml")); + generator.setTranslationFile(new File("D:/out1.xml")); + generator.execute(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/codegen/java/org/apache/fop/tools/merge-translation.xsl b/src/codegen/java/org/apache/fop/tools/merge-translation.xsl new file mode 100644 index 000000000..d15d22fd3 --- /dev/null +++ b/src/codegen/java/org/apache/fop/tools/merge-translation.xsl @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/codegen/java/org/apache/fop/tools/model2translation.xsl b/src/codegen/java/org/apache/fop/tools/model2translation.xsl new file mode 100644 index 000000000..a1cf404ee --- /dev/null +++ b/src/codegen/java/org/apache/fop/tools/model2translation.xsl @@ -0,0 +1,35 @@ + + + + + + + + + en + + + + + + + . + + + + diff --git a/src/documentation/content/xdocs/site.xml b/src/documentation/content/xdocs/site.xml index 18716903c..b0a3214e7 100644 --- a/src/documentation/content/xdocs/site.xml +++ b/src/documentation/content/xdocs/site.xml @@ -155,6 +155,7 @@ + diff --git a/src/documentation/content/xdocs/trunk/events.xml b/src/documentation/content/xdocs/trunk/events.xml new file mode 100644 index 000000000..d2fe5318c --- /dev/null +++ b/src/documentation/content/xdocs/trunk/events.xml @@ -0,0 +1,422 @@ + + + + + +
                                                                                        + Events/Processing Feedback + $Revision: 634267 $ +
                                                                                        + +
                                                                                        + Introduction +

                                                                                        + In versions until 0.20.5, FOP used + Avalon-style Logging where + it was possible to supply a logger per processing run. During the redesign + the logging infrastructure was switched over to + Commons Logging which is (like Log4J or + java.util.logging) a "static" logging framework (the logger is accessed through static + variables). This made it very difficult in a multi-threaded system to retrieve information + for a single processing run. +

                                                                                        +

                                                                                        + With FOP's event subsystem, we'd like to close this gap again and even go further. The + first point is to realize that we have two kinds of "logging". Firstly, we have the logging + infrastructure for the (FOP) developer who needs to be able to enable finer log messages + for certain parts of FOP to track down a certain problem. Secondly, we have the user who + would like to be informed about missing images, overflowing lines or substituted fonts. + These messages (or events) are targeted at less technical people and may ideally be + localized (translated). Furthermore, tool and solution builders would like to integrate + FOP into their own solutions. For example, an FO editor should be able to point the user + to the right place where a particular problem occurred while developing a document template. + Finally, some integrators would like to abort processing if a resource (an image or a font) + has not been found, while others would simply continue. The event system allows to + react on these events. +

                                                                                        +

                                                                                        + On this page, we won't discuss logging as such. We will show how the event subsystem can + be used for various tasks. We'll first look at the event subsystem from the consumer side. + Finally, the production of events inside FOP will be discussed (this is mostly interesting + for FOP developers only). +

                                                                                        +
                                                                                        +
                                                                                        + The consumer side +

                                                                                        + The event subsystem is located in the org.apache.fop.events package and its + base is the Event class. An instance is created for each event and is sent + to a set of EventListener instances by the EventBroadcaster. + An Event contains: +

                                                                                        +
                                                                                          +
                                                                                        • an event ID,
                                                                                        • +
                                                                                        • a source object (which generated the event),
                                                                                        • +
                                                                                        • a severity level (Info, Warning, Error and Fatal Error) and
                                                                                        • +
                                                                                        • a map of named parameters.
                                                                                        • +
                                                                                        +

                                                                                        + The EventFormatter class can be used to translate the events into + human-readable, localized messages. +

                                                                                        +

                                                                                        + A full example of what is shown here can be found in the + examples/embedding/java/embedding/events directory in the FOP distribution. + The example can also be accessed + via the web. +

                                                                                        +
                                                                                        + Writing an EventListener +

                                                                                        + The following code sample shows a very simple EventListener. It basically just sends + all events to System.out (stdout) or System.err (stderr) depending on the event severity. +

                                                                                        + +

                                                                                        + You can see that for every event the method processEvent of the + EventListener will be called. Inside this method you can do whatever + processing you would like including throwing a RuntimeException, if you want + to abort the current processing run. +

                                                                                        +

                                                                                        + The code above also shows how you can turn an event into a human-readable, localized + message that can be presented to a user. The EventFormatter class does + this for you. It provides additional methods if you'd like to explicitly specify + the locale. +

                                                                                        +

                                                                                        + It is possible to gather all events for a whole processing run so they can be + evaluated afterwards. However, care should be taken about memory consumption since + the events provide references to objects inside FOP which may themselves have + references to other objects. So holding on to these objects may mean that whole + object trees cannot be released! +

                                                                                        +
                                                                                        +
                                                                                        + Adding an EventListener +

                                                                                        + To register the event listener with FOP, get the EventBroadcaster which + is associated with the user agent (FOUserAgent) and add it there: +

                                                                                        + +

                                                                                        + Please note that this is done separately for each processing run, i.e. for each + new user agent. +

                                                                                        +
                                                                                        +
                                                                                        + An additional listener example +

                                                                                        + Here's an additional example of an event listener: +

                                                                                        +

                                                                                        + By default, FOP continues processing even if an image wasn't found. If you have + more strict requirements and want FOP to stop if an image is not available, you can + do something like the following: +

                                                                                        + +

                                                                                        + This throws a RuntimeException with the FileNotFoundException + as the cause. Further processing effectively stops in FOP. You can catch the exception + in your code and react as you see necessary. +

                                                                                        +
                                                                                        +
                                                                                        +
                                                                                        + The producer side (for FOP developers) +

                                                                                        + This section is primarily for FOP and FOP plug-in developers. It describes how to use + the event subsystem for producing events. +

                                                                                        + + The event package has been designed in order to be theoretically useful for use cases + outside FOP. If you think this is interesting independently from FOP, please talk to + us. + +
                                                                                        + Producing and sending an event +

                                                                                        + The basics are very simple. Just instantiate an Event object and fill + it with the necessary parameters. Then pass it to the EventBroadcaster + which distributes the events to the interested listeneners. Here's a code example: +

                                                                                        + +

                                                                                        + The Event.paramsBuilder() is a + fluent interface + to help with the build-up of the parameters. You could just as well instantiate a + Map (Map<String, Object>) and fill it with values. +

                                                                                        +
                                                                                        +
                                                                                        + The EventProducer interface +

                                                                                        + To simplify event production, the event subsystem provides the EventProducer + interface. You can create interfaces which extend EventProducer. These + interfaces will contain one method per event to be generated. By contract, each event + method must have as its first parameter a parameter named "source" (Type Object) which + indicates the object that generated the event. After that come an arbitrary number of + parameters of any type as needed by the event. +

                                                                                        +

                                                                                        + The event producer interface does not need to have any implementation. The implementation + is produced at runtime by a dynamic proxy created by DefaultEventBroadcaster. + The dynamic proxy creates Event instances for each method call against + the event producer interface. Each parameter (except "source") is added to the event's + parameter map. +

                                                                                        +

                                                                                        + To simplify the code needed to get an instance of the event producer interface it is + suggested to create a public inner provider class inside the interface. +

                                                                                        +

                                                                                        + Here's an example of such an event producer interface: +

                                                                                        + +

                                                                                        + To produce the same event as in the first example above, you'd use the following code: +

                                                                                        + +
                                                                                        +
                                                                                        + The event model +

                                                                                        + Inside an invocation handler for a dynamic proxy, there's no information about + the names of each parameter. The JVM doesn't provide it. The only thing you know is + the interface and method name. In order to properly fill the Event's + parameter map we need to know the parameter names. These are retrieved from an + event object model. This is found in the org.apache.fop.events.model + package. The data for the object model is retrieved from an XML representation of the + event model that is loaded as a resource. The XML representation is generated using an + Ant task at build time (ant resourcegen). The Ant task (found in + src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java) + scans FOP's sources for descendants of the EventProducer interface and + uses QDox to parse these interfaces. +

                                                                                        +

                                                                                        + Primarily, the QDox-based collector task records the parameters' names and types. + Furthermore, it extracts additional attributes embedded as Javadoc comments from + the methods. At the moment, the only such attribute is "@event.severity" which indicates + the default event severity (which can be changed by event listeners). The example event + producer above shows the Javadocs for an event method. +

                                                                                        +

                                                                                        + There's one more information that is extracted from the event producer information for + the event model: an optional primary exception. The first exception in the "throws" + declaration of an event method is noted. It is used to throw an exception from + the invocation handler if the event has an event severity of "FATAL" when all + listeners have been called (listeners can update the event severity). Please note + that an implementation of + org.apache.fop.events.EventExceptionManager$ExceptionFactory has to be + registered for the EventExceptionManager to be able to construct the + exception from an event. +

                                                                                        +

                                                                                        + For a given application, there can be multiple event models active at the same time. + In FOP, each renderer is considered to be a plug-in and provides its own specific + event model. The individual event models are provided through an + EventModelFactory. This interface is implemented for each event model + and registered through the service provider mechanism + (see the plug-ins section for details). +

                                                                                        +
                                                                                        +
                                                                                        + Event severity +

                                                                                        + Four different levels of severity for events has been defined: +

                                                                                        +
                                                                                          +
                                                                                        1. INFO: informational only
                                                                                        2. +
                                                                                        3. WARN: a Warning
                                                                                        4. +
                                                                                        5. ERROR: an error condition from which FOP can recover. FOP will continue processing.
                                                                                        6. +
                                                                                        7. FATAL: a fatal error which causes an exception in the end and FOP will stop processing.
                                                                                        8. +
                                                                                        +

                                                                                        + Event listeners can choose to ignore certain events based on their event severity. + Please note that you may recieve an event "twice" in a specific case: if there is + a fatal error an event is generated and sent to the listeners. After that an exception + is thrown with the same information and processing stops. If the fatal event is + shown to the user and the following exception is equally presented to the user it + may appear that the event is duplicated. Of course, the same information is just + published through two different channels. +

                                                                                        +
                                                                                        +
                                                                                        + Plug-ins to the event subsystem +

                                                                                        + The event subsystem is extensible. There are a number of extension points: +

                                                                                        +
                                                                                          +
                                                                                        • + org.apache.fop.events.model.EventModelFactory: Provides + an event model to the event subsystem. +
                                                                                        • +
                                                                                        • + org.apache.fop.events.EventExceptionManager$ExceptionFactory: + Creates exceptions for events, i.e. turns an event into a specific exception. +
                                                                                        • +
                                                                                        +

                                                                                        + The names in bold above are used as filenames for the service provider files that + are placed in the META-INF/services directory. That way, they are + automatically detected. This is a mechanism defined by the + JAR file specification. +

                                                                                        +
                                                                                        +
                                                                                        + Localization (L10n) +

                                                                                        + One goal of the event subsystem was to have localized (translated) event messages. + The EventFormatter class can be used to convert an event to a + human-readable message. Each EventProducer can provide its own XML-based + translation file. If there is none, a central translation file is used, called + "EventFormatter.xml" (found in the same directory as the EventFormatter + class). +

                                                                                        +

                                                                                        + The XML format used by the EventFormatter is the same as + Apache Cocoon's catalog format. Here's an example: +

                                                                                        + + + + [ (See position {loc})| (See {#gatherContextInfo})| (No context info available)] + + + RTF output requires that all table-columns for a table are defined. Output will be incorrect.{{locator}} + + + Ignored deferred event for {node} ({start,if,start,end}).{{locator}} + + +]]> +

                                                                                        + The example (extracted from the RTF handler's event producer) has message templates for + two event methods. The class used to do variable replacement in the templates is + org.apache.fop.util.text.AdvancedMessageFormat which is more powerful + than the MessageFormat classes provided by the Java class library + (java.util.text package). +

                                                                                        +

                                                                                        + "locator" is a template that is reused by the other message templates + by referencing it through "{{locator}}". This is some kind of include command. +

                                                                                        +

                                                                                        + Normal event parameters are accessed by name inside single curly braces, for example: + "{node}". For objects, this format just uses the toString() method to turn + the object into a string, unless there is an ObjectFormatter registered + for that type (there's an example for org.xml.sax.Locator). +

                                                                                        +

                                                                                        + The single curly braces pattern supports additional features. For example, it is possible + to do this: "{start,if,start,end}". "if" here is a special field modifier that evaluates + "start" as a boolean and if that is true returns the text right after the second comma + ("start"). Otherwise it returns the text after the third comma ("end"). The "equals" + modifier is similar to "if" but it takes as an additional (comma-separated) parameter + right after the "equals" modifier, a string that is compared to the value of the variable. + An example: {severity,equals,EventSeverity:FATAL,,some text} (this adds "some text" if + the severity is not FATAL). +

                                                                                        +

                                                                                        + Additional such modifiers can be added by implementing the + AdvancedMessageFormat$Part and AdvancedMessageFormat$PartFactory + interfaces. +

                                                                                        +

                                                                                        + Square braces can be used to specify optional template sections. The whole section will + be omitted if any of the variables used within are unavailable. Pipe (|) characters can + be used to specify alternative sub-templates (see "locator" above for an example). +

                                                                                        +

                                                                                        + Developers can also register a function (in the above example: + {#gatherContextInfo}) + to do more complex information rendering. These functions are implementations of the + AdvancedMessageFormat$Function interface. Please take care that this is + done in a locale-independent way as there is no locale information available, yet. +

                                                                                        +
                                                                                        +
                                                                                        + +
                                                                                        diff --git a/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory b/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory new file mode 100644 index 000000000..9fa7b8d04 --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory @@ -0,0 +1,4 @@ +org.apache.fop.events.ValidationExceptionFactory +org.apache.fop.events.PropertyExceptionFactory +org.apache.fop.events.UnsupportedOperationExceptionFactory +org.apache.fop.layoutmgr.LayoutException$LayoutExceptionFactory diff --git a/src/java/META-INF/services/org.apache.fop.events.model.EventModelFactory b/src/java/META-INF/services/org.apache.fop.events.model.EventModelFactory new file mode 100644 index 000000000..8dc13dbfd --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.events.model.EventModelFactory @@ -0,0 +1,7 @@ +org.apache.fop.events.FOPEventModelFactory +org.apache.fop.render.afp.AFPEventProducer$EventModelFactory +org.apache.fop.render.bitmap.BitmapRendererEventProducer$EventModelFactory +org.apache.fop.render.pcl.PCLEventProducer$EventModelFactory +org.apache.fop.render.pdf.PDFEventProducer$EventModelFactory +org.apache.fop.render.ps.PSEventProducer$EventModelFactory +org.apache.fop.render.rtf.RTFEventProducer$EventModelFactory diff --git a/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$Function b/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$Function new file mode 100644 index 000000000..375130f2a --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$Function @@ -0,0 +1 @@ +org.apache.fop.fo.FONode$GatherContextInfoFunction diff --git a/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$ObjectFormatter b/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$ObjectFormatter new file mode 100644 index 000000000..9e3860b31 --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$ObjectFormatter @@ -0,0 +1 @@ +org.apache.fop.util.text.LocatorFormatter diff --git a/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$PartFactory b/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$PartFactory new file mode 100644 index 000000000..1647fb8d5 --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$PartFactory @@ -0,0 +1,6 @@ +org.apache.fop.util.text.IfFieldPart$Factory +org.apache.fop.util.text.EqualsFieldPart$Factory +org.apache.fop.util.text.ChoiceFieldPart$Factory +org.apache.fop.util.text.HexFieldPart$Factory +org.apache.fop.util.text.GlyphNameFieldPart$Factory +org.apache.fop.events.EventFormatter$LookupFieldPartFactory diff --git a/src/java/org/apache/fop/apps/FOPException.java b/src/java/org/apache/fop/apps/FOPException.java index 3e1c180e9..851712b09 100644 --- a/src/java/org/apache/fop/apps/FOPException.java +++ b/src/java/org/apache/fop/apps/FOPException.java @@ -32,6 +32,8 @@ public class FOPException extends SAXException { private String systemId; private int line; private int column; + + private String localizedMessage; /** * Constructs a new FOP exception with the specified detail message. @@ -210,5 +212,24 @@ public class FOPException extends SAXException { } } } + + /** + * Sets the localized message for this exception. + * @param msg the localized message + */ + public void setLocalizedMessage(String msg) { + this.localizedMessage = msg; + } + + /** {@inheritDoc} */ + public String getLocalizedMessage() { + if (this.localizedMessage != null) { + return this.localizedMessage; + } else { + return super.getLocalizedMessage(); + } + } + + } diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index a7405b466..307087f74 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -36,6 +36,12 @@ import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext; import org.apache.fop.Version; +import org.apache.fop.events.DefaultEventBroadcaster; +import org.apache.fop.events.Event; +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.events.FOPEventListenerProxy; +import org.apache.fop.events.LoggingEventListener; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererFactory; @@ -89,6 +95,7 @@ public class FOUserAgent { private Renderer rendererOverride = null; private FOEventHandler foEventHandlerOverride = null; private boolean locatorEnabled = true; // true by default (for error messages). + private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster(); /** Producer: Metadata element for the system/software that produces * the document. (Some renderers can store this in the document.) @@ -530,5 +537,43 @@ public class FOUserAgent { return locatorEnabled; } + /** + * Returns the event broadcaster that control events sent inside a processing run. Clients + * can register event listeners with the event broadcaster to listen for events that occur + * while a document is being processed. + * @return the event broadcaster. + */ + public EventBroadcaster getEventBroadcaster() { + return this.eventBroadcaster; + } + + private class FOPEventBroadcaster extends DefaultEventBroadcaster { + + private FOPEventListenerProxy rootListener; + + public FOPEventBroadcaster() { + this.rootListener = new FOPEventListenerProxy( + this.listeners, FOUserAgent.this); + } + + /** {@inheritDoc} */ + public void broadcastEvent(Event event) { + rootListener.processEvent(event); + } + + /** {@inheritDoc} */ + protected EventProducer createProxyFor(Class clazz) { + if (!this.listeners.hasEventListeners()) { + //Backwards-compatibility: Make sure at least the LoggingEventListener is plugged + //in so no events are just silently swallowed. + addEventListener( + new LoggingEventListener(LogFactory.getLog(FOUserAgent.class))); + + } + return super.createProxyFor(clazz); + } + + } + } diff --git a/src/java/org/apache/fop/area/AreaEventProducer.java b/src/java/org/apache/fop/area/AreaEventProducer.java new file mode 100644 index 000000000..7747d2d79 --- /dev/null +++ b/src/java/org/apache/fop/area/AreaEventProducer.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.area; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; + +/** + * Event producer interface for events related to the area tree. + */ +public interface AreaEventProducer extends EventProducer { + + /** + * Provider class for the event producer. + */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static AreaEventProducer get(EventBroadcaster broadcaster) { + return (AreaEventProducer)broadcaster.getEventProducerFor( + AreaEventProducer.class); + } + } + + /** + * An unresolved ID reference was encountered. + * @param source the event source + * @param type the type of reference + * @param id the unresolved ID + * @event.severity WARN + */ + void unresolvedIDReference(Object source, String type, String id); + + /** + * An unresolved ID reference was encountered on a page. + * @param source the event source + * @param page the page the ID reference was found on + * @param id the unresolved ID + * @event.severity WARN + */ + void unresolvedIDReferenceOnPage(Object source, String page, String id); + + /** + * A page could not be loaded/deserialized from a file. + * @param source the event source + * @param page the page to be loaded + * @param e the original exception + * @event.severity ERROR + */ + void pageLoadError(Object source, String page, Exception e); + + /** + * A page could not be saved/serialized to a file. + * @param source the event source + * @param page the page to be serialized + * @param e the original exception + * @event.severity ERROR + */ + void pageSaveError(Object source, String page, Exception e); + + /** + * A page could not be rendered. + * @param source the event source + * @param page the page to be serialized + * @param e the original exception + * @event.severity ERROR + */ + void pageRenderingError(Object source, String page, Exception e); + +} diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java index 7454f4667..d3ea41554 100644 --- a/src/java/org/apache/fop/area/AreaTreeHandler.java +++ b/src/java/org/apache/fop/area/AreaTreeHandler.java @@ -325,8 +325,9 @@ public class AreaTreeHandler extends FOEventHandler { if (pageVPList != null) { res.resolveIDRef(ids[count], pageVPList); } else { - log.warn(odi.getName() + ": Unresolved id reference \"" - + ids[count] + "\" found."); + AreaEventProducer eventProducer = AreaEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.unresolvedIDReference(this, odi.getName(), ids[count]); idTracker.addUnresolvedIDRef(ids[count], res); } } diff --git a/src/java/org/apache/fop/area/AreaTreeObject.java b/src/java/org/apache/fop/area/AreaTreeObject.java index 94250deba..1c2269a01 100644 --- a/src/java/org/apache/fop/area/AreaTreeObject.java +++ b/src/java/org/apache/fop/area/AreaTreeObject.java @@ -23,7 +23,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.Map; -import org.apache.fop.util.QName; +import org.apache.xmlgraphics.util.QName; /** * Abstract base class for all area tree objects. @@ -53,12 +53,12 @@ public abstract class AreaTreeObject { if (atts.size() == 0) { return; } - Iterator iter = atts.keySet().iterator(); + Iterator iter = atts.entrySet().iterator(); while (iter.hasNext()) { - QName qName = (QName)iter.next(); - String value = (String)atts.get(qName); + Map.Entry entry = (Map.Entry)iter.next(); + String value = (String)entry.getValue(); //The casting is only to ensure type safety (too bad we can't use generics, yet) - setForeignAttribute(qName, value); + setForeignAttribute((QName)entry.getKey(), value); } } diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index fafb99ed6..19edd3d5e 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -50,6 +50,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.util.QName; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Trait.Background; @@ -78,7 +79,6 @@ import org.apache.fop.util.ColorUtil; import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactoryRegistry; import org.apache.fop.util.DefaultErrorListener; -import org.apache.fop.util.QName; /** * This is a parser for the area tree XML (intermediate format) which is used to reread an area diff --git a/src/java/org/apache/fop/area/CachedRenderPagesModel.java b/src/java/org/apache/fop/area/CachedRenderPagesModel.java index 363fa02d1..b34a7e8d1 100644 --- a/src/java/org/apache/fop/area/CachedRenderPagesModel.java +++ b/src/java/org/apache/fop/area/CachedRenderPagesModel.java @@ -19,24 +19,27 @@ package org.apache.fop.area; -import org.apache.commons.io.IOUtils; -import org.apache.fop.apps.FOPException; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.fonts.FontInfo; -import org.xml.sax.SAXException; - -import java.util.Map; -import java.util.HashMap; -import java.util.Iterator; - +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileOutputStream; import java.io.FileInputStream; -import java.io.ObjectOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.OutputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedInputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.xml.sax.SAXException; + +import org.apache.commons.io.IOUtils; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.events.ResourceEventProducer; +import org.apache.fop.fonts.FontInfo; /** * A simple cached render pages model. @@ -69,46 +72,39 @@ public class CachedRenderPagesModel extends RenderPagesModel { */ protected boolean checkPreparedPages(PageViewport newpage, boolean renderUnresolved) { for (Iterator iter = prepared.iterator(); iter.hasNext();) { - PageViewport p = (PageViewport)iter.next(); - if (p.isResolved() || renderUnresolved) { - if (p != newpage) { + PageViewport pageViewport = (PageViewport)iter.next(); + if (pageViewport.isResolved() || renderUnresolved) { + if (pageViewport != newpage) { try { // load page from cache - String name = (String)pageMap.get(p); + String name = (String)pageMap.get(pageViewport); File tempFile = new File(baseDir, name); log.debug("Loading page from: " + tempFile); ObjectInputStream in = new ObjectInputStream( new BufferedInputStream( new FileInputStream(tempFile))); try { - p.loadPage(in); + pageViewport.loadPage(in); } finally { IOUtils.closeQuietly(in); } if (!tempFile.delete()) { - log.warn("Temporary file could not be deleted: " + tempFile); + ResourceEventProducer eventProducer + = ResourceEventProducer.Provider.get( + renderer.getUserAgent().getEventBroadcaster()); + eventProducer.cannotDeleteTempFile(this, tempFile); } - pageMap.remove(p); + pageMap.remove(pageViewport); } catch (Exception e) { - log.error(e); + AreaEventProducer eventProducer + = AreaEventProducer.Provider.get( + renderer.getUserAgent().getEventBroadcaster()); + eventProducer.pageLoadError(this, pageViewport.getPageNumberString(), e); } } - try { - renderer.renderPage(p); - if (!p.isResolved()) { - String[] idrefs = p.getIDRefs(); - for (int count = 0; count < idrefs.length; count++) { - log.warn("Page " + p.getPageNumberString() - + ": Unresolved id reference \"" + idrefs[count] - + "\" found."); - } - } - } catch (Exception e) { - // use error handler to handle this FOP or IO Exception - log.error(e); - } - p.clear(); + renderPage(pageViewport); + pageViewport.clear(); iter.remove(); } else { if (!renderer.supportsOutOfOrder()) { @@ -147,8 +143,11 @@ public class CachedRenderPagesModel extends RenderPagesModel { if (log.isDebugEnabled()) { log.debug("Page saved to temporary file: " + tempFile); } - } catch (Exception e) { - log.error(e); + } catch (IOException ioe) { + AreaEventProducer eventProducer + = AreaEventProducer.Provider.get( + renderer.getUserAgent().getEventBroadcaster()); + eventProducer.pageSaveError(this, page.getPageNumberString(), ioe); } } diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java index af557ade9..da7ef1def 100644 --- a/src/java/org/apache/fop/area/PageViewport.java +++ b/src/java/org/apache/fop/area/PageViewport.java @@ -21,14 +21,15 @@ package org.apache.fop.area; import java.awt.Rectangle; import java.awt.geom.Rectangle2D; -import java.io.ObjectOutputStream; +import java.io.IOException; import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Collections; -import java.util.List; -import java.util.Map; import java.util.HashMap; import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; @@ -516,9 +517,9 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl * The map of unresolved references are set on the page so that * the resolvers can be properly serialized and reloaded. * @param out the object output stream to write the contents - * @throws Exception if there is a problem saving the page + * @throws IOException in case of an I/O error while serializing the page */ - public void savePage(ObjectOutputStream out) throws Exception { + public void savePage(ObjectOutputStream out) throws IOException { // set the unresolved references so they are serialized page.setUnresolvedReferences(unresolvedIDRefs); out.writeObject(page); @@ -531,9 +532,10 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl * if there are any unresolved references that were resolved * while saved they will be resolved on the page contents. * @param in the object input stream to read the page from - * @throws Exception if there is an error loading the page + * @throws ClassNotFoundException if a class was not found while loading the page + * @throws IOException if an I/O error occurred while loading the page */ - public void loadPage(ObjectInputStream in) throws Exception { + public void loadPage(ObjectInputStream in) throws IOException, ClassNotFoundException { page = (Page) in.readObject(); unresolvedIDRefs = page.getUnresolvedReferences(); if (unresolvedIDRefs != null && pendingResolved != null) { diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java index e080e9cbe..b21566902 100644 --- a/src/java/org/apache/fop/area/RenderPagesModel.java +++ b/src/java/org/apache/fop/area/RenderPagesModel.java @@ -156,23 +156,7 @@ public class RenderPagesModel extends AreaTreeModel { && pageViewport.getPageSequence().isFirstPage(pageViewport)) { renderer.startPageSequence(getCurrentPageSequence()); } - try { - renderer.renderPage(pageViewport); - if (!pageViewport.isResolved()) { - String[] idrefs = pageViewport.getIDRefs(); - for (int count = 0; count < idrefs.length; count++) { - log.warn("Page " + pageViewport.getPageNumberString() - + ": Unresolved id reference \"" + idrefs[count] - + "\" found."); - } - } - } catch (Exception e) { - // use error handler to handle this FOP or IO Exception - log.error("Error while rendering page " + pageViewport.getPageIndex(), e); - if (e instanceof RuntimeException) { - throw (RuntimeException)e; - } - } + renderPage(pageViewport); pageViewport.clear(); iter.remove(); } else { @@ -185,6 +169,33 @@ public class RenderPagesModel extends AreaTreeModel { return renderer.supportsOutOfOrder() || prepared.isEmpty(); } + /** + * Renders the given page and notified about unresolved IDs if any. + * @param pageViewport the page to be rendered. + */ + protected void renderPage(PageViewport pageViewport) { + try { + renderer.renderPage(pageViewport); + if (!pageViewport.isResolved()) { + String[] idrefs = pageViewport.getIDRefs(); + for (int count = 0; count < idrefs.length; count++) { + AreaEventProducer eventProducer = AreaEventProducer.Provider.get( + renderer.getUserAgent().getEventBroadcaster()); + eventProducer.unresolvedIDReferenceOnPage(this, + pageViewport.getPageNumberString(), idrefs[count]); + } + } + } catch (Exception e) { + AreaEventProducer eventProducer = AreaEventProducer.Provider.get( + renderer.getUserAgent().getEventBroadcaster()); + eventProducer.pageRenderingError(this, + pageViewport.getPageNumberString(), e); + if (e instanceof RuntimeException) { + throw (RuntimeException)e; + } + } + } + /** * Prepare a page. * An unresolved page can be prepared if the renderer supports diff --git a/src/java/org/apache/fop/events/CompositeEventListener.java b/src/java/org/apache/fop/events/CompositeEventListener.java new file mode 100644 index 000000000..a65728b71 --- /dev/null +++ b/src/java/org/apache/fop/events/CompositeEventListener.java @@ -0,0 +1,69 @@ +/* + * 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.events; + +import java.util.List; + +/** + * EventListener implementation forwards events to possibly multiple other EventListeners. + */ +public class CompositeEventListener implements EventListener { + + private List listeners = new java.util.ArrayList(); + + /** + * Adds an event listener to the broadcaster. It is appended to the list of previously + * registered listeners (the order of registration defines the calling order). + * @param listener the listener to be added + */ + public synchronized void addEventListener(EventListener listener) { + this.listeners.add(listener); + } + + /** + * Removes an event listener from the broadcaster. If the event listener is not registered, + * nothing happens. + * @param listener the listener to be removed + */ + public synchronized void removeEventListener(EventListener listener) { + this.listeners.remove(listener); + } + + private synchronized int getListenerCount() { + return this.listeners.size(); + } + + /** + * Indicates whether any listeners have been registered with the broadcaster. + * @return true if listeners are present, false otherwise + */ + public boolean hasEventListeners() { + return (getListenerCount() > 0); + } + + /** {@inheritDoc} */ + public synchronized void processEvent(Event event) { + for (int i = 0, c = getListenerCount(); i < c; i++) { + EventListener listener = (EventListener)this.listeners.get(i); + listener.processEvent(event); + } + } + +} diff --git a/src/java/org/apache/fop/events/DefaultEventBroadcaster.java b/src/java/org/apache/fop/events/DefaultEventBroadcaster.java new file mode 100644 index 000000000..bb1752a72 --- /dev/null +++ b/src/java/org/apache/fop/events/DefaultEventBroadcaster.java @@ -0,0 +1,160 @@ +/* + * 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.events; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.xmlgraphics.util.Service; + +import org.apache.fop.events.model.EventMethodModel; +import org.apache.fop.events.model.EventModel; +import org.apache.fop.events.model.EventModelFactory; +import org.apache.fop.events.model.EventProducerModel; +import org.apache.fop.events.model.EventSeverity; + +/** + * Default implementation of the EventBroadcaster interface. It holds a list of event listeners + * and can provide {@link EventProducer} instances for type-safe event production. + */ +public class DefaultEventBroadcaster implements EventBroadcaster { + + /** Holds all registered event listeners */ + protected CompositeEventListener listeners = new CompositeEventListener(); + + /** {@inheritDoc} */ + public void addEventListener(EventListener listener) { + this.listeners.addEventListener(listener); + } + + /** {@inheritDoc} */ + public void removeEventListener(EventListener listener) { + this.listeners.removeEventListener(listener); + } + + /** {@inheritDoc} */ + public boolean hasEventListeners() { + return this.listeners.hasEventListeners(); + } + + /** {@inheritDoc} */ + public void broadcastEvent(Event event) { + this.listeners.processEvent(event); + } + + private static List/**/ eventModels = new java.util.ArrayList(); + private Map proxies = new java.util.HashMap(); + + static { + Iterator iter = Service.providers(EventModelFactory.class, true); + while (iter.hasNext()) { + EventModelFactory factory = (EventModelFactory)iter.next(); + addEventModel(factory.createEventModel()); + } + } + + /** + * Adds a new {@link EventModel} to the list of registered event models. + * @param eventModel the event model instance + */ + public static void addEventModel(EventModel eventModel) { + eventModels.add(eventModel); + } + + /** {@inheritDoc} */ + public EventProducer getEventProducerFor(Class clazz) { + if (!EventProducer.class.isAssignableFrom(clazz)) { + throw new IllegalArgumentException( + "Class must be an implementation of the EventProducer interface: " + + clazz.getName()); + } + EventProducer producer; + producer = (EventProducer)this.proxies.get(clazz); + if (producer == null) { + producer = createProxyFor(clazz); + this.proxies.put(clazz, producer); + } + return producer; + } + + private EventProducerModel getEventProducerModel(Class clazz) { + for (int i = 0, c = eventModels.size(); i < c; i++) { + EventModel eventModel = (EventModel)eventModels.get(i); + EventProducerModel producerModel = eventModel.getProducer(clazz); + if (producerModel != null) { + return producerModel; + } + } + return null; + } + + /** + * Creates a dynamic proxy for the given EventProducer interface that will handle the + * conversion of the method call into the broadcasting of an event instance. + * @param clazz a descendant interface of EventProducer + * @return the EventProducer instance + */ + protected EventProducer createProxyFor(Class clazz) { + final EventProducerModel producerModel = getEventProducerModel(clazz); + if (producerModel == null) { + throw new IllegalStateException("Event model doesn't contain the definition for " + + clazz.getName()); + } + return (EventProducer)Proxy.newProxyInstance(clazz.getClassLoader(), + new Class[] {clazz}, + new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + String methodName = method.getName(); + EventMethodModel methodModel = producerModel.getMethod(methodName); + String eventID = producerModel.getInterfaceName() + "." + methodName; + if (methodModel == null) { + throw new IllegalStateException( + "Event model isn't consistent" + + " with the EventProducer interface. Please rebuild FOP!" + + " Affected method: " + + eventID); + } + Map params = new java.util.HashMap(); + int i = 1; + Iterator iter = methodModel.getParameters().iterator(); + while (iter.hasNext()) { + EventMethodModel.Parameter param + = (EventMethodModel.Parameter)iter.next(); + params.put(param.getName(), args[i]); + i++; + } + Event ev = new Event(args[0], eventID, methodModel.getSeverity(), params); + broadcastEvent(ev); + + if (ev.getSeverity() == EventSeverity.FATAL) { + EventExceptionManager.throwException(ev, + methodModel.getExceptionClass()); + } + return null; + } + }); + } + +} diff --git a/src/java/org/apache/fop/events/Event.java b/src/java/org/apache/fop/events/Event.java new file mode 100644 index 000000000..d3da1809e --- /dev/null +++ b/src/java/org/apache/fop/events/Event.java @@ -0,0 +1,150 @@ +/* + * 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.events; + +import java.util.Collections; +import java.util.EventObject; +import java.util.Map; + +import org.apache.fop.events.model.EventSeverity; + +/** + * This is the default event class used by this package. Each event has a unique event identifier + * (a String), a severity indicator and a map of name/value pairs. + */ +public class Event extends EventObject { + + private static final long serialVersionUID = -1310594422868258083L; + + private String eventID; + private EventSeverity severity; + private Map params; + + /** + * Creates a new Event. + * @param source the object that creates the event + * @param eventID the unique identifier of the event + * @param severity the severity level + * @param params the event parameters (a map of name/value pairs) + */ + public Event(Object source, String eventID, EventSeverity severity, Map params) { + super(source); + this.eventID = eventID; + setSeverity(severity); + this.params = params; + } + + /** + * Returns the event identifier. + * @return the event identifier + */ + public String getEventID() { + return this.eventID; + } + + /** + * Returns the event group identifier. + * @return the event group identifier (or null if there is no group identifier) + */ + public String getEventGroupID() { + int pos = this.eventID.lastIndexOf('.'); + if (pos > 0) { + return this.eventID.substring(0, pos); + } else { + return null; + } + } + + /** + * Returns the severity level. + * @return the severity level + */ + public EventSeverity getSeverity() { + return this.severity; + } + + /** + * Sets the event's severity level. This method can be used to increase or decrease the + * severity level in a listener. + * @param severity the new event severity + */ + public void setSeverity(EventSeverity severity) { + this.severity = severity; + } + + /** + * Returns a parameter. + * @param key the key to the parameter + * @return the parameter value or null if no value with this key is found + */ + public Object getParam(String key) { + if (this.params != null) { + return this.params.get(key); + } else { + return null; + } + } + + /** + * Returns an unmodifiable {@link java.util.Map} with all event parameters. + * @return the parameter map + */ + public Map getParams() { + return Collections.unmodifiableMap(this.params); + } + + /** + * Creates and returns a fluent builder object for building up the parameter map. + * @return the parameter builder + */ + public static ParamsBuilder paramsBuilder() { + return new ParamsBuilder(); + } + + /** + * This class is a fluent builder class for building up the parameter map. + */ + public static class ParamsBuilder { + private Map params; + + /** + * Adds a new parameter (a name/value pair). + * @param name the name of the parameter + * @param value the value of the parameter + * @return this instance + */ + public ParamsBuilder param(String name, Object value) { + if (this.params == null) { + this.params = new java.util.HashMap(); + } + this.params.put(name, value); + return this; + } + + /** + * Returns the accumulated parameter map. + * @return the accumulated parameter map + */ + public Map build() { + return this.params; + } + } + +} diff --git a/src/java/org/apache/fop/events/EventBroadcaster.java b/src/java/org/apache/fop/events/EventBroadcaster.java new file mode 100644 index 000000000..6c8df7375 --- /dev/null +++ b/src/java/org/apache/fop/events/EventBroadcaster.java @@ -0,0 +1,61 @@ +/* + * 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.events; + +/** + * The EventBroadcaster is the central relay point for events. It receives events from various + * parts of the application and forwards them to any registered EventListener. + */ +public interface EventBroadcaster { + + /** + * Adds an event listener to the broadcaster. It is appended to the list of previously + * registered listeners (the order of registration defines the calling order). + * @param listener the listener to be added + */ + void addEventListener(EventListener listener); + + /** + * Removes an event listener from the broadcaster. If the event listener is not registered, + * nothing happens. + * @param listener the listener to be removed + */ + void removeEventListener(EventListener listener); + + /** + * Indicates whether any listeners have been registered with the broadcaster. + * @return true if listeners are present, false otherwise + */ + boolean hasEventListeners(); + + /** + * Broadcasts an event. This method is usually called from within the observed component. + * @param event the event to be broadcast + */ + void broadcastEvent(Event event); + + /** + * Returns an event producer instance for the given interface class. + * @param clazz the Class object identifying an {@link EventProducer} interface + * @return the event producer instance + */ + EventProducer getEventProducerFor(Class clazz); + +} diff --git a/src/java/org/apache/fop/events/EventExceptionManager.java b/src/java/org/apache/fop/events/EventExceptionManager.java new file mode 100644 index 000000000..093ae7010 --- /dev/null +++ b/src/java/org/apache/fop/events/EventExceptionManager.java @@ -0,0 +1,84 @@ +/* + * 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.events; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.xmlgraphics.util.Service; + +/** + * This class is reponsible for converting events into exceptions. + */ +public class EventExceptionManager { + + private static final Map EXCEPTION_FACTORIES = new java.util.HashMap(); + + static { + Iterator iter; + iter = Service.providers(ExceptionFactory.class, true); + while (iter.hasNext()) { + ExceptionFactory factory = (ExceptionFactory)iter.next(); + EXCEPTION_FACTORIES.put(factory.getExceptionClass().getName(), factory); + } + } + + /** + * Converts an event into an exception and throws that. If the exception class is null, + * a {@link RuntimeException} will be thrown. + * @param event the event to be converted + * @param exceptionClass the exception class to be thrown + * @throws Throwable this happens always + */ + public static void throwException(Event event, String exceptionClass) throws Throwable { + if (exceptionClass != null) { + ExceptionFactory factory = (ExceptionFactory)EXCEPTION_FACTORIES.get(exceptionClass); + if (factory != null) { + throw factory.createException(event); + } else { + throw new IllegalArgumentException( + "No such ExceptionFactory available: " + exceptionClass); + } + } else { + String msg = EventFormatter.format(event); + throw new RuntimeException(msg); + } + } + + /** + * This interface is implementation by exception factories that can create exceptions from + * events. + */ + public interface ExceptionFactory { + + /** + * Creates an exception from an event. + * @param event the event + * @return the newly created exception + */ + Throwable createException(Event event); + + /** + * Returns the {@link Exception} class created by this factory. + * @return the exception class + */ + Class getExceptionClass(); + } +} diff --git a/src/java/org/apache/fop/events/EventFormatter.java b/src/java/org/apache/fop/events/EventFormatter.java new file mode 100644 index 000000000..56964039b --- /dev/null +++ b/src/java/org/apache/fop/events/EventFormatter.java @@ -0,0 +1,196 @@ +/* + * 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.events; + +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.util.XMLResourceBundle; +import org.apache.fop.util.text.AdvancedMessageFormat; +import org.apache.fop.util.text.AdvancedMessageFormat.Part; +import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; + +/** + * Converts events into human-readable, localized messages. + */ +public final class EventFormatter { + + private static final Pattern INCLUDES_PATTERN = Pattern.compile("\\{\\{.+\\}\\}"); + + private static ResourceBundle defaultBundle = XMLResourceBundle.getXMLBundle( + EventFormatter.class.getName(), EventFormatter.class.getClassLoader()); + + private static Log log = LogFactory.getLog(EventFormatter.class); + + private EventFormatter() { + //utility class + } + + /** + * Formats an event using the default locale. + * @param event the event + * @return the formatted message + */ + public static String format(Event event) { + ResourceBundle bundle = null; + String groupID = event.getEventGroupID(); + if (groupID != null) { + try { + bundle = XMLResourceBundle.getXMLBundle( + groupID, + EventFormatter.class.getClassLoader()); + } catch (MissingResourceException mre) { + if (log.isTraceEnabled()) { + log.trace("No XMLResourceBundle for " + groupID + " available."); + } + } + } + if (bundle == null) { + bundle = defaultBundle; + } + return format(event, bundle); + } + + /** + * Formats an event using a given locale. + * @param event the event + * @param locale the locale + * @return the formatted message + */ + public static String format(Event event, Locale locale) { + ResourceBundle bundle = null; + String groupID = event.getEventGroupID(); + if (groupID != null) { + try { + bundle = XMLResourceBundle.getXMLBundle( + groupID, locale, + EventFormatter.class.getClassLoader()); + } catch (MissingResourceException mre) { + if (log.isTraceEnabled()) { + log.trace("No XMLResourceBundle for " + groupID + " available."); + } + } + } + if (bundle == null) { + bundle = XMLResourceBundle.getXMLBundle( + EventFormatter.class.getName(), + locale, + EventFormatter.class.getClassLoader()); + } + return format(event, bundle); + } + + private static String format(Event event, ResourceBundle bundle) { + String template = bundle.getString(event.getEventID()); + return format(event, processIncludes(template, bundle)); + } + + private static String processIncludes(String template, ResourceBundle bundle) { + CharSequence input = template; + int replacements; + StringBuffer sb; + do { + sb = new StringBuffer(Math.max(16, input.length())); + replacements = processIncludesInner(input, sb, bundle); + input = sb; + } while (replacements > 0); + String s = sb.toString(); + return s; + } + + private static int processIncludesInner(CharSequence template, StringBuffer sb, + ResourceBundle bundle) { + int replacements = 0; + Matcher m = INCLUDES_PATTERN.matcher(template); + while (m.find()) { + String include = m.group(); + include = include.substring(2, include.length() - 2); + m.appendReplacement(sb, bundle.getString(include)); + replacements++; + } + m.appendTail(sb); + return replacements; + } + + /** + * Formats the event using a given pattern. The pattern needs to be compatible with + * {@link AdvancedMessageFormat}. + * @param event the event + * @param pattern the pattern (compatible with {@link AdvancedMessageFormat}) + * @return the formatted message + */ + public static String format(Event event, String pattern) { + AdvancedMessageFormat format = new AdvancedMessageFormat(pattern); + Map params = new java.util.HashMap(event.getParams()); + params.put("source", event.getSource()); + params.put("severity", event.getSeverity()); + return format.format(params); + } + + private static class LookupFieldPart implements Part { + + private String fieldName; + + public LookupFieldPart(String fieldName) { + this.fieldName = fieldName; + } + + public boolean isGenerated(Map params) { + return getKey(params) != null; + } + + public void write(StringBuffer sb, Map params) { + sb.append(defaultBundle.getString(getKey(params))); + } + + private String getKey(Map params) { + return (String)params.get(fieldName); + } + + /** {@inheritDoc} */ + public String toString() { + return "{" + this.fieldName + ", lookup}"; + } + + } + + /** PartFactory for lookups. */ + public static class LookupFieldPartFactory implements PartFactory { + + /** {@inheritDoc} */ + public Part newPart(String fieldName, String values) { + return new LookupFieldPart(fieldName); + } + + /** {@inheritDoc} */ + public String getFormat() { + return "lookup"; + } + + } + +} diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml new file mode 100644 index 000000000..f17da1161 --- /dev/null +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -0,0 +1,101 @@ + + + + + [ (See position {loc})| (See {#gatherContextInfo})| (No context info available)] + An fo:marker is permitted only as the descendant of an fo:flow. + An fo:retrieve-marker is permitted only as the descendant of an fo:static-content. + An fo:bidi-override that is a descendant of an fo:leader or of the fo:inline child of an fo:footnote may not have block-level children, unless it has a nearer ancestor that is an fo:inline-container. + An fo:inline that is a descendant of an fo:leader or fo:footnote may not have block-level children, unless it has a nearer ancestor that is an fo:inline-container. + The element must be a child of fo:simple-page-master. + The element must be a child of fo:declarations. + The element must be a child of fo:declarations or fo:simple-page-master. + For "{elementName}", only one "{offendingNode}" may be declared.{{locator}} + For "{elementName}", "{tooLateNode}" must be declared before "{tooEarlyNode}"!{{locator}} + "{offendingNode}" is not a valid child element of "{elementName}"![ {ruleViolated,lookup}]{{locator}} + "{elementName}" is missing child elements.[ +Required content model: {contentModel}]{{locator}} + Element "{elementName}" is missing required property "{propertyName}"!{{locator}} + Property ID "{id}" (found on "{elementName}") previously used; ID values must be unique within a document!{severity,equals,EventSeverity:FATAL,, +Any reference to it will be considered a reference to the first occurrence in the document.}{{locator}} + fo:marker must be an initial child: {mcname}{{locator}} + fo:marker "marker-class-name" must be unique for same parent: {mcname}{{locator}} + Invalid property encountered on "{elementName}": {attr}{{locator}} + Invalid property value encountered in {propName}="{propValue}"[: {e}]{{locator}} + The following feature isn't implemented by Apache FOP, yet: {feature} (on {elementName}){{locator}} + Missing attribute on {elementName}: Either external-destination or internal-destination must be specified.{{locator}} + Unable to clone subtree of fo:marker (marker-class-name="{markerClassName}") for fo:retrieve-marker.{{locator}} + Duplicate color profile profile name: {name}{{locator}} + Region-name ("{regionName}") is being mapped to multiple region-classes ({defaultRegionClass1} and {defaultRegionClass2}).{{locator}} + The page master name ("{name}") must be unique across page-masters and page-sequence-masters.{{locator}} + Duplicate flow-name "{flowName}" found within {elementName}.{{locator}} + The flow-name "{flowName}" on {elementName} could not be mapped to a region-name in the layout-master-set.{{locator}} + The master-reference "{masterReference}" on {elementName} matches no simple-page-master or page-sequence-master.{{locator}} + The region-name "{regionName}" for {elementName} is not permitted.{{locator}} + Border and padding for {elementName} "{regionName}" must be '0' (See 6.4.13 in XSL 1.0).{{locator}} + If overflow property is set to "scroll" on {elementName}, a column-count other than "1" may not be specified.{{locator}} + First element must be the fo:root formatting object. Found {elementName} instead. Please make sure you're producing a valid XSL-FO document. + Document is empty (something might be wrong with your XSLT stylesheet). + Unknown formatting object "{offendingNode}" encountered (a child of {elementName}}.{{locator}} + Only a value of "auto" for block-progression-dimension has a well-specified behavior on fo:table. Falling back to "auto".{{locator}} + In collapsing border model a table does not have padding (see http://www.w3.org/TR/REC-CSS2/tables.html#collapsing-borders), but a non-zero value for padding was found. The padding will be ignored.{{locator}} + Either fo:table-rows or fo:table-cells may be children of an {elementName} but not both.{{locator}} + This table uses the collapsing border model. In order to resolve borders in an efficient way the table-footer must be known before any table-body is parsed. Either put the footer at the correct place or switch to the separate border model.{{locator}} + starts-row/ends-row for fo:table-cells non-applicable for children of an fo:table-row.{{locator}} + The column-number or number of cells in the row overflows the number of fo:table-columns specified for the table.{{locator}} + {propName} must be 1 or bigger, but got {actualValue}{{locator}} + table-layout=\"fixed\" and column-width unspecified => falling back to proportional-column-width(1){{locator}} + padding-* properties are not applicable to {elementName}, but a non-zero value for padding was found.{{locator}} + {elementName} overlaps in column {column}. + {breakBefore,if,break-before,break-after} ignored on {elementName} because of row spanning in progress (See XSL 1.1, {breakBefore,if,7.20.2,7.20.1}){{locator}} + Image not found.[ URI: {uri}.]{{locator}} + Image not available.[ URI: {uri}.] Reason:[ {reason}][ {e}]{{locator}} + I/O error while loading image.[ URI: {uri}.][ Reason: {ioe}]{{locator}} + The intrinsic dimensions of an instream-foreign-object could not be determined.{{locator}} + Error while handling URI: {uri}. Reason: {e}{{locator}} + Some XML content will be ignored. Could not render XML in namespace "{namespaceURI}".[ Reason: {e}] + Some XML content will be ignored. No handler defined for XML with namespace "{namespaceURI}". + Error while writing an image to the target file.[ Reason: {e}] + Temporary file could not be deleted: {tempFile} + fo:leader is set to "use-content" but has no content.{{locator}} + Line {line} of a paragraph overflows the available area by {overflowLength,choice,50000#{overflowLength} millipoints|50000<more than 50 points}.{{locator}} + The contents of table-row {row} are taller than they should be (there is a block-progression-dimension or height constraint on the indicated row). Due to its contents the row grows to {effCellBPD} millipoints, but the row shouldn't get any taller than {maxCellBPD} millipoints.{{locator}} + table-layout="fixed" and width="auto", but auto-layout not supported => assuming width="100%".{{locator}} + The extent in inline-progression-direction (width) of a {elementName} is bigger than the available space ({effIPD}mpt > {maxIPD}mpt).{{locator}} + Adjusting end-indent based on overconstrained geometry rules for {elementName}.{{locator}} + Content overflows the viewport of an {elementName} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}} + Content overflows the viewport of the {elementName} on page {page} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}} + Flow "{flowName}" does not map to the region-body in page-master "{masterName}". FOP presently does not support this.{{locator}} + Subsequences exhausted in page-sequence-master "{pageSequenceMasterName}", {canRecover,if,using previous subsequence,cannot recover}.{{locator}} + No subsequences in page-sequence-master "{pageSequenceMasterName}".{{locator}} + No simple-page-master matching "{pageMasterName}" in page-sequence-master "{pageSequenceMasterName}".{{locator}} + SVG error: {message} + SVG alert: {message} + SVG info: {message} + SVG graphic could not be built. Reason: {e} + SVG graphic could not be rendered. Reason: {e} + I/O error while writing to target file.[ Reason: {ioe}] + {type}: Unresolved ID reference "{id}" found. + Page {page}: Unresolved ID reference "{id}" found. + Error while deserializing page {page}.[ Reason: {e}] + Error while serializing page {page}.[ Reason: {e}] + Error while rendering page {page}.[ Reason: {e}] + Font "{requested}" not found. Substituting with "{effective}". + Unable to load font file: {fontURL}.[ Reason: {e}] + Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}". + diff --git a/src/java/org/apache/fop/events/EventFormatter_de.xml b/src/java/org/apache/fop/events/EventFormatter_de.xml new file mode 100644 index 000000000..c65d24f73 --- /dev/null +++ b/src/java/org/apache/fop/events/EventFormatter_de.xml @@ -0,0 +1,23 @@ + + + + + [ (Siehe Position {loc})| (Siehe {#gatherContextInfo})| (Keine Kontextinformationen verfügbar)] + In "{elementName}" darf nur ein einziges "{offendingNode}" vorkommen!{{locator}} + Dem Element "{elementName}" fehlt ein verlangtes Property "{propertyName}"!{{locator}} + diff --git a/src/java/org/apache/fop/events/EventListener.java b/src/java/org/apache/fop/events/EventListener.java new file mode 100644 index 000000000..f8293aed9 --- /dev/null +++ b/src/java/org/apache/fop/events/EventListener.java @@ -0,0 +1,37 @@ +/* + * 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.events; + +/** + * This interface is implemented by clients who want to listen for events. + */ +public interface EventListener extends java.util.EventListener { + + /** + * This method is called for each event that is generated. With the event's ID it is possible + * to react to certain events. Events can also simply be recorded and presented to a user. + * It is possible to throw an (unchecked) exception if the processing needs to be aborted + * because some special event occured. This way the client can configure the behaviour of + * the observed application. + * @param event the event + */ + void processEvent(Event event); + +} diff --git a/src/java/org/apache/fop/events/EventProducer.java b/src/java/org/apache/fop/events/EventProducer.java new file mode 100644 index 000000000..88da771a4 --- /dev/null +++ b/src/java/org/apache/fop/events/EventProducer.java @@ -0,0 +1,31 @@ +/* + * 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.events; + +/** + * This is a marker interface which all event producer interfaces need to extend. These interfaces + * must agree to the following convention: + *
                                                                                          + *
                                                                                        • The first parameter of each method must be: Object source + *
                                                                                        + */ +public interface EventProducer { + +} diff --git a/src/java/org/apache/fop/events/FOPEventListenerProxy.java b/src/java/org/apache/fop/events/FOPEventListenerProxy.java new file mode 100644 index 000000000..d4c237844 --- /dev/null +++ b/src/java/org/apache/fop/events/FOPEventListenerProxy.java @@ -0,0 +1,73 @@ +/* + * 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.events; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.events.model.EventSeverity; +import org.apache.fop.fo.FOValidationEventProducer; +import org.apache.fop.layoutmgr.BlockLevelEventProducer; + +/** + * EventListener proxy that inspects all events and adjusts severity levels where necessary. + * For validation events, it reacts on each event based on the strict validation setting in + * the user agent. + * For layout events, it reduces the default severity level if FOP signals that it can recover + * from the event. + */ +public class FOPEventListenerProxy implements EventListener { + + private static final String FOVALIDATION_EVENT_ID_PREFIX + = FOValidationEventProducer.class.getName(); + + private static final String BLOCK_LEVEL_EVENT_ID_PREFIX + = BlockLevelEventProducer.class.getName(); + + private EventListener delegate; + private FOUserAgent userAgent; + + /** + * Main constructor. + * @param delegate the event listener to delegate events to + * @param userAgent the FO user agent + */ + public FOPEventListenerProxy(EventListener delegate, FOUserAgent userAgent) { + this.delegate = delegate; + this.userAgent = userAgent; + } + + /** {@inheritDoc} */ + public synchronized void processEvent(Event event) { + if (event.getEventID().startsWith(FOVALIDATION_EVENT_ID_PREFIX)) { + Boolean canRecover = (Boolean)event.getParam("canRecover"); + if (Boolean.TRUE.equals(canRecover) && !userAgent.validateStrictly()) { + //Reduce severity if FOP can recover + event.setSeverity(EventSeverity.WARN); + } + } else if (event.getEventID().startsWith(BLOCK_LEVEL_EVENT_ID_PREFIX)) { + Boolean canRecover = (Boolean)event.getParam("canRecover"); + if (Boolean.TRUE.equals(canRecover)) { + //Reduce severity if FOP can recover + event.setSeverity(EventSeverity.WARN); + } + } + this.delegate.processEvent(event); + } + +} diff --git a/src/java/org/apache/fop/events/FOPEventModelFactory.java b/src/java/org/apache/fop/events/FOPEventModelFactory.java new file mode 100644 index 000000000..5a75042fa --- /dev/null +++ b/src/java/org/apache/fop/events/FOPEventModelFactory.java @@ -0,0 +1,37 @@ +/* + * 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.events; + +import org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; + +/** + * Factory for FOP's main event model. + */ +public class FOPEventModelFactory extends AbstractEventModelFactory { + + private static final String EVENT_MODEL_FILENAME = "event-model.xml"; + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), EVENT_MODEL_FILENAME); + } + +} diff --git a/src/java/org/apache/fop/events/LoggingEventListener.java b/src/java/org/apache/fop/events/LoggingEventListener.java new file mode 100644 index 000000000..9ba8ed2df --- /dev/null +++ b/src/java/org/apache/fop/events/LoggingEventListener.java @@ -0,0 +1,92 @@ +/* + * 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.events; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.events.model.EventSeverity; + +/** + * EventListener implementation that redirects events to Commons Logging. The events are + * converted to localized messages. + */ +public class LoggingEventListener implements EventListener { + + /** Default logger instance */ + private static Log defaultLog = LogFactory.getLog(LoggingEventListener.class); + + private Log log; + private boolean skipFatal; + + /** + * Creates an instance logging to the default log category of this class. + */ + public LoggingEventListener() { + this(defaultLog); + } + + /** + * Creates an instance logging to a given logger. Events with fatal severity level will be + * skipped. + * @param log the target logger + */ + public LoggingEventListener(Log log) { + this(log, true); + } + + /** + * Creates an instance logging to a given logger. + * @param log the target logger + * @param skipFatal true if events with fatal severity level should be skipped (i.e. not logged) + */ + public LoggingEventListener(Log log, boolean skipFatal) { + this.log = log; + this.skipFatal = skipFatal; + } + + /** + * Returns the target logger for this instance. + * @return the target logger + */ + public Log getLog() { + return this.log; + } + + /** {@inheritDoc} */ + public void processEvent(Event event) { + String msg = EventFormatter.format(event); + EventSeverity severity = event.getSeverity(); + if (severity == EventSeverity.INFO) { + log.info(msg); + } else if (severity == EventSeverity.WARN) { + log.warn(msg); + } else if (severity == EventSeverity.ERROR) { + log.error(msg); + } else if (severity == EventSeverity.FATAL) { + if (!skipFatal) { + log.fatal(msg); + } + } else { + assert false; + } + } + +} diff --git a/src/java/org/apache/fop/events/PropertyExceptionFactory.java b/src/java/org/apache/fop/events/PropertyExceptionFactory.java new file mode 100644 index 000000000..667c4a16e --- /dev/null +++ b/src/java/org/apache/fop/events/PropertyExceptionFactory.java @@ -0,0 +1,47 @@ +/* + * 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.events; + +import java.util.Locale; + +import org.apache.fop.events.EventExceptionManager.ExceptionFactory; +import org.apache.fop.fo.expr.PropertyException; + +/** + * Exception factory for {@link PropertyException}. + */ +public class PropertyExceptionFactory implements ExceptionFactory { + + /** {@inheritDoc} */ + public Throwable createException(Event event) { + String msg = EventFormatter.format(event, Locale.ENGLISH); + PropertyException ex = new PropertyException(msg); + if (!Locale.ENGLISH.equals(Locale.getDefault())) { + ex.setLocalizedMessage(EventFormatter.format(event)); + } + return ex; + } + + /** {@inheritDoc} */ + public Class getExceptionClass() { + return PropertyException.class; + } + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/events/ResourceEventProducer.java b/src/java/org/apache/fop/events/ResourceEventProducer.java new file mode 100644 index 000000000..21da4f1d7 --- /dev/null +++ b/src/java/org/apache/fop/events/ResourceEventProducer.java @@ -0,0 +1,136 @@ +/* + * 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.events; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +import org.w3c.dom.Document; + +import org.xml.sax.Locator; + +import org.apache.xmlgraphics.image.loader.ImageException; + +/** + * Event producer interface for resource events (missing images, fonts etc.). + */ +public interface ResourceEventProducer extends EventProducer { + + /** + * Provider class for the event producer. + */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the requested event producer + */ + public static ResourceEventProducer get(EventBroadcaster broadcaster) { + return (ResourceEventProducer)broadcaster.getEventProducerFor( + ResourceEventProducer.class); + } + } + + /** + * Image not found. + * @param source the event source + * @param uri the original URI of the image + * @param fnfe the "file not found" exception + * @param loc the location of the error or null + * @event.severity ERROR + */ + void imageNotFound(Object source, String uri, FileNotFoundException fnfe, Locator loc); + + /** + * Error while processing image. + * @param source the event source + * @param uri the original URI of the image + * @param e the image exception + * @param loc the location of the error or null + * @event.severity ERROR + */ + void imageError(Object source, String uri, ImageException e, Locator loc); + + /** + * I/O error while loading an image. + * @param source the event source + * @param uri the original URI of the image + * @param ioe the I/O exception + * @param loc the location of the error or null + * @event.severity ERROR + */ + void imageIOError(Object source, String uri, IOException ioe, Locator loc); + + /** + * Error while writing/serializing an image to an output format. + * @param source the event source + * @param e the original exception + * @event.severity ERROR + */ + void imageWritingError(Object source, Exception e); + + /** + * Error while handling a URI. + * @param source the event source + * @param uri the original URI of the image + * @param e the original exception + * @param loc the location of the error or null + * @event.severity ERROR + */ + void uriError(Object source, String uri, Exception e, Locator loc); + + /** + * Intrinsic size of fo:instream-foreign-object could not be determined. + * @param source the event source + * @param loc the location of the error or null + * @event.severity ERROR + */ + void ifoNoIntrinsicSize(Object source, Locator loc); + + /** + * Error processing foreign XML content. + * @param source the event source + * @param doc the foreign XML + * @param namespaceURI the namespace URI of the foreign XML + * @param e the original exception + * @event.severity ERROR + */ + void foreignXMLProcessingError(Object source, Document doc, String namespaceURI, Exception e); + + /** + * No handler for foreign XML content. + * @param source the event source + * @param doc the foreign XML + * @param namespaceURI the namespace URI of the foreign XML + * @event.severity ERROR + */ + void foreignXMLNoHandler(Object source, Document doc, String namespaceURI); + + /** + * Cannot delete a temporary file. + * @param source the event source + * @param tempFile the temporary file + * @event.severity ERROR + */ + void cannotDeleteTempFile(Object source, File tempFile); + +} diff --git a/src/java/org/apache/fop/events/UnsupportedOperationExceptionFactory.java b/src/java/org/apache/fop/events/UnsupportedOperationExceptionFactory.java new file mode 100644 index 000000000..06ce8dd25 --- /dev/null +++ b/src/java/org/apache/fop/events/UnsupportedOperationExceptionFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.events; + +import java.util.Locale; + +import org.apache.fop.events.EventExceptionManager.ExceptionFactory; + +/** + * Exception factory for {@link UnsupportedOperationException}. + */ +public class UnsupportedOperationExceptionFactory implements ExceptionFactory { + + /** {@inheritDoc} */ + public Throwable createException(Event event) { + String msg = EventFormatter.format(event, Locale.ENGLISH); + UnsupportedOperationException ex = new UnsupportedOperationException(msg); + return ex; + } + + /** {@inheritDoc} */ + public Class getExceptionClass() { + return UnsupportedOperationException.class; + } + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/events/ValidationExceptionFactory.java b/src/java/org/apache/fop/events/ValidationExceptionFactory.java new file mode 100644 index 000000000..9dba84007 --- /dev/null +++ b/src/java/org/apache/fop/events/ValidationExceptionFactory.java @@ -0,0 +1,51 @@ +/* + * 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.events; + +import java.util.Locale; + +import org.xml.sax.Locator; + +import org.apache.fop.events.EventExceptionManager.ExceptionFactory; +import org.apache.fop.fo.ValidationException; + +/** + * Exception factory for {@link ValidationException}. + */ +public class ValidationExceptionFactory implements ExceptionFactory { + + /** {@inheritDoc} */ + public Throwable createException(Event event) { + Locator loc = (Locator)event.getParam("loc"); + String msg = EventFormatter.format(event, Locale.ENGLISH); + ValidationException ex = new ValidationException(msg, loc); + if (!Locale.ENGLISH.equals(Locale.getDefault())) { + ex.setLocalizedMessage(EventFormatter.format(event)); + } + return ex; + } + + /** {@inheritDoc} */ + public Class getExceptionClass() { + return ValidationException.class; + } + + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/events/model/AbstractEventModelFactory.java b/src/java/org/apache/fop/events/model/AbstractEventModelFactory.java new file mode 100644 index 000000000..ee980f34e --- /dev/null +++ b/src/java/org/apache/fop/events/model/AbstractEventModelFactory.java @@ -0,0 +1,61 @@ +/* + * 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.events.model; + +import java.io.InputStream; +import java.util.MissingResourceException; + +import javax.xml.transform.TransformerException; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.io.IOUtils; + +import org.apache.fop.events.DefaultEventBroadcaster; + +/** + * This interface is used to instantiate (load, parse) event models. + */ +public abstract class AbstractEventModelFactory implements EventModelFactory { + + /** + * Loads an event model and returns its instance. + * @param resourceBaseClass base class to use for loading resources + * @param resourceName the resource name pointing to the event model to be loaded + * @return the newly loaded event model. + */ + public EventModel loadModel(Class resourceBaseClass, String resourceName) { + InputStream in = resourceBaseClass.getResourceAsStream(resourceName); + if (in == null) { + throw new MissingResourceException( + "File " + resourceName + " not found", + DefaultEventBroadcaster.class.getName(), ""); + } + try { + return EventModelParser.parse(new StreamSource(in)); + } catch (TransformerException e) { + throw new MissingResourceException( + "Error reading " + resourceName + ": " + e.getMessage(), + DefaultEventBroadcaster.class.getName(), ""); + } finally { + IOUtils.closeQuietly(in); + } + } + +} diff --git a/src/java/org/apache/fop/events/model/EventMethodModel.java b/src/java/org/apache/fop/events/model/EventMethodModel.java new file mode 100644 index 000000000..930cda53d --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventMethodModel.java @@ -0,0 +1,198 @@ +/* + * 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.events.model; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import org.apache.xmlgraphics.util.XMLizable; + +/** + * Represents an event method. Each method in an event producer interface will result in one + * instance of EventMethodModel. + */ +public class EventMethodModel implements Serializable, XMLizable { + + private static final long serialVersionUID = -7548882973341444354L; + + private String methodName; + private EventSeverity severity; + private List params = new java.util.ArrayList(); + private String exceptionClass; + + /** + * Creates an new instance. + * @param methodName the event method's name + * @param severity the event severity + */ + public EventMethodModel(String methodName, EventSeverity severity) { + this.methodName = methodName; + this.severity = severity; + } + + /** + * Adds a method parameter. + * @param param the method parameter + */ + public void addParameter(Parameter param) { + this.params.add(param); + } + + /** + * Adds a method parameter. + * @param type the type of the parameter + * @param name the name of the parameter + * @return the resulting Parameter instance + */ + public Parameter addParameter(Class type, String name) { + Parameter param = new Parameter(type, name); + addParameter(param); + return param; + } + + /** + * Sets the event method name. + * @param name the event name + */ + public void setMethodName(String name) { + this.methodName = name; + } + + /** + * Returns the event method name + * @return the event name + */ + public String getMethodName() { + return this.methodName; + } + + /** + * Sets the event's severity level. + * @param severity the severity + */ + public void setSeverity(EventSeverity severity) { + this.severity = severity; + } + + /** + * Returns the event's severity level. + * @return the severity + */ + public EventSeverity getSeverity() { + return this.severity; + } + + /** + * Returns an unmodifiable list of parameters for this event method. + * @return the list of parameters + */ + public List getParameters() { + return Collections.unmodifiableList(this.params); + } + + /** + * Sets the primary exception class for this event method. Note: Not all event methods throw + * exceptions! + * @param exceptionClass the exception class + */ + public void setExceptionClass(String exceptionClass) { + this.exceptionClass = exceptionClass; + } + + /** + * Returns the primary exception class for this event method. This method returns null if + * the event is only informational or just a warning. + * @return the primary exception class or null + */ + public String getExceptionClass() { + return this.exceptionClass; + } + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(null, "name", "name", "CDATA", getMethodName()); + atts.addAttribute(null, "severity", "severity", "CDATA", getSeverity().getName()); + if (getExceptionClass() != null) { + atts.addAttribute(null, "exception", "exception", "CDATA", getExceptionClass()); + } + String elName = "method"; + handler.startElement(null, elName, elName, atts); + Iterator iter = this.params.iterator(); + while (iter.hasNext()) { + ((XMLizable)iter.next()).toSAX(handler); + } + handler.endElement(null, elName, elName); + } + + /** + * Represents an event parameter. + */ + public static class Parameter implements Serializable, XMLizable { + + private static final long serialVersionUID = 6062500277953887099L; + + private Class type; + private String name; + + /** + * Creates a new event parameter. + * @param type the parameter type + * @param name the parameter name + */ + public Parameter(Class type, String name) { + this.type = type; + this.name = name; + } + + /** + * Returns the parameter type. + * @return the parameter type + */ + public Class getType() { + return this.type; + } + + /** + * Returns the parameter name. + * @return the parameter name + */ + public String getName() { + return this.name; + } + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(null, "type", "type", "CDATA", getType().getName()); + atts.addAttribute(null, "name", "name", "CDATA", getName()); + String elName = "parameter"; + handler.startElement(null, elName, elName, atts); + handler.endElement(null, elName, elName); + } + + } +} diff --git a/src/java/org/apache/fop/events/model/EventModel.java b/src/java/org/apache/fop/events/model/EventModel.java new file mode 100644 index 000000000..61e221b3b --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventModel.java @@ -0,0 +1,135 @@ +/* + * 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.events.model; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.Iterator; +import java.util.Map; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import org.apache.xmlgraphics.util.XMLizable; + +/** + * Represents a whole event model that supports multiple event producers. + */ +public class EventModel implements Serializable, XMLizable { + + private static final long serialVersionUID = 7468592614934605082L; + + private Map producers = new java.util.LinkedHashMap(); + + /** + * Creates a new, empty event model + */ + public EventModel() { + } + + /** + * Adds the model of an event producer to the event model. + * @param producer the event producer model + */ + public void addProducer(EventProducerModel producer) { + this.producers.put(producer.getInterfaceName(), producer); + } + + /** + * Returns an iterator over the contained event producer models. + * @return an iterator (Iterator<EventProducerModel>) + */ + public Iterator getProducers() { + return this.producers.values().iterator(); + } + + /** + * Returns the model of an event producer with the given interface name. + * @param interfaceName the fully qualified name of the event producer + * @return the model instance for the event producer (or null if it wasn't found) + */ + public EventProducerModel getProducer(String interfaceName) { + return (EventProducerModel)this.producers.get(interfaceName); + } + + /** + * Returns the model of an event producer with the given interface. + * @param clazz the interface of the event producer + * @return the model instance for the event producer (or null if it wasn't found) + */ + public EventProducerModel getProducer(Class clazz) { + return getProducer(clazz.getName()); + } + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + String elName = "event-model"; + handler.startElement(null, elName, elName, atts); + Iterator iter = getProducers(); + while (iter.hasNext()) { + ((XMLizable)iter.next()).toSAX(handler); + } + handler.endElement(null, elName, elName); + } + + private void writeXMLizable(XMLizable object, File outputFile) throws IOException { + Result res = new StreamResult(outputFile); + + try { + SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + TransformerHandler handler = tFactory.newTransformerHandler(); + Transformer transformer = handler.getTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + handler.setResult(res); + handler.startDocument(); + object.toSAX(handler); + handler.endDocument(); + } catch (TransformerConfigurationException e) { + throw new IOException(e.getMessage()); + } catch (TransformerFactoryConfigurationError e) { + throw new IOException(e.getMessage()); + } catch (SAXException e) { + throw new IOException(e.getMessage()); + } + } + + /** + * Saves this event model to an XML file. + * @param modelFile the target file + * @throws IOException if an I/O error occurs + */ + public void saveToXML(File modelFile) throws IOException { + writeXMLizable(this, modelFile); + } + +} diff --git a/src/java/org/apache/fop/events/model/EventModelFactory.java b/src/java/org/apache/fop/events/model/EventModelFactory.java new file mode 100644 index 000000000..cd760501c --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventModelFactory.java @@ -0,0 +1,33 @@ +/* + * 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.events.model; + +/** + * This interface is used to instantiate (load, parse) event models. + */ +public interface EventModelFactory { + + /** + * Creates a new EventModel instance. + * @return the new EventModel instance + */ + EventModel createEventModel(); + +} diff --git a/src/java/org/apache/fop/events/model/EventModelParser.java b/src/java/org/apache/fop/events/model/EventModelParser.java new file mode 100644 index 000000000..600e495c5 --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventModelParser.java @@ -0,0 +1,140 @@ +/* + * 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.events.model; + +import java.util.Stack; + +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXTransformerFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.util.DefaultErrorListener; + +/** + * This is a parser for the event model XML. + */ +public class EventModelParser { + + /** Logger instance */ + protected static Log log = LogFactory.getLog(EventModelParser.class); + + private static SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + + /** + * Parses an event model file into an EventModel instance. + * @param src the Source instance pointing to the XML file + * @return the created event model structure + * @throws TransformerException if an error occurs while parsing the XML file + */ + public static EventModel parse(Source src) + throws TransformerException { + Transformer transformer = tFactory.newTransformer(); + transformer.setErrorListener(new DefaultErrorListener(log)); + + EventModel model = new EventModel(); + SAXResult res = new SAXResult(getContentHandler(model)); + + transformer.transform(src, res); + return model; + } + + /** + * Creates a new ContentHandler instance that you can send the event model XML to. The parsed + * content is accumulated in the model structure. + * @param model the EventModel + * @return the ContentHandler instance to receive the SAX stream from the XML file + */ + public static ContentHandler getContentHandler(EventModel model) { + return new Handler(model); + } + + private static class Handler extends DefaultHandler { + + private EventModel model; + private Stack objectStack = new Stack(); + + public Handler(EventModel model) { + this.model = model; + } + + /** {@inheritDoc} */ + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + try { + if ("event-model".equals(localName)) { + if (objectStack.size() > 0) { + throw new SAXException("event-model must be the root element"); + } + objectStack.push(model); + } else if ("producer".equals(localName)) { + EventProducerModel producer = new EventProducerModel( + attributes.getValue("name")); + EventModel parent = (EventModel)objectStack.peek(); + parent.addProducer(producer); + objectStack.push(producer); + } else if ("method".equals(localName)) { + EventSeverity severity = EventSeverity.valueOf(attributes.getValue("severity")); + String ex = attributes.getValue("exception"); + EventMethodModel method = new EventMethodModel( + attributes.getValue("name"), severity); + if (ex != null && ex.length() > 0) { + method.setExceptionClass(ex); + } + EventProducerModel parent = (EventProducerModel)objectStack.peek(); + parent.addMethod(method); + objectStack.push(method); + } else if ("parameter".equals(localName)) { + String className = attributes.getValue("type"); + Class type; + try { + type = Class.forName(className); + } catch (ClassNotFoundException e) { + throw new SAXException("Could not find Class for: " + className, e); + } + String name = attributes.getValue("name"); + EventMethodModel parent = (EventMethodModel)objectStack.peek(); + objectStack.push(parent.addParameter(type, name)); + } else { + throw new SAXException("Invalid element: " + qName); + } + } catch (ClassCastException cce) { + throw new SAXException("XML format error: " + qName, cce); + } + } + + /** {@inheritDoc} */ + public void endElement(String uri, String localName, String qName) throws SAXException { + objectStack.pop(); + } + + } + +} diff --git a/src/java/org/apache/fop/events/model/EventProducerModel.java b/src/java/org/apache/fop/events/model/EventProducerModel.java new file mode 100644 index 000000000..938609cd9 --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventProducerModel.java @@ -0,0 +1,105 @@ +/* + * 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.events.model; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Map; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import org.apache.xmlgraphics.util.XMLizable; + +/** + * Represents the model of an event producer with multiple event methods. + */ +public class EventProducerModel implements Serializable, XMLizable { + + private static final long serialVersionUID = 122267104123721902L; + + private String interfaceName; + private Map methods = new java.util.LinkedHashMap(); + + /** + * Creates a new instance. + * @param interfaceName the fully qualified interface name of the event producer + */ + public EventProducerModel(String interfaceName) { + this.interfaceName = interfaceName; + } + + /** + * Returns the fully qualified interface name of the event producer. + * @return the fully qualified interface name + */ + public String getInterfaceName() { + return this.interfaceName; + } + + /** + * Sets the fully qualified interface name of the event producer. + * @param name the fully qualified interface name + */ + public void setInterfaceName(String name) { + this.interfaceName = name; + } + + /** + * Adds a model instance of an event method. + * @param method the event method model + */ + public void addMethod(EventMethodModel method) { + this.methods.put(method.getMethodName(), method); + } + + /** + * Returns the model instance of an event method for the given method name. + * @param methodName the method name + * @return the model instance (or null if no method with the given name exists) + */ + public EventMethodModel getMethod(String methodName) { + return (EventMethodModel)this.methods.get(methodName); + } + + /** + * Returns an iterator over the contained event producer methods. + * @return an iterator (Iterator<EventMethodModel>) + */ + public Iterator getMethods() { + return this.methods.values().iterator(); + } + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(null, "name", "name", "CDATA", getInterfaceName()); + String elName = "producer"; + handler.startElement(null, elName, elName, atts); + Iterator iter = getMethods(); + while (iter.hasNext()) { + ((XMLizable)iter.next()).toSAX(handler); + } + handler.endElement(null, elName, elName); + } + + +} diff --git a/src/java/org/apache/fop/events/model/EventSeverity.java b/src/java/org/apache/fop/events/model/EventSeverity.java new file mode 100644 index 000000000..d37c53c1e --- /dev/null +++ b/src/java/org/apache/fop/events/model/EventSeverity.java @@ -0,0 +1,82 @@ +/* + * 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.events.model; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +/** Enumeration class for event severities. */ +public final class EventSeverity implements Serializable { + + private static final long serialVersionUID = 4108175215810759243L; + + /** info level */ + public static final EventSeverity INFO = new EventSeverity("INFO"); + /** warning level */ + public static final EventSeverity WARN = new EventSeverity("WARN"); + /** error level */ + public static final EventSeverity ERROR = new EventSeverity("ERROR"); + /** fatal error */ + public static final EventSeverity FATAL = new EventSeverity("FATAL"); + + private String name; + + /** + * Constructor to add a new named item. + * @param name Name of the item. + */ + private EventSeverity(String name) { + this.name = name; + } + + /** @return the name of the enumeration */ + public String getName() { + return this.name; + } + + /** + * Returns the enumeration/singleton object based on its name. + * @param name the name of the enumeration value + * @return the enumeration object + */ + public static EventSeverity valueOf(String name) { + if (INFO.getName().equalsIgnoreCase(name)) { + return INFO; + } else if (WARN.getName().equalsIgnoreCase(name)) { + return WARN; + } else if (ERROR.getName().equalsIgnoreCase(name)) { + return ERROR; + } else if (FATAL.getName().equalsIgnoreCase(name)) { + return FATAL; + } else { + throw new IllegalArgumentException("Illegal value for enumeration: " + name); + } + } + + private Object readResolve() throws ObjectStreamException { + return valueOf(getName()); + } + + /** {@inheritDoc} */ + public String toString() { + return "EventSeverity:" + name; + } + +} diff --git a/src/java/org/apache/fop/fo/ElementMapping.java b/src/java/org/apache/fop/fo/ElementMapping.java index 0f436ae28..a47e6affa 100644 --- a/src/java/org/apache/fop/fo/ElementMapping.java +++ b/src/java/org/apache/fop/fo/ElementMapping.java @@ -24,9 +24,10 @@ import java.util.HashMap; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import org.apache.fop.util.QName; import org.w3c.dom.DOMImplementation; +import org.apache.xmlgraphics.util.QName; + /** * Abstract base class for Element Mappings (including FO Element Mappings) * which provide the framework of valid elements and attibutes for a given diff --git a/src/java/org/apache/fop/fo/ElementMappingRegistry.java b/src/java/org/apache/fop/fo/ElementMappingRegistry.java index 2ba142203..abc4ec834 100644 --- a/src/java/org/apache/fop/fo/ElementMappingRegistry.java +++ b/src/java/org/apache/fop/fo/ElementMappingRegistry.java @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.Map; import org.w3c.dom.DOMImplementation; + import org.xml.sax.Locator; import org.apache.commons.logging.Log; @@ -144,7 +145,6 @@ public class ElementMappingRegistry { + "No element mapping definition found for " + FONode.getNodeString(namespaceURI, localName), locator); } else { - log.warn("Unknown formatting object " + namespaceURI + "^" + localName); fobjMaker = new UnknownXMLObj.Maker(namespaceURI); } } diff --git a/src/java/org/apache/fop/fo/FOElementMapping.java b/src/java/org/apache/fop/fo/FOElementMapping.java index 51ec85d21..62721afeb 100644 --- a/src/java/org/apache/fop/fo/FOElementMapping.java +++ b/src/java/org/apache/fop/fo/FOElementMapping.java @@ -22,7 +22,7 @@ package org.apache.fop.fo; // Java import java.util.HashMap; -import org.apache.fop.util.QName; +import org.apache.xmlgraphics.util.QName; /** * Element mapping class for all XSL-FO elements. diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index d226cfb6c..5a9a5bb9d 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -48,6 +48,7 @@ import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.pagination.Flow; import org.apache.fop.fo.pagination.PageSequence; +import org.apache.fop.fonts.FontEventAdapter; import org.apache.fop.fonts.FontInfo; /** @@ -101,6 +102,7 @@ public abstract class FOEventHandler { public FOEventHandler(FOUserAgent foUserAgent) { this.foUserAgent = foUserAgent; this.fontInfo = new FontInfo(); + this.fontInfo.setEventListener(new FontEventAdapter(foUserAgent.getEventBroadcaster())); } /** diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index f0422e414..197a2482d 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -21,6 +21,8 @@ package org.apache.fop.fo; // Java import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; import org.xml.sax.Attributes; import org.xml.sax.Locator; @@ -29,6 +31,8 @@ import org.xml.sax.helpers.LocatorImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.extensions.ExtensionAttachment; @@ -37,6 +41,7 @@ import org.apache.fop.fo.extensions.svg.SVGElementMapping; import org.apache.fop.fo.pagination.Root; import org.apache.fop.util.CharUtilities; import org.apache.fop.util.ContentHandlerFactory; +import org.apache.fop.util.text.AdvancedMessageFormat.Function; /** * Base class for nodes in the XML tree @@ -143,6 +148,10 @@ public abstract class FONode implements Cloneable { return parent.getFOEventHandler(); } + /** + * Indicates whether this node is a child of an fo:marker. + * @return true if this node is a child of an fo:marker + */ protected boolean inMarker() { return getFOEventHandler().inMarker(); } @@ -239,7 +248,7 @@ public abstract class FONode implements Cloneable { * @param start starting array element to add * @param end ending array element to add * @param pList currently applicable PropertyList - * @param locator location in fo source file. + * @param locator location in the XSL-FO source file. * @throws FOPException if there's a problem during processing */ protected void addCharacters(char[] data, int start, int end, @@ -343,54 +352,50 @@ public abstract class FONode implements Cloneable { } /** - * Helper function to standardize property error exceptions - * (e.g., not specifying either an internal- or an external-destination - * property for an FO:link) - * @param problem text to display that indicates the problem - * @throws ValidationException the validation error provoked by the method call + * Returns an instance of the FOValidationEventProducer. + * @return an event producer for FO validation */ - protected void attributeError(String problem) - throws ValidationException { - throw new ValidationException(errorText(locator) + getName() - + ", " + problem, locator); + protected FOValidationEventProducer getFOValidationEventProducer() { + return FOValidationEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); } - + /** - * Helper function to standardize attribute warnings - * (e.g., currently unsupported properties) - * @param problem text to display that indicates the problem + * Helper function to standardize "too many" error exceptions + * (e.g., two fo:declarations within fo:root) + * @param loc org.xml.sax.Locator object of the error (*not* parent node) + * @param nsURI namespace URI of incoming invalid node + * @param lName local name (i.e., no prefix) of incoming node + * @throws ValidationException the validation error provoked by the method call */ - public void attributeWarning(String problem) { - log.warn(warningText(locator) + getName() + ", " + problem); + protected void tooManyNodesError(Locator loc, String nsURI, String lName) + throws ValidationException { + tooManyNodesError(loc, new QName(nsURI, lName)); } /** * Helper function to standardize "too many" error exceptions * (e.g., two fo:declarations within fo:root) * @param loc org.xml.sax.Locator object of the error (*not* parent node) - * @param nsURI namespace URI of incoming invalid node - * @param lName local name (i.e., no prefix) of incoming node + * @param offendingNode the qualified name of the offending node * @throws ValidationException the validation error provoked by the method call */ - protected void tooManyNodesError(Locator loc, String nsURI, String lName) + protected void tooManyNodesError(Locator loc, QName offendingNode) throws ValidationException { - throw new ValidationException(errorText(loc) + "For " + getName() - + ", only one " + getNodeString(nsURI, lName) + " may be declared.", - loc); + getFOValidationEventProducer().tooManyNodes(this, getName(), offendingNode, loc); } /** * Helper function to standardize "too many" error exceptions * (e.g., two fo:declarations within fo:root) - * This overrloaded method helps make the caller code better self-documenting + * This overloaded method helps make the caller code better self-documenting * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param offendingNode incoming node that would cause a duplication. * @throws ValidationException the validation error provoked by the method call */ protected void tooManyNodesError(Locator loc, String offendingNode) throws ValidationException { - throw new ValidationException(errorText(loc) + "For " + getName() - + ", only one " + offendingNode + " may be declared.", loc); + tooManyNodesError(loc, new QName(FO_URI, offendingNode)); } /** @@ -402,9 +407,23 @@ public abstract class FONode implements Cloneable { * @throws ValidationException the validation error provoked by the method call */ protected void nodesOutOfOrderError(Locator loc, String tooLateNode, - String tooEarlyNode) throws ValidationException { - throw new ValidationException(errorText(loc) + "For " + getName() + ", " + tooLateNode - + " must be declared before " + tooEarlyNode + ".", loc); + String tooEarlyNode) throws ValidationException { + nodesOutOfOrderError(loc, tooLateNode, tooEarlyNode, false); + } + + /** + * Helper function to standardize "out of order" exceptions + * (e.g., fo:layout-master-set appearing after fo:page-sequence) + * @param loc org.xml.sax.Locator object of the error (*not* parent node) + * @param tooLateNode string name of node that should be earlier in document + * @param tooEarlyNode string name of node that should be later in document + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @throws ValidationException the validation error provoked by the method call + */ + protected void nodesOutOfOrderError(Locator loc, String tooLateNode, + String tooEarlyNode, boolean canRecover) throws ValidationException { + getFOValidationEventProducer().nodeOutOfOrder(this, getName(), + tooLateNode, tooEarlyNode, canRecover, loc); } /** @@ -417,24 +436,24 @@ public abstract class FONode implements Cloneable { */ protected void invalidChildError(Locator loc, String nsURI, String lName) throws ValidationException { - invalidChildError(loc, nsURI, lName, null); + invalidChildError(loc, getName(), nsURI, lName, null); } /** * Helper function to return "invalid child" exceptions with more * complex validation rules (i.e., needing more explanation of the problem) * @param loc org.xml.sax.Locator object of the error (*not* parent node) + * @param parentName the name of the parent element * @param nsURI namespace URI of incoming invalid node * @param lName local name (i.e., no prefix) of incoming node - * @param ruleViolated text explanation of problem + * @param ruleViolated name of the rule violated (used to lookup a resource in a bundle) * @throws ValidationException the validation error provoked by the method call */ - protected void invalidChildError(Locator loc, String nsURI, String lName, + protected void invalidChildError(Locator loc, String parentName, String nsURI, String lName, String ruleViolated) throws ValidationException { - throw new ValidationException(errorText(loc) + getNodeString(nsURI, lName) - + " is not a valid child element of " + getName() - + ((ruleViolated != null) ? ": " + ruleViolated : "."), loc); + getFOValidationEventProducer().invalidChild(this, parentName, + new QName(nsURI, lName), ruleViolated, loc); } /** @@ -446,9 +465,22 @@ public abstract class FONode implements Cloneable { */ protected void missingChildElementError(String contentModel) throws ValidationException { - throw new ValidationException(errorText(locator) + getName() - + " is missing child elements. \nRequired Content Model: " - + contentModel, locator); + getFOValidationEventProducer().missingChildElement(this, getName(), + contentModel, false, locator); + } + + /** + * Helper function to throw an error caused by missing mandatory child elements. + * E.g., fo:layout-master-set not having any page-master child element. + * @param contentModel The XSL Content Model for the fo: object or a similar description + * indicating the necessary child elements. + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @throws ValidationException the validation error provoked by the method call + */ + protected void missingChildElementError(String contentModel, boolean canRecover) + throws ValidationException { + getFOValidationEventProducer().missingChildElement(this, getName(), + contentModel, canRecover, locator); } /** @@ -458,8 +490,7 @@ public abstract class FONode implements Cloneable { */ protected void missingPropertyError(String propertyName) throws ValidationException { - throw new ValidationException(errorText(locator) + getName() - + " is missing required \"" + propertyName + "\" property.", locator); + getFOValidationEventProducer().missingProperty(this, getName(), propertyName, locator); } /** @@ -513,9 +544,10 @@ public abstract class FONode implements Cloneable { /** * Returns a String containing as much context information as possible about a node. Call - * this methods only in exceptional conditions because this method may perform quite extensive + * this method only in exceptional conditions because this method may perform quite extensive * information gathering inside the FO tree. - * @return a String containing + * @return a String containing context information + * @deprecated Not localized! Should rename getContextInfoAlt() to getContextInfo() when done! */ public String getContextInfo() { StringBuffer sb = new StringBuffer(); @@ -542,6 +574,54 @@ public abstract class FONode implements Cloneable { return sb.toString(); } + /** + * Returns a String containing as some context information about a node. It does not take the + * locator into consideration and returns null if no useful context information can be found. + * Call this method only in exceptional conditions because this method may perform quite + * extensive information gathering inside the FO tree. All text returned by this method that + * is not extracted from document content needs to be locale-independent. + * @return a String containing context information + */ + protected String getContextInfoAlt() { + String s = gatherContextInfo(); + if (s != null) { + StringBuffer sb = new StringBuffer(); + if (getLocalName() != null) { + sb.append(getName()); + sb.append(", "); + } + sb.append("\""); + sb.append(s); + sb.append("\""); + return sb.toString(); + } else { + return null; + } + } + + /** Function for AdvancedMessageFormat to retrieve context info from an FONode. */ + public static class GatherContextInfoFunction implements Function { + + /** {@inheritDoc} */ + public Object evaluate(Map params) { + Object obj = params.get("source"); + if (obj instanceof PropertyList) { + PropertyList propList = (PropertyList)obj; + obj = propList.getFObj(); + } + if (obj instanceof FONode) { + FONode node = (FONode)obj; + return node.getContextInfoAlt(); + } + return null; + } + + /** {@inheritDoc} */ + public Object getName() { + return "gatherContextInfo"; + } + } + /** * Gathers context information for the getContextInfo() method. * @return the collected context information or null, if none is available @@ -687,7 +767,7 @@ public abstract class FONode implements Cloneable { * of child nodes * @return the parent node */ - public FObj parentNode(); + FObj parentNode(); /** * Convenience method with return type of FONode @@ -695,7 +775,7 @@ public abstract class FONode implements Cloneable { * (FONode) next();) * @return the next node (if any), as a type FONode */ - public FONode nextNode(); + FONode nextNode(); /** * Convenience method with return type of FONode @@ -703,7 +783,7 @@ public abstract class FONode implements Cloneable { * (FONode) previous();) * @return the previous node (if any), as a type FONode */ - public FONode previousNode(); + FONode previousNode(); /** * Returns the first node in the list, and decreases the index, @@ -711,7 +791,7 @@ public abstract class FONode implements Cloneable { * @return the first node in the list * @throws NoSuchElementException if the list is empty */ - public FONode firstNode(); + FONode firstNode(); /** * Returns the last node in the list, and advances the @@ -720,7 +800,7 @@ public abstract class FONode implements Cloneable { * @return the last node in the list * @throws NoSuchElementException if the list is empty */ - public FONode lastNode(); + FONode lastNode(); } } diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index 6d1ac417f..99d37dba9 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -19,11 +19,11 @@ package org.apache.fop.fo; -// Java import java.awt.Color; import java.util.NoSuchElementException; -// FOP +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.flow.Block; @@ -34,9 +34,6 @@ import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.SpaceProperty; -// SAX -import org.xml.sax.Locator; - /** * A text node (PCDATA) in the formatting object tree. * @@ -396,7 +393,7 @@ public class FOText extends FONode { return ca[i]; } default: - log.warn("Invalid text-tranform value: " + textTransform); + assert false; //should never happen as the property subsystem catches that case return ca[i]; } } diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index d02a058fe..84abc4b8b 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -31,6 +31,8 @@ import org.xml.sax.helpers.DefaultHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FormattingResults; @@ -130,6 +132,7 @@ public class FOTreeBuilder extends DefaultHandler { throw new IllegalStateException("FOTreeBuilder (and the Fop class) cannot be reused." + " Please instantiate a new instance."); } + used = true; empty = true; rootFObj = null; // allows FOTreeBuilder to be reused @@ -146,8 +149,10 @@ public class FOTreeBuilder extends DefaultHandler { public void endDocument() throws SAXException { this.delegate.endDocument(); if (this.rootFObj == null && empty) { - throw new ValidationException( - "Document is empty (something might be wrong with your XSLT stylesheet)."); + FOValidationEventProducer eventProducer + = FOValidationEventProducer.Provider.get( + foEventHandler.getUserAgent().getEventBroadcaster()); + eventProducer.emptyDocument(this); } rootFObj = null; if (log.isDebugEnabled()) { @@ -178,18 +183,6 @@ public class FOTreeBuilder extends DefaultHandler { } } - /** - * Finds the {@link Maker} used to create {@link FONode} objects of a particular type - * - * @param namespaceURI URI for the namespace of the element - * @param localName name of the Element - * @return the ElementMapping.Maker that can create an FO object for this element - * @throws FOPException if a Maker could not be found for a bound namespace. - */ - private Maker findFOMaker(String namespaceURI, String localName) throws FOPException { - return elementMappingRegistry.findFOMaker(namespaceURI, localName, locator); - } - /** {@inheritDoc} */ public void warning(SAXParseException e) { log.warn(e.getLocalizedMessage()); @@ -258,22 +251,21 @@ public class FOTreeBuilder extends DefaultHandler { if (rootFObj == null) { empty = false; if (!namespaceURI.equals(FOElementMapping.URI) - || !localName.equals("root")) { - throw new ValidationException( - "Error: First element must be the fo:root formatting object. " - + "Found " + FONode.getNodeString(namespaceURI, localName) - + " instead." - + " Please make sure you're producing a valid XSL-FO document."); + || !localName.equals("root")) { + FOValidationEventProducer eventProducer + = FOValidationEventProducer.Provider.get( + foEventHandler.getUserAgent().getEventBroadcaster()); + eventProducer.invalidFORoot(this, FONode.getNodeString(namespaceURI, localName), + getEffectiveLocator()); } } else { // check that incoming node is valid for currentFObj - if (namespaceURI.equals(FOElementMapping.URI) - || namespaceURI.equals(ExtensionElementMapping.URI)) { + if (currentFObj.getNamespaceURI().equals(FOElementMapping.URI) + || currentFObj.getNamespaceURI().equals(ExtensionElementMapping.URI)) { currentFObj.validateChildNode(locator, namespaceURI, localName); } } - ElementMapping.Maker fobjMaker = - findFOMaker(namespaceURI, localName); + ElementMapping.Maker fobjMaker = findFOMaker(namespaceURI, localName); try { foNode = fobjMaker.make(currentFObj); @@ -342,8 +334,7 @@ public class FOTreeBuilder extends DefaultHandler { if (currentPropertyList != null && currentPropertyList.getFObj() == currentFObj && !foEventHandler.inMarker()) { - currentPropertyList = - currentPropertyList.getParentPropertyList(); + currentPropertyList = currentPropertyList.getParentPropertyList(); } if (currentFObj.getNameId() == Constants.FO_MARKER) { @@ -373,7 +364,29 @@ public class FOTreeBuilder extends DefaultHandler { /** {@inheritDoc} */ public void endDocument() throws SAXException { currentFObj = null; - } + } + + /** + * Finds the {@link Maker} used to create {@link FONode} objects of a particular type + * + * @param namespaceURI URI for the namespace of the element + * @param localName name of the Element + * @return the ElementMapping.Maker that can create an FO object for this element + * @throws FOPException if a Maker could not be found for a bound namespace. + */ + private Maker findFOMaker(String namespaceURI, String localName) throws FOPException { + Maker maker = elementMappingRegistry.findFOMaker(namespaceURI, localName, locator); + if (maker instanceof UnknownXMLObj.Maker) { + FOValidationEventProducer eventProducer + = FOValidationEventProducer.Provider.get( + foEventHandler.getUserAgent().getEventBroadcaster()); + eventProducer.unknownFormattingObject(this, currentFObj.getName(), + new QName(namespaceURI, localName), + getEffectiveLocator()); + } + return maker; + } + } } diff --git a/src/java/org/apache/fop/fo/FOValidationEventProducer.java b/src/java/org/apache/fop/fo/FOValidationEventProducer.java new file mode 100644 index 000000000..aa7b14941 --- /dev/null +++ b/src/java/org/apache/fop/fo/FOValidationEventProducer.java @@ -0,0 +1,348 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo; + +import org.xml.sax.Locator; + +import org.apache.xmlgraphics.util.QName; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.fo.expr.PropertyException; + +/** + * Event producer interface for XSL-FO validation messages. + */ +public interface FOValidationEventProducer extends EventProducer { + + /** + * Provider class for the event producer. + */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static FOValidationEventProducer get(EventBroadcaster broadcaster) { + return (FOValidationEventProducer)broadcaster.getEventProducerFor( + FOValidationEventProducer.class); + } + } + + /** + * Too many child nodes. + * @param source the event source + * @param elementName the name of the context node + * @param offendingNode the offending node + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void tooManyNodes(Object source, String elementName, QName offendingNode, + Locator loc) throws ValidationException; + + /** + * The node order is wrong. + * @param source the event source + * @param elementName the name of the context node + * @param tooLateNode string name of node that should be earlier in document + * @param tooEarlyNode string name of node that should be later in document + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + */ + void nodeOutOfOrder(Object source, String elementName, + String tooLateNode, String tooEarlyNode, boolean canRecover, + Locator loc) throws ValidationException; + + /** + * An invalid child was encountered. + * @param source the event source + * @param elementName the name of the context node + * @param offendingNode the offending node + * @param ruleViolated the rule that was violated or null + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + */ + void invalidChild(Object source, String elementName, QName offendingNode, String ruleViolated, + Locator loc) throws ValidationException; + + /** + * A required child element is missing. + * @param source the event source + * @param elementName the name of the context node + * @param contentModel the expected content model + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void missingChildElement(Object source, String elementName, + String contentModel, boolean canRecover, + Locator loc) throws ValidationException; + + /** + * An element is missing a required property. + * @param source the event source + * @param elementName the name of the context node + * @param propertyName the name of the missing property + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void missingProperty(Object source, String elementName, String propertyName, + Locator loc) throws ValidationException; + + /** + * An id was used twice in a document. + * @param source the event source + * @param elementName the name of the context node + * @param id the id that was reused + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void idNotUnique(Object source, String elementName, String id, boolean canRecover, + Locator loc) throws ValidationException; + + /** + * There are multiple color profiles defined with the same name. + * @param source the event source + * @param elementName the name of the context node + * @param name the duplicate color profile name + * @param loc the location of the error or null + * @event.severity WARN + */ + void colorProfileNameNotUnique(Object source, String elementName, String name, + Locator loc); + + /** + * There are multiple page masters defined with the same name. + * @param source the event source + * @param elementName the name of the context node + * @param name the duplicate page master name + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void masterNameNotUnique(Object source, String elementName, String name, + Locator loc) throws ValidationException; + + /** + * A marker is not an initial child on a node. + * @param source the event source + * @param elementName the name of the context node + * @param mcname the marker class name + * @param loc the location of the error or null + * @event.severity ERROR + */ + void markerNotInitialChild(Object source, String elementName, String mcname, Locator loc); + + /** + * A marker class name is not unique within the same parent. + * @param source the event source + * @param elementName the name of the context node + * @param mcname the marker class name + * @param loc the location of the error or null + * @event.severity ERROR + */ + void markerNotUniqueForSameParent(Object source, String elementName, + String mcname, Locator loc); + + /** + * An invalid property was found. + * @param source the event source + * @param elementName the name of the context node + * @param attr the invalid attribute + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void invalidProperty(Object source, String elementName, QName attr, boolean canRecover, + Locator loc) throws ValidationException; + + /** + * An invalid property value was encountered. + * @param source the event source + * @param elementName the name of the context node + * @param propName the property name + * @param propValue the property value + * @param e the property exception caused by the invalid value + * @param loc the location of the error or null + * @event.severity ERROR + */ + void invalidPropertyValue(Object source, String elementName, + String propName, String propValue, PropertyException e, + Locator loc); + + /** + * A feature is not supported, yet. + * @param source the event source + * @param elementName the name of the context node + * @param feature the unsupported feature + * @param loc the location of the error or null + * @event.severity WARN + */ + void unimplementedFeature(Object source, String elementName, String feature, + Locator loc); + + /** + * Missing internal-/external-destination on basic-link or bookmark. + * @param source the event source + * @param elementName the name of the context node + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void missingLinkDestination(Object source, String elementName, Locator loc) + throws ValidationException; + + /** + * Indicates a problem while cloning a marker (ex. due to invalid property values). + * @param source the event source + * @param markerClassName the "marker-class-name" of the marker + * @param fe the FOP exception that cause this problem + * @param loc the location of the error or null + * @event.severity ERROR + */ + void markerCloningFailed(Object source, String markerClassName, FOPException fe, Locator loc); + + /** + * A region name is mapped to multiple region classes. + * @param source the event source + * @param regionName the region name + * @param defaultRegionClass1 the first default region class + * @param defaultRegionClass2 the second default region class + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void regionNameMappedToMultipleRegionClasses(Object source, String regionName, + String defaultRegionClass1, String defaultRegionClass2, Locator loc) + throws ValidationException; + + /** + * There are multiple flows with the same name. + * @param source the event source + * @param elementName the name of the context node + * @param flowName the flow name + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void duplicateFlowNameInPageSequence(Object source, String elementName, String flowName, + Locator loc) throws ValidationException; + + /** + * A flow name could not be mapped to a region. + * @param source the event source + * @param elementName the name of the context node + * @param flowName the flow name + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void flowNameNotMapped(Object source, String elementName, String flowName, + Locator loc) throws ValidationException; + + /** + * A page master could not be found. + * @param source the event source + * @param elementName the name of the context node + * @param masterReference the page master reference + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void masterNotFound(Object source, String elementName, String masterReference, + Locator loc) throws ValidationException; + + /** + * An illegal region name was used. + * @param source the event source + * @param elementName the name of the context node + * @param regionName the region name + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void illegalRegionName(Object source, String elementName, String regionName, + Locator loc) throws ValidationException; + + /** + * A non-zero border and/or padding has been encountered on a region. + * @param source the event source + * @param elementName the name of the context node + * @param regionName the region name + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void nonZeroBorderPaddingOnRegion(Object source, String elementName, String regionName, + boolean canRecover, Locator loc) throws ValidationException; + + /** + * If overflow property is set to "scroll", a column-count other than "1" may not be specified. + * @param source the event source + * @param elementName the name of the context node + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void columnCountErrorOnRegionBodyOverflowScroll(Object source, String elementName, + Locator loc) throws ValidationException; + + /** + * fo:root must be root. + * @param source the event source + * @param elementName the name of the context node + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void invalidFORoot(Object source, String elementName, + Locator loc) throws ValidationException; + + /** + * No FO document was found. + * @param source the event source + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void emptyDocument(Object source) throws ValidationException; + + /** + * An unknown/unsupported formatting object has been encountered. + * @param source the event source + * @param elementName the name of the context node + * @param offendingNode the offending node + * @param loc the location of the error or null + * @event.severity WARN + */ + void unknownFormattingObject(Object source, String elementName, + QName offendingNode, Locator loc); + +} diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index b2587df2d..a03a351e0 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -27,13 +27,15 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.flow.Marker; import org.apache.fop.fo.properties.PropertyMaker; -import org.apache.fop.util.QName; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; /** * Base class for representation of formatting objects and their processing. @@ -171,25 +173,7 @@ public abstract class FObj extends FONode implements Constants { if (!idrefs.contains(id)) { idrefs.add(id); } else { - if (getUserAgent().validateStrictly()) { - throw new ValidationException("Property id \"" + id - + "\" previously used; id values must be unique" - + " in document.", locator); - } else { - if (log.isWarnEnabled()) { - StringBuffer msg = new StringBuffer(); - msg.append("Found non-unique id on ").append(getName()); - if (locator.getLineNumber() != -1) { - msg.append(" (at ").append(locator.getLineNumber()) - .append("/").append(locator.getColumnNumber()) - .append(")"); - } - msg.append("\nAny reference to it will be considered " - + "a reference to the first occurrence " - + "in the document."); - log.warn(msg); - } - } + getFOValidationEventProducer().idNotUnique(this, getName(), id, true, locator); } } } @@ -283,16 +267,22 @@ public abstract class FObj extends FONode implements Constants { return false; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FONodeIterator getChildNodes() { - if (firstChild != null) { + if (hasChildren()) { return new FObjIterator(this); } return null; } + /** + * Indicates whether this formatting object has children. + * @return true if there are children + */ + public boolean hasChildren() { + return this.firstChild != null; + } + /** * Return an iterator over the object's childNodes starting * at the passed-in node (= first call to iterator.next() will @@ -348,8 +338,8 @@ public abstract class FObj extends FONode implements Constants { if (node instanceof FObj || (node instanceof FOText && ((FOText) node).willCreateArea())) { - log.error( - "fo:marker must be an initial child: " + mcname); + getFOValidationEventProducer().markerNotInitialChild(this, getName(), + mcname, locator); return; } else if (node instanceof FOText) { iter.remove(); @@ -363,8 +353,8 @@ public abstract class FObj extends FONode implements Constants { if (!markers.containsKey(mcname)) { markers.put(mcname, marker); } else { - log.error("fo:marker 'marker-class-name' " - + "must be unique for same parent: " + mcname); + getFOValidationEventProducer().markerNotUniqueForSameParent(this, getName(), + mcname, locator); } } @@ -382,6 +372,33 @@ public abstract class FObj extends FONode implements Constants { return markers; } + /** {@inheritDoc} */ + protected String getContextInfoAlt() { + StringBuffer sb = new StringBuffer(); + if (getLocalName() != null) { + sb.append(getName()); + sb.append(", "); + } + if (hasId()) { + sb.append("id=").append(getId()); + return sb.toString(); + } + String s = gatherContextInfo(); + if (s != null) { + sb.append("\""); + if (s.length() < 32) { + sb.append(s); + } else { + sb.append(s.substring(0, 32)); + sb.append("..."); + } + sb.append("\""); + return sb.toString(); + } else { + return null; + } + } + /** {@inheritDoc} */ protected String gatherContextInfo() { if (getLocator() != null) { diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java index 3d050efed..b6766bfe9 100644 --- a/src/java/org/apache/fop/fo/PropertyList.java +++ b/src/java/org/apache/fop/fo/PropertyList.java @@ -20,13 +20,13 @@ package org.apache.fop.fo; // Java -import java.text.MessageFormat; - import org.xml.sax.Attributes; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.apps.FopFactory; import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.properties.CommonAbsolutePosition; @@ -41,7 +41,6 @@ import org.apache.fop.fo.properties.CommonRelativePosition; import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.PropertyMaker; -import org.apache.fop.util.QName; /** * Class containing the collection of properties for a given FObj. @@ -150,7 +149,7 @@ public abstract class PropertyList { * the default value. * @param propId The Constants ID of the property whose value is desired. * @return the Property corresponding to that name - * @throws PropertyException ... + * @throws PropertyException if there is a problem evaluating the property */ public Property get(int propId) throws PropertyException { return get(propId, true, true); @@ -166,7 +165,7 @@ public abstract class PropertyList { * value is needed * @param bTryDefault true when the default value may be used as a last resort * @return the property - * @throws PropertyException ... + * @throws PropertyException if there is a problem evaluating the property */ public Property get(int propId, boolean bTryInherit, boolean bTryDefault) throws PropertyException { @@ -321,20 +320,18 @@ public abstract class PropertyList { } else if (!factory.isNamespaceIgnored(attributeNS)) { ElementMapping mapping = factory.getElementMappingRegistry().getElementMapping( attributeNS); + QName attr = new QName(attributeNS, attributeName); if (mapping != null) { - QName attName = new QName(attributeNS, attributeName); - if (mapping.isAttributeProperty(attName) + if (mapping.isAttributeProperty(attr) && mapping.getStandardPrefix() != null) { convertAttributeToProperty(attributes, - mapping.getStandardPrefix() + ":" + attName.getLocalName(), + mapping.getStandardPrefix() + ":" + attr.getLocalName(), attributeValue); } else { - getFObj().addForeignAttribute(attName, attributeValue); + getFObj().addForeignAttribute(attr, attributeValue); } } else { - handleInvalidProperty( - "Error processing foreign attribute: " - + attributeNS + "/@" + attributeName, attributeName); + handleInvalidProperty(attr); } } } @@ -345,11 +342,8 @@ public abstract class PropertyList { * @param propertyName the property name to check * @return true if the base property name and the subproperty name (if any) * can be correctly mapped to an id - * @throws ValidationException in case the property name - * is invalid for the FO namespace */ - protected boolean isValidPropertyName(String propertyName) - throws ValidationException { + protected boolean isValidPropertyName(String propertyName) { int propId = FOPropertyMapping.getPropertyId( findBasePropertyName(propertyName)); @@ -359,9 +353,6 @@ public abstract class PropertyList { if (propId == -1 || (subpropId == -1 && findSubPropertyName(propertyName) != null)) { - String errorMessage = MessageFormat.format( - "Invalid property name ''{0}''.", new Object[] {propertyName}); - handleInvalidProperty(errorMessage, propertyName); return false; } return true; @@ -382,19 +373,23 @@ public abstract class PropertyList { if (attributeValue != null) { - if (!isValidPropertyName(attributeName)) { - //will log an error or throw an exception + if (attributeName.startsWith("xmlns:")) { + //Ignore namespace declarations return; } - FObj parentFO = fobj.findNearestAncestorFObj(); - /* Handle "compound" properties, ex. space-before.minimum */ String basePropertyName = findBasePropertyName(attributeName); String subPropertyName = findSubPropertyName(attributeName); int propId = FOPropertyMapping.getPropertyId(basePropertyName); int subpropId = FOPropertyMapping.getSubPropertyId(subPropertyName); + + if (propId == -1 + || (subpropId == -1 && subPropertyName != null)) { + handleInvalidProperty(new QName(null, attributeName)); + } + FObj parentFO = fobj.findNearestAncestorFObj(); PropertyMaker propertyMaker = findMaker(propId); if (propertyMaker == null) { @@ -417,8 +412,8 @@ public abstract class PropertyList { } prop = propertyMaker.make(this, attributeValue, parentFO); } else { // e.g. "leader-length.maximum" - Property baseProperty = - findBaseProperty(attributes, parentFO, propId, + Property baseProperty + = findBaseProperty(attributes, parentFO, propId, basePropertyName, propertyMaker); prop = propertyMaker.make(baseProperty, subpropId, this, attributeValue, parentFO); @@ -427,8 +422,8 @@ public abstract class PropertyList { putExplicit(propId, prop); } } catch (PropertyException e) { - log.error("Ignoring property: " - + attributeName + "=\"" + attributeValue + "\" (" + e.getMessage() + ")"); + fobj.getFOValidationEventProducer().invalidPropertyValue(this, fobj.getName(), + attributeName, attributeValue, e, fobj.locator); } } } @@ -465,18 +460,16 @@ public abstract class PropertyList { } /** - * @param message ... - * @param propName ... - * @throws ValidationException ... + * Handles an invalid property. + * @param attr the invalid attribute + * @throws ValidationException if an exception needs to be thrown depending on the + * validation settings */ - protected void handleInvalidProperty(String message, String propName) + protected void handleInvalidProperty(QName attr) throws ValidationException { - if (!propName.startsWith("xmlns")) { - if (fobj.getUserAgent().validateStrictly()) { - fobj.attributeError(message); - } else { - log.error(message + " Property ignored."); - } + if (!attr.getQName().startsWith("xmlns")) { + fobj.getFOValidationEventProducer().invalidProperty(this, fobj.getName(), + attr, true, fobj.locator); } } diff --git a/src/java/org/apache/fop/fo/expr/FromParentFunction.java b/src/java/org/apache/fop/fo/expr/FromParentFunction.java index b5a82de56..b09d3c95f 100644 --- a/src/java/org/apache/fop/fo/expr/FromParentFunction.java +++ b/src/java/org/apache/fop/fo/expr/FromParentFunction.java @@ -64,7 +64,13 @@ public class FromParentFunction extends FunctionBase { * non-inherited properties too. Perhaps the result is different for * a property line line-height which "inherits specified"??? */ - return pInfo.getPropertyList().getFromParent(FOPropertyMapping.getPropertyId(propName)); + int propId = FOPropertyMapping.getPropertyId(propName); + if (propId < 0) { + throw new PropertyException( + "Unknown property name used with inherited-property-value function: " + + propName); + } + return pInfo.getPropertyList().getFromParent(propId); } } diff --git a/src/java/org/apache/fop/fo/expr/InheritedPropFunction.java b/src/java/org/apache/fop/fo/expr/InheritedPropFunction.java index 3e5cadf04..e24c78caa 100644 --- a/src/java/org/apache/fop/fo/expr/InheritedPropFunction.java +++ b/src/java/org/apache/fop/fo/expr/InheritedPropFunction.java @@ -58,6 +58,11 @@ public class InheritedPropFunction extends FunctionBase { } int propId = FOPropertyMapping.getPropertyId(propName); + if (propId < 0) { + throw new PropertyException( + "Unknown property name used with inherited-property-value function: " + + propName); + } return pInfo.getPropertyList().getInherited(propId); } diff --git a/src/java/org/apache/fop/fo/expr/NearestSpecPropFunction.java b/src/java/org/apache/fop/fo/expr/NearestSpecPropFunction.java index 2aab5eee9..cdde96092 100644 --- a/src/java/org/apache/fop/fo/expr/NearestSpecPropFunction.java +++ b/src/java/org/apache/fop/fo/expr/NearestSpecPropFunction.java @@ -60,6 +60,11 @@ public class NearestSpecPropFunction extends FunctionBase { // NOTE: special cases for shorthand property // Should return COMPUTED VALUE int propId = FOPropertyMapping.getPropertyId(propName); + if (propId < 0) { + throw new PropertyException( + "Unknown property name used with inherited-property-value function: " + + propName); + } return pInfo.getPropertyList().getNearestSpecified(propId); } diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java index de1d019f4..fc61167b2 100644 --- a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java +++ b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java @@ -19,14 +19,15 @@ package org.apache.fop.fo.extensions; +import java.util.HashMap; +import java.util.Set; + +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.FONode; import org.apache.fop.fo.UnknownXMLObj; import org.apache.fop.fo.extensions.destination.Destination; -import org.apache.fop.util.QName; - -import java.util.HashMap; -import java.util.Set; /** * Element mapping for FOP's proprietary extension to XSL-FO. diff --git a/src/java/org/apache/fop/fo/extensions/destination/Destination.java b/src/java/org/apache/fop/fo/extensions/destination/Destination.java index d1e631e42..e3a2bbac4 100644 --- a/src/java/org/apache/fop/fo/extensions/destination/Destination.java +++ b/src/java/org/apache/fop/fo/extensions/destination/Destination.java @@ -19,15 +19,15 @@ package org.apache.fop.fo.extensions.destination; -import org.apache.fop.fo.ValidationException; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.pagination.Root; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.extensions.ExtensionElementMapping; - -import org.xml.sax.Attributes; -import org.xml.sax.Locator; +import org.apache.fop.fo.pagination.Root; /** * Class for named destinations in PDF. @@ -54,7 +54,7 @@ public class Destination extends FONode { Attributes attlist, PropertyList pList) throws FOPException { internalDestination = attlist.getValue("internal-destination"); if (internalDestination == null || internalDestination.length() == 0) { - attributeError("Missing attribute: internal-destination must be specified."); + missingPropertyError("internal-destination"); } } diff --git a/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java b/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java index 0fe6ed718..f99f9d947 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java +++ b/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java @@ -62,14 +62,16 @@ public abstract class AbstractListItemPart extends FObj { */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockItemFound) { - nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockItemFound) { + nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + } + } else if (!isBlockItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else { + blockItemFound = true; } - } else if (!isBlockItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else { - blockItemFound = true; } } @@ -79,17 +81,8 @@ public abstract class AbstractListItemPart extends FObj { protected void endOfNode() throws FOPException { if (!this.blockItemFound) { String contentModel = "marker* (%block;)+"; - if (getUserAgent().validateStrictly()) { - missingChildElementError(contentModel); - } else { - StringBuffer message = new StringBuffer( - errorText(getLocator())); - message.append(getName()) - .append(" is missing child elements. ") - .append("Required Content Model: ") - .append(contentModel); - log.warn(message.toString()); - } + getFOValidationEventProducer().missingChildElement(this, getName(), + contentModel, true, getLocator()); } } diff --git a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java index b6b827248..e9a1176d6 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java +++ b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java @@ -113,8 +113,10 @@ public abstract class AbstractPageNumberCitation extends FObj { * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** @return the Common Font Properties. */ diff --git a/src/java/org/apache/fop/fo/flow/BasicLink.java b/src/java/org/apache/fop/fo/flow/BasicLink.java index 61a4f8d19..b3ef48012 100644 --- a/src/java/org/apache/fop/fo/flow/BasicLink.java +++ b/src/java/org/apache/fop/fo/flow/BasicLink.java @@ -76,8 +76,7 @@ public class BasicLink extends Inline { externalDestination = null; } else if (externalDestination.length() == 0) { // slightly stronger than spec "should be specified" - attributeError("Missing attribute: Either external-destination or " + - "internal-destination must be specified."); + getFOValidationEventProducer().missingLinkDestination(this, getName(), locator); } } @@ -102,15 +101,17 @@ public class BasicLink extends Inline { * XSL Content Model: marker* (#PCDATA|%inline;|%block;)* */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockOrInlineItemFound) { - nodesOutOfOrderError(loc, "fo:marker", "(#PCDATA|%inline;|%block;)"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockOrInlineItemFound) { + nodesOutOfOrderError(loc, "fo:marker", "(#PCDATA|%inline;|%block;)"); + } + } else if (!isBlockOrInlineItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else { + blockOrInlineItemFound = true; } - } else if (!isBlockOrInlineItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else { - blockOrInlineItemFound = true; } } diff --git a/src/java/org/apache/fop/fo/flow/BidiOverride.java b/src/java/org/apache/fop/fo/flow/BidiOverride.java index 2157085ad..892f4a3c5 100644 --- a/src/java/org/apache/fop/fo/flow/BidiOverride.java +++ b/src/java/org/apache/fop/fo/flow/BidiOverride.java @@ -19,13 +19,14 @@ package org.apache.fop.fo.flow; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.SpaceProperty; -import org.xml.sax.Locator; /** * Class modelling the fo:bidi-override object. @@ -96,22 +97,21 @@ public class BidiOverride extends FObjMixed { * fo:inline-container." */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockOrInlineItemFound) { - nodesOutOfOrderError(loc, "fo:marker", - "(#PCDATA|%inline;|%block;)"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockOrInlineItemFound) { + nodesOutOfOrderError(loc, "fo:marker", + "(#PCDATA|%inline;|%block;)"); + } + } else if (!isBlockOrInlineItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else if (!canHaveBlockLevelChildren && isBlockItem(nsURI, localName)) { + invalidChildError(loc, getParent().getName(), nsURI, getName(), + "rule.bidiOverrideContent"); + } else { + blockOrInlineItemFound = true; } - } else if (!isBlockOrInlineItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else if (!canHaveBlockLevelChildren && isBlockItem(nsURI, localName)) { - String ruleViolated = "An fo:bidi-override" - + " that is a descendant of an fo:leader or of the fo:inline child" - + " of an fo:footnote may not have block-level children, unless it" - + " has a nearer ancestor that is an fo:inline-container."; - invalidChildError(loc, nsURI, localName, ruleViolated); - } else { - blockOrInlineItemFound = true; } } diff --git a/src/java/org/apache/fop/fo/flow/BlockContainer.java b/src/java/org/apache/fop/fo/flow/BlockContainer.java index a71999938..f1180ac16 100644 --- a/src/java/org/apache/fop/fo/flow/BlockContainer.java +++ b/src/java/org/apache/fop/fo/flow/BlockContainer.java @@ -114,15 +114,17 @@ public class BlockContainer extends FObj { * @todo - implement above restriction if possible */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockItemFound) { - nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockItemFound) { + nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + } + } else if (!isBlockItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else { + blockItemFound = true; } - } else if (!isBlockItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else { - blockItemFound = true; } } diff --git a/src/java/org/apache/fop/fo/flow/Character.java b/src/java/org/apache/fop/fo/flow/Character.java index 022d54af7..aad4209f9 100644 --- a/src/java/org/apache/fop/fo/flow/Character.java +++ b/src/java/org/apache/fop/fo/flow/Character.java @@ -22,6 +22,8 @@ package org.apache.fop.fo.flow; import java.awt.Color; import java.util.NoSuchElementException; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.CharIterator; @@ -35,7 +37,6 @@ import org.apache.fop.fo.properties.CommonHyphenation; import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.SpaceProperty; -import org.xml.sax.Locator; /** * Class modelling the fo:character object. @@ -134,8 +135,10 @@ public class Character extends FObj { * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** diff --git a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java index fdddf3918..07f765e52 100644 --- a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java +++ b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java @@ -32,6 +32,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.URISpecification; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; @@ -78,11 +79,17 @@ public class ExternalGraphic extends AbstractGraphics { try { info = manager.getImageInfo(url, userAgent.getImageSessionContext()); } catch (ImageException e) { - log.error("Image not available: " + e.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, url, e, getLocator()); } catch (FileNotFoundException fnfe) { - log.error(fnfe.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(this, url, fnfe, getLocator()); } catch (IOException ioe) { - log.error("I/O error while loading image: " + ioe.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, url, ioe, getLocator()); } if (info != null) { this.intrinsicWidth = info.getSize().getWidthMpt(); @@ -93,7 +100,6 @@ public class ExternalGraphic extends AbstractGraphics { = FixedLength.getInstance(-baseline); } } - //TODO Report to caller so he can decide to throw an exception } /** {@inheritDoc} */ @@ -107,8 +113,10 @@ public class ExternalGraphic extends AbstractGraphics { *
                                                                                        XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** @return the "src" property */ diff --git a/src/java/org/apache/fop/fo/flow/Float.java b/src/java/org/apache/fop/fo/flow/Float.java index 997f96c89..57d3b4ee1 100644 --- a/src/java/org/apache/fop/fo/flow/Float.java +++ b/src/java/org/apache/fop/fo/flow/Float.java @@ -46,7 +46,8 @@ public class Float extends FObj { super(parent); if (!notImplementedWarningGiven) { - log.warn("fo:float is not yet implemented."); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + getName(), getLocator()); notImplementedWarningGiven = true; } } @@ -63,10 +64,12 @@ public class Float extends FObj { * XSL Content Model: (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { if (!isBlockItem(nsURI, localName)) { invalidChildError(loc, nsURI, localName); } + } } /** diff --git a/src/java/org/apache/fop/fo/flow/Footnote.java b/src/java/org/apache/fop/fo/flow/Footnote.java index 95c9f25bc..c15a7e0ee 100644 --- a/src/java/org/apache/fop/fo/flow/Footnote.java +++ b/src/java/org/apache/fop/fo/flow/Footnote.java @@ -82,12 +82,13 @@ public class Footnote extends FObj { * generates an absolutely positioned area. */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("inline")) { + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("inline")) { if (footnoteCitation != null) { tooManyNodesError(loc, "fo:inline"); } - } else if (FO_URI.equals(nsURI) && localName.equals("footnote-body")) { + } else if (localName.equals("footnote-body")) { if (footnoteCitation == null) { nodesOutOfOrderError(loc, "fo:inline", "fo:footnote-body"); } else if (footnoteBody != null) { @@ -96,6 +97,7 @@ public class Footnote extends FObj { } else { invalidChildError(loc, nsURI, localName); } + } } /** diff --git a/src/java/org/apache/fop/fo/flow/FootnoteBody.java b/src/java/org/apache/fop/fo/flow/FootnoteBody.java index bb4c9b482..967d15215 100644 --- a/src/java/org/apache/fop/fo/flow/FootnoteBody.java +++ b/src/java/org/apache/fop/fo/flow/FootnoteBody.java @@ -73,10 +73,12 @@ public class FootnoteBody extends FObj { * XSL Content Model: (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { if (!isBlockItem(nsURI, localName)) { invalidChildError(loc, nsURI, localName); } + } } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/InitialPropertySet.java b/src/java/org/apache/fop/fo/flow/InitialPropertySet.java index 63299978d..6d0e495b7 100644 --- a/src/java/org/apache/fop/fo/flow/InitialPropertySet.java +++ b/src/java/org/apache/fop/fo/flow/InitialPropertySet.java @@ -72,8 +72,10 @@ public class InitialPropertySet extends FObj { * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** diff --git a/src/java/org/apache/fop/fo/flow/Inline.java b/src/java/org/apache/fop/fo/flow/Inline.java index 6bbd90ad1..50662d9f1 100644 --- a/src/java/org/apache/fop/fo/flow/Inline.java +++ b/src/java/org/apache/fop/fo/flow/Inline.java @@ -81,8 +81,8 @@ public class Inline extends InlineLevel { int lvlInCntr = findAncestor(FO_INLINE_CONTAINER); if (lvlLeader > 0) { - if (lvlInCntr < 0 || - (lvlInCntr > 0 && lvlInCntr > lvlLeader)) { + if (lvlInCntr < 0 + || (lvlInCntr > 0 && lvlInCntr > lvlLeader)) { canHaveBlockLevelChildren = false; } } else if (lvlFootnote > 0) { @@ -110,23 +110,20 @@ public class Inline extends InlineLevel { * nearer ancestor that is an fo:inline-container." (paraphrased) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockOrInlineItemFound) { - nodesOutOfOrderError(loc, "fo:marker", - "(#PCDATA|%inline;|%block;)"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockOrInlineItemFound) { + nodesOutOfOrderError(loc, "fo:marker", + "(#PCDATA|%inline;|%block;)"); + } + } else if (!isBlockOrInlineItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else if (!canHaveBlockLevelChildren && isBlockItem(nsURI, localName)) { + invalidChildError(loc, getParent().getName(), nsURI, getName(), "rule.inlineContent"); + } else { + blockOrInlineItemFound = true; } - } else if (!isBlockOrInlineItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else if (!canHaveBlockLevelChildren && isBlockItem(nsURI, localName)) { - String ruleViolated = - " An fo:inline that is a descendant of an fo:leader" + - " or fo:footnote may not have block-level children," + - " unless it has a nearer ancestor that is an" + - " fo:inline-container."; - invalidChildError(loc, nsURI, localName, ruleViolated); - } else { - blockOrInlineItemFound = true; } } diff --git a/src/java/org/apache/fop/fo/flow/InlineContainer.java b/src/java/org/apache/fop/fo/flow/InlineContainer.java index a8fb7858d..3c142afe9 100644 --- a/src/java/org/apache/fop/fo/flow/InlineContainer.java +++ b/src/java/org/apache/fop/fo/flow/InlineContainer.java @@ -86,15 +86,17 @@ public class InlineContainer extends FObj { * XSL Content Model: marker* (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockItemFound) { - nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockItemFound) { + nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + } + } else if (!isBlockItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else { + blockItemFound = true; } - } else if (!isBlockItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else { - blockItemFound = true; } } diff --git a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java index 531bd657a..802f59c30 100644 --- a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java +++ b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java @@ -20,12 +20,17 @@ package org.apache.fop.fo.flow; import java.awt.geom.Point2D; + +import org.xml.sax.Locator; + +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.XMLObj; -import org.xml.sax.Locator; /** * Class modelling the fo:instream-foreign-object object. @@ -39,6 +44,7 @@ public class InstreamForeignObject extends AbstractGraphics { //Additional value private Point2D intrinsicDimensions; + private boolean instrisicSizeDetermined; private Length intrinsicAlignmentAdjust; @@ -68,11 +74,11 @@ public class InstreamForeignObject extends AbstractGraphics { * XSL Content Model: one (1) non-XSL namespace child */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); } else if (firstChild != null) { - tooManyNodesError(loc, "child element"); + tooManyNodesError(loc, new QName(nsURI, null, localName)); } } @@ -81,32 +87,28 @@ public class InstreamForeignObject extends AbstractGraphics { return "instream-foreign-object"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_INSTREAM_FOREIGN_OBJECT; } - /** - * Preloads the image so the intrinsic size is available. - */ + /** Preloads the image so the intrinsic size is available. */ private void prepareIntrinsicSize() { - if (intrinsicDimensions == null) { + if (!this.instrisicSizeDetermined) { XMLObj child = (XMLObj) firstChild; Point2D csize = new Point2D.Float(-1, -1); intrinsicDimensions = child.getDimension(csize); if (intrinsicDimensions == null) { - log.error("Intrinsic dimensions of " - + " instream-foreign-object could not be determined"); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.ifoNoIntrinsicSize(this, getLocator()); } intrinsicAlignmentAdjust = child.getIntrinsicAlignmentAdjust(); + this.instrisicSizeDetermined = true; } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getIntrinsicWidth() { prepareIntrinsicSize(); if (intrinsicDimensions != null) { @@ -116,9 +118,7 @@ public class InstreamForeignObject extends AbstractGraphics { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getIntrinsicHeight() { prepareIntrinsicSize(); if (intrinsicDimensions != null) { @@ -128,11 +128,8 @@ public class InstreamForeignObject extends AbstractGraphics { } } - /** - * {@inheritDoc} - */ - public Length getIntrinsicAlignmentAdjust() - { + /** {@inheritDoc} */ + public Length getIntrinsicAlignmentAdjust() { prepareIntrinsicSize(); return intrinsicAlignmentAdjust; } diff --git a/src/java/org/apache/fop/fo/flow/ListBlock.java b/src/java/org/apache/fop/fo/flow/ListBlock.java index 86c581cc3..a196e92de 100644 --- a/src/java/org/apache/fop/fo/flow/ListBlock.java +++ b/src/java/org/apache/fop/fo/flow/ListBlock.java @@ -108,15 +108,17 @@ public class ListBlock extends FObj { * XSL Content Model: marker* (list-item)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (hasListItem) { - nodesOutOfOrderError(loc, "fo:marker", "fo:list-item"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (hasListItem) { + nodesOutOfOrderError(loc, "fo:marker", "fo:list-item"); + } + } else if (localName.equals("list-item")) { + hasListItem = true; + } else { + invalidChildError(loc, nsURI, localName); } - } else if (FO_URI.equals(nsURI) && localName.equals("list-item")) { - hasListItem = true; - } else { - invalidChildError(loc, nsURI, localName); } } diff --git a/src/java/org/apache/fop/fo/flow/ListItem.java b/src/java/org/apache/fop/fo/flow/ListItem.java index c09313ef6..cf0e05c56 100644 --- a/src/java/org/apache/fop/fo/flow/ListItem.java +++ b/src/java/org/apache/fop/fo/flow/ListItem.java @@ -98,22 +98,24 @@ public class ListItem extends FObj { */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (label != null) { - nodesOutOfOrderError(loc, "fo:marker", "fo:list-item-label"); + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (label != null) { + nodesOutOfOrderError(loc, "fo:marker", "fo:list-item-label"); + } + } else if (localName.equals("list-item-label")) { + if (label != null) { + tooManyNodesError(loc, "fo:list-item-label"); + } + } else if (localName.equals("list-item-body")) { + if (label == null) { + nodesOutOfOrderError(loc, "fo:list-item-label", "fo:list-item-body"); + } else if (body != null) { + tooManyNodesError(loc, "fo:list-item-body"); + } + } else { + invalidChildError(loc, nsURI, localName); } - } else if (FO_URI.equals(nsURI) && localName.equals("list-item-label")) { - if (label != null) { - tooManyNodesError(loc, "fo:list-item-label"); - } - } else if (FO_URI.equals(nsURI) && localName.equals("list-item-body")) { - if (label == null) { - nodesOutOfOrderError(loc, "fo:list-item-label", "fo:list-item-body"); - } else if (body != null) { - tooManyNodesError(loc, "fo:list-item-body"); - } - } else { - invalidChildError(loc, nsURI, localName); } } diff --git a/src/java/org/apache/fop/fo/flow/Marker.java b/src/java/org/apache/fop/fo/flow/Marker.java index 05c9862b2..168b18180 100644 --- a/src/java/org/apache/fop/fo/flow/Marker.java +++ b/src/java/org/apache/fop/fo/flow/Marker.java @@ -59,9 +59,8 @@ public class Marker extends FObjMixed { */ public void bind(PropertyList pList) throws FOPException { if (findAncestor(FO_FLOW) < 0) { - invalidChildError(locator, FO_URI, "marker", - "An fo:marker is permitted only as the descendant " - + "of an fo:flow"); + invalidChildError(locator, getParent().getName(), FO_URI, getName(), + "rule.markerDescendantOfFlow"); } markerClassName = pList.get(PR_MARKER_CLASS_NAME).getString(); @@ -112,9 +111,11 @@ public class Marker extends FObjMixed { * @todo implement "additional" constraint, possibly within fo:retrieve-marker */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!isBlockOrInlineItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!isBlockOrInlineItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } } } diff --git a/src/java/org/apache/fop/fo/flow/MultiCase.java b/src/java/org/apache/fop/fo/flow/MultiCase.java index 42ec9d9d0..e568fba46 100644 --- a/src/java/org/apache/fop/fo/flow/MultiCase.java +++ b/src/java/org/apache/fop/fo/flow/MultiCase.java @@ -46,7 +46,8 @@ public class MultiCase extends FObj { super(parent); if (!notImplementedWarningGiven) { - log.warn("fo:multi-case is not yet implemented."); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + getName(), getLocator()); notImplementedWarningGiven = true; } } diff --git a/src/java/org/apache/fop/fo/flow/MultiProperties.java b/src/java/org/apache/fop/fo/flow/MultiProperties.java index 00cb85dc7..bd3bd893e 100644 --- a/src/java/org/apache/fop/fo/flow/MultiProperties.java +++ b/src/java/org/apache/fop/fo/flow/MultiProperties.java @@ -49,7 +49,8 @@ public class MultiProperties extends FObj { super(parent); if (!notImplementedWarningGiven) { - log.warn("fo:multi-properties is not yet implemented."); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + getName(), getLocator()); notImplementedWarningGiven = true; } } @@ -69,13 +70,14 @@ public class MultiProperties extends FObj { */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("multi-property-set")) { + if (FO_URI.equals(nsURI)) { + if (localName.equals("multi-property-set")) { if (hasWrapper) { nodesOutOfOrderError(loc, "fo:multi-property-set", "fo:wrapper"); } else { hasMultiPropertySet = true; } - } else if (FO_URI.equals(nsURI) && localName.equals("wrapper")) { + } else if (localName.equals("wrapper")) { if (hasWrapper) { tooManyNodesError(loc, "fo:wrapper"); } else { @@ -84,6 +86,7 @@ public class MultiProperties extends FObj { } else { invalidChildError(loc, nsURI, localName); } + } } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/MultiPropertySet.java b/src/java/org/apache/fop/fo/flow/MultiPropertySet.java index 3c9c55b4f..caa31f7b9 100644 --- a/src/java/org/apache/fop/fo/flow/MultiPropertySet.java +++ b/src/java/org/apache/fop/fo/flow/MultiPropertySet.java @@ -45,7 +45,8 @@ public class MultiPropertySet extends FObj { super(parent); if (!notImplementedWarningGiven) { - log.warn("fo:multi-property-set is not yet implemented."); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + getName(), getLocator()); notImplementedWarningGiven = true; } } @@ -63,8 +64,10 @@ public class MultiPropertySet extends FObj { * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/MultiSwitch.java b/src/java/org/apache/fop/fo/flow/MultiSwitch.java index 7c70a7346..03f404aa3 100644 --- a/src/java/org/apache/fop/fo/flow/MultiSwitch.java +++ b/src/java/org/apache/fop/fo/flow/MultiSwitch.java @@ -47,7 +47,8 @@ public class MultiSwitch extends FObj { super(parent); if (!notImplementedWarningGiven) { - log.warn("fo:multi-switch is not yet implemented."); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + getName(), getLocator()); notImplementedWarningGiven = true; } } @@ -75,9 +76,11 @@ public class MultiSwitch extends FObj { * XSL Content Model: (multi-case+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!(FO_URI.equals(nsURI) && localName.equals("multi-case"))) { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!localName.equals("multi-case")) { + invalidChildError(loc, nsURI, localName); + } } } diff --git a/src/java/org/apache/fop/fo/flow/MultiToggle.java b/src/java/org/apache/fop/fo/flow/MultiToggle.java index 80b36f9f4..66442c2a7 100644 --- a/src/java/org/apache/fop/fo/flow/MultiToggle.java +++ b/src/java/org/apache/fop/fo/flow/MultiToggle.java @@ -47,7 +47,8 @@ public class MultiToggle extends FObj { super(parent); if (!notImplementedWarningGiven) { - log.warn("fo:multi-toggle is not yet implemented."); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + getName(), getLocator()); notImplementedWarningGiven = true; } } @@ -65,9 +66,11 @@ public class MultiToggle extends FObj { * XSL Content Model: (#PCDATA|%inline;|%block;)* */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!isBlockOrInlineItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!isBlockOrInlineItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } } } diff --git a/src/java/org/apache/fop/fo/flow/PageNumber.java b/src/java/org/apache/fop/fo/flow/PageNumber.java index 3eca1e16e..cc51dd28a 100644 --- a/src/java/org/apache/fop/fo/flow/PageNumber.java +++ b/src/java/org/apache/fop/fo/flow/PageNumber.java @@ -117,8 +117,10 @@ public class PageNumber extends FObj { * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** @return the Common Font Properties. */ diff --git a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java index 7356bc72e..ea6b6f1c5 100644 --- a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java @@ -21,6 +21,8 @@ package org.apache.fop.fo.flow; import java.util.Iterator; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FOText; @@ -30,7 +32,6 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableFObj; -import org.xml.sax.Locator; /** * Class modelling the fo:retrieve-marker object. @@ -48,21 +49,18 @@ public class RetrieveMarker extends FObjMixed { /** * Create a retrieve marker object. - * + * @param parent FONode that is the parent of this object * @see org.apache.fop.fo.FONode#FONode(FONode) */ public RetrieveMarker(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { if (findAncestor(FO_STATIC_CONTENT) < 0) { - invalidChildError(locator, FO_URI, "retrieve-marker", - "An fo:retrieve-marker is permitted only as the " + - " descendant of an fo:static-content."); + invalidChildError(locator, getParent().getName(), FO_URI, getName(), + "rule.retrieveMarkerDescendatOfStaticContent"); } retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME).getString(); @@ -81,8 +79,10 @@ public class RetrieveMarker extends FObjMixed { * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** @@ -206,13 +206,12 @@ public class RetrieveMarker extends FObjMixed { try { cloneFromMarker(marker); } catch (FOPException exc) { - log.error("fo:retrieve-marker unable to clone " - + "subtree of fo:marker (marker-class-name=" - + marker.getMarkerClassName() + ")", exc); + getFOValidationEventProducer().markerCloningFailed(this, + marker.getMarkerClassName(), exc, getLocator()); return; } - } else if (log.isInfoEnabled()) { - log.info("Empty marker retrieved..."); + } else if (log.isDebugEnabled()) { + log.debug("Empty marker retrieved..."); } return; } @@ -222,9 +221,7 @@ public class RetrieveMarker extends FObjMixed { return "retrieve-marker"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_RETRIEVE_MARKER; } diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index adf9b2101..87582fb47 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -19,12 +19,13 @@ package org.apache.fop.fo.flow; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.xml.sax.Locator; /** * Class modelling the fo:wrapper object. @@ -66,17 +67,19 @@ public class Wrapper extends FObjMixed { */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { - if (FO_URI.equals(nsURI) && "marker".equals(localName)) { - if (blockOrInlineItemFound) { - nodesOutOfOrderError(loc, "fo:marker", - "(#PCDATA|%inline;|%block;)"); + if (FO_URI.equals(nsURI)) { + if ("marker".equals(localName)) { + if (blockOrInlineItemFound) { + nodesOutOfOrderError(loc, "fo:marker", + "(#PCDATA|%inline;|%block;)"); + } + } else if (isBlockOrInlineItem(nsURI, localName)) { + //delegate validation to parent + FONode.validateChildNode(this.parent, loc, nsURI, localName); + blockOrInlineItemFound = true; + } else { + invalidChildError(loc, nsURI, localName); } - } else if (isBlockOrInlineItem(nsURI, localName)) { - //delegate validation to parent - FONode.validateChildNode(this.parent, loc, nsURI, localName); - blockOrInlineItemFound = true; - } else { - invalidChildError(loc, nsURI, localName); } } diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index 28a30c6f7..0d24491d9 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -120,13 +120,17 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { void endTableRow() { assert currentTableRow != null; if (currentRowIndex > 0 && currentTableRow.getBreakBefore() != Constants.EN_AUTO) { - currentTableRow.attributeWarning("break-before ignored because of row spanning " - + "in progress (See XSL 1.1, 7.20.2)"); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + currentTableRow.getUserAgent().getEventBroadcaster()); + eventProducer.breakIgnoredDueToRowSpanning(this, currentTableRow.getName(), true, + currentTableRow.getLocator()); } if (currentRowIndex < rows.size() - 1 && currentTableRow.getBreakAfter() != Constants.EN_AUTO) { - currentTableRow.attributeWarning("break-after ignored because of row spanning " - + "in progress (See XSL 1.1, 7.20.1)"); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + currentTableRow.getUserAgent().getEventBroadcaster()); + eventProducer.breakIgnoredDueToRowSpanning(this, currentTableRow.getName(), false, + currentTableRow.getLocator()); } for (Iterator iter = ((List) rows.get(currentRowIndex)).iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index 7d6611435..c1ef3857c 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -22,6 +22,8 @@ package org.apache.fop.fo.flow.table; import java.util.ArrayList; import java.util.List; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.ValidationPercentBaseContext; @@ -35,7 +37,6 @@ import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthPairProperty; import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.fo.properties.TableColLength; -import org.xml.sax.Locator; /** * Class modelling the fo:table object. @@ -126,20 +127,22 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { orphanContentLimit = pList.get(PR_X_ORPHAN_CONTENT_LIMIT).getLength(); if (!blockProgressionDimension.getOptimum(null).isAuto()) { - attributeWarning("only a value of \"auto\" for block-progression-dimension has a" - + " well-specified behavior on fo:table. Falling back to \"auto\""); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.nonAutoBPDOnTable(this, getLocator()); // Anyway, the bpd of a table is not used by the layout code } if (tableLayout == EN_AUTO) { - attributeWarning("table-layout=\"auto\" is currently not supported by FOP"); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + "table-layout=\"auto\"", getLocator()); } if (!isSeparateBorderModel() && getCommonBorderPaddingBackground().hasPadding( ValidationPercentBaseContext.getPseudoContext())) { //See "17.6.2 The collapsing border model" in CSS2 - attributeWarning("In collapsing border model a table does not have padding" - + " (see http://www.w3.org/TR/REC-CSS2/tables.html#collapsing-borders)" - + ", but a non-zero value for padding was found. The padding will be ignored."); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noTablePaddingWithCollapsingBorderModel(this, getLocator()); } /* Store reference to the property list, so @@ -163,7 +166,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { * XSL Content Model: (marker*,table-column*,table-header?,table-footer?,table-body+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { if ("marker".equals(localName)) { if (tableColumnFound || tableHeaderFound || tableFooterFound @@ -193,15 +196,11 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } else { tableFooterFound = true; if (tableBodyFound) { - if (getUserAgent().validateStrictly()) { - nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)"); - } else if (!isSeparateBorderModel()) { - nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)." - + " This table uses the collapsing border" - + " model. In order to resolve borders in an efficient way" - + " the table-footer must be known before any table-body" - + " is parsed. Either put the footer at the correct place" - + " or switch to the separate border model"); + nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)", true); + if (!isSeparateBorderModel()) { + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.footerOrderCannotRecover(this, getName(), getLocator()); } } } @@ -210,8 +209,6 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } else { invalidChildError(loc, nsURI, localName); } - } else { - invalidChildError(loc, nsURI, localName); } } @@ -225,6 +222,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { "(marker*,table-column*,table-header?,table-footer?" + ",table-body+)"); } + if (!hasChildren()) { + getParent().removeChild(this); + return; + } if (!inMarker()) { rowGroupBuilder.endTable(); /* clean up */ diff --git a/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java b/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java index f16931cfc..6dabf37db 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java +++ b/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java @@ -62,7 +62,8 @@ public class TableAndCaption extends FObj { super(parent); if (!notImplementedWarningGiven) { - log.warn("fo:table-and-caption is not yet implemented."); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + "fo:table-and-caption", getLocator()); notImplementedWarningGiven = true; } } @@ -83,30 +84,32 @@ public class TableAndCaption extends FObj { * XSL Content Model: marker* table-caption? table */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (tableCaptionFound) { - nodesOutOfOrderError(loc, "fo:marker", "fo:table-caption"); - } else if (tableFound) { - nodesOutOfOrderError(loc, "fo:marker", "fo:table"); - } - } else if (FO_URI.equals(nsURI) && localName.equals("table-caption")) { - if (tableCaptionFound) { - tooManyNodesError(loc, "fo:table-caption"); - } else if (tableFound) { - nodesOutOfOrderError(loc, "fo:table-caption", "fo:table"); - } else { - tableCaptionFound = true; - } - } else if (FO_URI.equals(nsURI) && localName.equals("table")) { - if (tableFound) { - tooManyNodesError(loc, "fo:table"); + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (tableCaptionFound) { + nodesOutOfOrderError(loc, "fo:marker", "fo:table-caption"); + } else if (tableFound) { + nodesOutOfOrderError(loc, "fo:marker", "fo:table"); + } + } else if (localName.equals("table-caption")) { + if (tableCaptionFound) { + tooManyNodesError(loc, "fo:table-caption"); + } else if (tableFound) { + nodesOutOfOrderError(loc, "fo:table-caption", "fo:table"); + } else { + tableCaptionFound = true; + } + } else if (localName.equals("table")) { + if (tableFound) { + tooManyNodesError(loc, "fo:table"); + } else { + tableFound = true; + } } else { - tableFound = true; + invalidChildError(loc, nsURI, localName); } - } else { - invalidChildError(loc, nsURI, localName); } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index de7bfda84..4e1673568 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -23,13 +23,14 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; /** * Class modelling the fo:table-body object. @@ -119,13 +120,8 @@ public class TableBody extends TableCellContainer { getFOEventHandler().endBody(this); if (!(tableRowsFound || tableCellsFound)) { - if (getUserAgent().validateStrictly()) { - missingChildElementError("marker* (table-row+|table-cell+)"); - } else { - log.error("fo:table-body must not be empty. " - + "Expected: marker* (table-row+|table-cell+)"); - getParent().removeChild(this); - } + missingChildElementError("marker* (table-row+|table-cell+)", true); + getParent().removeChild(this); } else { finishLastRowGroup(); } @@ -167,23 +163,20 @@ public class TableBody extends TableCellContainer { } else if (localName.equals("table-row")) { tableRowsFound = true; if (tableCellsFound) { - invalidChildError(loc, nsURI, localName, "Either fo:table-rows" - + " or fo:table-cells may be children of an " + getName() - + " but not both"); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noMixRowsAndCells(this, getName(), getLocator()); } } else if (localName.equals("table-cell")) { tableCellsFound = true; if (tableRowsFound) { - invalidChildError(loc, nsURI, localName, - "Either fo:table-rows or fo:table-cells " - + "may be children of an " - + getName() + " but not both"); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noMixRowsAndCells(this, getName(), getLocator()); } } else { invalidChildError(loc, nsURI, localName); } - } else { - invalidChildError(loc, nsURI, localName); } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableCaption.java b/src/java/org/apache/fop/fo/flow/table/TableCaption.java index 28174067c..416ef16ed 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCaption.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCaption.java @@ -57,7 +57,8 @@ public class TableCaption extends FObj { super(parent); if (!notImplementedWarningGiven) { - log.warn("fo:table-caption is not yet implemented."); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + "fo:table-caption", getLocator()); notImplementedWarningGiven = true; } } @@ -83,15 +84,17 @@ public class TableCaption extends FObj { * XSL Content Model: marker* (%block;) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockItemFound) { - nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockItemFound) { + nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + } + } else if (!isBlockItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else { + blockItemFound = true; } - } else if (!isBlockItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else { - blockItemFound = true; } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java index 80dbe5e2a..78e35eb52 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCell.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java @@ -102,17 +102,13 @@ public class TableCell extends TableFObj { */ public void endOfNode() throws FOPException { if (!blockItemFound) { - if (getUserAgent().validateStrictly()) { - missingChildElementError("marker* (%block;)+"); - } else if (firstChild != null) { - log.warn("fo:table-cell content that is not " - + "enclosed by a fo:block will be dropped/ignored."); - } + missingChildElementError("marker* (%block;)+", true); } if ((startsRow() || endsRow()) && getParent().getNameId() == FO_TABLE_ROW ) { - log.warn("starts-row/ends-row for fo:table-cells " - + "non-applicable for children of an fo:table-row."); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.startEndRowUnderTableRowWarning(this, getLocator()); } getFOEventHandler().endCell(this); } @@ -123,14 +119,16 @@ public class TableCell extends TableFObj { */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockItemFound) { - nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockItemFound) { + nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + } + } else if (!isBlockItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else { + blockItemFound = true; } - } else if (!isBlockItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else { - blockItemFound = true; } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java index 7c91be351..de9f271b5 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java @@ -24,7 +24,6 @@ import java.util.List; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ValidationException; /** * A common class for fo:table-body and fo:table-row which both can contain fo:table-cell. @@ -47,9 +46,9 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb Table t = getTable(); if (t.hasExplicitColumns()) { if (colNumber + colSpan - 1 > t.getNumberOfColumns()) { - throw new ValidationException(FONode.errorText(locator) + "column-number or " - + "number of cells in the row overflows the number of fo:table-column " - + "specified for the table."); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.tooManyCells(this, getLocator()); } } else { t.ensureColumnNumber(colNumber + colSpan - 1); diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java index aeb401893..e6f6b420e 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java +++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java @@ -82,12 +82,16 @@ public class TableColumn extends TableFObj { super.bind(pList); if (numberColumnsRepeated <= 0) { - throw new PropertyException("number-columns-repeated must be 1 or bigger, " - + "but got " + numberColumnsRepeated); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.valueMustBeBiggerGtEqOne(this, + "number-columns-repeated", numberColumnsRepeated, getLocator()); } if (numberColumnsSpanned <= 0) { - throw new PropertyException("number-columns-spanned must be 1 or bigger, " - + "but got " + numberColumnsSpanned); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.valueMustBeBiggerGtEqOne(this, + "number-columns-spanned", numberColumnsSpanned, getLocator()); } /* check for unspecified width and replace with default of @@ -96,8 +100,9 @@ public class TableColumn extends TableFObj { */ if (columnWidth.getEnum() == EN_AUTO) { if (!this.implicitColumn && !getTable().isAutoLayout()) { - log.warn("table-layout=\"fixed\" and column-width unspecified " - + "=> falling back to proportional-column-width(1)"); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.warnImplicitColumns(this, getLocator()); } columnWidth = new TableColLength(1.0, this); } @@ -146,7 +151,9 @@ public class TableColumn extends TableFObj { protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** @@ -240,7 +247,7 @@ public class TableColumn extends TableFObj { * * @param propId the id for the property to retrieve * @return the requested Property - * @throws PropertyException + * @throws PropertyException if there is a problem evaluating the property */ public Property getProperty(int propId) throws PropertyException { return this.pList.get(propId); diff --git a/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java b/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java new file mode 100644 index 000000000..44ddcc038 --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.flow.table; + +import org.xml.sax.Locator; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.expr.PropertyException; + +/** + * Event producer interface for table-specific XSL-FO validation messages. + */ +public interface TableEventProducer extends EventProducer { + + /** Provider class for the event producer. */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static TableEventProducer get(EventBroadcaster broadcaster) { + return (TableEventProducer)broadcaster.getEventProducerFor( + TableEventProducer.class); + } + } + + /** + * A value other than "auto" has been specified on fo:table. + * @param source the event source + * @param loc the location of the error or null + * @event.severity WARN + */ + void nonAutoBPDOnTable(Object source, Locator loc); + + /** + * Padding on fo:table is ignored if the collapsing border model is active. + * @param source the event source + * @param loc the location of the error or null + * @event.severity WARN + */ + void noTablePaddingWithCollapsingBorderModel(Object source, Locator loc); + + /** + * No mixing of table-rows and table-cells is allowed for direct children of table-body. + * @param source the event source + * @param elementName the name of the context node + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void noMixRowsAndCells(Object source, String elementName, Locator loc) + throws ValidationException; + + /** + * The table-footer was found after the table-body. FOP cannot recover with collapsed border + * model. + * @param source the event source + * @param elementName the name of the context node + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void footerOrderCannotRecover(Object source, String elementName, Locator loc) + throws ValidationException; + + /** + * starts-row/ends-row for fo:table-cells non-applicable for children of an fo:table-row + * @param source the event source + * @param loc the location of the error or null + * @event.severity WARN + */ + void startEndRowUnderTableRowWarning(Object source, Locator loc); + + /** + * Column-number or number of cells in the row overflows the number of fo:table-column + * specified for the table. + * @param source the event source + * @param loc the location of the error or null + * @throws ValidationException the validation error provoked by the method call + * @event.severity FATAL + */ + void tooManyCells(Object source, Locator loc) throws ValidationException; + + /** + * Property value must be 1 or bigger. + * @param source the event source + * @param propName the property name + * @param actualValue the actual value + * @param loc the location of the error or null + * @throws PropertyException the property error provoked by the method call + * @event.severity FATAL + */ + void valueMustBeBiggerGtEqOne(Object source, String propName, + int actualValue, Locator loc) throws PropertyException; + + /** + * table-layout=\"fixed\" and column-width unspecified + * => falling back to proportional-column-width(1) + * @param source the event source + * @param loc the location of the error or null + * @event.severity WARN + */ + void warnImplicitColumns(Object source, Locator loc); + + /** + * padding-* properties are not applicable. + * @param source the event source + * @param elementName the name of the context node + * @param loc the location of the error or null + * @event.severity WARN + */ + void paddingNotApplicable(Object source, String elementName, Locator loc); + + /** + * Cell overlap. + * @param source the event source + * @param elementName the name of the context node + * @param column the column index of the overlapping cell + * @param loc the location of the error or null + * @throws PropertyException the property error provoked by the method call + * @event.severity FATAL + */ + void cellOverlap(Object source, String elementName, int column, + Locator loc) throws PropertyException; + + /** + * Break ignored due to row spanning. + * @param source the event source + * @param elementName the name of the context node + * @param breakBefore true for "break-before", false for "break-after" + * @param loc the location of the error or null + * @event.severity WARN + */ + void breakIgnoredDueToRowSpanning(Object source, String elementName, boolean breakBefore, + Locator loc); + + +} diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 9618d7ff4..24528f622 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -58,9 +58,7 @@ public abstract class TableFObj extends FObj { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric(); @@ -71,9 +69,9 @@ public abstract class TableFObj extends FObj { && getNameId() != FO_TABLE_CELL && getCommonBorderPaddingBackground().hasPadding( ValidationPercentBaseContext.getPseudoContext())) { - attributeWarning( - "padding-* properties are not applicable to " + getName() - + ", but a non-zero value for padding was found."); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.paddingNotApplicable(this, getName(), getLocator()); } } @@ -156,17 +154,19 @@ public abstract class TableFObj extends FObj { ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); int columnIndex = p.getNumeric().getValue(); if (columnIndex <= 0) { + /* No warning necessary as the spec clearly defines how to handle these cases. log.warn("Specified negative or zero value for " + "column-number on " + fo.getName() + ": " + columnIndex + " forced to " - + columnIndexManager.getCurrentColumnNumber()); + + columnIndexManager.getCurrentColumnNumber());*/ return NumberProperty.getInstance(columnIndexManager.getCurrentColumnNumber()); } else { double tmpIndex = p.getNumeric().getNumericValue(); if (tmpIndex - columnIndex > 0.0) { columnIndex = (int) Math.round(tmpIndex); + /* No warning necessary as the spec clearly defines how to handle these cases. log.warn("Rounding specified column-number of " - + tmpIndex + " to " + columnIndex); + + tmpIndex + " to " + columnIndex);*/ p = NumberProperty.getInstance(columnIndex); } } @@ -179,16 +179,9 @@ public abstract class TableFObj extends FObj { /* if column-number is already in use by another * cell/column => error! */ - StringBuffer errorMessage = new StringBuffer(); - errorMessage.append(fo.getName() + " overlaps in column ") - .append(columnIndex + i); - org.xml.sax.Locator loc = fo.getLocator(); - if (loc != null && loc.getLineNumber() != -1) { - errorMessage.append(" (line #") - .append(loc.getLineNumber()).append(", column #") - .append(loc.getColumnNumber()).append(")"); - } - throw new PropertyException(errorMessage.toString()); + TableEventProducer eventProducer = TableEventProducer.Provider.get( + fo.getUserAgent().getEventBroadcaster()); + eventProducer.cellOverlap(this, fo.getName(), columnIndex + 1, fo.getLocator()); } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java index a025f92fd..e5261614b 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableRow.java +++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java @@ -19,6 +19,9 @@ package org.apache.fop.fo.flow.table; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; @@ -27,8 +30,6 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; /** * Class modelling the fo:table-row object. @@ -122,9 +123,11 @@ public class TableRow extends TableCellContainer { */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!(FO_URI.equals(nsURI) && localName.equals("table-cell"))) { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!localName.equals("table-cell")) { + invalidChildError(loc, nsURI, localName); + } } } diff --git a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java index 70a09b720..578d74c4d 100644 --- a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java @@ -32,7 +32,9 @@ import org.apache.fop.fo.PropertyList; public abstract class AbstractPageSequence extends FObj { // The value of properties relevant for fo:page-sequence. + /** the initial-page-number value */ protected Numeric initialPageNumber; + /** the force-page-count value */ protected int forcePageCount; private String format; private int letterValue; @@ -43,6 +45,7 @@ public abstract class AbstractPageSequence extends FObj { private PageNumberGenerator pageNumberGenerator; + /** the first page number generated by the page sequence */ protected int startingPageNumber = 0; /** @@ -54,9 +57,7 @@ public abstract class AbstractPageSequence extends FObj { super(parent); } - /** - * @see org.apache.fop.fo.FObj#bind(PropertyList) - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); initialPageNumber = pList.get(PR_INITIAL_PAGE_NUMBER).getNumeric(); @@ -68,16 +69,14 @@ public abstract class AbstractPageSequence extends FObj { referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); } - /** - * @see org.apache.fop.fo.FONode#startOfNode() - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { this.pageNumberGenerator = new PageNumberGenerator( format, groupingSeparator, groupingSize, letterValue); } - /** @see org.apache.fop.fo.FONode#endOfNode() */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { } diff --git a/src/java/org/apache/fop/fo/pagination/ColorProfile.java b/src/java/org/apache/fop/fo/pagination/ColorProfile.java index 9318a8896..6067b55c5 100644 --- a/src/java/org/apache/fop/fo/pagination/ColorProfile.java +++ b/src/java/org/apache/fop/fo/pagination/ColorProfile.java @@ -19,14 +19,14 @@ package org.apache.fop.fo.pagination; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.xml.sax.Locator; - /** * The fo:color-profile formatting object. * This loads the color profile when needed and resolves a requested color. @@ -39,15 +39,15 @@ public class ColorProfile extends FObj { // End of property values /** + * Creates a new color-profile element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public ColorProfile(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { src = pList.get(PR_SRC).getString(); colorProfileName = pList.get(PR_COLOR_PROFILE_NAME).getString(); @@ -59,12 +59,15 @@ public class ColorProfile extends FObj { XSL 1.0/FOP: EMPTY (no child nodes permitted) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + invalidChildError(loc, nsURI, localName); + } } /** * Return the "color-profile-name" property. + * @return the color-profile-name property */ public String getColorProfileName() { return colorProfileName; @@ -75,9 +78,7 @@ public class ColorProfile extends FObj { return "color-profile"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_COLOR_PROFILE; } diff --git a/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java b/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java index dfb4ba70b..a13808324 100644 --- a/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java @@ -45,15 +45,15 @@ public class ConditionalPageMasterReference extends FObj { // End of property values /** + * Creates a new conditional-page-master-reference element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public ConditionalPageMasterReference(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { masterReference = pList.get(PR_MASTER_REFERENCE).getString(); pagePosition = pList.get(PR_PAGE_POSITION).getEnum(); @@ -65,9 +65,7 @@ public class ConditionalPageMasterReference extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { getConcreteParent().addConditionalPageMasterReference(this); } @@ -81,8 +79,10 @@ public class ConditionalPageMasterReference extends FObj { * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + invalidChildError(loc, nsURI, localName); + } } /** diff --git a/src/java/org/apache/fop/fo/pagination/Declarations.java b/src/java/org/apache/fop/fo/pagination/Declarations.java index 9dc282d07..3eec2897a 100644 --- a/src/java/org/apache/fop/fo/pagination/Declarations.java +++ b/src/java/org/apache/fop/fo/pagination/Declarations.java @@ -42,6 +42,7 @@ public class Declarations extends FObj { private Map colorProfiles = null; /** + * Creates a new declarations element. * @param parent FONode that is the parent of this object */ public Declarations(FONode parent) { @@ -49,9 +50,7 @@ public class Declarations extends FObj { ((Root) parent).setDeclarations(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { // No properties defined for fo:declarations } @@ -73,6 +72,7 @@ public class Declarations extends FObj { /** * At the end of this element sort out the children into * a hashmap of color profiles and a list of extension attachments. + * @throws FOPException if there's a problem during processing */ protected void endOfNode() throws FOPException { if (firstChild != null) { @@ -83,7 +83,8 @@ public class Declarations extends FObj { if (!"".equals(cp.getColorProfileName())) { addColorProfile(cp); } else { - log.warn("color-profile-name required for color profile"); + getFOValidationEventProducer().missingProperty(this, + cp.getName(), "color-profile-name", locator); } } else { log.debug("Ignoring element " + node.getName() @@ -100,22 +101,18 @@ public class Declarations extends FObj { } if (colorProfiles.get(cp.getColorProfileName()) != null) { // duplicate names - log.warn("Duplicate fo:color-profile profile name: " - + cp.getColorProfileName()); + getFOValidationEventProducer().colorProfileNameNotUnique(this, + cp.getName(), cp.getColorProfileName(), locator); } colorProfiles.put(cp.getColorProfileName(), cp); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getLocalName() { return "declarations"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_DECLARATIONS; } diff --git a/src/java/org/apache/fop/fo/pagination/Flow.java b/src/java/org/apache/fop/fo/pagination/Flow.java index fc5d605cc..2ee77ff0a 100644 --- a/src/java/org/apache/fop/fo/pagination/Flow.java +++ b/src/java/org/apache/fop/fo/pagination/Flow.java @@ -45,16 +45,12 @@ public class Flow extends FObj { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { flowName = pList.get(PR_FLOW_NAME).getString(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { if (flowName == null || flowName.equals("")) { missingPropertyError("flow-name"); @@ -80,10 +76,7 @@ public class Flow extends FObj { getFOEventHandler().startFlow(this); } - /** - * Make sure content model satisfied, if so then tell the - * FOEventHandler that we are at the end of the flow. - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (!blockItemFound) { missingChildElementError("marker* (%block;)+"); @@ -96,21 +89,21 @@ public class Flow extends FObj { * XSL Content Model: marker* (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("marker")) { - if (blockItemFound) { - nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (blockItemFound) { + nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); + } + } else if (!isBlockItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } else { + blockItemFound = true; } - } else if (!isBlockItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else { - blockItemFound = true; } } - /** - * @return true (Flow can generate reference areas) - */ + /** {@inheritDoc} */ public boolean generatesReferenceAreas() { return true; } @@ -125,9 +118,7 @@ public class Flow extends FObj { return "flow"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_FLOW; } diff --git a/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java b/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java index 54eb29744..1b57be57d 100644 --- a/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java +++ b/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java @@ -46,31 +46,27 @@ public class LayoutMasterSet extends FObj { private Map pageSequenceMasters; /** + * Creates a new layout-master-set element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public LayoutMasterSet(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { // No properties in layout-master-set. } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { getRoot().setLayoutMasterSet(this); simplePageMasters = new java.util.HashMap(); pageSequenceMasters = new java.util.HashMap(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (firstChild == null) { missingChildElementError("(simple-page-master|page-sequence-master)+"); @@ -83,14 +79,12 @@ public class LayoutMasterSet extends FObj { XSL/FOP: (simple-page-master|page-sequence-master)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { if (!localName.equals("simple-page-master") && !localName.equals("page-sequence-master")) { invalidChildError(loc, nsURI, localName); } - } else { - invalidChildError(loc, nsURI, localName); } } @@ -104,23 +98,20 @@ public class LayoutMasterSet extends FObj { Map allRegions = new java.util.HashMap(); for (Iterator spm = simplePageMasters.values().iterator(); spm.hasNext();) { - SimplePageMaster simplePageMaster = - (SimplePageMaster)spm.next(); + SimplePageMaster simplePageMaster + = (SimplePageMaster)spm.next(); Map spmRegions = simplePageMaster.getRegions(); for (Iterator e = spmRegions.values().iterator(); e.hasNext();) { Region region = (Region) e.next(); if (allRegions.containsKey(region.getRegionName())) { - String defaultRegionName = - (String) allRegions.get(region.getRegionName()); + String defaultRegionName + = (String) allRegions.get(region.getRegionName()); if (!defaultRegionName.equals(region.getDefaultRegionName())) { - throw new ValidationException("Region-name (" - + region.getRegionName() - + ") is being mapped to multiple " - + "region-classes (" - + defaultRegionName + " and " - + region.getDefaultRegionName() - + ")", locator); + getFOValidationEventProducer().regionNameMappedToMultipleRegionClasses(this, + region.getRegionName(), + defaultRegionName, + region.getDefaultRegionName(), getLocator()); } } allRegions.put(region.getRegionName(), @@ -141,21 +132,16 @@ public class LayoutMasterSet extends FObj { // check for duplication of master-name String masterName = sPM.getMasterName(); if (existsName(masterName)) { - throw new ValidationException("'master-name' (" - + masterName - + ") must be unique " - + "across page-masters and page-sequence-masters", sPM.getLocator()); + getFOValidationEventProducer().masterNameNotUnique(this, + getName(), + masterName, sPM.getLocator()); } this.simplePageMasters.put(masterName, sPM); } private boolean existsName(String masterName) { - if (simplePageMasters.containsKey(masterName) - || pageSequenceMasters.containsKey(masterName)) { - return true; - } else { - return false; - } + return (simplePageMasters.containsKey(masterName) + || pageSequenceMasters.containsKey(masterName)); } /** @@ -181,10 +167,9 @@ public class LayoutMasterSet extends FObj { throws ValidationException { // check against duplication of master-name if (existsName(masterName)) { - throw new ValidationException("'master-name' (" - + masterName - + ") must be unique " - + "across page-masters and page-sequence-masters", pSM.getLocator()); + getFOValidationEventProducer().masterNameNotUnique(this, + getName(), + masterName, pSM.getLocator()); } this.pageSequenceMasters.put(masterName, pSM); } @@ -220,9 +205,7 @@ public class LayoutMasterSet extends FObj { return "layout-master-set"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_LAYOUT_MASTER_SET; } diff --git a/src/java/org/apache/fop/fo/pagination/PageNumberGenerator.java b/src/java/org/apache/fop/fo/pagination/PageNumberGenerator.java index 4289076ea..50620f678 100644 --- a/src/java/org/apache/fop/fo/pagination/PageNumberGenerator.java +++ b/src/java/org/apache/fop/fo/pagination/PageNumberGenerator.java @@ -43,7 +43,7 @@ public class PageNumberGenerator { private int minPadding = 0; // for decimal formats // preloaded strings of zeros - private String zeros[] = { + private String[] zeros = { "", "0", "00", "000", "0000", "00000" }; @@ -128,10 +128,10 @@ public class PageNumberGenerator { } private String makeRoman(int num) { - int arabic[] = { + int[] arabic = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; - String roman[] = { + String[] roman = { "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i" }; diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java index 91649fbc5..3d155a1da 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java @@ -78,9 +78,7 @@ public class PageSequence extends AbstractPageSequence { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); country = pList.get(PR_COUNTRY).getString(); @@ -93,9 +91,7 @@ public class PageSequence extends AbstractPageSequence { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); flowMap = new java.util.HashMap(); @@ -105,9 +101,8 @@ public class PageSequence extends AbstractPageSequence { this.pageSequenceMaster = getRoot().getLayoutMasterSet().getPageSequenceMaster(masterReference); if (this.pageSequenceMaster == null) { - throw new ValidationException("master-reference '" + masterReference - + "' for fo:page-sequence matches no" - + " simple-page-master or page-sequence-master", locator); + getFOValidationEventProducer().masterNotFound(this, getName(), + masterReference, getLocator()); } } @@ -128,7 +123,7 @@ public class PageSequence extends AbstractPageSequence { XSL Content Model: (title?,static-content*,flow) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { if (localName.equals("title")) { if (titleFO != null) { @@ -149,8 +144,6 @@ public class PageSequence extends AbstractPageSequence { } else { invalidChildError(loc, nsURI, localName); } - } else { - invalidChildError(loc, nsURI, localName); } } @@ -184,18 +177,15 @@ public class PageSequence extends AbstractPageSequence { String flowName = flow.getFlowName(); if (hasFlowName(flowName)) { - throw new ValidationException("duplicate flow-name \"" - + flowName - + "\" found within fo:page-sequence", flow.getLocator()); + getFOValidationEventProducer().duplicateFlowNameInPageSequence(this, flow.getName(), + flowName, flow.getLocator()); } if (!getRoot().getLayoutMasterSet().regionNameExists(flowName) && !flowName.equals("xsl-before-float-separator") && !flowName.equals("xsl-footnote-separator")) { - throw new ValidationException("flow-name \"" - + flowName - + "\" could not be mapped to a region-name in the" - + " layout-master-set", flow.getLocator()); + getFOValidationEventProducer().flowNameNotMapped(this, flow.getName(), + flowName, flow.getLocator()); } } diff --git a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java index 34ad299bd..4258a1139 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java @@ -29,6 +29,7 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.layoutmgr.BlockLevelEventProducer; /** * The page-sequence-master formatting object. @@ -53,6 +54,8 @@ public class PageSequenceMaster extends FObj { // but the actual FO's are MasterReferences. /** + * Creates a new page-sequence-master element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public PageSequenceMaster(FONode parent) { @@ -95,20 +98,18 @@ public class PageSequenceMaster extends FObj { * repeatable-page-master-alternatives)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { if (!localName.equals("single-page-master-reference") && !localName.equals("repeatable-page-master-reference") && !localName.equals("repeatable-page-master-alternatives")) { invalidChildError(loc, nsURI, localName); } - } else { - invalidChildError(loc, nsURI, localName); } } /** - * Adds a new suqsequence specifier to the page sequence master. + * Adds a new subsequence specifier to the page sequence master. * @param pageMasterReference the subsequence to add */ protected void addSubsequenceSpecifier(SubSequenceSpecifier pageMasterReference) { @@ -199,8 +200,10 @@ public class PageSequenceMaster extends FObj { if (currentSubSequence == null) { currentSubSequence = getNextSubSequence(); if (currentSubSequence == null) { - throw new FOPException("no subsequences in page-sequence-master '" - + masterName + "'"); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.missingSubsequencesInPageSequenceMaster(this, + masterName, getLocator()); } } String pageMasterName = currentSubSequence @@ -209,14 +212,10 @@ public class PageSequenceMaster extends FObj { while (pageMasterName == null) { SubSequenceSpecifier nextSubSequence = getNextSubSequence(); if (nextSubSequence == null) { - if (!canRecover) { - throw new FOPException("subsequences exhausted in page-sequence-master '" - + masterName - + "', cannot recover"); - } - log.warn("subsequences exhausted in page-sequence-master '" - + masterName - + "', using previous subsequence"); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.pageSequenceMasterExhausted(this, + masterName, canRecover, getLocator()); currentSubSequence.reset(); canRecover = false; } else { @@ -228,9 +227,10 @@ public class PageSequenceMaster extends FObj { SimplePageMaster pageMaster = this.layoutMasterSet .getSimplePageMaster(pageMasterName); if (pageMaster == null) { - throw new FOPException("No simple-page-master matching '" - + pageMasterName + "' in page-sequence-master '" - + masterName + "'"); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noMatchingPageMaster(this, + masterName, pageMasterName, getLocator()); } return pageMaster; } @@ -240,9 +240,7 @@ public class PageSequenceMaster extends FObj { return "page-sequence-master"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_PAGE_SEQUENCE_MASTER; } diff --git a/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java b/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java index 94c0314a3..0b3cff276 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java @@ -22,8 +22,8 @@ package org.apache.fop.fo.pagination; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FObj; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; @@ -39,15 +39,14 @@ public class PageSequenceWrapper extends FObj { // End of property values /** + * Creates a new page-sequence-wrapper element. * @param parent FONode that is the parent of this object */ public PageSequenceWrapper(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); indexClass = pList.get(PR_INDEX_CLASS).getString(); @@ -59,10 +58,12 @@ public class PageSequenceWrapper extends FObj { XSL/FOP: (bookmark+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!(FO_URI.equals(nsURI) && (localName.equals("page-sequence") || - localName.equals("page-sequence-wrapper")))) { + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!(localName.equals("page-sequence") + || localName.equals("page-sequence-wrapper"))) { invalidChildError(loc, nsURI, localName); + } } } @@ -81,9 +82,7 @@ public class PageSequenceWrapper extends FObj { return "page-sequence-wrapper"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_PAGE_SEQUENCE_WRAPPER; } diff --git a/src/java/org/apache/fop/fo/pagination/Region.java b/src/java/org/apache/fop/fo/pagination/Region.java index 2516f90d8..ded86514b 100644 --- a/src/java/org/apache/fop/fo/pagination/Region.java +++ b/src/java/org/apache/fop/fo/pagination/Region.java @@ -30,7 +30,6 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; /** @@ -50,6 +49,8 @@ public abstract class Region extends FObj { private SimplePageMaster layoutMaster; /** + * Creates a new Region. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ protected Region(FONode parent) { @@ -57,9 +58,7 @@ public abstract class Region extends FObj { layoutMaster = (SimplePageMaster) parent; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); // clip = pList.get(PR_CLIP); @@ -76,18 +75,16 @@ public abstract class Region extends FObj { // check that name is OK. Not very pretty. if (isReserved(getRegionName()) && !getRegionName().equals(getDefaultRegionName())) { - throw new ValidationException("region-name '" + regionName - + "' for " + this.getName() - + " is not permitted.", locator); + getFOValidationEventProducer().illegalRegionName(this, getName(), + regionName, getLocator()); } } //TODO do we need context for getBPPaddingAndBorder() and getIPPaddingAndBorder()? - if (getUserAgent().validateStrictly() - && (getCommonBorderPaddingBackground().getBPPaddingAndBorder(false, null) != 0 + if ((getCommonBorderPaddingBackground().getBPPaddingAndBorder(false, null) != 0 || getCommonBorderPaddingBackground().getIPPaddingAndBorder(false, null) != 0)) { - throw new PropertyException("Border and padding for region \"" - + regionName + "\" must be '0' (See 6.4.13 in XSL 1.0)."); + getFOValidationEventProducer().nonZeroBorderPaddingOnRegion(this, getName(), + regionName, true, getLocator()); } } @@ -96,8 +93,10 @@ public abstract class Region extends FObj { * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** @@ -121,7 +120,7 @@ public abstract class Region extends FObj { * @param name a region name to check * @return true if the name parameter is a reserved region name */ - protected boolean isReserved(String name) /*throws FOPException*/ { + protected boolean isReserved(String name) { return (name.equals("xsl-region-before") || name.equals("xsl-region-start") || name.equals("xsl-region-end") @@ -130,9 +129,7 @@ public abstract class Region extends FObj { || name.equals("xsl-footnote-separator")); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean generatesReferenceAreas() { return true; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionAfter.java b/src/java/org/apache/fop/fo/pagination/RegionAfter.java index 9459a6637..2852358b5 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionAfter.java +++ b/src/java/org/apache/fop/fo/pagination/RegionAfter.java @@ -34,15 +34,15 @@ import org.apache.fop.datatypes.SimplePercentBaseContext; public class RegionAfter extends RegionBA { /** + * Creates a new region-after element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public RegionAfter(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Rectangle getViewportRectangle (FODimension reldims, SimplePageMaster spm) { /* Special rules apply to resolving extent as values are resolved relative * to the page size and reference orientation. @@ -82,9 +82,7 @@ public class RegionAfter extends RegionBA { return vpRect; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected String getDefaultRegionName() { return "xsl-region-after"; } @@ -94,9 +92,7 @@ public class RegionAfter extends RegionBA { return "region-after"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_REGION_AFTER; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionBA.java b/src/java/org/apache/fop/fo/pagination/RegionBA.java index 768af2489..279164a96 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBA.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBA.java @@ -36,15 +36,15 @@ public abstract class RegionBA extends SideRegion { // End of property values /** + * Creates a new region (before or after). + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ protected RegionBA(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); precedence = pList.get(PR_PRECEDENCE).getEnum(); diff --git a/src/java/org/apache/fop/fo/pagination/RegionBefore.java b/src/java/org/apache/fop/fo/pagination/RegionBefore.java index 6115d8dd8..076737252 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBefore.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBefore.java @@ -32,23 +32,22 @@ import org.apache.fop.fo.FONode; * The fo:region-before element. */ public class RegionBefore extends RegionBA { + /** + * Creates a new region-before element. + * @param parent the parent element * @see org.apache.fop.fo.FONode#FONode(FONode) */ public RegionBefore(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected String getDefaultRegionName() { return "xsl-region-before"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Rectangle getViewportRectangle (FODimension reldims, SimplePageMaster spm) { /* Special rules apply to resolving extent as values are resolved relative * to the page size and reference orientation. @@ -91,9 +90,7 @@ public class RegionBefore extends RegionBA { return "region-before"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_REGION_BEFORE; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionBody.java b/src/java/org/apache/fop/fo/pagination/RegionBody.java index 4de2dd1b4..9700e72fc 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBody.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBody.java @@ -43,29 +43,29 @@ public class RegionBody extends Region { // End of property values /** + * Creates a new region-body element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public RegionBody(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonMarginBlock = pList.getMarginBlockProps(); columnCount = pList.get(PR_COLUMN_COUNT).getNumeric(); columnGap = pList.get(PR_COLUMN_GAP).getLength(); - if ((getColumnCount() > 1) && (getOverflow() == EN_SCROLL)) { + if ((getColumnCount() != 1) && (getOverflow() == EN_SCROLL)) { /* This is an error (See XSL Rec, fo:region-body description). * The Rec allows for acting as if "1" is chosen in * these cases, but we will need to be able to change Numeric * values in order to do this. */ - attributeError("If overflow property is set to \"scroll\"," - + " a column-count other than \"1\" may not be specified."); + getFOValidationEventProducer().columnCountErrorOnRegionBodyOverflowScroll(this, + getName(), getLocator()); } } @@ -93,9 +93,7 @@ public class RegionBody extends Region { return columnGap.getValue(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Rectangle getViewportRectangle (FODimension reldims, SimplePageMaster spm) { /* Special rules apply to resolving margins in the page context. * Contrary to normal margins in this case top and bottom margin @@ -143,9 +141,7 @@ public class RegionBody extends Region { reldims.bpd - before - after); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected String getDefaultRegionName() { return "xsl-region-body"; } @@ -155,9 +151,7 @@ public class RegionBody extends Region { return "region-body"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_REGION_BODY; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionEnd.java b/src/java/org/apache/fop/fo/pagination/RegionEnd.java index 912be9097..13f65d71a 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionEnd.java +++ b/src/java/org/apache/fop/fo/pagination/RegionEnd.java @@ -22,26 +22,26 @@ package org.apache.fop.fo.pagination; // Java import java.awt.Rectangle; -// FOP -import org.apache.fop.fo.FONode; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.SimplePercentBaseContext; +import org.apache.fop.fo.FONode; /** * The fo:region-end element. */ public class RegionEnd extends RegionSE { + /** + * Creates a new region-end element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public RegionEnd(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Rectangle getViewportRectangle (FODimension reldims, SimplePageMaster spm) { /* Special rules apply to resolving extent as values are resolved relative * to the page size and reference orientation. @@ -80,9 +80,7 @@ public class RegionEnd extends RegionSE { return vpRect; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected String getDefaultRegionName() { return "xsl-region-end"; } @@ -92,9 +90,7 @@ public class RegionEnd extends RegionSE { return "region-end"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_REGION_END; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionSE.java b/src/java/org/apache/fop/fo/pagination/RegionSE.java index 735623352..183b44342 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionSE.java +++ b/src/java/org/apache/fop/fo/pagination/RegionSE.java @@ -35,15 +35,15 @@ public abstract class RegionSE extends SideRegion { // End of property values /** + * Creates a new region (start or end). + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ protected RegionSE(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); } diff --git a/src/java/org/apache/fop/fo/pagination/RegionStart.java b/src/java/org/apache/fop/fo/pagination/RegionStart.java index d78b19c3d..7a69cfdac 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionStart.java +++ b/src/java/org/apache/fop/fo/pagination/RegionStart.java @@ -32,16 +32,17 @@ import org.apache.fop.datatypes.SimplePercentBaseContext; * The fo:region-start element. */ public class RegionStart extends RegionSE { + /** + * Creates a new region-start element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public RegionStart(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Rectangle getViewportRectangle (FODimension reldims, SimplePageMaster spm) { /* Special rules apply to resolving extent as values are resolved relative * to the page size and reference orientation. @@ -77,9 +78,7 @@ public class RegionStart extends RegionSE { return vpRect; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected String getDefaultRegionName() { return "xsl-region-start"; } @@ -89,9 +88,7 @@ public class RegionStart extends RegionSE { return "region-start"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_REGION_START; } diff --git a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java index 9d2fe652c..509b81f21 100644 --- a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java +++ b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java @@ -52,38 +52,29 @@ public class RepeatablePageMasterAlternatives extends FObj private boolean hasPagePositionOnly = false; /** + * Creates a new repeatable-page-master-alternatives element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public RepeatablePageMasterAlternatives(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { maximumRepeats = pList.get(PR_MAXIMUM_REPEATS); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { conditionalPageMasterRefs = new java.util.ArrayList(); - if (parent.getName().equals("fo:page-sequence-master")) { - PageSequenceMaster pageSequenceMaster = (PageSequenceMaster)parent; - pageSequenceMaster.addSubsequenceSpecifier(this); - } else { - throw new ValidationException("fo:repeatable-page-master-alternatives " - + "must be child of fo:page-sequence-master, not " - + parent.getName(), locator); - } + assert parent.getName().equals("fo:page-sequence-master"); //Validation by the parent + PageSequenceMaster pageSequenceMaster = (PageSequenceMaster)parent; + pageSequenceMaster.addSubsequenceSpecifier(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (firstChild == null) { missingChildElementError("(conditional-page-master-reference+)"); @@ -95,10 +86,11 @@ public class RepeatablePageMasterAlternatives extends FObj XSL/FOP: (conditional-page-master-reference+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!(FO_URI.equals(nsURI) - && localName.equals("conditional-page-master-reference"))) { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!localName.equals("conditional-page-master-reference")) { + invalidChildError(loc, nsURI, localName); + } } } @@ -117,11 +109,7 @@ public class RepeatablePageMasterAlternatives extends FObj } } - /** - * Get the next matching page master from the conditional - * page master references. - * @see org.apache.fop.fo.pagination.SubSequenceSpecifier - */ + /** {@inheritDoc} */ public String getNextPageMasterName(boolean isOddPage, boolean isFirstPage, boolean isLastPage, @@ -183,12 +171,11 @@ public class RepeatablePageMasterAlternatives extends FObj } /** {@inheritDoc} */ - /** @see org.apache.fop.fo.pagination.SubSequenceSpecifier#hasPagePositionOnly() */ public boolean hasPagePositionOnly() { return this.hasPagePositionOnly; } - /** @see org.apache.fop.fo.FONode#getLocalName() */ + /** {@inheritDoc} */ public String getLocalName() { return "repeatable-page-master-alternatives"; } diff --git a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java index 172324232..87dc248c0 100644 --- a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java @@ -47,15 +47,15 @@ public class RepeatablePageMasterReference extends FObj private int numberConsumed = 0; /** + * Creates a new repeatable-page-master-reference element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public RepeatablePageMasterReference(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { masterReference = pList.get(PR_MASTER_REFERENCE).getString(); maximumRepeats = pList.get(PR_MAXIMUM_REPEATS); @@ -65,9 +65,7 @@ public class RepeatablePageMasterReference extends FObj } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { PageSequenceMaster pageSequenceMaster = (PageSequenceMaster) parent; @@ -83,13 +81,13 @@ public class RepeatablePageMasterReference extends FObj * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + invalidChildError(loc, nsURI, localName); + } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getNextPageMasterName(boolean isOddPage, boolean isFirstPage, boolean isLastPage, diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java index 6e079cf47..1cff9c3d6 100644 --- a/src/java/org/apache/fop/fo/pagination/Root.java +++ b/src/java/org/apache/fop/fo/pagination/Root.java @@ -25,7 +25,6 @@ import java.util.List; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; @@ -62,7 +61,9 @@ public class Root extends FObj { */ private FOEventHandler foEventHandler = null; - /** + /** + * Creates a new root element. + * @param parent the parent node (must be null) * @see org.apache.fop.fo.FONode#FONode(FONode) */ public Root(FONode parent) { @@ -137,13 +138,6 @@ public class Root extends FObj { } - /** @inheritDoc */ - protected void validateChildNode(Locator loc, FONode child) throws ValidationException { - if (child instanceof AbstractPageSequence) { - pageSequenceFound = true; - } - } - /** * Sets the FOEventHandler object that this Root is attached to * @param foEventHandler the FOEventHandler object @@ -291,9 +285,7 @@ public class Root extends FObj { return bookmarkTree; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Root getRoot() { return this; } @@ -303,9 +295,7 @@ public class Root extends FObj { return "root"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_ROOT; } diff --git a/src/java/org/apache/fop/fo/pagination/SideRegion.java b/src/java/org/apache/fop/fo/pagination/SideRegion.java index 14328aa9b..552ca871b 100644 --- a/src/java/org/apache/fop/fo/pagination/SideRegion.java +++ b/src/java/org/apache/fop/fo/pagination/SideRegion.java @@ -31,7 +31,11 @@ public abstract class SideRegion extends Region { private Length extent; - /** @see org.apache.fop.fo.FONode#FONode(FONode) */ + /** + * Creates a new side region. + * @param parent the parent node + * @see org.apache.fop.fo.FONode#FONode(FONode) + */ protected SideRegion(FONode parent) { super(parent); } diff --git a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java index ba1c0a6af..85a5081c8 100644 --- a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java +++ b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java @@ -63,15 +63,15 @@ public class SimplePageMaster extends FObj { private boolean hasRegionEnd = false; /** + * Creates a new simple-page-master element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public SimplePageMaster(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { commonMarginBlock = pList.getMarginBlockProps(); masterName = pList.get(PR_MASTER_NAME).getString(); @@ -85,9 +85,7 @@ public class SimplePageMaster extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { LayoutMasterSet layoutMasterSet = (LayoutMasterSet) parent; @@ -101,9 +99,7 @@ public class SimplePageMaster extends FObj { regions = new HashMap(5); } - /** - * Make sure content model satisfied. - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (!hasRegionBody) { missingChildElementError( @@ -116,72 +112,70 @@ public class SimplePageMaster extends FObj { * XSL Content Model: (region-body,region-before?,region-after?,region-start?,region-end?) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("region-body")) { - if (hasRegionBody) { - tooManyNodesError(loc, "fo:region-body"); - } else { - hasRegionBody = true; - } - } else if (FO_URI.equals(nsURI) && localName.equals("region-before")) { - if (!hasRegionBody) { - nodesOutOfOrderError(loc, "fo:region-body", "fo:region-before"); - } else if (hasRegionBefore) { - tooManyNodesError(loc, "fo:region-before"); - } else if (hasRegionAfter) { - nodesOutOfOrderError(loc, "fo:region-before", "fo:region-after"); - } else if (hasRegionStart) { - nodesOutOfOrderError(loc, "fo:region-before", "fo:region-start"); - } else if (hasRegionEnd) { - nodesOutOfOrderError(loc, "fo:region-before", "fo:region-end"); - } else { - hasRegionBody = true; - } - } else if (FO_URI.equals(nsURI) && localName.equals("region-after")) { - if (!hasRegionBody) { - nodesOutOfOrderError(loc, "fo:region-body", "fo:region-after"); - } else if (hasRegionAfter) { - tooManyNodesError(loc, "fo:region-after"); - } else if (hasRegionStart) { - nodesOutOfOrderError(loc, "fo:region-after", "fo:region-start"); - } else if (hasRegionEnd) { - nodesOutOfOrderError(loc, "fo:region-after", "fo:region-end"); - } else { - hasRegionAfter = true; - } - } else if (FO_URI.equals(nsURI) && localName.equals("region-start")) { - if (!hasRegionBody) { - nodesOutOfOrderError(loc, "fo:region-body", "fo:region-start"); - } else if (hasRegionStart) { - tooManyNodesError(loc, "fo:region-start"); - } else if (hasRegionEnd) { - nodesOutOfOrderError(loc, "fo:region-start", "fo:region-end"); - } else { - hasRegionStart = true; - } - } else if (FO_URI.equals(nsURI) && localName.equals("region-end")) { - if (!hasRegionBody) { - nodesOutOfOrderError(loc, "fo:region-body", "fo:region-end"); - } else if (hasRegionEnd) { - tooManyNodesError(loc, "fo:region-end"); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("region-body")) { + if (hasRegionBody) { + tooManyNodesError(loc, "fo:region-body"); + } else { + hasRegionBody = true; + } + } else if (localName.equals("region-before")) { + if (!hasRegionBody) { + nodesOutOfOrderError(loc, "fo:region-body", "fo:region-before"); + } else if (hasRegionBefore) { + tooManyNodesError(loc, "fo:region-before"); + } else if (hasRegionAfter) { + nodesOutOfOrderError(loc, "fo:region-before", "fo:region-after"); + } else if (hasRegionStart) { + nodesOutOfOrderError(loc, "fo:region-before", "fo:region-start"); + } else if (hasRegionEnd) { + nodesOutOfOrderError(loc, "fo:region-before", "fo:region-end"); + } else { + hasRegionBody = true; + } + } else if (localName.equals("region-after")) { + if (!hasRegionBody) { + nodesOutOfOrderError(loc, "fo:region-body", "fo:region-after"); + } else if (hasRegionAfter) { + tooManyNodesError(loc, "fo:region-after"); + } else if (hasRegionStart) { + nodesOutOfOrderError(loc, "fo:region-after", "fo:region-start"); + } else if (hasRegionEnd) { + nodesOutOfOrderError(loc, "fo:region-after", "fo:region-end"); + } else { + hasRegionAfter = true; + } + } else if (localName.equals("region-start")) { + if (!hasRegionBody) { + nodesOutOfOrderError(loc, "fo:region-body", "fo:region-start"); + } else if (hasRegionStart) { + tooManyNodesError(loc, "fo:region-start"); + } else if (hasRegionEnd) { + nodesOutOfOrderError(loc, "fo:region-start", "fo:region-end"); + } else { + hasRegionStart = true; + } + } else if (localName.equals("region-end")) { + if (!hasRegionBody) { + nodesOutOfOrderError(loc, "fo:region-body", "fo:region-end"); + } else if (hasRegionEnd) { + tooManyNodesError(loc, "fo:region-end"); + } else { + hasRegionEnd = true; + } } else { - hasRegionEnd = true; + invalidChildError(loc, nsURI, localName); } - } else { - invalidChildError(loc, nsURI, localName); } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean generatesReferenceAreas() { return true; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { if (child instanceof Region) { addRegion((Region)child); @@ -268,9 +262,7 @@ public class SimplePageMaster extends FObj { return "simple-page-master"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_SIMPLE_PAGE_MASTER; } diff --git a/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java b/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java index 43d8e40dc..119ec409e 100644 --- a/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java @@ -46,6 +46,8 @@ public class SinglePageMasterReference extends FObj private int state; /** + * Creates a new single-page-master-reference element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public SinglePageMasterReference(FONode parent) { @@ -53,9 +55,7 @@ public class SinglePageMasterReference extends FObj this.state = FIRST; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { masterReference = pList.get(PR_MASTER_REFERENCE).getString(); @@ -64,9 +64,7 @@ public class SinglePageMasterReference extends FObj } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { PageSequenceMaster pageSequenceMaster = (PageSequenceMaster) parent; pageSequenceMaster.addSubsequenceSpecifier(this); @@ -77,8 +75,10 @@ public class SinglePageMasterReference extends FObj * XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + invalidChildError(loc, nsURI, localName); + } } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/pagination/StaticContent.java b/src/java/org/apache/fop/fo/pagination/StaticContent.java index 62d73e56d..184438b6f 100644 --- a/src/java/org/apache/fop/fo/pagination/StaticContent.java +++ b/src/java/org/apache/fop/fo/pagination/StaticContent.java @@ -27,24 +27,22 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:static-content object. + * Class modeling the fo:static-content object. */ public class StaticContent extends Flow { /** + * Creates a new static-content element. * @param parent FONode that is the parent of this object */ public StaticContent(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { if (getFlowName() == null || getFlowName().equals("")) { - throw new ValidationException("A 'flow-name' is required for " - + getName() + ".", locator); + missingPropertyError("flow-name"); } getFOEventHandler().startFlow(this); } @@ -66,9 +64,11 @@ public class StaticContent extends Flow { * XSL Content Model: (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!isBlockItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!isBlockItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } } } diff --git a/src/java/org/apache/fop/fo/pagination/Title.java b/src/java/org/apache/fop/fo/pagination/Title.java index 398424152..f6f625ea8 100644 --- a/src/java/org/apache/fop/fo/pagination/Title.java +++ b/src/java/org/apache/fop/fo/pagination/Title.java @@ -27,7 +27,7 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.flow.InlineLevel; /** - * Class modelling the fo:title object. + * Class modeling the fo:title object. */ public class Title extends InlineLevel { // The value of properties relevant for fo:title. @@ -35,6 +35,7 @@ public class Title extends InlineLevel { // End of property values /** + * Creates a new title element. * @param parent FONode that is the parent of this object */ public Title(FONode parent) { @@ -46,22 +47,20 @@ public class Title extends InlineLevel { XSL/FOP: (#PCDATA|%inline;)* */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!isInlineItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!isInlineItem(nsURI, localName)) { + invalidChildError(loc, nsURI, localName); + } } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getLocalName() { return "title"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_TITLE; } diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java b/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java index e588bb3f8..7f55ec51b 100644 --- a/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java +++ b/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java @@ -20,10 +20,13 @@ package org.apache.fop.fo.pagination.bookmarks; import java.util.ArrayList; +import java.util.List; + import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FObj; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; @@ -68,10 +71,10 @@ public class Bookmark extends FObj { externalDestination = null; } else if (externalDestination.length() == 0) { // slightly stronger than spec "should be specified" - attributeError("Missing attribute: Either external-destination or " + - "internal-destination must be specified."); + getFOValidationEventProducer().missingLinkDestination(this, getName(), locator); } else { - attributeWarning("external-destination property not currently supported"); + getFOValidationEventProducer().unimplementedFeature(this, getName(), + "external-destination", getLocator()); } } @@ -80,18 +83,20 @@ public class Bookmark extends FObj { XSL/FOP: (bookmark-title, bookmark*) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI) && localName.equals("bookmark-title")) { + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("bookmark-title")) { if (bookmarkTitle != null) { tooManyNodesError(loc, "fo:bookmark-title"); } - } else if (FO_URI.equals(nsURI) && localName.equals("bookmark")) { + } else if (localName.equals("bookmark")) { if (bookmarkTitle == null) { nodesOutOfOrderError(loc, "fo:bookmark-title", "fo:bookmark"); } } else { invalidChildError(loc, nsURI, localName); } + } } /** @@ -123,10 +128,18 @@ public class Bookmark extends FObj { return bookmarkTitle == null ? "" : bookmarkTitle.getTitle(); } + /** + * Returns the value of the internal-destination property. + * @return the internal-destination + */ public String getInternalDestination() { return internalDestination; } + /** + * Returns the value of the external-destination property. + * @return the external-destination + */ public String getExternalDestination() { return externalDestination; } @@ -141,7 +154,11 @@ public class Bookmark extends FObj { return bShow; } - public ArrayList getChildBookmarks() { + /** + * Returns a list of child bookmarks. + * @return the list of child bookmarks + */ + public List getChildBookmarks() { return childBookmarks; } @@ -150,9 +167,7 @@ public class Bookmark extends FObj { return "bookmark"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_BOOKMARK; } diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java index f31aad1cb..c7024f2aa 100644 --- a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java +++ b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java @@ -21,8 +21,8 @@ package org.apache.fop.fo.pagination.bookmarks; import org.xml.sax.Locator; -import org.apache.fop.fo.FObj; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; @@ -45,15 +45,16 @@ public class BookmarkTitle extends FObj { /** * Add the characters to this BookmarkTitle. - * The text data inside the BookmarkTitle xml element + * The text data inside the BookmarkTitle XML element * is used for the BookmarkTitle string. * * @param data the character data * @param start the start position in the data array * @param end the end position in the character array - * @param locator location in fo source file. + * @param pList the currently valid property list + * @param locator location in FO source file. */ - protected void addCharacters(char data[], int start, int end, + protected void addCharacters(char[] data, int start, int end, PropertyList pList, Locator locator) { title += new String(data, start, end - start); @@ -64,8 +65,10 @@ public class BookmarkTitle extends FObj { XSL/FOP: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { + if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); + } } /** @@ -82,9 +85,7 @@ public class BookmarkTitle extends FObj { return "bookmark-title"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_BOOKMARK_TITLE; } diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTree.java b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTree.java index 6190fa22a..0f1d8a8b7 100644 --- a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTree.java +++ b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTree.java @@ -21,6 +21,7 @@ package org.apache.fop.fo.pagination.bookmarks; // Java import java.util.ArrayList; +import java.util.List; import org.xml.sax.Locator; @@ -39,15 +40,15 @@ public class BookmarkTree extends FObj { private ArrayList bookmarks = new ArrayList(); /** + * Creates a new bookmark-tree element. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public BookmarkTree(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void addChildNode(FONode obj) { if (obj instanceof Bookmark) { bookmarks.add(obj); @@ -69,14 +70,19 @@ public class BookmarkTree extends FObj { XSL/FOP: (bookmark+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (!(FO_URI.equals(nsURI) && - localName.equals("bookmark"))) { + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (!localName.equals("bookmark")) { invalidChildError(loc, nsURI, localName); + } } } - public ArrayList getBookmarks() { + /** + * Returns the root bookmarks. + * @return the root bookmarks + */ + public List getBookmarks() { return bookmarks; } @@ -85,9 +91,7 @@ public class BookmarkTree extends FObj { return "bookmark-tree"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getNameId() { return FO_BOOKMARK_TREE; } diff --git a/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java b/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java index 69ca372e5..5a5cf95c5 100644 --- a/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java +++ b/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * -/* $Id:$ */ +/* $Id$ */ package org.apache.fop.fo.properties; diff --git a/src/java/org/apache/fop/fonts/FontEventAdapter.java b/src/java/org/apache/fop/fonts/FontEventAdapter.java new file mode 100644 index 000000000..516999f70 --- /dev/null +++ b/src/java/org/apache/fop/fonts/FontEventAdapter.java @@ -0,0 +1,82 @@ +/* + * 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.fonts; + +import java.util.Map; + +import org.apache.fop.events.Event; +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.model.EventSeverity; + +/** + * Event listener interface for font-related events. This interface extends FontEventListener + * and EventProducer for integration into FOP's event subsystem. + */ +public class FontEventAdapter implements FontEventListener { + + private EventBroadcaster eventBroadcaster; + + /** + * Creates a new FontEventAdapter. + * @param broadcaster the event broadcaster to send the generated events to + */ + public FontEventAdapter(EventBroadcaster broadcaster) { + this.eventBroadcaster = broadcaster; + } + + /** + * Returns the event group ID. + * @return the event group ID + */ + protected String getEventGroupID() { + return getClass().getName(); + } + + /** {@inheritDoc} */ + public void fontSubstituted(Object source, FontTriplet requested, FontTriplet effective) { + Map params = new java.util.HashMap(); + params.put("requested", requested); + params.put("effective", effective); + Event ev = new Event(source, getEventGroupID() + ".fontSubstituted", + EventSeverity.WARN, params); + this.eventBroadcaster.broadcastEvent(ev); + } + + /** {@inheritDoc} */ + public void fontLoadingErrorAtAutoDetection(Object source, String fontURL, Exception e) { + Map params = new java.util.HashMap(); + params.put("fontURL", fontURL); + params.put("e", e); + Event ev = new Event(source, getEventGroupID() + ".fontLoadingErrorAtAutoDetection", + EventSeverity.WARN, params); + this.eventBroadcaster.broadcastEvent(ev); + } + + /** {@inheritDoc} */ + public void glyphNotAvailable(Object source, char ch, String fontName) { + Map params = new java.util.HashMap(); + params.put("ch", new Character(ch)); + params.put("fontName", fontName); + Event ev = new Event(source, getEventGroupID() + ".glyphNotAvailable", + EventSeverity.WARN, params); + this.eventBroadcaster.broadcastEvent(ev); + } + +} diff --git a/src/java/org/apache/fop/fonts/FontEventListener.java b/src/java/org/apache/fop/fonts/FontEventListener.java new file mode 100644 index 000000000..512df0ac0 --- /dev/null +++ b/src/java/org/apache/fop/fonts/FontEventListener.java @@ -0,0 +1,52 @@ +/* + * 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.fonts; + + +/** + * Event listener interface for font-related events. + */ +public interface FontEventListener { + + /** + * Notifies about a font being substituted as the requested one isn't available. + * @param source the event source + * @param requested the requested font triplet + * @param effective the effective font triplet + */ + void fontSubstituted(Object source, FontTriplet requested, FontTriplet effective); + + /** + * An error occurred while loading a font for auto-detection. + * @param source the event source + * @param fontURL the font URL + * @param e the original exception + */ + void fontLoadingErrorAtAutoDetection(Object source, String fontURL, Exception e); + + /** + * A glyph has been requested that is not available in the font. + * @param source the event source + * @param ch the character for which the glyph isn't available + * @param fontName the name of the font + */ + void glyphNotAvailable(Object source, char ch, String fontName); + +} diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index 218734f15..950134eb6 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -67,6 +67,8 @@ public class FontInfo { /** Cache for Font instances. */ private Map fontInstanceCache = new java.util.HashMap(); + private FontEventListener eventListener; + /** * Main constructor */ @@ -77,6 +79,15 @@ public class FontInfo { this.usedFonts = new java.util.HashMap(); } + /** + * Sets the font event listener that can be used to receive events about particular events + * in this class. + * @param listener the font event listener + */ + public void setEventListener(FontEventListener listener) { + this.eventListener = listener; + } + /** * Checks if the font setup is valid (At least the ultimate fallback font * must be registered.) @@ -158,6 +169,9 @@ public class FontInfo { public void addMetrics(String name, FontMetrics metrics) { // add the given metrics as a font with the given name + if (metrics instanceof Typeface) { + ((Typeface)metrics).setEventListener(this.eventListener); + } this.fonts.put(name, metrics); } @@ -364,8 +378,12 @@ public class FontInfo { } if (!loggedFontKeys.contains(replacedKey)) { loggedFontKeys.add(replacedKey); - log.warn("Font '" + replacedKey + "' not found. " - + "Substituting with '" + newKey + "'."); + if (this.eventListener != null) { + this.eventListener.fontSubstituted(this, replacedKey, newKey); + } else { + log.warn("Font '" + replacedKey + "' not found. " + + "Substituting with '" + newKey + "'."); + } } } diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index 07b5be305..5490e13f1 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -141,6 +141,7 @@ public class LazyFont extends Typeface implements FontDescriptor { throw new RuntimeException(ioex.getMessage()); } } + realFont.setEventListener(this.eventListener); isMetricsLoaded = true; } } diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index ac12b7615..0a47d52ab 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -117,18 +117,22 @@ public class SingleByteFont extends CustomFont { } //Give up, character is not available - Character ch = new Character(c); - if (warnedChars == null) { - warnedChars = new java.util.HashSet(); - } - if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { - warnedChars.add(ch); - if (warnedChars.size() == 8) { - log.warn("Many requested glyphs are not available in font " + getFontName()); - } else { - log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) - + ", " + Glyphs.charToGlyphName(c) - + ") not available in font " + getFontName()); + if (this.eventListener != null) { + this.eventListener.glyphNotAvailable(this, c, getFontName()); + } else { + Character ch = new Character(c); + if (warnedChars == null) { + warnedChars = new java.util.HashSet(); + } + if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { + warnedChars.add(ch); + if (warnedChars.size() == 8) { + log.warn("Many requested glyphs are not available in font " + getFontName()); + } else { + log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) + + ", " + Glyphs.charToGlyphName(c) + + ") not available in font " + getFontName()); + } } } return NOT_FOUND; diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java index 173d2e8a3..b6c78a3b0 100644 --- a/src/java/org/apache/fop/fonts/Typeface.java +++ b/src/java/org/apache/fop/fonts/Typeface.java @@ -30,6 +30,9 @@ public abstract class Typeface implements FontMetrics { */ private long charMapOps = 0; + /** An optional event listener that receives events such as missing glyphs etc. */ + protected FontEventListener eventListener; + /** * Get the encoding of the font. * @return the encoding @@ -80,5 +83,14 @@ public abstract class Typeface implements FontMetrics { return getAscender(size); } + /** + * Sets the font event listener that can be used to receive events about particular events + * in this class. + * @param listener the font event listener + */ + public void setEventListener(FontEventListener listener) { + this.eventListener = listener; + } + } diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index 8207eb140..b223ea7a1 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -35,6 +35,7 @@ import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.EmbedFontInfo; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontCache; +import org.apache.fop.fonts.FontEventListener; import org.apache.fop.fonts.FontLoader; import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontTriplet; @@ -52,6 +53,17 @@ public class FontInfoFinder { /** logging instance */ private Log log = LogFactory.getLog(FontInfoFinder.class); + private FontEventListener eventListener; + + /** + * Sets the font event listener that can be used to receive events about particular events + * in this class. + * @param listener the font event listener + */ + public void setEventListener(FontEventListener listener) { + this.eventListener = listener; + } + /** * Attempts to determine FontTriplets from a given CustomFont. * It seems to be fairly accurate but will probably require some tweaking over time @@ -180,7 +192,6 @@ public class FontInfoFinder { // try to determine triplet information from font file CustomFont customFont = null; - if (fontUrl.toExternalForm().endsWith(".ttc")) { // Get a list of the TTC Font names List ttcNames = null; //List @@ -193,7 +204,9 @@ public class FontInfoFinder { FontFileReader reader = new FontFileReader(in); ttcNames = ttf.getTTCnames(reader); } catch (Exception e) { - log.error(e); + if (this.eventListener != null) { + this.eventListener.fontLoadingErrorAtAutoDetection(this, fontFileURI, e); + } } finally { IOUtils.closeQuietly(in); } @@ -212,14 +225,16 @@ public class FontInfoFinder { try { ttfLoader = new TTFFontLoader(fontFileURI, fontName, resolver); customFont = ttfLoader.getFont(); + if (this.eventListener != null) { + customFont.setEventListener(this.eventListener); + } } catch (Exception e) { - //TODO Too verbose (it's an error but we don't care if some fonts can't be loaded) - //if (log.isErrorEnabled()) { - log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage()); - //} if (fontCache != null) { fontCache.registerFailedFont(embedUrl, fileLastModified); } + if (this.eventListener != null) { + this.eventListener.fontLoadingErrorAtAutoDetection(this, embedUrl, e); + } continue; } EmbedFontInfo fi = fontInfoFromCustomFont(fontUrl, customFont, fontCache); @@ -233,14 +248,16 @@ public class FontInfoFinder { // The normal case try { customFont = FontLoader.loadFont(fontUrl, null, resolver); + if (this.eventListener != null) { + customFont.setEventListener(this.eventListener); + } } catch (Exception e) { - //TODO Too verbose (it's an error but we don't care if some fonts can't be loaded) - //if (log.isErrorEnabled()) { - log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage()); - //} if (fontCache != null) { fontCache.registerFailedFont(embedUrl, fileLastModified); } + if (this.eventListener != null) { + this.eventListener.fontLoadingErrorAtAutoDetection(this, embedUrl, e); + } return null; } EmbedFontInfo fi = fontInfoFromCustomFont(fontUrl, customFont, fontCache); @@ -250,7 +267,6 @@ public class FontInfoFinder { return null; } } - } diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java index 81b3b4c07..be0995d8c 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -27,8 +27,11 @@ import java.util.Map; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; +import org.apache.batik.bridge.UserAgent; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageException; @@ -40,7 +43,7 @@ import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.apache.xmlgraphics.util.UnitConv; -import org.apache.fop.svg.SVGUserAgent; +import org.apache.fop.svg.SimpleSVGUserAgent; /** * This ImageConverter converts SVG images to Java2D. @@ -52,6 +55,9 @@ import org.apache.fop.svg.SVGUserAgent; */ public class ImageConverterSVG2G2D extends AbstractImageConverter { + /** logger */ + private static Log log = LogFactory.getLog(ImageConverterSVG2G2D.class); + /** {@inheritDoc} */ public Image convert(Image src, Map hints) throws ImageException { checkSourceFlavor(src); @@ -67,9 +73,7 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { if (ptm != null) { pxToMillimeter = (float)UnitConv.mm2in(ptm.doubleValue()); } - SVGUserAgent ua = new SVGUserAgent( - pxToMillimeter, - new AffineTransform()); + UserAgent ua = createBatikUserAgent(pxToMillimeter); GVTBuilder builder = new GVTBuilder(); final BridgeContext ctx = new BridgeContext(ua); @@ -107,6 +111,25 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { return g2dImage; } + /** + * Creates a user agent for Batik. Override to provide your own user agent. + * @param pxToMillimeter the source resolution (in px per millimeter) + * @return the newly created user agent + */ + protected SimpleSVGUserAgent createBatikUserAgent(float pxToMillimeter) { + return new SimpleSVGUserAgent( + pxToMillimeter, + new AffineTransform()) { + + /** {@inheritDoc} */ + public void displayMessage(String message) { + //TODO Refine and pipe through to caller + log.debug(message); + } + + }; + } + /** {@inheritDoc} */ public ImageFlavor getSourceFlavor() { return ImageFlavor.XML_DOM; diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java index e59e06b6b..20557a644 100644 --- a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -32,6 +32,7 @@ import org.w3c.dom.svg.SVGDocument; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.UnitProcessor; +import org.apache.batik.bridge.UserAgent; import org.apache.batik.dom.svg.SAXSVGDocumentFactory; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.dom.svg.SVGOMDocument; @@ -46,7 +47,7 @@ import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.util.MimeConstants; -import org.apache.fop.svg.SVGUserAgent; +import org.apache.fop.svg.SimpleSVGUserAgent; import org.apache.fop.util.UnclosableInputStream; /** @@ -154,8 +155,15 @@ public class PreloaderSVG extends AbstractImagePreloader { private ImageInfo createImageInfo(String uri, ImageContext context, SVGDocument doc) { Element e = doc.getRootElement(); float pxUnitToMillimeter = 25.4f / context.getSourceResolution(); - SVGUserAgent userAg = new SVGUserAgent(pxUnitToMillimeter, - new AffineTransform()); + UserAgent userAg = new SimpleSVGUserAgent(pxUnitToMillimeter, + new AffineTransform()) { + + /** {@inheritDoc} */ + public void displayMessage(String message) { + log.debug(message); + } + + }; BridgeContext ctx = new BridgeContext(userAg); UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 65d537bcd..4ef0579f2 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -198,11 +198,11 @@ public abstract class AbstractBreaker { } /** - * Returns a PageBreakingLayoutListener for the PageBreakingAlgorithm to notify about layout - * problems. + * Creates and returns a PageBreakingLayoutListener for the PageBreakingAlgorithm to + * notify about layout problems. * @return the listener instance or null if no notifications are needed */ - protected PageBreakingAlgorithm.PageBreakingLayoutListener getLayoutListener() { + protected PageBreakingAlgorithm.PageBreakingLayoutListener createLayoutListener() { return null; } @@ -320,7 +320,7 @@ public abstract class AbstractBreaker { log.debug("PLM> start of algorithm (" + this.getClass().getName() + "), flow BPD =" + flowBPD); PageBreakingAlgorithm alg = new PageBreakingAlgorithm(getTopLevelLM(), - getPageProvider(), getLayoutListener(), + getPageProvider(), createLayoutListener(), alignment, alignmentLast, footnoteSeparatorLength, isPartOverflowRecoveryActivated(), autoHeight, isSinglePartFavored()); int iOptPageCount; diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index e8ca88c1c..f01f0e12f 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -35,7 +35,6 @@ import org.apache.fop.area.CTM; import org.apache.fop.area.Trait; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.Length; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.BlockContainer; import org.apache.fop.fo.properties.CommonAbsolutePosition; import org.apache.fop.traits.MinOptMax; @@ -239,11 +238,11 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager int availableIPD = referenceIPD - getIPIndents(); if (getContentAreaIPD() > availableIPD) { - log.warn(FONode.decorateWithContextInfo( - "The extent in inline-progression-direction (width) of a block-container is" - + " bigger than the available space (" - + getContentAreaIPD() + "mpt > " + context.getRefIPD() + "mpt)", - getBlockContainerFO())); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getBlockContainerFO().getUserAgent().getEventBroadcaster()); + eventProducer.objectTooWide(this, getBlockContainerFO().getName(), + getContentAreaIPD(), context.getRefIPD(), + getBlockContainerFO().getLocator()); } MinOptMax stackLimit = new MinOptMax(relDims.bpd); @@ -378,10 +377,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager */ if (contentOverflows) { - log.warn("Contents overflow block-container viewport: clipping"); - if (getBlockContainerFO().getOverflow() == EN_ERROR_IF_OVERFLOW) { - //TODO Throw layout exception - } + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getBlockContainerFO().getUserAgent().getEventBroadcaster()); + boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW); + eventProducer.viewportOverflow(this, getBlockContainerFO().getName(), + breaker.getOverflowAmount(), needClip(), canRecover, + getBlockContainerFO().getLocator()); } } addKnuthElementsForBorderPaddingAfter(returnList, true); @@ -526,10 +527,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager //TODO Maybe check for page overflow when autoHeight=true if (!autoHeight & (contentOverflows)) { - log.warn("Contents overflow block-container viewport: clipping"); - if (getBlockContainerFO().getOverflow() == EN_ERROR_IF_OVERFLOW) { - //TODO Throw layout exception - } + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getBlockContainerFO().getUserAgent().getEventBroadcaster()); + boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW); + eventProducer.viewportOverflow(this, getBlockContainerFO().getName(), + breaker.getOverflowAmount(), needClip(), canRecover, + getBlockContainerFO().getLocator()); } } @@ -602,7 +605,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } public boolean isOverflow() { - return !isEmpty() && (deferredAlg.getPageBreaks().size() > 1); + if (isEmpty()) { + return false; + } else { + return (deferredAlg.getPageBreaks().size() > 1) + || (deferredAlg.totalWidth - deferredAlg.totalShrink) + > deferredAlg.getLineWidth(); + } + } + + public int getOverflowAmount() { + return (deferredAlg.totalWidth - deferredAlg.totalShrink) + - deferredAlg.getLineWidth(); } protected LayoutManager getTopLevelLM() { diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java new file mode 100644 index 000000000..c31a70477 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java @@ -0,0 +1,168 @@ +/* + * 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.layoutmgr; + +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; + +/** + * Event producer interface for block-level layout managers. + */ +public interface BlockLevelEventProducer extends EventProducer { + + /** + * Provider class for the event producer. + */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static BlockLevelEventProducer get(EventBroadcaster broadcaster) { + return (BlockLevelEventProducer)broadcaster.getEventProducerFor( + BlockLevelEventProducer.class); + } + } + + /** + * The contents of a table-row are too big to fit in the constraints. + * @param source the event source + * @param row the row number + * @param effCellBPD the effective extent in block-progression direction of the cell + * @param maxCellBPD the maximum extent in block-progression direction of the cell + * @param loc the location of the error or null + * @event.severity WARN + */ + void rowTooTall(Object source, int row, int effCellBPD, int maxCellBPD, Locator loc); + + /** + * Auto-table layout is not supported, yet. + * @param source the event source + * @param loc the location of the error or null + * @event.severity INFO + */ + void tableFixedAutoWidthNotSupported(Object source, Locator loc); + + /** + * An formatting object is too wide. + * @param source the event source + * @param elementName the formatting object + * @param effIPD the effective extent in inline-progression direction of the table contents + * @param maxIPD the maximum extent in inline-progression direction available + * @param loc the location of the error or null + * @event.severity WARN + */ + void objectTooWide(Object source, String elementName, int effIPD, int maxIPD, Locator loc); + + /** + * An overconstrained geometry adjustment rule was triggered (5.3.4, XSL 1.0). + * @param source the event source + * @param elementName the formatting object + * @param amount the amount of the adjustment (in mpt) + * @param loc the location of the error or null + * @event.severity INFO + */ + void overconstrainedAdjustEndIndent(Object source, String elementName, int amount, Locator loc); + + /** + * Contents overflow a viewport. + * @param source the event source + * @param elementName the formatting object + * @param amount the amount by which the contents overflow (in mpt) + * @param clip true if the content will be clipped + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @throws LayoutException the layout error provoked by the method call + * @event.severity FATAL + */ + void viewportOverflow(Object source, String elementName, + int amount, boolean clip, boolean canRecover, + Locator loc) throws LayoutException; + + /** + * Contents overflow a region viewport. + * @param source the event source + * @param elementName the formatting object + * @param page the page number/name where the overflow happened + * @param amount the amount by which the contents overflow (in mpt) + * @param clip true if the content will be clipped + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @throws LayoutException the layout error provoked by the method call + * @event.severity FATAL + */ + void regionOverflow(Object source, String elementName, + String page, + int amount, boolean clip, boolean canRecover, + Locator loc) throws LayoutException; + + /** + * Indicates that FOP doesn't support flows that are not mapped to region-body, yet. + * @param source the event source + * @param flowName the flow name + * @param masterName the page master name + * @param loc the location of the error or null + * @throws UnsupportedOperationException the layout error provoked by the method call + * @event.severity FATAL + */ + void flowNotMappingToRegionBody(Object source, String flowName, String masterName, + Locator loc) throws UnsupportedOperationException; + + /** + * A page sequence master is exhausted. + * @param source the event source + * @param pageSequenceMasterName the name of the page sequence master + * @param canRecover indicates whether FOP can recover from this problem and continue working + * @param loc the location of the error or null + * @throws FOPException the error provoked by the method call + * @event.severity FATAL + */ + void pageSequenceMasterExhausted(Object source, String pageSequenceMasterName, + boolean canRecover, Locator loc) throws FOPException; + + /** + * No subsequences in page sequence master. + * @param source the event source + * @param pageSequenceMasterName the name of the page sequence master + * @param loc the location of the error or null + * @throws FOPException the error provoked by the method call + * @event.severity FATAL + */ + void missingSubsequencesInPageSequenceMaster(Object source, String pageSequenceMasterName, + Locator loc) throws FOPException; + + /** + * No single-page-master matching in page sequence master. + * @param source the event source + * @param pageSequenceMasterName the name of the page sequence master + * @param pageMasterName the name of the page master not matching + * @param loc the location of the error or null + * @throws FOPException the error provoked by the method call + * @event.severity FATAL + */ + void noMatchingPageMaster(Object source, String pageSequenceMasterName, + String pageMasterName, Locator loc) throws FOPException; + +} diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 67ed1de9f..cb6db6b01 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -201,6 +201,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (ipd < 0) { //5.3.4, XSL 1.0, Overconstrained Geometry log.debug("Adjusting end-indent based on overconstrained geometry rules for " + fobj); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getFObj().getUserAgent().getEventBroadcaster()); + eventProducer.overconstrainedAdjustEndIndent(this, + getFObj().getName(), ipd, getFObj().getLocator()); endIndent += ipd; ipd = 0; //TODO Should we skip layout for a block that has ipd=0? @@ -212,7 +216,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** * Sets the content area IPD by directly supplying the value. * end-indent is adjusted based on overconstrained geometry rules, if necessary. - * + * @param contentIPD the IPD of the content * @return the resulting content area IPD */ protected int updateContentAreaIPDwithOverconstrainedAdjust(int contentIPD) { @@ -220,6 +224,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (ipd < 0) { //5.3.4, XSL 1.0, Overconstrained Geometry log.debug("Adjusting end-indent based on overconstrained geometry rules for " + fobj); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getFObj().getUserAgent().getEventBroadcaster()); + eventProducer.overconstrainedAdjustEndIndent(this, + getFObj().getName(), ipd, getFObj().getLocator()); endIndent += ipd; } setContentAreaIPD(contentIPD); diff --git a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java index 21856c781..086d91c31 100644 --- a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java @@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr; import java.awt.Dimension; import java.awt.Rectangle; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -46,6 +47,7 @@ import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.Viewport; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.URISpecification; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExternalDocument; import org.apache.fop.layoutmgr.inline.ImageLayout; @@ -140,17 +142,28 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan pageIndex++; } } catch (URISyntaxException e) { - log.error("Error parsing or constructing URIs based on URI: " + uri); + getResourceEventProducer().uriError(this, uri, e, + getExternalDocument().getLocator()); return; } } + } catch (FileNotFoundException fnfe) { + getResourceEventProducer().imageNotFound(this, uri, fnfe, + getExternalDocument().getLocator()); } catch (IOException ioe) { - log.error("Image not available: " + uri, ioe); + getResourceEventProducer().imageIOError(this, uri, ioe, + getExternalDocument().getLocator()); } catch (ImageException ie) { - log.error("Error while inspecting image: " + uri + " (" + ie.getMessage() + ")"); + getResourceEventProducer().imageError(this, uri, ie, + getExternalDocument().getLocator()); } } + private ResourceEventProducer getResourceEventProducer() { + return ResourceEventProducer.Provider.get( + getExternalDocument().getUserAgent().getEventBroadcaster()); + } + private void makePageForImage(ImageInfo info, ImageLayout layout) { this.imageLayout = layout; curPage = makeNewPage(false, false); diff --git a/src/java/org/apache/fop/layoutmgr/LayoutException.java b/src/java/org/apache/fop/layoutmgr/LayoutException.java new file mode 100644 index 000000000..350cc758a --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/LayoutException.java @@ -0,0 +1,105 @@ +/* + * 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.layoutmgr; + +import java.util.Locale; + +import org.apache.fop.events.Event; +import org.apache.fop.events.EventFormatter; +import org.apache.fop.events.EventExceptionManager.ExceptionFactory; + +/** + * Exception thrown by FOP if an unrecoverable layout error occurs. An example: An area overflows + * a viewport that has overflow="error-if-overflow". + * + * @todo Discuss if this should become a checked exception. + */ +public class LayoutException extends RuntimeException { + + private static final long serialVersionUID = 5157080040923740433L; + + private String localizedMessage; + private LayoutManager layoutManager; + + /** + * Constructs a new layout exception with the specified detail message. + * @param message the detail message. + */ + public LayoutException(String message) { + this(message, null); + } + + /** + * Constructs a new layout exception with the specified detail message. + * @param message the detail message + * @param lm the layout manager that throws the exception + */ + public LayoutException(String message, LayoutManager lm) { + super(message); + this.layoutManager = lm; + } + + /** + * Sets the localized message for this exception. + * @param msg the localized message + */ + public void setLocalizedMessage(String msg) { + this.localizedMessage = msg; + } + + /** {@inheritDoc} */ + public String getLocalizedMessage() { + if (this.localizedMessage != null) { + return this.localizedMessage; + } else { + return super.getLocalizedMessage(); + } + } + + /** + * Returns the layout manager that detected the problem. + * @return the layout manager (or null) + */ + public LayoutManager getLayoutManager() { + return this.layoutManager; + } + + /** Exception factory for {@link LayoutException}. */ + public static class LayoutExceptionFactory implements ExceptionFactory { + + /** {@inheritDoc} */ + public Throwable createException(Event event) { + Object source = event.getSource(); + LayoutManager lm = (source instanceof LayoutManager) ? (LayoutManager)source : null; + String msg = EventFormatter.format(event, Locale.ENGLISH); + LayoutException ex = new LayoutException(msg, lm); + if (!Locale.ENGLISH.equals(Locale.getDefault())) { + ex.setLocalizedMessage(EventFormatter.format(event)); + } + return ex; + } + + /** {@inheritDoc} */ + public Class getExceptionClass() { + return LayoutException.class; + } + + } +} diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index 3e100cd50..d6be75758 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -27,7 +27,6 @@ import org.apache.fop.area.Block; import org.apache.fop.area.Footnote; import org.apache.fop.area.PageViewport; import org.apache.fop.fo.Constants; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.Region; @@ -79,27 +78,25 @@ public class PageBreaker extends AbstractBreaker { return pslm.getPageProvider(); } - /** - * {@inheritDoc} - */ - protected PageBreakingLayoutListener getLayoutListener() { + /** {@inheritDoc} */ + protected PageBreakingLayoutListener createLayoutListener() { return new PageBreakingLayoutListener() { - public void notifyOverflow(int part, FObj obj) { + public void notifyOverflow(int part, int amount, FObj obj) { Page p = pageProvider.getPage( false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST); RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion( Region.FO_REGION_BODY); - String err = FONode.decorateWithContextInfo( - "Content of the region-body on page " - + p.getPageViewport().getPageNumberString() - + " overflows the available area in block-progression dimension.", - obj); - if (body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW) { - throw new RuntimeException(err); - } else { - log.warn(err); - } + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + body.getUserAgent().getEventBroadcaster()); + + boolean canRecover = (body.getOverflow() != Constants.EN_ERROR_IF_OVERFLOW); + boolean needClip = (body.getOverflow() == Constants.EN_HIDDEN + || body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW); + eventProducer.regionOverflow(this, body.getName(), + p.getPageViewport().getPageNumberString(), + amount, needClip, canRecover, + body.getLocator()); } }; @@ -297,7 +294,7 @@ public class PageBreaker extends AbstractBreaker { //Restart last page PageBreakingAlgorithm algRestart = new PageBreakingAlgorithm( getTopLevelLM(), - getPageProvider(), getLayoutListener(), + getPageProvider(), createLayoutListener(), alg.getAlignment(), alg.getAlignmentLast(), footnoteSeparatorLength, isPartOverflowRecoveryActivated(), false, false); @@ -356,7 +353,7 @@ public class PageBreaker extends AbstractBreaker { //Restart last page PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm( getTopLevelLM(), - getPageProvider(), getLayoutListener(), + getPageProvider(), createLayoutListener(), alignment, Constants.EN_START, footnoteSeparatorLength, isPartOverflowRecoveryActivated(), pslm.getCurrentPV().getBodyRegion().getColumnCount()); diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index d98d29b5c..5e3d0a887 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -27,7 +27,6 @@ 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.FObj; import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition; import org.apache.fop.traits.MinOptMax; @@ -289,7 +288,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { private void resetFootnotes(LinkedList elementLists) { for (int i = 0; i < elementLists.size(); i++) { - LinkedList removedList = (LinkedList) footnotesList.remove(footnotesList.size() - 1); + /*LinkedList removedList = (LinkedList)*/footnotesList.remove(footnotesList.size() - 1); lengthList.remove(lengthList.size() - 1); // update totalFootnotesLength @@ -332,11 +331,13 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { actualWidth += allFootnotes; insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes; footnoteListIndex = footnotesList.size() - 1; - footnoteElementIndex = ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1; - } else if (((canDeferOldFootnotes = checkCanDeferOldFootnotes(pageNode, elementIndex)) + footnoteElementIndex + = ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1; + } else if (((canDeferOldFootnotes + = checkCanDeferOldFootnotes(pageNode, elementIndex)) || newFootnotes) - && (footnoteSplit = getFootnoteSplit(pageNode, getLineWidth() - actualWidth, - canDeferOldFootnotes)) > 0) { + && (footnoteSplit = getFootnoteSplit(pageNode, + getLineWidth() - actualWidth, canDeferOldFootnotes)) > 0) { // it is allowed to break or even defer footnotes if either: // - there are new footnotes in the last piece of content, and // there is space to add at least a piece of the first one @@ -356,7 +357,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { actualWidth += allFootnotes; insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes; footnoteListIndex = footnotesList.size() - 1; - footnoteElementIndex = ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1; + footnoteElementIndex + = ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1; } } else { // all footnotes have already been placed on previous pages @@ -381,7 +383,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { */ private boolean checkCanDeferOldFootnotes(KnuthPageNode node, int contentElementIndex) { return (noBreakBetween(node.position, contentElementIndex) - && deferredFootnotes(node.footnoteListIndex, node.footnoteElementIndex, node.totalFootnotes)); + && deferredFootnotes(node.footnoteListIndex, + node.footnoteElementIndex, node.totalFootnotes)); } /** @@ -455,7 +458,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { * @param availableLength available space for footnotes * @param canDeferOldFootnotes */ - private int getFootnoteSplit(KnuthPageNode activeNode, int availableLength, boolean canDeferOldFootnotes) { + private int getFootnoteSplit(KnuthPageNode activeNode, int availableLength, + boolean canDeferOldFootnotes) { return getFootnoteSplit(activeNode.footnoteListIndex, activeNode.footnoteElementIndex, activeNode.totalFootnotes, @@ -520,7 +524,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { } // try adding a split of the next note - noteListIterator = ((LinkedList) footnotesList.get(listIndex)).listIterator(elementIndex); + noteListIterator = ((LinkedList) footnotesList.get(listIndex)) + .listIterator(elementIndex); int prevSplitLength = 0; int prevIndex = -1; @@ -754,14 +759,6 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { } } - private int getPartCount() { - if (pageBreaks == null) { - return 0; - } else { - return pageBreaks.size(); - } - } - public void updateData1(int total, double demerits) { } @@ -774,12 +771,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { if (difference + bestActiveNode.availableShrink < 0) { if (!autoHeight) { if (layoutListener != null) { - layoutListener.notifyOverflow(bestActiveNode.line - 1, getFObj()); - } else if (log.isWarnEnabled()) { - log.warn(FONode.decorateWithContextInfo( - "Part/page " + (bestActiveNode.line - 1) - + " overflows the available area in block-progression dimension.", - getFObj())); + layoutListener.notifyOverflow(bestActiveNode.line - 1, -difference, getFObj()); } } } @@ -890,9 +882,10 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { /** * Issued when an overflow is detected * @param part the number of the part (page) this happens on + * @param amount the amount by which the area overflows (in mpt) * @param obj the root FO object where this happens */ - void notifyOverflow(int part, FObj obj); + void notifyOverflow(int part, int amount, FObj obj); } diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java index e16c3396a..037f02094 100644 --- a/src/java/org/apache/fop/layoutmgr/PageProvider.java +++ b/src/java/org/apache/fop/layoutmgr/PageProvider.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.fo.Constants; @@ -74,6 +75,7 @@ public class PageProvider implements Constants { /** * Main constructor. + * @param ath the area tree handler * @param ps The page-sequence the provider operates on */ public PageProvider(AreaTreeHandler ath, PageSequence ps) { @@ -258,10 +260,10 @@ public class PageProvider implements Constants { if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) { // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to // any region), but we don't support it yet. - throw new FOPException("Flow '" + pageSeq.getMainFlow().getFlowName() - + "' does not map to the region-body in page-master '" - + spm.getMasterName() + "'. FOP presently " - + "does not support this."); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + pageSeq.getUserAgent().getEventBroadcaster()); + eventProducer.flowNotMappingToRegionBody(this, + pageSeq.getMainFlow().getFlowName(), spm.getMasterName(), spm.getLocator()); } Page page = new Page(spm, index, pageNumberString, isBlank); //Set unique key obtained from the AreaTreeHandler diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index b1e414527..763ddf58d 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -29,10 +29,12 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.RegionReference; -import org.apache.fop.fo.FONode; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FObj; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.SideRegion; import org.apache.fop.fo.pagination.StaticContent; +import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener; import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; import org.apache.fop.layoutmgr.inline.TextLayoutManager; import org.apache.fop.traits.MinOptMax; @@ -240,12 +242,17 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { breaker.doLayout(targetBPD, autoHeight); if (breaker.isOverflow()) { if (!autoHeight) { - //Overflow handling - if (regionFO.getOverflow() == EN_ERROR_IF_OVERFLOW) { - //TODO throw layout exception - } - log.warn(FONode.decorateWithContextInfo( - "static-content overflows the available area.", fobj)); + String page = getPSLM().getCurrentPage().getPageViewport().getPageNumberString(); + + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getStaticContentFO().getUserAgent().getEventBroadcaster()); + boolean canRecover = (regionFO.getOverflow() != EN_ERROR_IF_OVERFLOW); + boolean needClip = (regionFO.getOverflow() == Constants.EN_HIDDEN + || regionFO.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW); + eventProducer.regionOverflow(this, regionFO.getName(), + page, + breaker.getOverflowAmount(), needClip, canRecover, + getStaticContentFO().getLocator()); } } } @@ -262,7 +269,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { private StaticContentLayoutManager lm; private int displayAlign; private int ipd; - private boolean overflow = false; + private int overflow = 0; public StaticContentBreaker(StaticContentLayoutManager lm, int ipd, int displayAlign) { @@ -288,9 +295,26 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } public boolean isOverflow() { + return (this.overflow != 0); + } + + public int getOverflowAmount() { return this.overflow; } + /** {@inheritDoc} */ + protected PageBreakingLayoutListener createLayoutListener() { + return new PageBreakingLayoutListener() { + + public void notifyOverflow(int part, int amount, FObj obj) { + if (StaticContentBreaker.this.overflow == 0) { + StaticContentBreaker.this.overflow = amount; + } + } + + }; + } + protected LayoutManager getTopLevelLM() { return lm; } @@ -340,9 +364,6 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { protected void doPhase3(PageBreakingAlgorithm alg, int partCount, BlockSequence originalList, BlockSequence effectiveList) { - if (partCount > 1) { - overflow = true; - } //Rendering all parts (not just the first) at once for the case where the parts that //overflow should be visible. alg.removeAllPageBreaks(); diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index ff7c5b3ce..2af844c5c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -60,7 +60,6 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager */ private static Log log = LogFactory.getLog(ContentLayoutManager.class); - private FOUserAgent userAgent; private Area holder; private int stackSize; private LayoutManager parentLM; diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLevelEventProducer.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLevelEventProducer.java new file mode 100644 index 000000000..51d2720cb --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLevelEventProducer.java @@ -0,0 +1,66 @@ +/* + * 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.layoutmgr.inline; + +import org.xml.sax.Locator; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; + +/** + * Event producer interface for inline-level layout managers. + */ +public interface InlineLevelEventProducer extends EventProducer { + + /** + * Provider class for the event producer. + */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static InlineLevelEventProducer get(EventBroadcaster broadcaster) { + return (InlineLevelEventProducer)broadcaster.getEventProducerFor( + InlineLevelEventProducer.class); + } + } + + /** + * fo:leader with "use-content" but without children. + * @param source the event source + * @param loc the location of the error or null + * @event.severity ERROR + */ + void leaderWithoutContent(Object source, Locator loc); + + /** + * A line overflows. + * @param source the event source + * @param line the number number + * @param overflowLength the length by which the content overflows the available space (in mpt) + * @param loc the location of the error or null + * @event.severity WARN + */ + void lineOverflows(Object source, int line, int overflowLength, Locator loc); + +} diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index f4bcde96f..1e7c793df 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -19,11 +19,15 @@ package org.apache.fop.layoutmgr.inline; +import java.util.LinkedList; +import java.util.List; + import org.apache.fop.area.Trait; import org.apache.fop.area.inline.FilledArea; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.TextArea; +import org.apache.fop.fo.FObj; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; @@ -41,10 +45,6 @@ import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.MinOptMax; -import java.util.List; -import java.util.LinkedList; -import org.apache.fop.fo.FObj; - /** * LayoutManager for the fo:leader formatting object */ @@ -159,7 +159,9 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { leaderArea = fa; } else if (fobj.getLeaderPattern() == EN_USECONTENT) { if (fobj.getChildNodes() == null) { - fobj.getLogger().error("Leader use-content with no content"); + InlineLevelEventProducer eventProducer = InlineLevelEventProducer.Provider.get( + getFObj().getUserAgent().getEventBroadcaster()); + eventProducer.leaderWithoutContent(this, getFObj().getLocator()); return null; } @@ -339,9 +341,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { return returnList; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getBaseLength(int lengthBase, FObj fobj) { return getParent().getBaseLength(lengthBase, getParent().getFObj()); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 9a818232c..1258fbe18 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -34,7 +34,6 @@ import org.apache.fop.area.inline.InlineArea; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.Constants; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.properties.CommonHyphenation; import org.apache.fop.fonts.Font; @@ -384,11 +383,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager if (log.isWarnEnabled()) { int lack = difference + bestActiveNode.availableShrink; if (lack < 0) { + InlineLevelEventProducer eventProducer + = InlineLevelEventProducer.Provider.get( + getFObj().getUserAgent().getEventBroadcaster()); + eventProducer.lineOverflows(this, addedPositions + 1, + -lack, getFObj().getLocator()); String textDiff = (lack < -50000 ? "more than 50 points" : (-lack) + "mpt"); - log.warn(FONode.decorateWithContextInfo( - "Line " + (addedPositions + 1) - + " of a paragraph overflows the available area by " - + textDiff + ".", getFObj())); } } @@ -1430,7 +1430,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager auxCount++; } } - log.trace(" Word to hyphenate: " + sbChars.toString()); + if (log.isTraceEnabled()) { + log.trace(" Word to hyphenate: " + sbChars.toString()); + } // find hyphenation points HyphContext hc = getHyphenContext(sbChars); // ask each LM to hyphenate its word fragment diff --git a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java index 2ef2be908..bd032e610 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java +++ b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java @@ -25,9 +25,9 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.datatypes.PercentBaseContext; -import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableColumn; @@ -77,12 +77,14 @@ public class ColumnSetup { } } //Post-processing the list (looking for gaps) + //TODO The following block could possibly be removed int pos = 1; ListIterator ppIter = columns.listIterator(); while (ppIter.hasNext()) { TableColumn col = (TableColumn)ppIter.next(); if (col == null) { - log.error("Found a gap in the table-columns at position " + pos); + assert false; //Gaps are filled earlier by fo.flow.table.Table.finalizeColumns() + //log.error("Found a gap in the table-columns at position " + pos); } pos++; } @@ -100,7 +102,9 @@ public class ColumnSetup { if (index > size) { if (index > maxColIndexReferenced) { maxColIndexReferenced = index; - if (!(size == 1 && getColumn(1).isImplicitColumn())) { + TableColumn col = getColumn(1); + if (!(size == 1 && col.isImplicitColumn())) { + assert false; //TODO Seems to be removable as this is now done in the FO tree log.warn(FONode.decorateWithContextInfo( "There are fewer table-columns than are needed. " + "Column " + index + " was accessed, but only " @@ -193,8 +197,7 @@ public class ColumnSetup { if (colWidth != null) { sumCols += colWidth.getValue(tlm); if (colWidth instanceof TableColLength) { - factors += - ((TableColLength) colWidth).getTableUnits(); + factors += ((TableColLength) colWidth).getTableUnits(); } } } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 9c97ca827..72e78b84f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -24,6 +24,7 @@ import java.util.LinkedList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; @@ -32,6 +33,7 @@ import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; +import org.apache.fop.layoutmgr.BlockLevelEventProducer; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.MinOptMaxUtil; @@ -193,7 +195,9 @@ class RowGroupLayoutManager { row.setHeight(rowHeights[rgi]); row.setExplicitHeight(explicitRowHeight); // TODO re-enable and improve after clarification + //See http://markmail.org/message/h25ycwwu7qglr4k4 // if (maxCellBPD > row.getExplicitHeight().max) { +//old: // log.warn(FONode.decorateWithContextInfo( // "The contents of row " + (row.getIndex() + 1) // + " are taller than they should be (there is a" @@ -203,10 +207,12 @@ class RowGroupLayoutManager { // + " to " + maxCellBPD + " millipoints, but the row shouldn't get" // + " any taller than " + row.getExplicitHeight() + " millipoints.", // row.getTableRow())); +//new (with events): +// BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Factory.create( +// tableRow.getUserAgent().getEventBroadcaster()); +// eventProducer.rowTooTall(this, row.getIndex() + 1, +// maxCellBPD, row.getExplicitHeight().max, tableRow.getLocator()); // } - if (log.isDebugEnabled()) { - log.debug(" height=" + rowHeights[rgi] + " explicit=" + explicitRowHeight); - } } } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index d6bba5cb5..720ca5faa 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -26,6 +26,7 @@ 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; @@ -34,6 +35,7 @@ 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.BlockLevelEventProducer; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ConditionalElementListener; @@ -189,9 +191,9 @@ public class TableLayoutManager extends BlockStackingLayoutManager updateContentAreaIPDwithOverconstrainedAdjust(contentIPD); } else { if (!getTable().isAutoLayout()) { - log.info("table-layout=\"fixed\" and width=\"auto\", " - + "but auto-layout not supported " - + "=> assuming width=\"100%\""); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getTable().getUserAgent().getEventBroadcaster()); + eventProducer.tableFixedAutoWidthNotSupported(this, getTable().getLocator()); } updateContentAreaIPDwithOverconstrainedAdjust(); } @@ -204,11 +206,11 @@ public class TableLayoutManager extends BlockStackingLayoutManager } int availableIPD = referenceIPD - getIPIndents(); if (getContentAreaIPD() > availableIPD) { - log.warn(FONode.decorateWithContextInfo( - "The extent in inline-progression-direction (width) of a table is" - + " bigger than the available space (" - + getContentAreaIPD() + "mpt > " + context.getRefIPD() + "mpt)", - getTable())); + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getTable().getUserAgent().getEventBroadcaster()); + eventProducer.objectTooWide(this, getTable().getName(), + getContentAreaIPD(), context.getRefIPD(), + getTable().getLocator()); } /* initialize unit to determine computed values diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index f74699fd5..2c47875d9 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -30,12 +30,14 @@ import org.w3c.dom.Document; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; +import org.apache.batik.dom.AbstractDocument; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.apache.fop.render.RendererContext.RendererContextWrapper; +import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; /** @@ -46,9 +48,6 @@ import org.apache.fop.svg.SVGUserAgent; */ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererContextConstants { - /** logging instance */ - private static Log log = LogFactory.getLog(AbstractGenericSVGHandler.class); - /** {@inheritDoc} */ public void handleXML(RendererContext context, Document doc, String ns) throws Exception { @@ -73,7 +72,7 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC //Prepare SVGUserAgent ua = new SVGUserAgent( - context.getUserAgent().getSourcePixelUnitToMillimeter(), + context.getUserAgent(), new AffineTransform()); GVTBuilder builder = new GVTBuilder(); final BridgeContext ctx = new BridgeContext(ua); @@ -83,7 +82,9 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC try { root = builder.build(ctx, doc); } catch (Exception e) { - log.error("SVG graphic could not be built: " + e.getMessage(), e); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgNotBuilt(this, e, getDocumentURI(doc)); return; } @@ -114,6 +115,20 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC x, y, wrappedContext.getWidth(), wrappedContext.getHeight()); } + /** + * Gets the document URI from a Document instance if possible. + * @param doc the Document + * @return the URI or null + */ + protected String getDocumentURI(Document doc) { + String docURI = null; + if (doc instanceof AbstractDocument) { + AbstractDocument level3Doc = (AbstractDocument)doc; + docURI = level3Doc.getDocumentURI(); + } + return docURI; + } + /** * Override this method to update the renderer context if it needs special settings for * certain conditions. diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 9e13476f6..b38d973c5 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -31,6 +31,7 @@ import org.w3c.dom.Document; import org.apache.batik.parser.AWTTransformProducer; import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.util.QName; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -45,7 +46,6 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.FontMetrics; import org.apache.fop.traits.BorderProps; -import org.apache.fop.util.QName; /** * Abstract base class for renderers like PDF and PostScript where many painting operations diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 32c4b33c4..ca3d007d0 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -67,6 +67,7 @@ import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.Viewport; import org.apache.fop.area.inline.WordArea; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; @@ -113,21 +114,15 @@ public abstract class AbstractRenderer private Set warnedXMLHandlers; - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public abstract void setupFontInfo(FontInfo fontInfo); - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void setUserAgent(FOUserAgent agent) { userAgent = agent; } - /** - * @return the associated FOUserAgent - */ + /** {@inheritDoc} */ public FOUserAgent getUserAgent() { return userAgent; } @@ -797,10 +792,11 @@ public abstract class AbstractRenderer = new XMLHandlerConfigurator(userAgent); configurator.configure(ctx, namespace); handler.handleXML(ctx, doc, namespace); - } catch (Throwable t) { + } catch (Exception e) { // could not handle document - log.error("Some XML content will be ignored. " - + "Could not render XML", t); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + ctx.getUserAgent().getEventBroadcaster()); + eventProducer.foreignXMLProcessingError(this, doc, namespace, e); } } else { if (warnedXMLHandlers == null) { @@ -809,8 +805,9 @@ public abstract class AbstractRenderer if (!warnedXMLHandlers.contains(namespace)) { // no handler found for document warnedXMLHandlers.add(namespace); - log.warn("Some XML content will be ignored. " - + "No handler defined for XML: " + namespace); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + ctx.getUserAgent().getEventBroadcaster()); + eventProducer.foreignXMLNoHandler(this, doc, namespace); } } } diff --git a/src/java/org/apache/fop/render/Renderer.java b/src/java/org/apache/fop/render/Renderer.java index b40eec0cf..03b4582f7 100644 --- a/src/java/org/apache/fop/render/Renderer.java +++ b/src/java/org/apache/fop/render/Renderer.java @@ -88,6 +88,12 @@ public interface Renderer { */ void setUserAgent(FOUserAgent agent); + /** + * Returns the associated user agent. + * @return the user agent + */ + FOUserAgent getUserAgent(); + /** * Set up the given FontInfo. * diff --git a/src/java/org/apache/fop/render/RendererEventProducer.java b/src/java/org/apache/fop/render/RendererEventProducer.java new file mode 100644 index 000000000..365c8f430 --- /dev/null +++ b/src/java/org/apache/fop/render/RendererEventProducer.java @@ -0,0 +1,53 @@ +/* + * 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.render; + +import java.io.IOException; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; + +/** + * Event producer interface for rendering-specific events. + */ +public interface RendererEventProducer extends EventProducer { + + /** Provider class for the event producer. */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static RendererEventProducer get(EventBroadcaster broadcaster) { + return (RendererEventProducer)broadcaster.getEventProducerFor( + RendererEventProducer.class); + } + } + + /** + * I/O error while writing target file. + * @param source the event source + * @param ioe the original I/O error + * @event.severity ERROR + */ + void ioError(Object source, IOException ioe); +} diff --git a/src/java/org/apache/fop/render/afp/AFPEventProducer.java b/src/java/org/apache/fop/render/afp/AFPEventProducer.java new file mode 100644 index 000000000..615c54c32 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPEventProducer.java @@ -0,0 +1,63 @@ +/* + * 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.render.afp; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; + +/** + * Event producer interface for AFP-specific events. + */ +public interface AFPEventProducer extends EventProducer { + + /** Provider class for the event producer. */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static AFPEventProducer get(EventBroadcaster broadcaster) { + return (AFPEventProducer)broadcaster.getEventProducerFor( + AFPEventProducer.class); + } + } + + /** Event model factory for AFP. */ + public static class EventModelFactory extends AbstractEventModelFactory { + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), "event-model.xml"); + } + + } + + /** + * Warn about using default font setup. + * @param source the event source + * @event.severity WARN + */ + void warnDefaultFontSetup(Object source); + +} diff --git a/src/java/org/apache/fop/render/afp/AFPEventProducer.xml b/src/java/org/apache/fop/render/afp/AFPEventProducer.xml new file mode 100644 index 000000000..8eec9b656 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPEventProducer.xml @@ -0,0 +1,4 @@ + + + No AFP fonts configured. Using default setup. + diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 205873493..83b8048f9 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -70,6 +70,7 @@ import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; import org.apache.fop.datatypes.URISpecification; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.FontInfo; @@ -291,7 +292,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } } else { - log.warn("No AFP fonts configured - using default setup"); + AFPEventProducer eventProducer = AFPEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.warnDefaultFontSetup(this); } if (this.fontInfo.fontLookup("sans-serif", "normal", 400) == null) { CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZH200 ", @@ -909,7 +912,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { RendererContext context; context = super.createRendererContext(x, y, width, height, foreignAttributes); context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, - new Boolean(!this.colorImages)); + Boolean.valueOf(!this.colorImages)); return context; } @@ -1014,13 +1017,17 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } catch (ImageException ie) { - log.error("Error while processing image: " - + (info != null ? info.toString() : uri), ie); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); } catch (FileNotFoundException fe) { - log.error(fe.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null); } catch (IOException ioe) { - log.error("I/O error while processing image: " - + (info != null ? info.toString() : uri), ioe); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); } /* @@ -1195,7 +1202,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { image.getWidth(), image.getHeight(), this.bitsPerPixel); } } catch (IOException ioe) { - log.error("Error while serializing bitmap: " + ioe.getMessage(), ioe); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageWritingError(this, ioe); } } @@ -1305,8 +1314,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } catch (Throwable ex) { encoding = AFPConstants.EBCIDIC_ENCODING; log.warn( - "renderText():: Error getting encoding for font " - + " - using default encoding " + "renderText():: Error getting encoding for font '" + + tf.getFullName() + + "' - using default encoding " + encoding); } diff --git a/src/java/org/apache/fop/render/bitmap/BitmapRendererEventProducer.java b/src/java/org/apache/fop/render/bitmap/BitmapRendererEventProducer.java new file mode 100644 index 000000000..7b26d0771 --- /dev/null +++ b/src/java/org/apache/fop/render/bitmap/BitmapRendererEventProducer.java @@ -0,0 +1,80 @@ +/* + * 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.render.bitmap; + +import java.io.IOException; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; + +/** + * Event producer interface for events generated by the bitmap renderers. + */ +public interface BitmapRendererEventProducer extends EventProducer { + + /** Provider class for the event producer. */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static BitmapRendererEventProducer get(EventBroadcaster broadcaster) { + return (BitmapRendererEventProducer)broadcaster.getEventProducerFor( + BitmapRendererEventProducer.class); + } + } + + /** Event model factory for this event producer. */ + public static class EventModelFactory extends AbstractEventModelFactory { + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), "event-model.xml"); + } + + } + + /** + * No filename information available. Stopping early after the first page. + * @param source the event source + * @event.severity WARN + */ + void stoppingAfterFirstPageNoFilename(Object source); + + /** + * Image writer does not support multiple images. Only the first page has been produced. + * @param source the event source + * @event.severity WARN + */ + void stoppingAfterFirstPageNoMultiWriter(Object source); + + /** + * No ImageWriter found. + * @param source the event source + * @param mime the target MIME type + * @throws IOException the I/O error provoked by the method call + * @event.severity FATAL + */ + void noImageWriterFound(Object source, String mime) throws IOException; +} diff --git a/src/java/org/apache/fop/render/bitmap/BitmapRendererEventProducer.xml b/src/java/org/apache/fop/render/bitmap/BitmapRendererEventProducer.xml new file mode 100644 index 000000000..a05af3e21 --- /dev/null +++ b/src/java/org/apache/fop/render/bitmap/BitmapRendererEventProducer.xml @@ -0,0 +1,6 @@ + + + No filename information available. Stopping early after the first page. + Image writer does not support multiple images. Only the first page has been produced. + Could not get an ImageWriter to produce "{mime}". The most likely explanation for this is a class loading problem. + diff --git a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java index bedd2c499..8613ef7b8 100644 --- a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java +++ b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java @@ -23,12 +23,12 @@ import java.awt.image.RenderedImage; import java.io.IOException; import java.io.OutputStream; +import org.apache.commons.io.IOUtils; + import org.apache.xmlgraphics.image.writer.ImageWriter; import org.apache.xmlgraphics.image.writer.ImageWriterParams; import org.apache.xmlgraphics.image.writer.ImageWriterRegistry; -import org.apache.commons.io.IOUtils; - import org.apache.fop.apps.MimeConstants; import org.apache.fop.area.PageViewport; import org.apache.fop.render.java2d.Java2DRenderer; @@ -74,8 +74,10 @@ public class PNGRenderer extends Java2DRenderer { OutputStream os = getCurrentOutputStream(i); if (os == null) { - log.warn("No filename information available." - + " Stopping early after the first page."); + BitmapRendererEventProducer eventProducer + = BitmapRendererEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.stoppingAfterFirstPageNoFilename(this); break; } try { @@ -104,9 +106,10 @@ public class PNGRenderer extends Java2DRenderer { // Encode PNG image ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor(getMimeType()); if (writer == null) { - throw new IOException("Could not get an ImageWriter to produce " - + getMimeType() + ". The most likely explanation for this is a class" - + " loading problem."); + BitmapRendererEventProducer eventProducer + = BitmapRendererEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noImageWriterFound(this, getMimeType()); } if (log.isDebugEnabled()) { log.debug("Writing image using " + writer.getClass().getName()); diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java index 4f64e45e1..9291427d2 100644 --- a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java +++ b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java @@ -129,7 +129,10 @@ public class TIFFRenderer extends Java2DRenderer { // Creates writer ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor(getMimeType()); if (writer == null) { - throw new NullPointerException("No ImageWriter for " + getMimeType() + " available!"); + BitmapRendererEventProducer eventProducer + = BitmapRendererEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noImageWriterFound(this, getMimeType()); } if (writer.supportsMultiImageWriter()) { MultiImageWriter multiWriter = writer.createMultiImageWriter(outputStream); @@ -145,8 +148,10 @@ public class TIFFRenderer extends Java2DRenderer { } else { writer.writeImage((RenderedImage) pageImagesItr.next(), outputStream, writerParams); if (pageImagesItr.hasNext()) { - log.error("Image encoder does not support multiple images. Only the first page" - + " has been produced."); + BitmapRendererEventProducer eventProducer + = BitmapRendererEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.stoppingAfterFirstPageNoFilename(this); } } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 583d2ad2f..0ffe3307a 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -66,6 +66,7 @@ import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; import org.apache.fop.datatypes.URISpecification; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; @@ -930,13 +931,17 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem pos, foreignAttributes); } } catch (ImageException ie) { - log.error("Error while processing image: " - + (info != null ? info.toString() : uri), ie); - } catch (FileNotFoundException fnfe) { - log.error(fnfe.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); + } catch (FileNotFoundException fe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null); } catch (IOException ioe) { - log.error("I/O error while processing image: " - + (info != null ? info.toString() : uri), ioe); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); } } diff --git a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java index 51b458cfe..64ac823fc 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java +++ b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java @@ -23,26 +23,25 @@ import java.awt.geom.AffineTransform; import org.w3c.dom.Document; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.XMLHandler; -import org.apache.fop.render.RendererContext; -import org.apache.fop.svg.SVGUserAgent; - -// Commons-Logging +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.GVTBuilder; +import org.apache.batik.gvt.GraphicsNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.batik.bridge.GVTBuilder; -import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.dom.svg.SVGDOMImplementation; -import org.apache.batik.gvt.GraphicsNode; +import org.apache.fop.render.AbstractGenericSVGHandler; +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererContext; +import org.apache.fop.svg.SVGEventProducer; +import org.apache.fop.svg.SVGUserAgent; /** * Java2D XML handler for SVG (uses Apache Batik). * This handler handles XML for foreign objects when rendering to Java2D. * The properties from the Java2D renderer are subject to change. */ -public class Java2DSVGHandler implements XMLHandler, Java2DRendererContextConstants { +public class Java2DSVGHandler extends AbstractGenericSVGHandler + implements Java2DRendererContextConstants { /** logging instance */ private static Log log = LogFactory.getLog(Java2DSVGHandler.class); @@ -54,16 +53,6 @@ public class Java2DSVGHandler implements XMLHandler, Java2DRendererContextConsta //nop } - /** {@inheritDoc} */ - public void handleXML(RendererContext context, - Document doc, String ns) throws Exception { - Java2DInfo pdfi = getJava2DInfo(context); - - if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) { - renderSVGDocument(context, doc, pdfi); - } - } - /** * Get the pdf information from the render context. * @@ -106,23 +95,18 @@ public class Java2DSVGHandler implements XMLHandler, Java2DRendererContextConsta } } - /** - * Render the svg document. - * @param context the renderer context - * @param doc the svg document - * @param info the pdf information of the current context - */ + /** {@inheritDoc} */ protected void renderSVGDocument(RendererContext context, - Document doc, - Java2DInfo info) { + Document doc) { + Java2DInfo info = getJava2DInfo(context); + if (log.isDebugEnabled()) { + log.debug("renderSVGDocument(" + context + ", " + doc + ", " + info + ")"); + } - log.debug("renderSVGDocument(" + context + ", " + doc + ", " + info + ")"); - int x = info.currentXPosition; int y = info.currentYPosition; - float ptom = context.getUserAgent().getSourcePixelUnitToMillimeter(); - SVGUserAgent ua = new SVGUserAgent(ptom, new AffineTransform()); + SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), new AffineTransform()); GVTBuilder builder = new GVTBuilder(); BridgeContext ctx = new BridgeContext(ua); @@ -131,7 +115,9 @@ public class Java2DSVGHandler implements XMLHandler, Java2DRendererContextConsta try { root = builder.build(ctx, doc); } catch (Exception e) { - log.error("SVG graphic could not be built: " + e.getMessage(), e); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgNotBuilt(this, e, getDocumentURI(doc)); return; } @@ -158,7 +144,9 @@ public class Java2DSVGHandler implements XMLHandler, Java2DRendererContextConsta try { root.paint(info.state.getGraph()); } catch (Exception e) { - log.error("Error while painting SVG", e); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgRenderingError(this, e, getDocumentURI(doc)); } info.state.getGraph().setTransform(origTransform); @@ -169,9 +157,4 @@ public class Java2DSVGHandler implements XMLHandler, Java2DRendererContextConsta return (renderer instanceof Java2DRenderer); } - - /** {@inheritDoc} */ - public String getNamespace() { - return SVGDOMImplementation.SVG_NAMESPACE_URI; - } } diff --git a/src/java/org/apache/fop/render/pcl/PCLEventProducer.java b/src/java/org/apache/fop/render/pcl/PCLEventProducer.java new file mode 100644 index 000000000..3e72de293 --- /dev/null +++ b/src/java/org/apache/fop/render/pcl/PCLEventProducer.java @@ -0,0 +1,66 @@ +/* + * 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.render.pcl; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; + +/** + * Event producer interface for events generated by the PCL renderer. + */ +public interface PCLEventProducer extends EventProducer { + + /** Provider class for the event producer. */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static PCLEventProducer get(EventBroadcaster broadcaster) { + return (PCLEventProducer)broadcaster.getEventProducerFor( + PCLEventProducer.class); + } + } + + /** Event model factory for this event producer. */ + public static class EventModelFactory extends AbstractEventModelFactory { + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), "event-model.xml"); + } + + } + + /** + * Paper type could not be determined. Falling back to another. + * @param source the event source + * @param pageWidth the page width (in millipoints) + * @param pageHeight the page height (in millipoints) + * @param fallbackPaper the paper type that will be used instead + * @event.severity WARN + */ + void paperTypeUnavailable(Object source, long pageWidth, long pageHeight, String fallbackPaper); + +} diff --git a/src/java/org/apache/fop/render/pcl/PCLEventProducer.xml b/src/java/org/apache/fop/render/pcl/PCLEventProducer.xml new file mode 100644 index 000000000..a3b36fd60 --- /dev/null +++ b/src/java/org/apache/fop/render/pcl/PCLEventProducer.xml @@ -0,0 +1,4 @@ + + + Paper type ({pageWidth} x {pageHeight} mpt) could not be determined. Falling back to: {fallbackPaper} + diff --git a/src/java/org/apache/fop/render/pcl/PCLGenerator.java b/src/java/org/apache/fop/render/pcl/PCLGenerator.java index 3eb8ec425..5ca9a8bf9 100644 --- a/src/java/org/apache/fop/render/pcl/PCLGenerator.java +++ b/src/java/org/apache/fop/render/pcl/PCLGenerator.java @@ -43,9 +43,11 @@ import java.text.DecimalFormatSymbols; import java.util.Locale; import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.fop.util.UnitConv; + import org.apache.xmlgraphics.image.GraphicsUtil; +import org.apache.fop.util.UnitConv; + /** * This class provides methods for generating PCL print files. */ @@ -355,16 +357,16 @@ public class PCLGenerator { if (usePCLShades || Color.black.equals(col) || Color.white.equals(col)) { - writeCommand("*c" + formatDouble4(w / 100) + "h" - + formatDouble4(h / 100) + "V"); + writeCommand("*c" + formatDouble4(w / 100.0) + "h" + + formatDouble4(h / 100.0) + "V"); int lineshade = convertToPCLShade(col); writeCommand("*c" + lineshade + "G"); writeCommand("*c2P"); //Shaded fill } else { defineGrayscalePattern(col, 32, DITHER_MATRIX_4X4); - writeCommand("*c" + formatDouble4(w / 100) + "h" - + formatDouble4(h / 100) + "V"); + writeCommand("*c" + formatDouble4(w / 100.0) + "h" + + formatDouble4(h / 100.0) + "V"); writeCommand("*c32G"); writeCommand("*c4P"); //User-defined pattern } diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 1d606e919..b89fba9c1 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -58,6 +58,7 @@ import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.java2d.GraphicContext; import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.xmlgraphics.util.QName; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.MimeConstants; @@ -77,6 +78,7 @@ import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.Viewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.datatypes.URISpecification; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; @@ -85,12 +87,12 @@ import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.PrintRenderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; +import org.apache.fop.render.RendererEventProducer; import org.apache.fop.render.java2d.FontMetricsMapper; import org.apache.fop.render.java2d.FontSetup; import org.apache.fop.render.java2d.Java2DRenderer; import org.apache.fop.render.pcl.extensions.PCLElementMapping; import org.apache.fop.traits.BorderProps; -import org.apache.fop.util.QName; import org.apache.fop.util.UnitConv; /* Note: @@ -208,7 +210,9 @@ public class PCLRenderer extends PrintRenderer { */ protected void handleIOTrouble(IOException ioe) { if (!ioTrouble) { - log.error("Error while writing to target file", ioe); + RendererEventProducer eventProducer = RendererEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.ioError(this, ioe); ioTrouble = true; } } @@ -417,11 +421,15 @@ public class PCLRenderer extends PrintRenderer { if (this.currentPageDefinition == null) { this.currentPageDefinition = PCLPageDefinition.getDefaultPageDefinition(); - log.warn("Paper type could not be determined. Falling back to: " - + this.currentPageDefinition.getName()); + PCLEventProducer eventProducer = PCLEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.paperTypeUnavailable(this, pagewidth, pageheight, + this.currentPageDefinition.getName()); + } + if (log.isDebugEnabled()) { + log.debug("page size: " + currentPageDefinition.getPhysicalPageSize()); + log.debug("logical page: " + currentPageDefinition.getLogicalPageRect()); } - log.debug("page size: " + currentPageDefinition.getPhysicalPageSize()); - log.debug("logical page: " + currentPageDefinition.getLogicalPageRect()); if (this.currentPageDefinition.isLandscapeFormat()) { gen.writeCommand("&l1O"); //Orientation } else { @@ -1107,12 +1115,17 @@ public class PCLRenderer extends PrintRenderer { } } catch (ImageException ie) { - log.error("Error while processing image: " - + (info != null ? info.toString() : uri), ie); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); } catch (FileNotFoundException fe) { - log.error(fe.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null); } catch (IOException ioe) { - handleIOTrouble(ioe); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); } } diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererContext.java b/src/java/org/apache/fop/render/pcl/PCLRendererContext.java index 62d4bcaa4..422b9d51d 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererContext.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererContext.java @@ -19,9 +19,10 @@ package org.apache.fop.render.pcl; +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.render.RendererContext; -import org.apache.fop.util.QName; /** * Wrapper on the RendererContext to access the information structure for drawing diff --git a/src/java/org/apache/fop/render/pdf/PDFEventProducer.java b/src/java/org/apache/fop/render/pdf/PDFEventProducer.java new file mode 100644 index 000000000..f8b1bbb33 --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/PDFEventProducer.java @@ -0,0 +1,64 @@ +/* + * 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.render.pdf; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; + +/** + * Event producer interface for events generated by the PDF renderer. + */ +public interface PDFEventProducer extends EventProducer { + + /** Provider class for the event producer. */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static PDFEventProducer get(EventBroadcaster broadcaster) { + return (PDFEventProducer)broadcaster.getEventProducerFor( + PDFEventProducer.class); + } + } + + /** Event model factory for this event producer. */ + public static class EventModelFactory extends AbstractEventModelFactory { + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), "event-model.xml"); + } + + } + + /** + * Some link targets haven't been fully resolved. + * @param source the event source + * @param count the number of unresolved links + * @event.severity WARN + */ + void nonFullyResolvedLinkTargets(Object source, int count); + +} diff --git a/src/java/org/apache/fop/render/pdf/PDFEventProducer.xml b/src/java/org/apache/fop/render/pdf/PDFEventProducer.xml new file mode 100644 index 000000000..fd57d5099 --- /dev/null +++ b/src/java/org/apache/fop/render/pdf/PDFEventProducer.xml @@ -0,0 +1,4 @@ + + + {count} link target{count,equals,1,,s} could not be fully resolved and now point{count,equals,1,,s} to the top of the page or {count,equals,1,is,are} dysfunctional. + diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 268791ac2..936bf4384 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -73,6 +73,7 @@ import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; import org.apache.fop.datatypes.URISpecification; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.extensions.xmp.XMPMetadata; @@ -490,13 +491,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { PDFGoTo gt = (PDFGoTo) unfinishedGoTos.get(0); finishIDGoTo(gt, defaultPos); } - boolean one = count == 1; - String pl = one ? "" : "s"; - String ww = one ? "was" : "were"; - String ia = one ? "is" : "are"; - log.warn("" + count + " link target" + pl + " could not be fully resolved and " - + ww + " now point to the top of the page or " - + ia + " dysfunctional."); // dysfunctional if pageref is null + PDFEventProducer eventProducer = PDFEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.nonFullyResolvedLinkTargets(this, count); + // dysfunctional if pageref is null } } @@ -555,16 +553,17 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { private void renderDestination(DestinationData dd) { String targetID = dd.getIDRef(); - if (targetID != null && targetID.length() > 0) { - PageViewport pv = dd.getPageViewport(); - if (pv == null) { - log.warn("Unresolved destination item received: " + dd.getIDRef()); - } + if (targetID == null || targetID.length() == 0) { + throw new IllegalArgumentException("DestinationData must contain a ID reference"); + } + PageViewport pv = dd.getPageViewport(); + if (pv != null) { PDFGoTo gt = getPDFGoToForID(targetID, pv.getKey()); pdfDoc.getFactory().makeDestination( dd.getIDRef(), gt.makeReference()); } else { - log.warn("DestinationData item with null or empty IDRef received."); + //Warning already issued by AreaTreeHandler (debug level is sufficient) + log.debug("Unresolved destination item received: " + dd.getIDRef()); } } @@ -584,22 +583,22 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { PDFOutline pdfOutline = null; String targetID = bookmarkItem.getIDRef(); - if (targetID != null && targetID.length() > 0) { - PageViewport pv = bookmarkItem.getPageViewport(); - if (pv != null) { - String pvKey = pv.getKey(); - PDFGoTo gt = getPDFGoToForID(targetID, pvKey); - // create outline object: - PDFOutline parent = parentBookmarkItem != null - ? parentBookmarkItem - : pdfDoc.getOutlineRoot(); - pdfOutline = pdfDoc.getFactory().makeOutline(parent, - bookmarkItem.getBookmarkTitle(), gt, bookmarkItem.showChildItems()); - } else { - log.warn("Bookmark with IDRef \"" + targetID + "\" has a null PageViewport."); - } + if (targetID == null || targetID.length() == 0) { + throw new IllegalArgumentException("DestinationData must contain a ID reference"); + } + PageViewport pv = bookmarkItem.getPageViewport(); + if (pv != null) { + String pvKey = pv.getKey(); + PDFGoTo gt = getPDFGoToForID(targetID, pvKey); + // create outline object: + PDFOutline parent = parentBookmarkItem != null + ? parentBookmarkItem + : pdfDoc.getOutlineRoot(); + pdfOutline = pdfDoc.getFactory().makeOutline(parent, + bookmarkItem.getBookmarkTitle(), gt, bookmarkItem.showChildItems()); } else { - log.warn("Bookmark item with null or empty IDRef received."); + //Warning already issued by AreaTreeHandler (debug level is sufficient) + log.debug("Bookmark with IDRef \"" + targetID + "\" has a null PageViewport."); } for (int i = 0; i < bookmarkItem.getCount(); i++) { @@ -1368,15 +1367,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { if (annotsAllowed) { action = getPDFGoToForID(idRef, pvKey); } - } else if (pvKeyOK) { - log.warn("Internal link trait with PageViewport key " + pvKey - + " contains no ID reference."); - } else if (idRefOK) { - log.warn("Internal link trait with ID reference " + idRef - + " contains no PageViewport key."); } else { - log.warn("Internal link trait received with neither PageViewport key" - + " nor ID reference."); + //Warnings already issued by AreaTreeHandler } } @@ -1671,7 +1663,9 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { x, y, posInt.width, posInt.height, foreignAttributes); handler.generateImage(context, img, origin, posInt); } catch (IOException ioe) { - log.error("I/O error while handling image: " + info, ioe); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageWritingError(this, ioe); return; } } else { @@ -1680,13 +1674,17 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { + info + " (" + img.getClass().getName() + ")"); } } catch (ImageException ie) { - log.error("Error while processing image: " - + (info != null ? info.toString() : uri), ie); - } catch (FileNotFoundException fnfe) { - log.error(fnfe.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); + } catch (FileNotFoundException fe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null); } catch (IOException ioe) { - log.error("I/O error while processing image: " - + (info != null ? info.toString() : uri), ioe); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); } // output new data @@ -1810,18 +1808,34 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { return MIME_TYPE; } + /** + * Sets the PDF/A mode for the PDF renderer. + * @param mode the PDF/A mode + */ public void setAMode(PDFAMode mode) { this.pdfAMode = mode; } + /** + * Sets the PDF/X mode for the PDF renderer. + * @param mode the PDF/X mode + */ public void setXMode(PDFXMode mode) { this.pdfXMode = mode; } + /** + * Sets the output color profile for the PDF renderer. + * @param outputProfileURI the URI to the output color profile + */ public void setOutputProfileURI(String outputProfileURI) { this.outputProfileURI = outputProfileURI; } + /** + * Sets the filter map to be used by the PDF renderer. + * @param filterMap the filter map + */ public void setFilterMap(Map filterMap) { this.filterMap = filterMap; } diff --git a/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java b/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java index cbc0a8ec9..cb7c7cf89 100644 --- a/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java @@ -36,6 +36,8 @@ import org.apache.batik.util.SVGConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.FontInfo; @@ -51,8 +53,8 @@ import org.apache.fop.render.RendererContextConstants; import org.apache.fop.svg.PDFAElementBridge; import org.apache.fop.svg.PDFBridgeContext; import org.apache.fop.svg.PDFGraphics2D; +import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; -import org.apache.fop.util.QName; /** * PDF XML handler for SVG (uses Apache Batik). @@ -144,8 +146,9 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler try { super.renderSVGDocument(context, doc); } catch (IOException ioe) { - log.error("I/O error while rendering SVG graphic: " - + ioe.getMessage(), ioe); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgRenderingError(this, ioe, getDocumentURI(doc)); } return; } @@ -153,15 +156,13 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler int yOffset = pdfInfo.currentYPosition; FOUserAgent userAgent = context.getUserAgent(); - log.debug("Generating SVG at " - + userAgent.getTargetResolution() - + "dpi."); final float deviceResolution = userAgent.getTargetResolution(); - log.debug("Generating SVG at " + deviceResolution + "dpi."); - log.debug("Generating SVG at " + deviceResolution + "dpi."); + if (log.isDebugEnabled()) { + log.debug("Generating SVG at " + deviceResolution + "dpi."); + } final float uaResolution = userAgent.getSourceResolution(); - SVGUserAgent ua = new SVGUserAgent(25.4f / uaResolution, new AffineTransform()); + SVGUserAgent ua = new SVGUserAgent(userAgent, new AffineTransform()); //Scale for higher resolution on-the-fly images from Batik double s = uaResolution / deviceResolution; @@ -188,8 +189,9 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler root = builder.build(ctx, doc); builder = null; } catch (Exception e) { - log.error("svg graphic could not be built: " - + e.getMessage(), e); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgNotBuilt(this, e, getDocumentURI(doc)); return; } // get the 'width' and 'height' attributes of the SVG document @@ -261,8 +263,9 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler root.paint(graphics); pdfInfo.currentStream.add(graphics.getString()); } catch (Exception e) { - log.error("svg graphic could not be rendered: " - + e.getMessage(), e); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgRenderingError(this, e, getDocumentURI(doc)); } pdfInfo.pdfState.pop(); renderer.restoreGraphicsState(); diff --git a/src/java/org/apache/fop/render/ps/PSEventProducer.java b/src/java/org/apache/fop/render/ps/PSEventProducer.java new file mode 100644 index 000000000..451ed1cea --- /dev/null +++ b/src/java/org/apache/fop/render/ps/PSEventProducer.java @@ -0,0 +1,65 @@ +/* + * 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.render.ps; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; + +/** + * Event producer interface for events generated by the PostScript renderer. + */ +public interface PSEventProducer extends EventProducer { + + /** Provider class for the event producer. */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static PSEventProducer get(EventBroadcaster broadcaster) { + return (PSEventProducer)broadcaster.getEventProducerFor( + PSEventProducer.class); + } + } + + /** Event model factory for this event producer. */ + public static class EventModelFactory extends AbstractEventModelFactory { + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), "event-model.xml"); + } + + } + + /** + * A PostScript dictionary could not be parsed. + * @param source the event source + * @param content the PostScript content + * @param e the original exception + * @event.severity ERROR + */ + void postscriptDictionaryParseError(Object source, String content, Exception e); + +} diff --git a/src/java/org/apache/fop/render/ps/PSEventProducer.xml b/src/java/org/apache/fop/render/ps/PSEventProducer.xml new file mode 100644 index 000000000..a0078223a --- /dev/null +++ b/src/java/org/apache/fop/render/ps/PSEventProducer.xml @@ -0,0 +1,4 @@ + + + Failed to parse dictionary string. Reason: {e}, content = "{content}" + diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index 7e32977e6..e4d582ba2 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -85,6 +85,7 @@ import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.WordArea; import org.apache.fop.datatypes.URISpecification; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.Font; @@ -95,6 +96,7 @@ import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.ImageAdapter; import org.apache.fop.render.RendererContext; +import org.apache.fop.render.RendererEventProducer; import org.apache.fop.render.ps.extensions.PSCommentAfter; import org.apache.fop.render.ps.extensions.PSCommentBefore; import org.apache.fop.render.ps.extensions.PSExtensionAttachment; @@ -296,7 +298,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer */ protected void handleIOTrouble(IOException ioe) { if (!ioTrouble) { - log.error("Error while writing to target file", ioe); + RendererEventProducer eventProducer = RendererEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.ioError(this, ioe); ioTrouble = true; } } @@ -522,12 +526,17 @@ public class PSRenderer extends AbstractPathOrientedRenderer } } catch (ImageException ie) { - log.error("Error while processing image: " - + (info != null ? info.toString() : uri), ie); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); } catch (FileNotFoundException fe) { - log.error(fe.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null); } catch (IOException ioe) { - handleIOTrouble(ioe); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); } } @@ -1070,8 +1079,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer try { this.pageDeviceDictionary.putAll(PSDictionary.valueOf(content)); } catch (PSDictionaryFormatException e) { - log.error("Failed to parse dictionary string: " - + e.getMessage() + ", content = '" + content + "'"); + PSEventProducer eventProducer = PSEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.postscriptDictionaryParseError(this, content, e); } } } else if (attachment instanceof PSCommentBefore) { @@ -1169,8 +1179,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer try { pageDeviceDictionary.putAll(PSDictionary.valueOf(content)); } catch (PSDictionaryFormatException e) { - log.error("failed to parse dictionary string: " - + e.getMessage() + ", [" + content + "]"); + PSEventProducer eventProducer = PSEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.postscriptDictionaryParseError(this, content, e); } } } diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java index 5cfe617c8..ebe098282 100644 --- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java +++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java @@ -23,31 +23,24 @@ package org.apache.fop.render.ps; import java.awt.geom.AffineTransform; import java.io.IOException; -// DOM import org.w3c.dom.Document; -import org.w3c.dom.svg.SVGDocument; -import org.w3c.dom.svg.SVGSVGElement; -// Batik import org.apache.avalon.framework.configuration.Configuration; -import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.bridge.ViewBox; -import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.ps.PSGenerator; -// FOP import org.apache.fop.fonts.FontInfo; +import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; -import org.apache.fop.render.XMLHandler; import org.apache.fop.render.RendererContext; +import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.ps.PSGenerator; - -// Commons-Logging -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * PostScript XML handler for SVG. Uses Apache Batik for SVG processing. @@ -57,7 +50,8 @@ import org.apache.commons.logging.LogFactory; * * @version $Id$ */ -public class PSSVGHandler implements XMLHandler, PSRendererContextConstants { +public class PSSVGHandler extends AbstractGenericSVGHandler + implements PSRendererContextConstants { /** logging instance */ private static Log log = LogFactory.getLog(PSSVGHandler.class); @@ -68,16 +62,6 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants { public PSSVGHandler() { } - /** {@inheritDoc} */ - public void handleXML(RendererContext context, - Document doc, String ns) throws Exception { - PSInfo psi = getPSInfo(context); - - if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) { - renderSVGDocument(context, doc, psi); - } - } - /** * Get the pdf information from the render context. * @@ -234,10 +218,10 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants { * Render the svg document. * @param context the renderer context * @param doc the svg document - * @param psInfo the pdf information of the current context */ protected void renderSVGDocument(RendererContext context, - Document doc, PSInfo psInfo) { + Document doc) { + PSInfo psInfo = getPSInfo(context); int xOffset = psInfo.currentXPosition; int yOffset = psInfo.currentYPosition; PSGenerator gen = psInfo.psGenerator; @@ -250,9 +234,7 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants { } SVGUserAgent ua - = new SVGUserAgent( - context.getUserAgent().getSourcePixelUnitToMillimeter(), - new AffineTransform()); + = new SVGUserAgent(context.getUserAgent(), new AffineTransform()); PSGraphics2D graphics = new PSGraphics2D(strokeText, gen); graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); @@ -273,8 +255,9 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants { try { root = builder.build(ctx, doc); } catch (Exception e) { - log.error("SVG graphic could not be built: " - + e.getMessage(), e); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgNotBuilt(this, e, getDocumentURI(doc)); return; } // get the 'width' and 'height' attributes of the SVG document @@ -305,10 +288,10 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants { // viewBox puts it. gen.concatMatrix(sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f); + /* SVGSVGElement svg = ((SVGDocument)doc).getRootElement(); AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, - psInfo.getWidth() / 1000f, psInfo.getHeight() / 1000f); - /* + psInfo.getWidth() / 1000f, psInfo.getHeight() / 1000f, ctx); if (!at.isIdentity()) { double[] vals = new double[6]; at.getMatrix(vals); @@ -322,15 +305,17 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants { try { root.paint(graphics); } catch (Exception e) { - log.error("SVG graphic could not be rendered: " - + e.getMessage(), e); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgRenderingError(this, e, getDocumentURI(doc)); } gen.restoreGraphicsState(); gen.commentln("%FOPEndSVG"); } catch (IOException ioe) { - log.error("SVG graphic could not be rendered: " - + ioe.getMessage(), ioe); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgRenderingError(this, ioe, getDocumentURI(doc)); } } @@ -339,10 +324,5 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants { return (renderer instanceof PSRenderer); } - /** {@inheritDoc} */ - public String getNamespace() { - return SVGDOMImplementation.SVG_NAMESPACE_URI; - } - } diff --git a/src/java/org/apache/fop/render/ps/ResourceHandler.java b/src/java/org/apache/fop/render/ps/ResourceHandler.java index 0dfb8029f..1a363c90e 100644 --- a/src/java/org/apache/fop/render/ps/ResourceHandler.java +++ b/src/java/org/apache/fop/render/ps/ResourceHandler.java @@ -20,8 +20,8 @@ package org.apache.fop.render.ps; import java.awt.geom.Dimension2D; -import java.awt.image.RenderedImage; import java.awt.geom.Rectangle2D; +import java.awt.image.RenderedImage; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -68,6 +68,7 @@ import org.apache.xmlgraphics.ps.dsc.events.PostScriptComment; import org.apache.xmlgraphics.ps.dsc.tools.DSCTools; import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fonts.FontInfo; /** @@ -321,7 +322,10 @@ public class ResourceHandler implements DSCParserConstants, PSSupportedFlavors { throw new UnsupportedOperationException("Unsupported image type: " + img); } } catch (ImageException ie) { - throw new IOException("Error while generating form for image: " + ie.getMessage()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + userAgent.getEventBroadcaster()); + eventProducer.imageError(resTracker, (info != null ? info.toString() : uri), + ie, null); } } } diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java index a6e77fb13..1eb1d9d13 100644 --- a/src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java @@ -22,7 +22,6 @@ package org.apache.fop.render.ps.extensions; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ValidationException; /** * Base postscript commment element class @@ -46,8 +45,8 @@ public abstract class AbstractPSCommentElement extends AbstractPSExtensionElemen protected void startOfNode() throws FOPException { if (parent.getNameId() != Constants.FO_DECLARATIONS && parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) { - throw new ValidationException(getName() - + " must be a child of fo:declarations or fo:simple-page-master."); + invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), + "rule.childOfSPMorDeclarations"); } } diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java index a10bb7518..31e44d2d2 100644 --- a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java @@ -20,14 +20,14 @@ package org.apache.fop.render.ps.extensions; // FOP +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.xml.sax.Locator; - /** * Base class for the PostScript-specific extension elements. */ @@ -98,7 +98,7 @@ public abstract class AbstractPSExtensionElement extends FONode { * @see org.apache.fop.fo.FONode#getNormalNamespacePrefix() */ public String getNormalNamespacePrefix() { - return "fox"; + return "ps"; } /** diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java index 6823d75d9..78b2f91eb 100644 --- a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java +++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java @@ -20,13 +20,14 @@ package org.apache.fop.render.ps.extensions; // FOP +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; /** * Base class for the PostScript-specific extension elements. @@ -36,15 +37,15 @@ public abstract class AbstractPSExtensionObject extends FONode { private PSSetupCode setupCode = new PSSetupCode(); /** + * Main constructor. + * @param parent the parent node * @see org.apache.fop.fo.FONode#FONode(FONode) */ public AbstractPSExtensionObject(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { @@ -71,7 +72,7 @@ public abstract class AbstractPSExtensionObject extends FONode { /**{@inheritDoc} */ public String getNormalNamespacePrefix() { - return "fox"; + return "ps"; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java index 306cd7bda..1dd0f4be6 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java @@ -27,6 +27,7 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; */ public class PSCommentAfterElement extends AbstractPSCommentElement { + /** the element name */ protected static final String ELEMENT = "ps-comment-after"; /** diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java index 6058f355b..5d3c863f5 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java @@ -27,6 +27,7 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; */ public class PSCommentBeforeElement extends AbstractPSCommentElement { + /** the element name */ protected static final String ELEMENT = "ps-comment-before"; /** diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java index 456d97430..e69500736 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java @@ -19,13 +19,15 @@ package org.apache.fop.render.ps.extensions; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; /** * ContentHandler (parser) for restoring PSExtension objects from XML. @@ -91,25 +93,19 @@ public class PSExtensionHandler extends DefaultHandler content.append(ch, start, length); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endDocument() throws SAXException { if (listener != null) { listener.notifyObjectBuilt(getObject()); } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Object getObject() { return returnedObject; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void setObjectBuiltListener(ObjectBuiltListener listener) { this.listener = listener; } diff --git a/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java index ad46b9364..207c11e76 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java @@ -22,13 +22,13 @@ package org.apache.fop.render.ps.extensions; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ValidationException; /** * Extension element for fox:ps-page-setup-code. */ public class PSPageSetupCodeElement extends AbstractPSExtensionObject { + /** The element name */ protected static final String ELEMENT = "ps-page-setup-code"; /** @@ -43,7 +43,8 @@ public class PSPageSetupCodeElement extends AbstractPSExtensionObject { protected void startOfNode() throws FOPException { super.startOfNode(); if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) { - throw new ValidationException(getName() + " must be a child of fo:simple-page-master."); + invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), + "rule.childOfSPM"); } } diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java index b512c6888..21acc8001 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java @@ -19,20 +19,21 @@ package org.apache.fop.render.ps.extensions; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; /** * Extension element for ps:ps-setpagedevice. */ public class PSSetPageDeviceElement extends AbstractPSExtensionElement { + /** The element name */ protected static final String ELEMENT = "ps-setpagedevice"; /** @@ -52,8 +53,8 @@ public class PSSetPageDeviceElement extends AbstractPSExtensionElement { super.startOfNode(); if ( !((parent.getNameId() == Constants.FO_DECLARATIONS) || (parent.getNameId() == Constants.FO_SIMPLE_PAGE_MASTER)) ) { - throw new ValidationException( getName() - + " must be a child of fo:declarations or fo:simple-page-master."); + invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), + "rule.childOfSPMorDeclarations"); } } diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java index ec7216c44..e76dfeb64 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java @@ -22,13 +22,13 @@ package org.apache.fop.render.ps.extensions; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ValidationException; /** * Extension element for fox:ps-setup-code. */ public class PSSetupCodeElement extends AbstractPSExtensionObject { + /** The element name */ protected static final String ELEMENT = "ps-setup-code"; /** @@ -43,7 +43,8 @@ public class PSSetupCodeElement extends AbstractPSExtensionObject { protected void startOfNode() throws FOPException { super.startOfNode(); if (parent.getNameId() != Constants.FO_DECLARATIONS) { - throw new ValidationException(getName() + " must be a child of fo:declarations."); + invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), + "rule.childOfDeclarations"); } } diff --git a/src/java/org/apache/fop/render/rtf/RTFEventProducer.java b/src/java/org/apache/fop/render/rtf/RTFEventProducer.java new file mode 100644 index 000000000..a2646af46 --- /dev/null +++ b/src/java/org/apache/fop/render/rtf/RTFEventProducer.java @@ -0,0 +1,94 @@ +/* + * 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.render.rtf; + +import org.xml.sax.Locator; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; +import org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; +import org.apache.fop.fo.FONode; + +/** + * Event producer interface for events generated by the RTF renderer. + */ +public interface RTFEventProducer extends EventProducer { + + /** Provider class for the event producer. */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static RTFEventProducer get(EventBroadcaster broadcaster) { + return (RTFEventProducer)broadcaster.getEventProducerFor( + RTFEventProducer.class); + } + } + + /** Event model factory for this event producer. */ + public static class EventModelFactory extends AbstractEventModelFactory { + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), "event-model.xml"); + } + + } + + /** + * The RTF handler only supports simple-page-masters. + * @param source the event source + * @param masterReference the reference page-master-set + * @param loc the location of the error or null + * @event.severity WARN + */ + void onlySPMSupported(Object source, String masterReference, Locator loc); + + /** + * No simple-page-master could be determined- + * @param source the event source + * @param loc the location of the error or null + * @event.severity WARN + */ + void noSPMFound(Object source, Locator loc); + + /** + * The RTF handler requires explicit table-columns for now. + * @param source the event source + * @param loc the location of the error or null + * @event.severity WARN + */ + void explicitTableColumnsRequired(Object source, Locator loc); + + /** + * The RTF handler ignored some deferred event (i.e. an unsupported element). + * @param source the event source + * @param node the FO tree node being ignored + * @param start true for start, false for end + * @param loc the location of the error or null + * @event.severity WARN + */ + void ignoredDeferredEvent(Object source, FONode node, boolean start, Locator loc); + +} diff --git a/src/java/org/apache/fop/render/rtf/RTFEventProducer.xml b/src/java/org/apache/fop/render/rtf/RTFEventProducer.xml new file mode 100644 index 000000000..8f1f21a81 --- /dev/null +++ b/src/java/org/apache/fop/render/rtf/RTFEventProducer.xml @@ -0,0 +1,8 @@ + + + [ (See position {loc})| (See {#gatherContextInfo})| (No context info available)] + Only simple-page-masters are supported on page-sequences. Using default simple-page-master from page-sequence-master "{masterReference}".{{locator}} + No simple-page-master could be determined. + No table-columns found on table. RTF output requires that all table-columns for a table are defined. Output will be incorrect.{{locator}} + Ignored deferred event for {node} ({start,if,start,end}).{{locator}} + diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index d2f2c4192..88e34e17a 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -21,6 +21,7 @@ package org.apache.fop.render.rtf; // Java import java.awt.geom.Point2D; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -51,6 +52,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.SimplePercentBaseContext; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; @@ -88,6 +90,7 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.fonts.FontSetup; import org.apache.fop.render.DefaultFontResolver; +import org.apache.fop.render.RendererEventProducer; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfBeforeContainer; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfListContainer; @@ -158,6 +161,16 @@ public class RTFHandler extends FOEventHandler { FontSetup.setup(fontInfo, null, new DefaultFontResolver(userAgent)); } + /** + * Central exception handler for I/O exceptions. + * @param ioe IOException to handle + */ + protected void handleIOTrouble(IOException ioe) { + RendererEventProducer eventProducer = RendererEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.ioError(this, ioe); + } + /** * {@inheritDoc} */ @@ -195,9 +208,9 @@ public class RTFHandler extends FOEventHandler { this.pagemaster = pageSeq.getRoot().getLayoutMasterSet().getSimplePageMaster(reference); if (this.pagemaster == null) { - log.warn("Only simple-page-masters are supported on page-sequences: " - + reference); - log.warn("Using default simple-page-master from page-sequence-master..."); + RTFEventProducer eventProducer = RTFEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.onlySPMSupported(this, reference, pageSeq.getLocator()); PageSequenceMaster master = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(reference); this.pagemaster = master.getNextSimplePageMaster( @@ -218,7 +231,9 @@ public class RTFHandler extends FOEventHandler { PageAttributesConverter.convertPageAttributes( pagemaster)); } else { - log.warn("No simple-page-master could be determined!"); + RTFEventProducer eventProducer = RTFEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noSPMFound(this, pageSeq.getLocator()); } builderContext.pushContainer(sect); @@ -226,9 +241,7 @@ public class RTFHandler extends FOEventHandler { bHeaderSpecified = false; bFooterSpecified = false; } catch (IOException ioe) { - // TODO could we throw Exception in all FOEventHandler events? - log.error("startPageSequence: " + ioe.getMessage(), ioe); - //TODO throw new FOPException(ioe); + handleIOTrouble(ioe); } catch (FOPException fope) { // TODO could we throw Exception in all FOEventHandler events? log.error("startPageSequence: " + fope.getMessage(), fope); @@ -338,8 +351,7 @@ public class RTFHandler extends FOEventHandler { log.warn("A " + fl.getLocalName() + " has been skipped: " + fl.getFlowName()); } } catch (IOException ioe) { - log.error("startFlow: " + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startFlow: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -396,9 +408,7 @@ public class RTFHandler extends FOEventHandler { textrun.pushBlockAttributes(rtfAttr); textrun.addBookmark(bl.getId()); } catch (IOException ioe) { - // TODO could we throw Exception in all FOEventHandler events? - log.error("startBlock: " + ioe.getMessage()); - throw new RuntimeException("IOException: " + ioe); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startBlock: " + e.getMessage()); throw new RuntimeException("Exception: " + e); @@ -427,8 +437,7 @@ public class RTFHandler extends FOEventHandler { textrun.popBlockAttributes(); } catch (IOException ioe) { - log.error("startBlock:" + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startBlock:" + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -457,9 +466,7 @@ public class RTFHandler extends FOEventHandler { textrun.addParagraphBreak(); textrun.pushBlockAttributes(rtfAttr); } catch (IOException ioe) { - // TODO could we throw Exception in all FOEventHandler events? - log.error("startBlock: " + ioe.getMessage()); - throw new RuntimeException("IOException: " + ioe); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startBlock: " + e.getMessage()); throw new RuntimeException("Exception: " + e); @@ -486,8 +493,7 @@ public class RTFHandler extends FOEventHandler { textrun.popBlockAttributes(); } catch (IOException ioe) { - log.error("startBlock:" + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startBlock:" + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -530,6 +536,8 @@ public class RTFHandler extends FOEventHandler { table.setBorderAttributes(borderAttributes); builderContext.pushContainer(table); + } catch (IOException ioe) { + handleIOTrouble(ioe); } catch (Exception e) { log.error("startTable:" + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -590,7 +598,6 @@ public class RTFHandler extends FOEventHandler { log.error("startColumn: " + e.getMessage()); throw new RuntimeException(e.getMessage()); } - } /** @@ -649,8 +656,7 @@ public class RTFHandler extends FOEventHandler { textrun.pushInlineAttributes(rtfAttr); textrun.addBookmark(inl.getId()); } catch (IOException ioe) { - log.error("startInline:" + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (FOPException fe) { log.error("startInline:" + fe.getMessage()); throw new RuntimeException(fe.getMessage()); @@ -677,8 +683,7 @@ public class RTFHandler extends FOEventHandler { RtfTextrun textrun = container.getTextrun(); textrun.popInlineAttributes(); } catch (IOException ioe) { - log.error("startInline:" + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startInline:" + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -698,6 +703,8 @@ public class RTFHandler extends FOEventHandler { RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this); tbl.setHeaderAttribs(atts); + } catch (IOException ioe) { + handleIOTrouble(ioe); } catch (Exception e) { log.error("startBody: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -715,6 +722,8 @@ public class RTFHandler extends FOEventHandler { try { RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this); tbl.setHeaderAttribs(null); + } catch (IOException ioe) { + handleIOTrouble(ioe); } catch (Exception e) { log.error("endBody: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -745,6 +754,8 @@ public class RTFHandler extends FOEventHandler { // reset column iteration index to correctly access column widths builderContext.getTableContext().selectFirstColumn(); + } catch (IOException ioe) { + handleIOTrouble(ioe); } catch (Exception e) { log.error("startRow: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -778,6 +789,8 @@ public class RTFHandler extends FOEventHandler { tctx.selectNextColumn(); } + } catch (IOException ioe) { + handleIOTrouble(ioe); } catch (Exception e) { log.error("endRow: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -870,6 +883,8 @@ public class RTFHandler extends FOEventHandler { } builderContext.pushContainer(cell); + } catch (IOException ioe) { + handleIOTrouble(ioe); } catch (Exception e) { log.error("startCell: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -906,8 +921,7 @@ public class RTFHandler extends FOEventHandler { ListAttributesConverter.convertAttributes(lb)); builderContext.pushContainer(newList); } catch (IOException ioe) { - log.error("startList: " + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (FOPException fe) { log.error("startList: " + fe.getMessage()); throw new RuntimeException(fe.getMessage()); @@ -961,8 +975,7 @@ public class RTFHandler extends FOEventHandler { builderContext.pushContainer(list.newListItem()); } catch (IOException ioe) { - log.error("startList: " + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startList: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -995,8 +1008,7 @@ public class RTFHandler extends FOEventHandler { RtfListItemLabel label = item.new RtfListItemLabel(item); builderContext.pushContainer(label); } catch (IOException ioe) { - log.error("startPageNumber:" + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startPageNumber: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -1077,8 +1089,7 @@ public class RTFHandler extends FOEventHandler { builderContext.pushContainer(link); } catch (IOException ioe) { - log.error("startLink:" + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startLink: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -1104,21 +1115,28 @@ public class RTFHandler extends FOEventHandler { return; } + String uri = eg.getURL(); + ImageInfo info = null; try { - String uri = eg.getURL(); //set image data FOUserAgent userAgent = eg.getUserAgent(); ImageManager manager = userAgent.getFactory().getImageManager(); - ImageInfo info = manager.getImageInfo(uri, userAgent.getImageSessionContext()); - if (info == null) { - log.error("Image could not be found: " + uri); - return; - } + info = manager.getImageInfo(uri, userAgent.getImageSessionContext()); putGraphic(eg, info); - } catch (Exception e) { - log.error("Error while handling an external-graphic: " + e.getMessage(), e); + } catch (ImageException ie) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); + } catch (FileNotFoundException fe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null); + } catch (IOException ioe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); } } @@ -1144,6 +1162,12 @@ public class RTFHandler extends FOEventHandler { // Set the image size to the size of the svg. Point2D csize = new Point2D.Float(-1, -1); Point2D intrinsicDimensions = child.getDimension(csize); + if (intrinsicDimensions == null) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.ifoNoIntrinsicSize(this, child.getLocator()); + return; + } size.setSizeInMillipoints( (int)Math.round(intrinsicDimensions.getX() * 1000), (int)Math.round(intrinsicDimensions.getY() * 1000)); @@ -1157,8 +1181,14 @@ public class RTFHandler extends FOEventHandler { Image converted = manager.convertImage(image, FLAVORS); putGraphic(ifo, converted); - } catch (Exception e) { - log.error("Error while handling an instream-foreign-object: " + e.getMessage(), e); + } catch (ImageException ie) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, null, ie, null); + } catch (IOException ioe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, null, ioe, null); } } @@ -1183,7 +1213,9 @@ public class RTFHandler extends FOEventHandler { putGraphic(abstractGraphic, image); } catch (ImageException ie) { - log.error("Error while loading/processing image: " + info.getOriginalURI(), ie); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, null, ie, null); } } @@ -1210,8 +1242,9 @@ public class RTFHandler extends FOEventHandler { } if (rawData == null) { - log.warn(FONode.decorateWithContextInfo("Image could not be embedded: " - + image, abstractGraphic)); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageWritingError(this, null); return; } @@ -1322,9 +1355,7 @@ public class RTFHandler extends FOEventHandler { builderContext.pushContainer(rtfFootnote); } catch (IOException ioe) { - // TODO could we throw Exception in all FOEventHandler events? - log.error("startFootnote: " + ioe.getMessage()); - throw new RuntimeException("IOException: " + ioe); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startFootnote: " + e.getMessage()); throw new RuntimeException("Exception: " + e); @@ -1358,9 +1389,7 @@ public class RTFHandler extends FOEventHandler { rtfFootnote.startBody(); } catch (IOException ioe) { - // TODO could we throw Exception in all FOEventHandler events? - log.error("startFootnoteBody: " + ioe.getMessage()); - throw new RuntimeException("IOException: " + ioe); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startFootnoteBody: " + e.getMessage()); throw new RuntimeException("Exception: " + e); @@ -1383,9 +1412,7 @@ public class RTFHandler extends FOEventHandler { rtfFootnote.endBody(); } catch (IOException ioe) { - // TODO could we throw Exception in all FOEventHandler events? - log.error("endFootnoteBody: " + ioe.getMessage()); - throw new RuntimeException("IOException: " + ioe); + handleIOTrouble(ioe); } catch (Exception e) { log.error("endFootnoteBody: " + e.getMessage()); throw new RuntimeException("Exception: " + e); @@ -1421,10 +1448,8 @@ public class RTFHandler extends FOEventHandler { textrun.pushInlineAttributes(rtfAttr); textrun.addString(new String(data, start, length - start)); textrun.popInlineAttributes(); - } catch (IOException ioe) { - // FIXME could we throw Exception in all FOEventHandler events? - log.error("characters: " + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + } catch (IOException ioe) { + handleIOTrouble(ioe); } catch (Exception e) { log.error("characters:" + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -1452,8 +1477,7 @@ public class RTFHandler extends FOEventHandler { RtfTextrun textrun = container.getTextrun(); textrun.addPageNumber(rtfAttr); } catch (IOException ioe) { - log.error("startPageNumber:" + ioe.getMessage()); - throw new RuntimeException(ioe.getMessage()); + handleIOTrouble(ioe); } catch (Exception e) { log.error("startPageNumber: " + e.getMessage()); throw new RuntimeException(e.getMessage()); @@ -1611,7 +1635,9 @@ public class RTFHandler extends FOEventHandler { endCell( (TableCell) foNode); } } else { - log.warn("Ignored deferred event for " + foNode); + RTFEventProducer eventProducer = RTFEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.ignoredDeferredEvent(this, foNode, bStart, foNode.getLocator()); } } @@ -1655,8 +1681,9 @@ public class RTFHandler extends FOEventHandler { } } else { //TODO Implement implicit column setup handling! - log.warn("No table-columns found on table. RTF output requires that all" - + " table-columns for a table are defined. Output will be incorrect."); + RTFEventProducer eventProducer = RTFEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.explicitTableColumnsRequired(this, table.getLocator()); } //recurse table-header diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 66cce0ae1..eb3c92e1b 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -41,6 +41,7 @@ import org.xml.sax.SAXException; import org.xml.sax.ext.LexicalHandler; import org.xml.sax.helpers.AttributesImpl; +import org.apache.xmlgraphics.util.QName; import org.apache.xmlgraphics.util.XMLizable; import org.apache.fop.apps.FOPException; @@ -90,7 +91,6 @@ import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.XMLHandler; import org.apache.fop.util.ColorUtil; -import org.apache.fop.util.QName; /** * Renderer that renders areas to XML for debugging purposes. diff --git a/src/java/org/apache/fop/svg/SVGEventProducer.java b/src/java/org/apache/fop/svg/SVGEventProducer.java new file mode 100644 index 000000000..8894f3f58 --- /dev/null +++ b/src/java/org/apache/fop/svg/SVGEventProducer.java @@ -0,0 +1,89 @@ +/* + * 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.svg; + +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.events.EventProducer; + +/** + * Event producer interface for SVG-related events. + */ +public interface SVGEventProducer extends EventProducer { + + /** + * Provider class for the event producer. + */ + class Provider { + + /** + * Returns an event producer. + * @param broadcaster the event broadcaster to use + * @return the event producer + */ + public static SVGEventProducer get(EventBroadcaster broadcaster) { + return (SVGEventProducer)broadcaster.getEventProducerFor( + SVGEventProducer.class); + } + } + + /** + * Error during SVG processing. Either message or e must be set. + * @param source the event source + * @param message the error message (or null) + * @param e the exception (or null) + * @event.severity ERROR + */ + void error(Object source, String message, Exception e); + + /** + * Alert during SVG processing. + * @param source the event source + * @param message the error message + * @event.severity WARN + */ + void alert(Object source, String message); + + /** + * Info during SVG processing. + * @param source the event source + * @param message the error message + * @event.severity INFO + */ + void info(Object source, String message); + + /** + * SVG graphic could not be built due to an exception. + * @param source the event source + * @param e the original exception + * @param uri the URI of the SVG graphic + * @event.severity ERROR + */ + void svgNotBuilt(Object source, Exception e, String uri); + + /** + * SVG graphic could not be rendered due to an exception. + * @param source the event source + * @param e the original exception + * @param uri the URI of the SVG graphic + * @event.severity ERROR + */ + void svgRenderingError(Object source, Exception e, String uri); + +} diff --git a/src/java/org/apache/fop/svg/SVGUserAgent.java b/src/java/org/apache/fop/svg/SVGUserAgent.java index 540f490de..8d7754fcb 100644 --- a/src/java/org/apache/fop/svg/SVGUserAgent.java +++ b/src/java/org/apache/fop/svg/SVGUserAgent.java @@ -19,49 +19,42 @@ package org.apache.fop.svg; -import javax.xml.parsers.SAXParserFactory; -import org.apache.batik.bridge.UserAgentAdapter; - -// Java import java.awt.geom.AffineTransform; -import java.awt.geom.Dimension2D; -import java.awt.Dimension; -// Commons-Logging -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.apache.fop.apps.FOUserAgent; /** - * The SVG user agent. - * This is an implementation of the batik svg user agent - * for handling errors and getting user agent values. + * The SVG user agent. This is an implementation of the Batik SVG user agent. */ -public class SVGUserAgent extends UserAgentAdapter { - private AffineTransform currentTransform = null; - private float pixelUnitToMillimeter = 0.0f; +public class SVGUserAgent extends SimpleSVGUserAgent { + + private SVGEventProducer eventProducer; + private Exception lastException; /** - * logging instance + * Creates a new SVGUserAgent. + * @param foUserAgent the FO user agent to associate with this SVG user agent + * @param at the current transform */ - private Log logger = LogFactory.getLog(SVGUserAgent.class); + public SVGUserAgent(FOUserAgent foUserAgent, AffineTransform at) { + super(foUserAgent.getSourcePixelUnitToMillimeter(), at); + this.eventProducer = SVGEventProducer.Provider.get(foUserAgent.getEventBroadcaster()); + } /** * Creates a new SVGUserAgent. - * @param pixelUnitToMM the pixel to millimeter conversion factor - * currently in effect - * @param at the current transform + * @param foUserAgent the FO user agent to associate with this SVG user agent */ - public SVGUserAgent(float pixelUnitToMM, AffineTransform at) { - pixelUnitToMillimeter = pixelUnitToMM; - currentTransform = at; + public SVGUserAgent(FOUserAgent foUserAgent) { + this(foUserAgent, new AffineTransform()); } - + /** - * Returns the logger associated with this user agent. - * @return Logger the logger + * Returns the last exception sent to the {@link #displayError(Exception)} method. + * @return the last exception or null if no exception occurred */ - protected final Log getLogger() { - return logger; + public Exception getLastException() { + return this.lastException; } /** @@ -69,7 +62,7 @@ public class SVGUserAgent extends UserAgentAdapter { * @param message the message to display */ public void displayError(String message) { - logger.error(message); + this.eventProducer.error(this, message, null); } /** @@ -77,7 +70,8 @@ public class SVGUserAgent extends UserAgentAdapter { * @param ex the exception to display */ public void displayError(Exception ex) { - logger.error("SVG Error" + ex.getMessage(), ex); + this.lastException = ex; + this.eventProducer.error(this, ex.getLocalizedMessage(), ex); } /** @@ -86,7 +80,7 @@ public class SVGUserAgent extends UserAgentAdapter { * @param message the message to display */ public void displayMessage(String message) { - logger.info(message); + this.eventProducer.info(this, message); } /** @@ -94,78 +88,7 @@ public class SVGUserAgent extends UserAgentAdapter { * @param message the message to display */ public void showAlert(String message) { - logger.warn(message); - } - - /** - * Returns a customized the pixel to mm factor. - * @return the pixel unit to millimeter conversion factor - */ - public float getPixelUnitToMillimeter() { - return pixelUnitToMillimeter; + this.eventProducer.alert(this, message); } - /** - * Returns the language settings. - * @return the languages supported - */ - public String getLanguages() { - return "en"; // userLanguages; - } - - /** - * Returns the media type for this rendering. - * @return the media for fo documents is "print" - */ - public String getMedia() { - return "print"; - } - - /** - * Returns the user stylesheet uri. - * @return null if no user style sheet was specified. - */ - public String getUserStyleSheetURI() { - return null; // userStyleSheetURI; - } - - /** - * Returns the class name of the XML parser. - * @return the XML parser class name - */ - public String getXMLParserClassName() { - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - return factory.newSAXParser().getXMLReader().getClass().getName(); - } catch (Exception e) { - return null; - } - } - - /** - * Is the XML parser validating. - * @return true if the xml parser is validating - */ - public boolean isXMLParserValidating() { - return false; - } - - /** - * Get the transform of the svg document. - * @return the transform - */ - public AffineTransform getTransform() { - return currentTransform; - } - - /** - * Get the default viewport size for an svg document. - * This returns a default value of 100x100. - * @return the default viewport size - */ - public Dimension2D getViewportSize() { - return new Dimension(100, 100); - } - -} - +} \ No newline at end of file diff --git a/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java b/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java new file mode 100644 index 000000000..4df1af34e --- /dev/null +++ b/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java @@ -0,0 +1,126 @@ +/* + * 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.svg; + +import java.awt.Dimension; +import java.awt.geom.AffineTransform; +import java.awt.geom.Dimension2D; + +import javax.xml.parsers.SAXParserFactory; + +import org.apache.batik.bridge.UserAgentAdapter; + +/** + * A simple SVG user agent. + * This is an implementation of the Batik SVG user agent. It ignores any message output sent + * by Batik. + */ +public class SimpleSVGUserAgent extends UserAgentAdapter { + + private AffineTransform currentTransform = null; + private float pixelUnitToMillimeter = 0.0f; + + /** + * Creates a new user agent. + * @param pixelUnitToMM the pixel to millimeter conversion factor currently in effect + * @param at the current transform + */ + public SimpleSVGUserAgent(float pixelUnitToMM, AffineTransform at) { + pixelUnitToMillimeter = pixelUnitToMM; + currentTransform = at; + } + + /** + * Returns a customized the pixel to mm factor. + * @return the pixel unit to millimeter conversion factor + */ + public float getPixelUnitToMillimeter() { + return pixelUnitToMillimeter; + } + + /** + * Returns the language settings. + * @return the languages supported + */ + public String getLanguages() { + return "en"; // userLanguages; + } + + /** + * Returns the media type for this rendering. + * @return the media for FO documents is "print" + */ + public String getMedia() { + return "print"; + } + + /** + * Returns the user stylesheet URI. + * @return null if no user style sheet was specified. + */ + public String getUserStyleSheetURI() { + return null; // userStyleSheetURI; + } + + /** + * Returns the class name of the XML parser. + * @return the XML parser class name + */ + public String getXMLParserClassName() { + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + return factory.newSAXParser().getXMLReader().getClass().getName(); + } catch (Exception e) { + return null; + } + } + + /** + * Is the XML parser validating. + * @return true if the XML parser is validating + */ + public boolean isXMLParserValidating() { + return false; + } + + /** + * Get the transform of the SVG document. + * @return the transform + */ + public AffineTransform getTransform() { + return currentTransform; + } + + /** {@inheritDoc} */ + public void setTransform(AffineTransform at) { + this.currentTransform = at; + } + + /** + * Get the default viewport size for an SVG document. + * This returns a default value of 100x100. + * @return the default viewport size + */ + public Dimension2D getViewportSize() { + return new Dimension(100, 100); + } + +} + diff --git a/src/java/org/apache/fop/util/QName.java b/src/java/org/apache/fop/util/QName.java index 390e29dd9..132f5b4dc 100644 --- a/src/java/org/apache/fop/util/QName.java +++ b/src/java/org/apache/fop/util/QName.java @@ -19,23 +19,17 @@ package org.apache.fop.util; -import java.io.Serializable; - /** * Represents a qualified name of an XML element or an XML attribute. *

                                                                                        * Note: This class allows to carry a namespace prefix but it is not used in the equals() and * hashCode() methods. + * @deprecated Use the XML Graphics Commons variant instead! */ -public class QName implements Serializable { +public class QName extends org.apache.xmlgraphics.util.QName { private static final long serialVersionUID = -5225376740044770690L; - private String namespaceURI; - private String localName; - private String prefix; - private int hashCode; - /** * Main constructor. * @param namespaceURI the namespace URI @@ -43,16 +37,7 @@ public class QName implements Serializable { * @param localName the local name */ public QName(String namespaceURI, String prefix, String localName) { - if (localName == null) { - throw new NullPointerException("Parameter localName must not be null"); - } - if (localName.length() == 0) { - throw new IllegalArgumentException("Parameter localName must not be empty"); - } - this.namespaceURI = namespaceURI; - this.prefix = prefix; - this.localName = localName; - this.hashCode = toHashString().hashCode(); + super(namespaceURI, prefix, localName); } /** @@ -61,78 +46,7 @@ public class QName implements Serializable { * @param qName the qualified name */ public QName(String namespaceURI, String qName) { - if (qName == null) { - throw new NullPointerException("Parameter localName must not be null"); - } - if (qName.length() == 0) { - throw new IllegalArgumentException("Parameter localName must not be empty"); - } - this.namespaceURI = namespaceURI; - int p = qName.indexOf(':'); - if (p > 0) { - this.prefix = qName.substring(0, p); - this.localName = qName.substring(p + 1); - } else { - this.prefix = null; - this.localName = qName; - } - this.hashCode = toHashString().hashCode(); + super(namespaceURI, qName); } - /** @return the namespace URI */ - public String getNamespaceURI() { - return this.namespaceURI; - } - - /** @return the namespace prefix */ - public String getPrefix() { - return this.prefix; - } - - /** @return the local name */ - public String getLocalName() { - return this.localName; - } - - /** @return the fully qualified name */ - public String getQName() { - return getPrefix() != null ? getPrefix() + ':' + getLocalName() : getLocalName(); - } - - /** {@inheritDoc} */ - public int hashCode() { - return this.hashCode; - } - - /** {@inheritDoc} */ - public boolean equals(Object obj) { - if (obj == null) { - return false; - } else if (obj == this) { - return true; - } else { - if (obj instanceof QName) { - QName other = (QName)obj; - if ((getNamespaceURI() == null && other.getNamespaceURI() == null) - || getNamespaceURI().equals(other.getNamespaceURI())) { - return getLocalName().equals(other.getLocalName()); - } - } - } - return false; - } - - /** {@inheritDoc} */ - public String toString() { - return prefix != null - ? (prefix + ":" + localName) - : toHashString(); - } - - private String toHashString() { - return (namespaceURI != null - ? ("{" + namespaceURI + "}" + localName) - : localName); - } - } diff --git a/src/java/org/apache/fop/util/XMLResourceBundle.java b/src/java/org/apache/fop/util/XMLResourceBundle.java new file mode 100644 index 000000000..1b320816b --- /dev/null +++ b/src/java/org/apache/fop/util/XMLResourceBundle.java @@ -0,0 +1,398 @@ +/* + * 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.io.IOException; +import java.io.InputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.Stack; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.stream.StreamSource; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import org.apache.xmlgraphics.util.QName; + +/** + * This class is a ResourceBundle that loads its contents from XML files instead of properties + * files (like PropertiesResourceBundle). + *

                                                                                        + * The XML format for this resource bundle implementation is the following + * (the same as Apache Cocoon's XMLResourceBundle): + *

                                                                                        + * <catalogue xml:lang="en">
                                                                                        + *   <message key="key1">Message <br/> Value 1</message>
                                                                                        + *   <message key="key2">Message <br/> Value 1</message>
                                                                                        + *   ...
                                                                                        + * </catalogue>
                                                                                        + * 
                                                                                        + */ +public class XMLResourceBundle extends ResourceBundle { + + //Note: Some code here has been copied and adapted from Apache Harmony! + + private Properties resources = new Properties(); + + private Locale locale; + + private static SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + + /** + * Creates a resource bundle from an InputStream. + * @param in the stream to read from + * @throws IOException if an I/O error occurs + */ + public XMLResourceBundle(InputStream in) throws IOException { + try { + Transformer transformer = tFactory.newTransformer(); + StreamSource src = new StreamSource(in); + SAXResult res = new SAXResult(new CatalogueHandler()); + transformer.transform(src, res); + } catch (TransformerException e) { + throw new IOException("Error while parsing XML resource bundle: " + e.getMessage()); + } + } + + /** + * Gets a resource bundle using the specified base name, default locale, and class loader. + * @param baseName the base name of the resource bundle, a fully qualified class name + * @param loader the class loader from which to load the resource bundle + * @return a resource bundle for the given base name and the default locale + * @throws MissingResourceException if no resource bundle for the specified base name can be + * found + * @see java.util.ResourceBundle#getBundle(String) + */ + public static ResourceBundle getXMLBundle(String baseName, ClassLoader loader) + throws MissingResourceException { + return getXMLBundle(baseName, Locale.getDefault(), loader); + } + + /** + * Gets a resource bundle using the specified base name, locale, and class loader. + * @param baseName the base name of the resource bundle, a fully qualified class name + * @param locale the locale for which a resource bundle is desired + * @param loader the class loader from which to load the resource bundle + * @return a resource bundle for the given base name and locale + * @throws MissingResourceException if no resource bundle for the specified base name can be + * found + * @see java.util.ResourceBundle#getBundle(String, Locale, ClassLoader) + */ + public static ResourceBundle getXMLBundle(String baseName, Locale locale, ClassLoader loader) + throws MissingResourceException { + if (loader == null) { + throw new NullPointerException("loader must not be null"); + } + if (baseName == null) { + throw new NullPointerException("baseName must not be null"); + } + + ResourceBundle bundle; + if (!locale.equals(Locale.getDefault())) { + bundle = handleGetXMLBundle(baseName, "_" + locale, false, loader); + if (bundle != null) { + return bundle; + } + } + bundle = handleGetXMLBundle(baseName, "_" + Locale.getDefault(), true, loader); + if (bundle != null) { + return bundle; + } + throw new MissingResourceException( + baseName + " (" + locale + ")", baseName + '_' + locale, null); + } + + static class MissingBundle extends ResourceBundle { + public Enumeration getKeys() { + return null; + } + + public Object handleGetObject(String name) { + return null; + } + } + + private static final ResourceBundle MISSING = new MissingBundle(); + private static final ResourceBundle MISSINGBASE = new MissingBundle(); + + private static Map cache = new java.util.WeakHashMap(); + //> + + private static ResourceBundle handleGetXMLBundle(String base, String locale, + boolean loadBase, final ClassLoader loader) { + XMLResourceBundle bundle = null; + String bundleName = base + locale; + Object cacheKey = loader != null ? (Object) loader : (Object) "null"; + Hashtable loaderCache; // + synchronized (cache) { + loaderCache = (Hashtable)cache.get(cacheKey); + if (loaderCache == null) { + loaderCache = new Hashtable(); + cache.put(cacheKey, loaderCache); + } + } + ResourceBundle result = (ResourceBundle)loaderCache.get(bundleName); + if (result != null) { + if (result == MISSINGBASE) { + return null; + } + if (result == MISSING) { + if (!loadBase) { + return null; + } + String extension = strip(locale); + if (extension == null) { + return null; + } + return handleGetXMLBundle(base, extension, loadBase, loader); + } + return result; + } + + final String fileName = bundleName.replace('.', '/') + ".xml"; + InputStream stream = (InputStream)AccessController + .doPrivileged(new PrivilegedAction() { + public Object run() { + return loader == null + ? ClassLoader.getSystemResourceAsStream(fileName) + : loader.getResourceAsStream(fileName); + } + }); + if (stream != null) { + try { + try { + bundle = new XMLResourceBundle(stream); + } finally { + stream.close(); + } + bundle.setLocale(locale); + } catch (IOException e) { + throw new MissingResourceException(e.getMessage(), base, null); + } + } + + String extension = strip(locale); + if (bundle != null) { + if (extension != null) { + ResourceBundle parent = handleGetXMLBundle(base, extension, true, + loader); + if (parent != null) { + bundle.setParent(parent); + } + } + loaderCache.put(bundleName, bundle); + return bundle; + } + + if (extension != null) { + ResourceBundle fallback = handleGetXMLBundle(base, extension, loadBase, loader); + if (fallback != null) { + loaderCache.put(bundleName, fallback); + return fallback; + } + } + loaderCache.put(bundleName, loadBase ? MISSINGBASE : MISSING); + return null; + } + + private void setLocale(String name) { + String language = "", country = "", variant = ""; + if (name.length() > 1) { + int nextIndex = name.indexOf('_', 1); + if (nextIndex == -1) { + nextIndex = name.length(); + } + language = name.substring(1, nextIndex); + if (nextIndex + 1 < name.length()) { + int index = nextIndex; + nextIndex = name.indexOf('_', nextIndex + 1); + if (nextIndex == -1) { + nextIndex = name.length(); + } + country = name.substring(index + 1, nextIndex); + if (nextIndex + 1 < name.length()) { + variant = name.substring(nextIndex + 1, name.length()); + } + } + } + this.locale = new Locale(language, country, variant); + } + + private static String strip(String name) { + int index = name.lastIndexOf('_'); + if (index != -1) { + return name.substring(0, index); + } + return null; + } + + private Enumeration getLocalKeys() { + return (Enumeration)resources.propertyNames(); + } + + /** {@inheritDoc} */ + public Locale getLocale() { + return this.locale; + } + + /** {@inheritDoc} */ + public Enumeration getKeys() { + if (parent == null) { + return getLocalKeys(); + } + return new Enumeration() { + private Enumeration local = getLocalKeys(); + private Enumeration pEnum = parent.getKeys(); + + private Object nextElement; + + private boolean findNext() { + if (nextElement != null) { + return true; + } + while (pEnum.hasMoreElements()) { + Object next = pEnum.nextElement(); + if (!resources.containsKey(next)) { + nextElement = next; + return true; + } + } + return false; + } + + public boolean hasMoreElements() { + if (local.hasMoreElements()) { + return true; + } + return findNext(); + } + + public Object nextElement() { + if (local.hasMoreElements()) { + return local.nextElement(); + } + if (findNext()) { + Object result = nextElement; + nextElement = null; + return result; + } + // Cause an exception + return pEnum.nextElement(); + } + }; + } + + /** {@inheritDoc} */ + protected Object handleGetObject(String key) { + if (key == null) { + throw new NullPointerException("key must not be null"); + } + return resources.get(key); + } + + /** {@inheritDoc} */ + public String toString() { + return "XMLResourceBundle: " + getLocale(); + } + + private class CatalogueHandler extends DefaultHandler { + + private static final String CATALOGUE = "catalogue"; + private static final String MESSAGE = "message"; + + private StringBuffer valueBuffer = new StringBuffer(); + private Stack elementStack = new Stack(); + private String currentKey = null; + + private boolean isOwnNamespace(String uri) { + return ("".equals(uri)); + } + + private QName getParentElementName() { + return (QName)elementStack.peek(); + } + + /** {@inheritDoc} */ + public void startElement(String uri, String localName, String qName, + Attributes atts) throws SAXException { + super.startElement(uri, localName, qName, atts); + QName elementName = new QName(uri, qName); + if (isOwnNamespace(uri)) { + if (CATALOGUE.equals(localName)) { + //nop + } else if (MESSAGE.equals(localName)) { + if (!CATALOGUE.equals(getParentElementName().getLocalName())) { + throw new SAXException(MESSAGE + " must be a child of " + CATALOGUE); + } + this.currentKey = atts.getValue("key"); + } else { + throw new SAXException("Invalid element name: " + elementName); + } + } else { + //ignore + } + this.valueBuffer.setLength(0); + elementStack.push(elementName); + } + + /** {@inheritDoc} */ + public void endElement(String uri, String localName, String qName) throws SAXException { + super.endElement(uri, localName, qName); + elementStack.pop(); + if (isOwnNamespace(uri)) { + if (CATALOGUE.equals(localName)) { + //nop + } else if (MESSAGE.equals(localName)) { + if (this.currentKey == null) { + throw new SAXException( + "current key is null (attribute 'key' might be mistyped)"); + } + resources.put(this.currentKey, this.valueBuffer.toString()); + this.currentKey = null; + } + } else { + //ignore + } + this.valueBuffer.setLength(0); + } + + /** {@inheritDoc} */ + public void characters(char[] ch, int start, int length) throws SAXException { + super.characters(ch, start, length); + valueBuffer.append(ch, start, length); + } + + } + +} diff --git a/src/java/org/apache/fop/util/text/AdvancedMessageFormat.java b/src/java/org/apache/fop/util/text/AdvancedMessageFormat.java new file mode 100644 index 000000000..a2169156a --- /dev/null +++ b/src/java/org/apache/fop/util/text/AdvancedMessageFormat.java @@ -0,0 +1,487 @@ +/* + * 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.text; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.xmlgraphics.util.Service; + + +/** + * Formats messages based on a template and with a set of named parameters. This is similar to + * {@link java.util.MessageFormat} but uses named parameters and supports conditional sub-groups. + *

                                                                                        + * Example: + *

                                                                                        + *

                                                                                        Missing field "{fieldName}"[ at location: {location}]!

                                                                                        + *
                                                                                          + *
                                                                                        • Curly brackets ("{}") are used for fields.
                                                                                        • + *
                                                                                        • Square brackets ("[]") are used to delimit conditional sub-groups. A sub-group is + * conditional when all fields inside the sub-group have a null value. In the case, everything + * between the brackets is skipped.
                                                                                        • + *
                                                                                        + */ +public class AdvancedMessageFormat { + + /** Regex that matches "," but not "\," (escaped comma) */ + static final Pattern COMMA_SEPARATOR_REGEX = Pattern.compile("(? 0) { + parent.addChild(new TextPart(sb.toString())); + sb.setLength(0); + } + i++; + int nesting = 1; + while (i < len) { + ch = pattern.charAt(i); + if (ch == '{') { + nesting++; + } else if (ch == '}') { + nesting--; + if (nesting == 0) { + i++; + break; + } + } + sb.append(ch); + i++; + } + parent.addChild(parseField(sb.toString())); + sb.setLength(0); + break; + case ']': + i++; + break loop; //Current composite is finished + case '[': + if (sb.length() > 0) { + parent.addChild(new TextPart(sb.toString())); + sb.setLength(0); + } + i++; + CompositePart composite = new CompositePart(true); + parent.addChild(composite); + i += parseInnerPattern(pattern, composite, sb, i); + break; + case '|': + if (sb.length() > 0) { + parent.addChild(new TextPart(sb.toString())); + sb.setLength(0); + } + parent.newSection(); + i++; + break; + case '\\': + if (i < len - 1) { + i++; + ch = pattern.charAt(i); + } + //no break here! Must be right before "default" section + default: + sb.append(ch); + i++; + } + } + if (sb.length() > 0) { + parent.addChild(new TextPart(sb.toString())); + sb.setLength(0); + } + return i - start; + } + + private Part parseField(String field) { + String[] parts = COMMA_SEPARATOR_REGEX.split(field, 3); + String fieldName = parts[0]; + if (parts.length == 1) { + if (fieldName.startsWith("#")) { + return new FunctionPart(fieldName.substring(1)); + } else { + return new SimpleFieldPart(fieldName); + } + } else { + String format = parts[1]; + PartFactory factory = (PartFactory)PART_FACTORIES.get(format); + if (factory == null) { + throw new IllegalArgumentException( + "No PartFactory available under the name: " + format); + } + if (parts.length == 2) { + return factory.newPart(fieldName, null); + } else { + return factory.newPart(fieldName, parts[2]); + } + } + } + + private static Function getFunction(String functionName) { + return (Function)FUNCTIONS.get(functionName); + } + + /** + * Formats a message with the given parameters. + * @param params a Map of named parameters (Contents: ) + * @return the formatted message + */ + public String format(Map params) { + StringBuffer sb = new StringBuffer(); + format(params, sb); + return sb.toString(); + } + + /** + * Formats a message with the given parameters. + * @param params a Map of named parameters (Contents: ) + * @param target the target StringBuffer to write the formatted message to + */ + public void format(Map params, StringBuffer target) { + rootPart.write(target, params); + } + + /** + * Represents a message template part. This interface is implemented by various variants of + * the single curly braces pattern ({field}, {field,if,yes,no} etc.). + */ + public interface Part { + + /** + * Writes the formatted part to a string buffer. + * @param sb the target string buffer + * @param params the parameters to work with + */ + void write(StringBuffer sb, Map params); + + /** + * Indicates whether there is any content that is generated by this message part. + * @param params the parameters to work with + * @return true if the part has content + */ + boolean isGenerated(Map params); + } + + /** + * Implementations of this interface parse a field part and return message parts. + */ + public interface PartFactory { + + /** + * Creates a new part by parsing the values parameter to configure the part. + * @param fieldName the field name + * @param values the unparsed parameter values + * @return the new message part + */ + Part newPart(String fieldName, String values); + + /** + * Returns the name of the message part format. + * @return the name of the message part format + */ + String getFormat(); + } + + /** + * Implementations of this interface format certain objects to strings. + */ + public interface ObjectFormatter { + + /** + * Formats an object to a string and writes the result to a string buffer. + * @param sb the target string buffer + * @param obj the object to be formatted + */ + void format(StringBuffer sb, Object obj); + + /** + * Indicates whether a given object is supported. + * @param obj the object + * @return true if the object is supported by the formatter + */ + boolean supportsObject(Object obj); + } + + /** + * Implementations of this interface do some computation based on the message parameters + * given to it. Note: at the moment, this has to be done in a local-independent way since + * there is no locale information. + */ + public interface Function { + + /** + * Executes the function. + * @param params the message parameters + * @return the function result + */ + Object evaluate(Map params); + + /** + * Returns the name of the function. + * @return the name of the function + */ + Object getName(); + } + + private static class TextPart implements Part { + + private String text; + + public TextPart(String text) { + this.text = text; + } + + public void write(StringBuffer sb, Map params) { + sb.append(text); + } + + public boolean isGenerated(Map params) { + return true; + } + + /** {@inheritDoc} */ + public String toString() { + return this.text; + } + } + + private static class SimpleFieldPart implements Part { + + private String fieldName; + + public SimpleFieldPart(String fieldName) { + this.fieldName = fieldName; + } + + public void write(StringBuffer sb, Map params) { + if (!params.containsKey(fieldName)) { + throw new IllegalArgumentException( + "Message pattern contains unsupported field name: " + fieldName); + } + Object obj = params.get(fieldName); + formatObject(obj, sb); + } + + public boolean isGenerated(Map params) { + Object obj = params.get(fieldName); + return obj != null; + } + + /** {@inheritDoc} */ + public String toString() { + return "{" + this.fieldName + "}"; + } + } + + /** + * Formats an object to a string and writes the result to a string buffer. This method + * usually uses the object's toString() method unless there is an + * {@link ObjectFormatter} that supports the object. {@link ObjectFormatter}s are registered + * through the service provider mechanism defined by the JAR specification. + * @param obj the object to be formatted + * @param target the target string buffer + */ + public static void formatObject(Object obj, StringBuffer target) { + if (obj instanceof String) { + target.append(obj); + } else { + boolean handled = false; + Iterator iter = OBJECT_FORMATTERS.iterator(); + while (iter.hasNext()) { + ObjectFormatter formatter = (ObjectFormatter)iter.next(); + if (formatter.supportsObject(obj)) { + formatter.format(target, obj); + handled = true; + break; + } + } + if (!handled) { + target.append(String.valueOf(obj)); + } + } + } + + private static class FunctionPart implements Part { + + private Function function; + + public FunctionPart(String functionName) { + this.function = getFunction(functionName); + if (this.function == null) { + throw new IllegalArgumentException("Unknown function: " + functionName); + } + } + + public void write(StringBuffer sb, Map params) { + Object obj = this.function.evaluate(params); + formatObject(obj, sb); + } + + public boolean isGenerated(Map params) { + Object obj = this.function.evaluate(params); + return obj != null; + } + + /** {@inheritDoc} */ + public String toString() { + return "{#" + this.function.getName() + "}"; + } + } + + private static class CompositePart implements Part { + + protected List parts = new java.util.ArrayList(); + private boolean conditional; + private boolean hasSections = false; + + public CompositePart(boolean conditional) { + this.conditional = conditional; + } + + private CompositePart(List parts) { + this.parts.addAll(parts); + this.conditional = true; + } + + public void addChild(Part part) { + if (part == null) { + throw new NullPointerException("part must not be null"); + } + if (hasSections) { + CompositePart composite = (CompositePart)this.parts.get(this.parts.size() - 1); + composite.addChild(part); + } else { + this.parts.add(part); + } + } + + public void newSection() { + if (!hasSections) { + List p = this.parts; + //Dropping into a different mode... + this.parts = new java.util.ArrayList(); + this.parts.add(new CompositePart(p)); + hasSections = true; + } + this.parts.add(new CompositePart(true)); + } + + public void write(StringBuffer sb, Map params) { + if (hasSections) { + Iterator iter = this.parts.iterator(); + while (iter.hasNext()) { + CompositePart part = (CompositePart)iter.next(); + if (part.isGenerated(params)) { + part.write(sb, params); + break; + } + } + } else { + if (isGenerated(params)) { + Iterator iter = this.parts.iterator(); + while (iter.hasNext()) { + Part part = (Part)iter.next(); + part.write(sb, params); + } + } + } + } + + public boolean isGenerated(Map params) { + if (hasSections) { + Iterator iter = this.parts.iterator(); + while (iter.hasNext()) { + Part part = (Part)iter.next(); + if (part.isGenerated(params)) { + return true; + } + } + return false; + } else { + if (conditional) { + Iterator iter = this.parts.iterator(); + while (iter.hasNext()) { + Part part = (Part)iter.next(); + if (!part.isGenerated(params)) { + return false; + } + } + } + return true; + } + } + + /** {@inheritDoc} */ + public String toString() { + return this.parts.toString(); + } + } + + + static String unescapeComma(String string) { + return string.replaceAll("\\\\,", ","); + } +} diff --git a/src/java/org/apache/fop/util/text/ChoiceFieldPart.java b/src/java/org/apache/fop/util/text/ChoiceFieldPart.java new file mode 100644 index 000000000..df457a02b --- /dev/null +++ b/src/java/org/apache/fop/util/text/ChoiceFieldPart.java @@ -0,0 +1,91 @@ +/* + * 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.text; + +import java.text.ChoiceFormat; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.fop.util.text.AdvancedMessageFormat.Part; +import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; + +/** + * Defines a "choice" field part that works like {@link ChoiceFormat}. + */ +public class ChoiceFieldPart implements Part { + + private static final Pattern VARIABLE_REGEX = Pattern.compile("\\{([^\\}]+)\\}"); + + private String fieldName; + private ChoiceFormat choiceFormat; + + /** + * Creates a new choice part. + * @param fieldName the field name to work on + * @param choicesPattern the choices pattern (as used by {@link ChoiceFormat}) + */ + public ChoiceFieldPart(String fieldName, String choicesPattern) { + this.fieldName = fieldName; + this.choiceFormat = new ChoiceFormat(choicesPattern); + } + + /** {@inheritDoc} */ + public boolean isGenerated(Map params) { + Object obj = params.get(fieldName); + return obj != null; + } + + /** {@inheritDoc} */ + public void write(StringBuffer sb, Map params) { + Object obj = params.get(fieldName); + Number num = (Number)obj; + String result = this.choiceFormat.format(num.doubleValue()); + Matcher m = VARIABLE_REGEX.matcher(result); + if (m.find()) { + //Resolve inner variables + AdvancedMessageFormat f = new AdvancedMessageFormat(result); + f.format(params, sb); + } else { + sb.append(result); + } + } + + /** {@inheritDoc} */ + public String toString() { + return "{" + this.fieldName + ",choice, ....}"; + } + + /** Factory for ChoiceFieldPart. */ + public static class Factory implements PartFactory { + + /** {@inheritDoc} */ + public Part newPart(String fieldName, String values) { + return new ChoiceFieldPart(fieldName, values); + } + + /** {@inheritDoc} */ + public String getFormat() { + return "choice"; + } + + } + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/util/text/EqualsFieldPart.java b/src/java/org/apache/fop/util/text/EqualsFieldPart.java new file mode 100644 index 000000000..2114b0d00 --- /dev/null +++ b/src/java/org/apache/fop/util/text/EqualsFieldPart.java @@ -0,0 +1,92 @@ +/* + * 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.text; + +import java.util.Map; + +import org.apache.fop.util.text.AdvancedMessageFormat.Part; +import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; + +/** + * Defines an "equals" field part that can compare a field's string value against another string. + * It returns either of two possible values attached as additional part parameters. Example: + * {field,equals,new,This is new!,This is old!} + */ +public class EqualsFieldPart extends IfFieldPart { + + private String equalsValue; + + /** + * Creates a new "equals" field part. + * @param fieldName the field name + * @param values the unparsed parameter values + */ + public EqualsFieldPart(String fieldName, String values) { + super(fieldName, values); + } + + /** {@inheritDoc} */ + protected void parseValues(String values) { + String[] parts = AdvancedMessageFormat.COMMA_SEPARATOR_REGEX.split(values, 3); + this.equalsValue = parts[0]; + if (parts.length == 1) { + throw new IllegalArgumentException( + "'equals' format must have at least 2 parameters"); + } + if (parts.length == 3) { + ifValue = AdvancedMessageFormat.unescapeComma(parts[1]); + elseValue = AdvancedMessageFormat.unescapeComma(parts[2]); + } else { + ifValue = AdvancedMessageFormat.unescapeComma(parts[1]); + } + } + + /** {@inheritDoc} */ + protected boolean isTrue(Map params) { + Object obj = params.get(fieldName); + if (obj != null) { + return String.valueOf(obj).equals(this.equalsValue); + } else { + return false; + } + } + + /** {@inheritDoc} */ + public String toString() { + return "{" + this.fieldName + ", equals " + this.equalsValue + "}"; + } + + /** + * Part factory for "equals". + */ + public static class Factory implements PartFactory { + + /** {@inheritDoc} */ + public Part newPart(String fieldName, String values) { + return new EqualsFieldPart(fieldName, values); + } + + /** {@inheritDoc} */ + public String getFormat() { + return "equals"; + } + + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/util/text/GlyphNameFieldPart.java b/src/java/org/apache/fop/util/text/GlyphNameFieldPart.java new file mode 100644 index 000000000..5d78cdfad --- /dev/null +++ b/src/java/org/apache/fop/util/text/GlyphNameFieldPart.java @@ -0,0 +1,89 @@ +/* + * 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.text; + +import java.util.Map; + +import org.apache.xmlgraphics.fonts.Glyphs; + +import org.apache.fop.util.text.AdvancedMessageFormat.Part; +import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; + +/** + * Function formatting a character to a glyph name. + */ +public class GlyphNameFieldPart implements Part { + + private String fieldName; + + /** + * Creates a new glyph name field part + * @param fieldName the field name + */ + public GlyphNameFieldPart(String fieldName) { + this.fieldName = fieldName; + } + + /** {@inheritDoc} */ + public boolean isGenerated(Map params) { + Object obj = params.get(fieldName); + return obj != null && getGlyphName(obj).length() > 0; + } + + private String getGlyphName(Object obj) { + if (obj instanceof Character) { + return Glyphs.charToGlyphName(((Character)obj).charValue()); + } else { + throw new IllegalArgumentException( + "Value for glyph name part must be a Character but was: " + + obj.getClass().getName()); + } + } + + /** {@inheritDoc} */ + public void write(StringBuffer sb, Map params) { + if (!params.containsKey(fieldName)) { + throw new IllegalArgumentException( + "Message pattern contains unsupported field name: " + fieldName); + } + Object obj = params.get(fieldName); + sb.append(getGlyphName(obj)); + } + + /** {@inheritDoc} */ + public String toString() { + return "{" + this.fieldName + ",glyph-name}"; + } + + /** Factory for {@link GlyphNameFieldPart}. */ + public static class Factory implements PartFactory { + + /** {@inheritDoc} */ + public Part newPart(String fieldName, String values) { + return new GlyphNameFieldPart(fieldName); + } + + /** {@inheritDoc} */ + public String getFormat() { + return "glyph-name"; + } + + } +} diff --git a/src/java/org/apache/fop/util/text/HexFieldPart.java b/src/java/org/apache/fop/util/text/HexFieldPart.java new file mode 100644 index 000000000..19f47f3d7 --- /dev/null +++ b/src/java/org/apache/fop/util/text/HexFieldPart.java @@ -0,0 +1,84 @@ +/* + * 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.text; + +import java.util.Map; + +import org.apache.fop.util.text.AdvancedMessageFormat.Part; +import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; + +/** + * Function formatting a number or character to a hex value. + */ +public class HexFieldPart implements Part { + + private String fieldName; + + /** + * Creates a new hex field part + * @param fieldName the field name + */ + public HexFieldPart(String fieldName) { + this.fieldName = fieldName; + } + + /** {@inheritDoc} */ + public boolean isGenerated(Map params) { + Object obj = params.get(fieldName); + return obj != null; + } + + /** {@inheritDoc} */ + public void write(StringBuffer sb, Map params) { + if (!params.containsKey(fieldName)) { + throw new IllegalArgumentException( + "Message pattern contains unsupported field name: " + fieldName); + } + Object obj = params.get(fieldName); + if (obj instanceof Character) { + sb.append(Integer.toHexString(((Character)obj).charValue())); + } else if (obj instanceof Number) { + sb.append(Integer.toHexString(((Number)obj).intValue())); + } else { + throw new IllegalArgumentException("Incompatible value for hex field part: " + + obj.getClass().getName()); + } + } + + /** {@inheritDoc} */ + public String toString() { + return "{" + this.fieldName + ",hex}"; + } + + /** Factory for {@link HexFieldPart}. */ + public static class Factory implements PartFactory { + + /** {@inheritDoc} */ + public Part newPart(String fieldName, String values) { + return new HexFieldPart(fieldName); + } + + /** {@inheritDoc} */ + public String getFormat() { + return "hex"; + } + + } +} diff --git a/src/java/org/apache/fop/util/text/IfFieldPart.java b/src/java/org/apache/fop/util/text/IfFieldPart.java new file mode 100644 index 000000000..31cd8f36c --- /dev/null +++ b/src/java/org/apache/fop/util/text/IfFieldPart.java @@ -0,0 +1,116 @@ +/* + * 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.text; + +import java.util.Map; + +import org.apache.fop.util.text.AdvancedMessageFormat.Part; +import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; + +/** + * Defines an "if" field part that checks if field's value is true or false. + * It returns either of two possible values attached as additional part parameters. Example: + * {field,if,Yes,No} + */ +public class IfFieldPart implements Part { + + /** the field name for the part */ + protected String fieldName; + /** the value being returned if the field is true */ + protected String ifValue; + /** the value being returned if the field is false */ + protected String elseValue; + + /** + * Creates a new "if" field part. + * @param fieldName the field name + * @param values the unparsed parameter values + */ + public IfFieldPart(String fieldName, String values) { + this.fieldName = fieldName; + parseValues(values); + } + + /** + * Parses the parameter values + * @param values the unparsed parameter values + */ + protected void parseValues(String values) { + String[] parts = AdvancedMessageFormat.COMMA_SEPARATOR_REGEX.split(values, 2); + if (parts.length == 2) { + ifValue = AdvancedMessageFormat.unescapeComma(parts[0]); + elseValue = AdvancedMessageFormat.unescapeComma(parts[1]); + } else { + ifValue = AdvancedMessageFormat.unescapeComma(values); + } + } + + /** {@inheritDoc} */ + public void write(StringBuffer sb, Map params) { + boolean isTrue = isTrue(params); + if (isTrue) { + sb.append(ifValue); + } else if (elseValue != null) { + sb.append(elseValue); + } + } + + /** + * Indicates whether the field's value is true. If the field is not a boolen, it is true + * if the field is not null. + * @param params the message parameters + * @return true the field's value as boolean + */ + protected boolean isTrue(Map params) { + Object obj = params.get(fieldName); + if (obj instanceof Boolean) { + return ((Boolean)obj).booleanValue(); + } else { + return (obj != null); + } + } + + /** {@inheritDoc} */ + public boolean isGenerated(Map params) { + return isTrue(params) || (elseValue != null); + } + + /** {@inheritDoc} */ + public String toString() { + return "{" + this.fieldName + ", if...}"; + } + + /** + * Part factory for "if". + */ + public static class Factory implements PartFactory { + + /** {@inheritDoc} */ + public Part newPart(String fieldName, String values) { + return new IfFieldPart(fieldName, values); + } + + /** {@inheritDoc} */ + public String getFormat() { + return "if"; + } + + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/util/text/LocatorFormatter.java b/src/java/org/apache/fop/util/text/LocatorFormatter.java new file mode 100644 index 000000000..d9532c66d --- /dev/null +++ b/src/java/org/apache/fop/util/text/LocatorFormatter.java @@ -0,0 +1,42 @@ +/* + * 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.text; + +import org.xml.sax.Locator; + +import org.apache.fop.util.text.AdvancedMessageFormat.ObjectFormatter; + +/** + * Object formatter for the SAX Locator object. + */ +public class LocatorFormatter implements ObjectFormatter { + + /** {@inheritDoc} */ + public void format(StringBuffer sb, Object obj) { + Locator loc = (Locator)obj; + sb.append(loc.getLineNumber()).append(":").append(loc.getColumnNumber()); + } + + /** {@inheritDoc} */ + public boolean supportsObject(Object obj) { + return obj instanceof Locator; + } + +} \ No newline at end of file diff --git a/test/java/META-INF/services/org.apache.fop.events.model.EventModelFactory b/test/java/META-INF/services/org.apache.fop.events.model.EventModelFactory new file mode 100644 index 000000000..a40d5658a --- /dev/null +++ b/test/java/META-INF/services/org.apache.fop.events.model.EventModelFactory @@ -0,0 +1 @@ +org.apache.fop.events.FOPTestEventModelFactory \ No newline at end of file diff --git a/test/java/org/apache/fop/UtilityCodeTestSuite.java b/test/java/org/apache/fop/UtilityCodeTestSuite.java index 86a3469ce..d2577c251 100644 --- a/test/java/org/apache/fop/UtilityCodeTestSuite.java +++ b/test/java/org/apache/fop/UtilityCodeTestSuite.java @@ -23,12 +23,14 @@ import junit.framework.Test; import junit.framework.TestSuite; import org.apache.fop.pdf.PDFObjectTestCase; +import org.apache.fop.events.BasicEventTestCase; import org.apache.fop.traits.BorderPropsTestCase; import org.apache.fop.util.DataURIResolverTestCase; import org.apache.fop.util.ElementListUtilsTestCase; import org.apache.fop.util.PDFNumberTestCase; import org.apache.fop.util.ColorUtilTestCase; import org.apache.fop.util.UnitConvTestCase; +import org.apache.fop.util.XMLResourceBundleTestCase; /** * Test suite for FOP's utility classes. @@ -50,6 +52,8 @@ public class UtilityCodeTestSuite { suite.addTest(new TestSuite(BorderPropsTestCase.class)); suite.addTest(new TestSuite(ElementListUtilsTestCase.class)); suite.addTest(new TestSuite(DataURIResolverTestCase.class)); + suite.addTest(new TestSuite(BasicEventTestCase.class)); + suite.addTest(new TestSuite(XMLResourceBundleTestCase.class)); //$JUnit-END$ return suite; } diff --git a/test/java/org/apache/fop/events/BasicEventTestCase.java b/test/java/org/apache/fop/events/BasicEventTestCase.java new file mode 100644 index 000000000..d365ca0ec --- /dev/null +++ b/test/java/org/apache/fop/events/BasicEventTestCase.java @@ -0,0 +1,95 @@ +/* + * 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.events; + +import junit.framework.TestCase; + +import org.apache.fop.events.model.EventSeverity; + +public class BasicEventTestCase extends TestCase { + + public void testBasics() throws Exception { + + MyEventListener listener = new MyEventListener(); + + EventBroadcaster broadcaster = new DefaultEventBroadcaster(); + broadcaster.addEventListener(listener); + assertTrue(broadcaster.hasEventListeners()); + + Event ev = new Event(this, "123", EventSeverity.INFO, + Event.paramsBuilder() + .param("reason", "I'm tired") + .param("blah", new Integer(23)) + .build()); + broadcaster.broadcastEvent(ev); + + ev = listener.event; + assertNotNull(ev); + assertEquals("123", listener.event.getEventID()); + assertEquals(EventSeverity.INFO, listener.event.getSeverity()); + assertEquals("I'm tired", ev.getParam("reason")); + assertEquals(new Integer(23), ev.getParam("blah")); + + broadcaster.removeEventListener(listener); + assertFalse(broadcaster.hasEventListeners()); + + //Just check that there are no NPEs + broadcaster.broadcastEvent(ev); + } + + public void testEventProducer() throws Exception { + MyEventListener listener = new MyEventListener(); + + EventBroadcaster broadcaster = new DefaultEventBroadcaster(); + broadcaster.addEventListener(listener); + assertTrue(broadcaster.hasEventListeners()); + + + TestEventProducer producer = TestEventProducer.Provider.get(broadcaster); + producer.complain(this, "I'm tired", 23); + + Event ev = listener.event; + assertNotNull(ev); + assertEquals("org.apache.fop.events.TestEventProducer.complain", + listener.event.getEventID()); + assertEquals(EventSeverity.WARN, listener.event.getSeverity()); + assertEquals("I'm tired", ev.getParam("reason")); + assertEquals(new Integer(23), ev.getParam("blah")); + + broadcaster.removeEventListener(listener); + assertFalse(broadcaster.hasEventListeners()); + + //Just check that there are no NPEs + broadcaster.broadcastEvent(ev); + } + + private class MyEventListener implements EventListener { + + private Event event; + + public void processEvent(Event event) { + if (this.event != null) { + fail("Multiple events received"); + } + this.event = event; + } + } + +} diff --git a/test/java/org/apache/fop/events/FOPTestEventModelFactory.java b/test/java/org/apache/fop/events/FOPTestEventModelFactory.java new file mode 100644 index 000000000..796a9cfb5 --- /dev/null +++ b/test/java/org/apache/fop/events/FOPTestEventModelFactory.java @@ -0,0 +1,37 @@ +/* + * 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.events; + +import org.apache.fop.events.model.AbstractEventModelFactory; +import org.apache.fop.events.model.EventModel; + +/** + * Factory for FOP's test event model. + */ +public class FOPTestEventModelFactory extends AbstractEventModelFactory { + + private static final String EVENT_MODEL_FILENAME = "test-event-model.xml"; + + /** {@inheritDoc} */ + public EventModel createEventModel() { + return loadModel(getClass(), EVENT_MODEL_FILENAME); + } + +} diff --git a/test/java/org/apache/fop/events/TestEventProducer.java b/test/java/org/apache/fop/events/TestEventProducer.java new file mode 100644 index 000000000..7dfba75ba --- /dev/null +++ b/test/java/org/apache/fop/events/TestEventProducer.java @@ -0,0 +1,48 @@ +/* + * 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.events; + +public interface TestEventProducer extends EventProducer { + + /** + * Complain about something. + * @param source the event source + * @param reason the reason for the complaint + * @param blah the complaint + * @event.severity WARN + */ + void complain(Object source, String reason, int blah); + + /** + * Express joy about something. + * @param source the event source + * @param what the cause for the joy + * @event.severity INFO + */ + void enjoy(Object source, String what); + + public class Provider { + + public static TestEventProducer get(EventBroadcaster broadcaster) { + return (TestEventProducer)broadcaster.getEventProducerFor(TestEventProducer.class); + } + } + +} diff --git a/test/java/org/apache/fop/util/AdvancedMessageFormatTestCase.java b/test/java/org/apache/fop/util/AdvancedMessageFormatTestCase.java new file mode 100644 index 000000000..c0e003573 --- /dev/null +++ b/test/java/org/apache/fop/util/AdvancedMessageFormatTestCase.java @@ -0,0 +1,183 @@ +/* + * 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.Map; + +import junit.framework.TestCase; + +import org.xml.sax.helpers.LocatorImpl; + +import org.apache.fop.events.model.EventSeverity; +import org.apache.fop.util.text.AdvancedMessageFormat; + +/** + * Tests for EventFormatter. + */ +public class AdvancedMessageFormatTestCase extends TestCase { + + public void testFormatting() throws Exception { + String msg; + AdvancedMessageFormat format; + + String pattern + = "Element \"{elementName}\" is missing[ required property \"{propertyName}\"]!"; + format = new AdvancedMessageFormat(pattern); + + Map params = new java.util.HashMap(); + params.put("node", new Object()); + params.put("elementName", "fo:external-graphic"); + params.put("propertyName", "src"); + + msg = format.format(params); + assertEquals("Element \"fo:external-graphic\" is missing required property \"src\"!", msg); + + params.remove("propertyName"); + msg = format.format(params); + assertEquals("Element \"fo:external-graphic\" is missing!", msg); + + pattern + = "Testing \\{escaped \\[characters\\], now a normal field {elementName}!"; + format = new AdvancedMessageFormat(pattern); + msg = format.format(params); + assertEquals("Testing {escaped [characters], now a normal field fo:external-graphic!", msg); + + pattern = "Multi-conditional: [case1: {var1}|case2: {var2}|case3: {var3}]"; + format = new AdvancedMessageFormat(pattern); + + params = new java.util.HashMap(); + msg = format.format(params); + assertEquals("Multi-conditional: ", msg); + + params.put("var3", "value3"); + msg = format.format(params); + assertEquals("Multi-conditional: case3: value3", msg); + params.put("var1", "value1"); + msg = format.format(params); + assertEquals("Multi-conditional: case1: value1", msg); + } + + public void testObjectFormatting() throws Exception { + String msg; + AdvancedMessageFormat format; + + String pattern + = "Here's a Locator: {locator}"; + format = new AdvancedMessageFormat(pattern); + + Map params = new java.util.HashMap(); + LocatorImpl loc = new LocatorImpl(); + loc.setColumnNumber(7); + loc.setLineNumber(12); + params.put("locator", loc); + + msg = format.format(params); + assertEquals("Here\'s a Locator: 12:7", msg); + } + + public void testIfFormatting() throws Exception { + String msg; + AdvancedMessageFormat format; + + format = new AdvancedMessageFormat("You are{isBad,if, not} nice!"); + + Map params = new java.util.HashMap(); + + params.put("isBad", Boolean.FALSE); + msg = format.format(params); + assertEquals("You are nice!", msg); + + params.put("isBad", Boolean.TRUE); + msg = format.format(params); + assertEquals("You are not nice!", msg); + + format = new AdvancedMessageFormat("You are{isGood,if, very, not so} nice!"); + + params = new java.util.HashMap(); + + msg = format.format(params); //isGood is missing + assertEquals("You are not so nice!", msg); + + params.put("isGood", Boolean.FALSE); + msg = format.format(params); + assertEquals("You are not so nice!", msg); + + params.put("isGood", Boolean.TRUE); + msg = format.format(params); + assertEquals("You are very nice!", msg); + + format = new AdvancedMessageFormat("You are{isGood,if, very\\, very} nice!"); + + params = new java.util.HashMap(); + + msg = format.format(params); //isGood is missing + assertEquals("You are nice!", msg); + + params.put("isGood", Boolean.FALSE); + msg = format.format(params); + assertEquals("You are nice!", msg); + + params.put("isGood", Boolean.TRUE); + msg = format.format(params); + assertEquals("You are very, very nice!", msg); + } + + public void testEqualsFormatting() throws Exception { + String msg; + AdvancedMessageFormat format; + + format = new AdvancedMessageFormat( + "Error{severity,equals,EventSeverity:FATAL,,\nSome explanation!}"); + + Map params = new java.util.HashMap(); + + params.put("severity", EventSeverity.FATAL); + msg = format.format(params); + assertEquals("Error", msg); + + params.put("severity", EventSeverity.WARN); + msg = format.format(params); + assertEquals("Error\nSome explanation!", msg); + } + + public void testChoiceFormatting() throws Exception { + String msg; + AdvancedMessageFormat format; + + format = new AdvancedMessageFormat( + "You have {amount,choice,0#nothing|0<{amount} bucks|100 + + Hello World! + Untranslatable + \ No newline at end of file diff --git a/test/java/org/apache/fop/util/XMLResourceBundleTestCase_de.xml b/test/java/org/apache/fop/util/XMLResourceBundleTestCase_de.xml new file mode 100644 index 000000000..44cf5a5b4 --- /dev/null +++ b/test/java/org/apache/fop/util/XMLResourceBundleTestCase_de.xml @@ -0,0 +1,4 @@ + + + Hallo Welt! + \ No newline at end of file diff --git a/test/java/org/apache/fop/util/invalid-translation-file.xml b/test/java/org/apache/fop/util/invalid-translation-file.xml new file mode 100644 index 000000000..09306b7cc --- /dev/null +++ b/test/java/org/apache/fop/util/invalid-translation-file.xml @@ -0,0 +1,5 @@ + + + Hello World! + blah + \ No newline at end of file -- cgit v1.2.3 From e48db7acffdb0e9a0f0fe4eb36e5a3f5205b73e1 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 14 Apr 2008 12:41:00 +0000 Subject: Fixed a possible follow-up NPE when the TTC cannot be loaded. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@647770 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index b223ea7a1..ce33bc5b6 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -196,7 +196,6 @@ public class FontInfoFinder { // Get a list of the TTC Font names List ttcNames = null; //List String fontFileURI = fontUrl.toExternalForm().trim(); - TTFFontLoader ttfLoader = new TTFFontLoader(fontFileURI, resolver); InputStream in = null; try { in = FontLoader.openFontUri(resolver, fontFileURI); @@ -207,6 +206,7 @@ public class FontInfoFinder { if (this.eventListener != null) { this.eventListener.fontLoadingErrorAtAutoDetection(this, fontFileURI, e); } + return null; } finally { IOUtils.closeQuietly(in); } @@ -223,7 +223,7 @@ public class FontInfoFinder { log.debug("Loading " + fontName); } try { - ttfLoader = new TTFFontLoader(fontFileURI, fontName, resolver); + TTFFontLoader ttfLoader = new TTFFontLoader(fontFileURI, fontName, resolver); customFont = ttfLoader.getFont(); if (this.eventListener != null) { customFont.setEventListener(this.eventListener); -- cgit v1.2.3 From 3b525dc8b0c9278d0449c6d59a08dcaa24b3c7a5 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 15 Apr 2008 06:07:00 +0000 Subject: A note about the generation of event-model.xml. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@648122 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/events.xml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/events.xml b/src/documentation/content/xdocs/trunk/events.xml index d2fe5318c..51a1bb6cc 100644 --- a/src/documentation/content/xdocs/trunk/events.xml +++ b/src/documentation/content/xdocs/trunk/events.xml @@ -275,6 +275,12 @@ producer.complain(this, "I'm tired", 23);]]> scans FOP's sources for descendants of the EventProducer interface and uses QDox to parse these interfaces.

                                                                                        +

                                                                                        + The event model XML files are generated during build by the Ant task mentioned above when + running the "resourcegen" task. So just run "ant resourcegen" if you receive + a MissingResourceException at runtime indicating that + "event-model.xml" is missing. +

                                                                                        Primarily, the QDox-based collector task records the parameters' names and types. Furthermore, it extracts additional attributes embedded as Javadoc comments from -- cgit v1.2.3 From f993b978c0dfc1ed4c336c97b29eef9b80caf187 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 15 Apr 2008 10:19:44 +0000 Subject: Adjust information on logging given the availability of the event package. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@648206 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/embedding.xml | 32 ++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/embedding.xml b/src/documentation/content/xdocs/trunk/embedding.xml index b2c802db7..9ed42dd9d 100644 --- a/src/documentation/content/xdocs/trunk/embedding.xml +++ b/src/documentation/content/xdocs/trunk/embedding.xml @@ -175,17 +175,6 @@ try { processing run anymore. The log output of multiple, simultaneously running FOP instances is sent to the same logger.

                                                                                        - - We know this may be an issue in multi-threaded server environments if you'd like to - know what's going on in every single FOP processing run. We're planning to add an - additional feedback facility to FOP which can be used to obtain all sorts of specific - feedback (validation messages, layout problems etc.). "Static logging" is mainly - interesting for a developer working on FOP and for advanced users who are debugging - FOP. We don't consider the logging output to be useful to normal FOP users. Please - have some patience until we can add this feature or jump in and help us build it. We've - set up a Wiki page - which documents what we're going to build. -

                                                                                        By default, Jakarta Commons Logging uses JDK logging (available in JDKs 1.4 or higher) as its backend. You can configure Commons @@ -193,6 +182,27 @@ try { documentation for Jakarta Commons Logging on how to configure alternative backends.

                                                                                        +

                                                                                        + As a result of the above we differentiate between to kinds of "logging": +

                                                                                        + +

                                                                                        + The use of "feedback" instead of "logging" is intentional. Most people were using + log output as a means to get feedback from events within FOP. Therefore, FOP now + includes an event package which can be used to receive feedback from + the layout engine and other components within FOP per rendering run. + This feedback is not just some + text but event objects with parameters so these events can be interpreted by code. + Of course, there is a facility to turn these events into normal human-readable + messages. For details, please read on on the Events page. + This leaves normal logging to be mostly a thing used by the FOP developers + although anyone can surely activate certain logging categories but the feedback + from the loggers won't be separated by processing runs. If this is required, + the Events subsystem is the right approach. +

                                                                                      • -- cgit v1.2.3 From 01a9c273a28516c5850b5d3044e801603158b76b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 15 Apr 2008 19:18:46 +0000 Subject: First part of the implementation of stage 1 for advanced keeps (see Wiki): Integer values are treated differently from "always" values in keep-together.within-column for all block-level FOs. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@648381 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 4 +- src/java/org/apache/fop/fo/flow/table/EffRow.java | 22 +++- .../org/apache/fop/fo/flow/table/GridUnit.java | 9 ++ .../fop/layoutmgr/BlockContainerLayoutManager.java | 31 ++---- .../apache/fop/layoutmgr/BlockLayoutManager.java | 44 ++++---- .../fop/layoutmgr/BlockLevelLayoutManager.java | 11 ++ .../fop/layoutmgr/BlockStackingLayoutManager.java | 114 +++++++++++++++------ .../org/apache/fop/layoutmgr/ElementListUtils.java | 17 +++ .../apache/fop/layoutmgr/FlowLayoutManager.java | 6 +- .../fop/layoutmgr/FootnoteBodyLayoutManager.java | 9 +- src/java/org/apache/fop/layoutmgr/KeepUtil.java | 70 +++++++++++++ .../fop/layoutmgr/StaticContentLayoutManager.java | 5 + .../fop/layoutmgr/inline/LineLayoutManager.java | 9 +- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 17 +-- .../list/ListItemContentLayoutManager.java | 17 +-- .../fop/layoutmgr/list/ListItemLayoutManager.java | 26 +++-- .../table/TableAndCaptionLayoutManager.java | 21 +++- .../layoutmgr/table/TableCaptionLayoutManager.java | 23 ++++- .../layoutmgr/table/TableCellLayoutManager.java | 73 +++---------- .../layoutmgr/table/TableContentLayoutManager.java | 7 +- .../fop/layoutmgr/table/TableLayoutManager.java | 20 ++-- .../apache/fop/layoutmgr/table/TableStepper.java | 12 ++- .../block-container_keep-together_integers_1.xml | 95 +++++++++++++++++ .../block_keep-together_integers_1.xml | 100 ++++++++++++++++++ .../block_keep-together_integers_2.xml | 95 +++++++++++++++++ .../block_keep-together_overflow_1.xml | 4 +- .../list-block_keep-together.xml | 97 +++++++++++++++--- .../standard-testcases/table_keep-together.xml | 61 ++++++++++- 28 files changed, 806 insertions(+), 213 deletions(-) create mode 100644 src/java/org/apache/fop/layoutmgr/KeepUtil.java create mode 100644 test/layoutengine/standard-testcases/block-container_keep-together_integers_1.xml create mode 100644 test/layoutengine/standard-testcases/block_keep-together_integers_1.xml create mode 100644 test/layoutengine/standard-testcases/block_keep-together_integers_2.xml (limited to 'src') diff --git a/build.xml b/build.xml index 5a72154f7..f946872ef 100644 --- a/build.xml +++ b/build.xml @@ -924,7 +924,7 @@ list of possible build targets. - + @@ -982,7 +982,7 @@ list of possible build targets. - + diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java index 0b00b9620..31a8260cc 100644 --- a/src/java/org/apache/fop/fo/flow/table/EffRow.java +++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java @@ -23,6 +23,8 @@ import java.util.Iterator; import java.util.List; import org.apache.fop.fo.Constants; +import org.apache.fop.layoutmgr.BlockLevelLayoutManager; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.table.TableRowIterator; import org.apache.fop.traits.MinOptMax; import org.apache.fop.util.BreakUtil; @@ -211,10 +213,26 @@ public class EffRow { * @return true if this row must be kept together */ public boolean mustKeepTogether() { - TableRow row = getTableRow(); - return row != null && row.mustKeepTogether(); + return getKeepTogetherStrength() != BlockLevelLayoutManager.KEEP_AUTO; } + /** + * Returns the keep-together strength for this element. Note: The keep strength returned does + * not take the parent table's keeps into account! + * @return the keep-together strength + */ + public int getKeepTogetherStrength() { + TableRow row = getTableRow(); + int strength = BlockLevelLayoutManager.KEEP_AUTO; + if (row != null) { + strength = Math.max(strength, KeepUtil.getKeepStrength( + row.getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + row.getKeepTogether().getWithinColumn())); + } + return strength; + } + /** * Returns the break class for this row. This is a combination of break-before set on * the first children of any cells starting on this row. diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java index b9394ff31..578fcb883 100644 --- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java @@ -64,11 +64,16 @@ public class GridUnit { /** flags for the grid unit */ private byte flags = 0; + /** the border-before specification */ ConditionalBorder borderBefore; + /** the border-after specification */ ConditionalBorder borderAfter; + /** the border-start specification */ BorderSpecification borderStart; + /** the border-end specification */ BorderSpecification borderEnd; + /** The border model helper associated with the table */ protected CollapsingBorderModel collapsingBorderModel; /** @@ -146,6 +151,10 @@ public class GridUnit { } } + /** + * Returns the table cell associated with this grid unit. + * @return the table cell + */ public TableCell getCell() { return cell; } diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index f01f0e12f..c0220e75e 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -308,22 +308,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (prevLM != null) { // there is a block handled by prevLM // before the one handled by curLM - if (mustKeepTogether() - || prevLM.mustKeepWithNext() - || curLM.mustKeepWithPrevious()) { - // add an infinite penalty to forbid a break between - // blocks - contentList.add(new BreakElement( - new Position(this), KnuthElement.INFINITE, context)); - } else if (!((ListElement) contentList.getLast()).isGlue()) { - // add a null penalty to allow a break between blocks - contentList.add(new BreakElement( - new Position(this), 0, context)); - } else { - // the last element in contentList is a glue; - // it is a feasible breakpoint, there is no need to add - // a penalty - } + addInBetweenBreak(contentList, context, childLC); } contentList.addAll(returnedList); if (returnedList.size() == 0) { @@ -1004,15 +989,19 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public boolean mustKeepTogether() { - //TODO Keeps will have to be more sophisticated sooner or later - return super.mustKeepTogether() - || !getBlockContainerFO().getKeepTogether().getWithinPage().isAuto() - || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto(); + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; + strength = Math.max(strength, KeepUtil.getKeepStrength( + getBlockContainerFO().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + getBlockContainerFO().getKeepTogether().getWithinColumn())); + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; } /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { + //TODO Keeps will have to be more sophisticated sooner or later return !getBlockContainerFO().getKeepWithPrevious().getWithinPage().isAuto() || !getBlockContainerFO().getKeepWithPrevious().getWithinColumn().isAuto(); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index f5270107c..253ec2af1 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -33,7 +33,6 @@ import org.apache.fop.datatypes.Length; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; -import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; import org.apache.fop.layoutmgr.inline.LineLayoutManager; import org.apache.fop.traits.MinOptMax; @@ -79,11 +78,13 @@ public class BlockLayoutManager extends BlockStackingLayoutManager proxyLMiter = new ProxyLMiter(); } + /** {@inheritDoc} */ public void initialize() { super.initialize(); FontInfo fi = getBlockFO().getFOEventHandler().getFontInfo(); FontTriplet[] fontkeys = getBlockFO().getCommonFont().getFontState(fi); - Font initFont = fi.getFontInstance(fontkeys[0], getBlockFO().getCommonFont().fontSize.getValue(this)); + Font initFont = fi.getFontInstance(fontkeys[0], + getBlockFO().getCommonFont().fontSize.getValue(this)); lead = initFont.getAscender(); follow = -initFont.getDescender(); //middleShift = -fs.getXHeight() / 2; @@ -135,7 +136,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager */ protected class ProxyLMiter extends LMiter { - /* + /** * Constructs a proxy iterator for Block LM. */ public ProxyLMiter() { @@ -206,40 +207,31 @@ public class BlockLayoutManager extends BlockStackingLayoutManager return llm; } - /** - * {@inheritDoc} - */ - public boolean mustKeepTogether() { - // TODO Keeps will have to be more sophisticated sooner or later - // TODO This is a quick fix for the fact that the parent is not always a BlockLevelLM; - // eventually mustKeepTogether() must be moved up to the LM interface - return (!getBlockFO().getKeepTogether().getWithinPage().isAuto() - || !getBlockFO().getKeepTogether().getWithinColumn().isAuto() - || (getParent() instanceof BlockLevelLayoutManager - && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) - || (getParent() instanceof InlineLayoutManager - && ((InlineLayoutManager) getParent()).mustKeepTogether())); + /** {@inheritDoc} */ + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; + strength = Math.max(strength, KeepUtil.getKeepStrength( + getBlockFO().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + getBlockFO().getKeepTogether().getWithinColumn())); + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { + //TODO Keeps will have to be more sophisticated sooner or later return !getBlockFO().getKeepWithPrevious().getWithinPage().isAuto() || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithNext() { return !getBlockFO().getKeepWithNext().getWithinPage().isAuto() || !getBlockFO().getKeepWithNext().getWithinColumn().isAuto(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java index 7e0e9e50e..3dc7ed46e 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java @@ -35,10 +35,21 @@ public interface BlockLevelLayoutManager extends LayoutManager { /** Adjustment class: adjustment for line height */ int LINE_HEIGHT_ADJUSTMENT = 3; + /** The integer value for "auto" keep strength */ + int KEEP_AUTO = Integer.MIN_VALUE; + /** The integer value for "always" keep strength */ + int KEEP_ALWAYS = Integer.MAX_VALUE; + int negotiateBPDAdjustment(int adj, KnuthElement lastElement); void discardSpace(KnuthGlue spaceGlue); + /** + * Returns the keep-together strength for this element. + * @return the keep-together strength + */ + int getKeepTogetherStrength(); + /** * @return true if this element must be kept together */ diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index cb6db6b01..c6ead8d59 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -335,27 +335,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (prevLM != null) { // there is a block handled by prevLM // before the one handled by curLM - if (mustKeepTogether() - || context.isKeepWithNextPending() - || childLC.isKeepWithPreviousPending()) { - // Clear keep pending flag - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - // add an infinite penalty to forbid a break between - // blocks - contentList.add(new BreakElement( - new Position(this), KnuthElement.INFINITE, context)); - } else if (!((ListElement) contentList.getLast()).isGlue()) { - // add a null penalty to allow a break between blocks - contentList.add(new BreakElement( - new Position(this), 0, context)); - } else { - // the last element in contentList is a glue; - // it is a feasible breakpoint, there is no need to add - // a penalty - log.warn("glue-type break possibility not handled properly, yet"); - //TODO Does this happen? If yes, need to deal with border and padding - //at the break possibility - } + addInBetweenBreak(contentList, context, childLC); } if (returnedList == null || returnedList.size() == 0) { //Avoid NoSuchElementException below (happens with empty blocks) @@ -432,6 +412,66 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager return returnList; } + /** + * Adds a break element to the content list between individual child elements. + * @param contentList the content list to populate + * @param context the current layout context + * @param childLC the currently active child layout context + */ + protected void addInBetweenBreak(LinkedList contentList, LayoutContext context, + LayoutContext childLC) { + if (mustKeepTogether() + || context.isKeepWithNextPending() + || childLC.isKeepWithPreviousPending()) { + + int strength = getKeepTogetherStrength(); + if (context.isKeepWithNextPending()) { + context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); + strength = KEEP_ALWAYS; + } + if (childLC.isKeepWithPreviousPending()) { + childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); + strength = KEEP_ALWAYS; + } + int penalty = KeepUtil.getPenaltyForKeep(strength); + + // add a penalty to forbid or discourage a break between blocks + contentList.add(new BreakElement( + new Position(this), penalty, context)); + return; + } + + ListElement last = (ListElement)contentList.getLast(); + if (last.isGlue()) { + // the last element in contentList is a glue; + // it is a feasible breakpoint, there is no need to add + // a penalty + log.warn("glue-type break possibility not handled properly, yet"); + //TODO Does this happen? If yes, need to deal with border and padding + //at the break possibility + } else if (!ElementListUtils.endsWithNonInfinitePenalty(contentList)) { + + // TODO vh: this is hacky + // The getNextKnuthElements method of TableCellLM must not be called + // twice, otherwise some settings like indents or borders will be + // counted several times and lead to a wrong output. Anyway the + // getNextKnuthElements methods should be called only once eventually + // (i.e., when multi-threading the code), even when there are forced + // breaks. + // If we add a break possibility after a forced break the + // AreaAdditionUtil.addAreas method will act on a sequence starting + // with a SpaceResolver.SpaceHandlingBreakPosition element, having no + // LM associated to it. Thus it will stop early instead of adding + // areas for following Positions. The above test aims at preventing + // such a situation from occurring. add a null penalty to allow a break + // between blocks + + // add a null penalty to allow a break between blocks + contentList.add(new BreakElement( + new Position(this), 0, context)); + } + } + /** * {@inheritDoc} */ @@ -759,26 +799,34 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } /** - * {@inheritDoc} + * Retrieves and returns the keep-together strength from the parent element. + * @return the keep-together strength */ - // default action: ask parentLM + protected int getParentKeepTogetherStrength() { + int strength = KEEP_AUTO; + if (getParent() instanceof BlockLevelLayoutManager) { + strength = ((BlockLevelLayoutManager)getParent()).getKeepTogetherStrength(); + } else if (getParent() instanceof InlineLayoutManager) { + if (((InlineLayoutManager) getParent()).mustKeepTogether()) { + strength = KEEP_ALWAYS; + } + //TODO Fix me + //strength = ((InlineLayoutManager) getParent()).getKeepTogetherStrength(); + } + return strength; + } + + /** {@inheritDoc} */ public boolean mustKeepTogether() { - return ((getParent() instanceof BlockLevelLayoutManager - && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) - || (getParent() instanceof InlineLayoutManager - && ((InlineLayoutManager) getParent()).mustKeepTogether())); + return getKeepTogetherStrength() > KEEP_AUTO; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { return false; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithNext() { return false; } diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java index a2baba2fc..9a87e71c4 100644 --- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java +++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java @@ -189,6 +189,23 @@ public class ElementListUtils { return last.isForcedBreak(); } + /** + * Indicates whether the given element list ends with a penalty with a non-infinite penalty + * value. + * @param elems the element list + * @return true if the list ends with a non-infinite penalty + */ + public static boolean endsWithNonInfinitePenalty(LinkedList elems) { + ListElement last = (ListElement)elems.getLast(); + if (last.isPenalty() && ((KnuthPenalty)last).getP() < KnuthElement.INFINITE) { + return true; + } else if (last instanceof BreakElement + && ((BreakElement)last).getPenaltyValue() < KnuthElement.INFINITE) { + return true; + } + return false; + } + /** * Determines the position of the previous break before the start index on an * element list. diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 115532cf1..ecfcbe2b4 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -208,10 +208,10 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public boolean mustKeepTogether() { - return false; + public int getKeepTogetherStrength() { + return KEEP_AUTO; } - + /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { return false; diff --git a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java index 71f4df314..351504cd7 100644 --- a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java @@ -19,11 +19,11 @@ package org.apache.fop.layoutmgr; +import java.util.LinkedList; + import org.apache.fop.area.Area; import org.apache.fop.fo.flow.FootnoteBody; -import java.util.LinkedList; - /** * Layout manager for footnote bodies. */ @@ -91,4 +91,9 @@ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { return (FootnoteBody) fobj; } + /** {@inheritDoc} */ + public int getKeepTogetherStrength() { + return getParentKeepTogetherStrength(); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/KeepUtil.java b/src/java/org/apache/fop/layoutmgr/KeepUtil.java new file mode 100644 index 000000000..1fd595ae0 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/KeepUtil.java @@ -0,0 +1,70 @@ +/* + * 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.layoutmgr; + +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.properties.Property; + +/** + * Utility class for working with keeps. + */ +public class KeepUtil { + + /** + * Converts a keep property into an integer value. + *

                                                                                        + * Note: The conversion restricts the effectively available integer range by two values. + * Integer.MIN_VALUE is used to represent the value "auto" and + * Integer.MAX_VALUE is used to represebt the value "always". + * @param keep the keep property + * @return the keep value as an integer + */ + public static int getKeepStrength(Property keep) { + if (keep.isAuto()) { + return BlockLevelLayoutManager.KEEP_AUTO; + } else if (keep.getEnum() == Constants.EN_ALWAYS) { + return BlockLevelLayoutManager.KEEP_ALWAYS; + } else { + return keep.getNumber().intValue(); + } + } + + /** + * Returns the penalty value to be used for a certain keep strength. + *

                                                                                          + *
                                                                                        • "auto": returns 0
                                                                                        • + *
                                                                                        • "always": returns KnuthElement.INFINITE
                                                                                        • + *
                                                                                        • otherwise: returns KnuthElement.INFINITE - 1
                                                                                        • + *
                                                                                        + * @param keepStrength the keep strength + * @return the penalty value + */ + public static int getPenaltyForKeep(int keepStrength) { + if (keepStrength == BlockLevelLayoutManager.KEEP_AUTO) { + return 0; + } + int penalty = KnuthElement.INFINITE; + if (keepStrength < BlockLevelLayoutManager.KEEP_ALWAYS) { + penalty--; + } + return penalty; + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 763ddf58d..0d88f2a1d 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -405,5 +405,10 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { this.contentAreaBPD = contentAreaBPD; } + /** {@inheritDoc} */ + public int getKeepTogetherStrength() { + return KEEP_AUTO; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 1258fbe18..08a3f3eff 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -1271,13 +1271,16 @@ public class LineLayoutManager extends InlineStackingLayoutManager } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepTogether() { return ((BlockLevelLayoutManager) getParent()).mustKeepTogether(); } + /** {@inheritDoc} */ + public int getKeepTogetherStrength() { + return ((BlockLevelLayoutManager) getParent()).getKeepTogetherStrength(); + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index c17ddc711..eb64e0bf0 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -32,6 +32,7 @@ import org.apache.fop.fo.flow.ListBlock; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListUtils; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; @@ -278,15 +279,19 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public boolean mustKeepTogether() { - //TODO Keeps will have to be more sophisticated sooner or later - return super.mustKeepTogether() - || !getListBlockFO().getKeepTogether().getWithinPage().isAuto() - || !getListBlockFO().getKeepTogether().getWithinColumn().isAuto(); + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; + strength = Math.max(strength, KeepUtil.getKeepStrength( + getListBlockFO().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + getListBlockFO().getKeepTogether().getWithinColumn())); + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; } - + /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { + //TODO Keeps will have to be more sophisticated sooner or later return !getListBlockFO().getKeepWithPrevious().getWithinPage().isAuto() || !getListBlockFO().getKeepWithPrevious().getWithinColumn().isAuto(); } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 8b0028a8f..be7dbdbba 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -28,8 +28,8 @@ import org.apache.fop.area.Block; import org.apache.fop.fo.flow.AbstractListItemPart; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; @@ -221,12 +221,15 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public boolean mustKeepTogether() { - //TODO Keeps will have to be more sophisticated sooner or later - return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() - || !getPartFO().getKeepTogether().getWithinPage().isAuto() - || !getPartFO().getKeepTogether().getWithinColumn().isAuto(); + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; + strength = Math.max(strength, KeepUtil.getKeepStrength( + getPartFO().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + getPartFO().getKeepTogether().getWithinColumn())); + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; } - + } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index c6b5b8cf9..b727f8860 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -32,12 +32,12 @@ import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListItem; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.ElementListUtils; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; @@ -305,14 +305,17 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager //Additional penalty height from penalties in the source lists int additionalPenaltyHeight = 0; + int stepPenalty = 0; KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]); if (endEl instanceof KnuthPenalty) { additionalPenaltyHeight = endEl.getW(); + stepPenalty = Math.max(stepPenalty, endEl.getP()); } endEl = (KnuthElement)elementLists[1].get(end[1]); if (endEl instanceof KnuthPenalty) { additionalPenaltyHeight = Math.max( additionalPenaltyHeight, endEl.getW()); + stepPenalty = Math.max(stepPenalty, endEl.getP()); } int boxHeight = step - addedBoxHeight - penaltyHeight; @@ -324,10 +327,13 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager start[0], end[0], start[1], end[1]); returnList.add(new KnuthBox(boxHeight, stepPosition, false)); if (addedBoxHeight < totalHeight) { - int p = 0; - if (keepWithNextActive || mustKeepTogether()) { + int p = stepPenalty; + if (keepWithNextActive) { p = KnuthPenalty.INFINITE; } + if (mustKeepTogether()) { + p = Math.max(p, KeepUtil.getPenaltyForKeep(getKeepTogetherStrength())); + } returnList.add(new BreakElement(stepPosition, penaltyHeight, p, -1, context)); } } @@ -630,15 +636,19 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public boolean mustKeepTogether() { - //TODO Keeps will have to be more sophisticated sooner or later - return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() - || !getListItemFO().getKeepTogether().getWithinPage().isAuto() - || !getListItemFO().getKeepTogether().getWithinColumn().isAuto(); + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; + strength = Math.max(strength, KeepUtil.getKeepStrength( + getListItemFO().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + getListItemFO().getKeepTogether().getWithinColumn())); + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; } /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { + //TODO Keeps will have to be more sophisticated sooner or later return !getListItemFO().getKeepWithPrevious().getWithinPage().isAuto() || !getListItemFO().getKeepWithPrevious().getWithinColumn().isAuto(); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index 2e5bbdf1f..fc0d587ff 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -19,12 +19,12 @@ package org.apache.fop.layoutmgr.table; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; import org.apache.fop.fo.flow.table.TableAndCaption; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.area.Area; -import org.apache.fop.area.Block; /** * LayoutManager for a table-and-caption FO. @@ -191,5 +191,18 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { curBlockArea.addBlock((Block) childArea); } } -} - + + /** {@inheritDoc} */ + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; + /* TODO Complete me! + strength = Math.max(strength, KeepUtil.getKeepStrength( + getTableAndCaption().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + getTableAndCaption().getKeepTogether().getWithinColumn())); + */ + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; + } + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 674fd9a90..8c4908547 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -19,12 +19,12 @@ package org.apache.fop.layoutmgr.table; +import org.apache.fop.area.Area; +import org.apache.fop.area.Block; import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.area.Area; -import org.apache.fop.area.Block; /** * LayoutManager for a table-caption FO. @@ -46,6 +46,11 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { super(node); } + /** @return the table-caption FO */ + public TableCaption getTableCaption() { + return (TableCaption)this.fobj; + } + /** * Get the next break position for the caption. * @@ -190,5 +195,19 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { curBlockArea.addBlock((Block) childArea); } } + + /** {@inheritDoc} */ + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; + /* TODO Complete me! + strength = Math.max(strength, KeepUtil.getKeepStrength( + getTableCaption().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + getTableCaption().getKeepTogether().getWithinColumn())); + */ + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 8acfebca0..291e27ae2 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -27,7 +27,6 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.Trait; -import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; @@ -41,13 +40,12 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.layoutmgr.AreaAdditionUtil; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; -import org.apache.fop.layoutmgr.BreakElement; +import org.apache.fop.layoutmgr.KeepUtil; 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 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.SpaceResolver; @@ -162,46 +160,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager if (prevLM != null) { // there is a block handled by prevLM // before the one handled by curLM - if (mustKeepTogether() - || context.isKeepWithNextPending() - || childLC.isKeepWithPreviousPending()) { - //Clear keep pending flag - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); - // add an infinite penalty to forbid a break between - // blocks - contentList.add(new BreakElement( - new Position(this), KnuthElement.INFINITE, context)); - //contentList.add(new KnuthPenalty(0, - // KnuthElement.INFINITE, false, - // new Position(this), false)); - } else if (!(((ListElement) contentList.getLast()).isGlue() - || (((ListElement)contentList.getLast()).isPenalty() - && ((KnuthPenalty)contentList.getLast()).getP() < KnuthElement.INFINITE) - || (contentList.getLast() instanceof BreakElement - && ((BreakElement)contentList.getLast()).getPenaltyValue() < KnuthElement.INFINITE))) { - // TODO vh: this is hacky - // The getNextKnuthElements method of TableCellLM must not be called - // twice, otherwise some settings like indents or borders will be - // counted several times and lead to a wrong output. Anyway the - // getNextKnuthElements methods should be called only once eventually - // (i.e., when multi-threading the code), even when there are forced - // breaks. - // If we add a break possibility after a forced break the - // AreaAdditionUtil.addAreas method will act on a sequence starting - // with a SpaceResolver.SpaceHandlingBreakPosition element, having no - // LM associated to it. Thus it will stop early instead of adding - // areas for following Positions. The above test aims at preventing - // such a situation from occurring. add a null penalty to allow a break - // between blocks - contentList.add(new BreakElement( - new Position(this), 0, context)); - //contentList.add(new KnuthPenalty(0, 0, false, - // new Position(this), false)); - } else { - // the last element in contentList is a feasible breakpoint, there is - // no need to add a penalty - } + addInBetweenBreak(contentList, context, childLC); } contentList.addAll(returnedList); if (returnedList.size() == 0) { @@ -596,22 +555,22 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager // TODO Auto-generated method stub } - /** - * {@inheritDoc} - */ - public boolean mustKeepTogether() { - //TODO Keeps will have to be more sophisticated sooner or later - boolean keep = ((BlockLevelLayoutManager)getParent()).mustKeepTogether(); + /** {@inheritDoc} */ + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; if (primaryGridUnit.getRow() != null) { - keep |= primaryGridUnit.getRow().mustKeepTogether(); + strength = Math.max(strength, KeepUtil.getKeepStrength( + primaryGridUnit.getRow().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + primaryGridUnit.getRow().getKeepTogether().getWithinColumn())); } - return keep; + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { + //TODO Keeps will have to be more sophisticated sooner or later return false; //TODO FIX ME /* return !fobj.getKeepWithPrevious().getWithinPage().isAuto() @@ -619,9 +578,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager */ } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithNext() { return false; //TODO FIX ME /* diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 7cdeb79d5..235bc1fd2 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -27,6 +27,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; @@ -36,6 +37,7 @@ import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListUtils; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPossPosIter; @@ -226,9 +228,12 @@ public class TableContentLayoutManager implements PercentBaseContext { nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); int penaltyValue = 0; keepBetween |= context.isKeepWithPreviousPending(); - if (keepBetween || tableLM.getTable().mustKeepTogether()) { + if (keepBetween) { penaltyValue = KnuthElement.INFINITE; } + penaltyValue = Math.max(penaltyValue, + KeepUtil.getPenaltyForKeep(getTableLM().getKeepTogetherStrength())); + breakBetween = BreakUtil.compareBreakClasses(breakBetween, context.getBreakBefore()); if (breakBetween != Constants.EN_AUTO) { diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 720ca5faa..5738a027c 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -39,6 +39,7 @@ import org.apache.fop.layoutmgr.BlockLevelEventProducer; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ConditionalElementListener; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.LayoutContext; @@ -445,16 +446,17 @@ public class TableLayoutManager extends BlockStackingLayoutManager } - /** - * {@inheritDoc} - */ - public boolean mustKeepTogether() { - //TODO Keeps will have to be more sophisticated sooner or later - return super.mustKeepTogether() - || !getTable().getKeepTogether().getWithinPage().isAuto() - || !getTable().getKeepTogether().getWithinColumn().isAuto(); + /** {@inheritDoc} */ + public int getKeepTogetherStrength() { + int strength = KEEP_AUTO; + strength = Math.max(strength, KeepUtil.getKeepStrength( + getTable().getKeepTogether().getWithinPage())); + strength = Math.max(strength, KeepUtil.getKeepStrength( + getTable().getKeepTogether().getWithinColumn())); + strength = Math.max(strength, getParentKeepTogetherStrength()); + return strength; } - + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index ba67e38e4..07894a07b 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -25,11 +25,13 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.Constants; 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.layoutmgr.BreakElement; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.KnuthPenalty; @@ -234,13 +236,15 @@ public class TableStepper { ActiveCell activeCell = (ActiveCell) iter.next(); keepWithNext |= activeCell.keepWithNextSignal(); } - if (keepWithNext || getTableLM().mustKeepTogether()) { + if (keepWithNext) { p = KnuthPenalty.INFINITE; } if (!rowFinished) { - if (rowGroup[activeRowIndex].mustKeepTogether()) { - p = KnuthPenalty.INFINITE; - } + p = Math.max(p, KeepUtil.getPenaltyForKeep( + rowGroup[activeRowIndex].getKeepTogetherStrength())); + //The above call doesn't take the penalty from the table into account, so... + p = Math.max(p, KeepUtil.getPenaltyForKeep( + getTableLM().getKeepTogetherStrength())); } else if (activeRowIndex < rowGroup.length - 1) { if (rowGroup[activeRowIndex].mustKeepWithNext() || rowGroup[activeRowIndex + 1].mustKeepWithPrevious()) { diff --git a/test/layoutengine/standard-testcases/block-container_keep-together_integers_1.xml b/test/layoutengine/standard-testcases/block-container_keep-together_integers_1.xml new file mode 100644 index 000000000..24a779303 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_keep-together_integers_1.xml @@ -0,0 +1,95 @@ + + + + + +

                                                                                        + This test checks keep-together with integer values. +

                                                                                        +

                                                                                        + Widows and Orphans are disabled in this test to avoid side-effects. +

                                                                                        +
                                                                                        + + + + + + + + + + + + + block1 + block2 + + + block3 + block4 + + + + block5 + block6 + + + + block7 + block8 + + + + + block9 + blockA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + +
                                                                                        diff --git a/test/layoutengine/standard-testcases/block_keep-together_integers_1.xml b/test/layoutengine/standard-testcases/block_keep-together_integers_1.xml new file mode 100644 index 000000000..f6027bf01 --- /dev/null +++ b/test/layoutengine/standard-testcases/block_keep-together_integers_1.xml @@ -0,0 +1,100 @@ + + + + + +

                                                                                        + This test checks keep-together with integer values. +

                                                                                        +

                                                                                        + Widows and Orphans are disabled in this test to avoid side-effects. +

                                                                                        +
                                                                                        + + + + + + + + + + block1 + block2 + block3 + + The quick brown fox jumps over the lazy dog. + The quick brown fox jumps over the lazy dog. + The quick brown fox jumps over the lazy dog. + + + + block4 + block5 + + block6 + block7 + block8 + block9 + + block10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + +
                                                                                        diff --git a/test/layoutengine/standard-testcases/block_keep-together_integers_2.xml b/test/layoutengine/standard-testcases/block_keep-together_integers_2.xml new file mode 100644 index 000000000..f07c28fbe --- /dev/null +++ b/test/layoutengine/standard-testcases/block_keep-together_integers_2.xml @@ -0,0 +1,95 @@ + + + + + +

                                                                                        + This test checks keep-together with integer values. +

                                                                                        +

                                                                                        + Widows and Orphans are disabled in this test to avoid side-effects. +

                                                                                        +
                                                                                        + + + + + + + + + + + + + block1 + block2 + + + block3 + block4 + + + + block5 + block6 + + + + block7 + block8 + + + + + block9 + blockA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + +
                                                                                        diff --git a/test/layoutengine/standard-testcases/block_keep-together_overflow_1.xml b/test/layoutengine/standard-testcases/block_keep-together_overflow_1.xml index a4a2de62c..b940ad837 100644 --- a/test/layoutengine/standard-testcases/block_keep-together_overflow_1.xml +++ b/test/layoutengine/standard-testcases/block_keep-together_overflow_1.xml @@ -44,7 +44,7 @@ block1 block2 - + block3 block4 block5 @@ -53,7 +53,7 @@ block8 block9 - + block10 block11 block12 diff --git a/test/layoutengine/standard-testcases/list-block_keep-together.xml b/test/layoutengine/standard-testcases/list-block_keep-together.xml index bd11d2b23..757b02539 100644 --- a/test/layoutengine/standard-testcases/list-block_keep-together.xml +++ b/test/layoutengine/standard-testcases/list-block_keep-together.xml @@ -25,14 +25,15 @@ - + block1 - + @@ -54,16 +55,16 @@ block2 - - + + label1 item1 - item1 @@ -76,10 +77,43 @@ block3 + + + + label1 + + + item1 + item1 + + + + + label1 + + + item1 + item1 + + + + label3 + + + item3 + + + + block4 + + + label1 @@ -88,47 +122,80 @@ item1 - + label2 - + + item2 item2 + + + label3 + + + item3 + + - block4 + block5 - + + + - + + - - + + + - + + + + + + + + + + + + + + + + + + + + + 3 diff --git a/test/layoutengine/standard-testcases/table_keep-together.xml b/test/layoutengine/standard-testcases/table_keep-together.xml index dc3a6f0c0..227f5ede4 100644 --- a/test/layoutengine/standard-testcases/table_keep-together.xml +++ b/test/layoutengine/standard-testcases/table_keep-together.xml @@ -25,16 +25,16 @@ - + block1 - - - + + + @@ -58,6 +58,35 @@ block2 + + + block1b + + + + + + + line1 + line2 + + + line1 + + + + + line1 + + + line1 + + + + + block2b + + @@ -69,7 +98,7 @@ - + @@ -79,5 +108,27 @@ 3 + + + + + + + + + + + + + + + + + + + + + 3 + -- cgit v1.2.3 From 0caddb1f5ef53f3b725bdd94fa99fb95326942d7 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Apr 2008 07:01:19 +0000 Subject: HeadURL was missing in the properties. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@648985 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/Version.java b/src/java/org/apache/fop/Version.java index 4545d071e..7e421ad29 100644 --- a/src/java/org/apache/fop/Version.java +++ b/src/java/org/apache/fop/Version.java @@ -41,7 +41,7 @@ public final class Version { if (version == null) { //Fallback if FOP is used in a development environment String headURL - = "$HeadURL: http://svn.apache.org/repos/asf/xmlgraphics/fop/trunk/src/java/org/apache/fop/Version.java $"; + = "$HeadURL$"; version = headURL; final String pathPrefix = "/xmlgraphics/fop/"; int pos = version.indexOf(pathPrefix); -- cgit v1.2.3 From 54e844c8c55d8f4adc7a4579771276dc7229794b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Apr 2008 08:59:48 +0000 Subject: Bugfix: Avoid stopping early when no EmbedFontInfos are found during font detection. Submitted by: Raphael Parree git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649012 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/PrintRendererConfigurator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index ccff3baa1..674c357df 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -236,7 +236,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator EmbedFontInfo[] embedFontInfos = finder.find(fontUrl, resolver, fontCache); if (embedFontInfos == null) { - return; + continue; } for (int i = 0, c = embedFontInfos.length; i < c; i++) { -- cgit v1.2.3 From e5ee5c2bcf5872ecaf03c6e6e8c5a73904ee4a67 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Apr 2008 13:33:07 +0000 Subject: Bugzilla #44678: Added ability to pass in the PrinterJob instance through the renderer options. Submitted by: Antti Karanta Modifications/Additions to patch: - Don't remove the contructor with the PrinterJob parameter, just deprecate it. - Adjust old-style print example to use renderer options git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649091 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/embedding/ExampleFO2OldStylePrint.java | 24 +++----- .../org/apache/fop/render/print/PrintRenderer.java | 67 +++++++++++++++++----- status.xml | 4 ++ 3 files changed, 65 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/examples/embedding/java/embedding/ExampleFO2OldStylePrint.java b/examples/embedding/java/embedding/ExampleFO2OldStylePrint.java index 588d2c5d7..d9bc1d11d 100644 --- a/examples/embedding/java/embedding/ExampleFO2OldStylePrint.java +++ b/examples/embedding/java/embedding/ExampleFO2OldStylePrint.java @@ -24,21 +24,18 @@ import java.awt.print.PrinterJob; import java.io.File; import java.io.IOException; -//JAXP +import javax.xml.transform.Result; +import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; -import javax.xml.transform.Source; -import javax.xml.transform.Result; -import javax.xml.transform.stream.StreamSource; import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamSource; - -// FOP +import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; -import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FopFactory; -import org.apache.fop.render.print.PrintRenderer; +import org.apache.fop.apps.MimeConstants; /** * This class demonstrates printing an FO file to a PrinterJob instance. @@ -63,15 +60,10 @@ public class ExampleFO2OldStylePrint { try { //Set up a custom user agent so we can supply our own renderer instance FOUserAgent userAgent = fopFactory.newFOUserAgent(); + userAgent.getRendererOptions().put("printerjob", printerJob); - //Set up our own PrintRenderer instance so we can supply a special PrinterJob instance. - PrintRenderer renderer = new PrintRenderer(printerJob); - renderer.setUserAgent(userAgent); - - userAgent.setRendererOverride(renderer); - - // Construct fop with desired output format (here, it is set through the user agent) - Fop fop = fopFactory.newFop(userAgent); + // Construct FOP with desired output format + Fop fop = fopFactory.newFop(MimeConstants.MIME_FOP_PRINT, userAgent); // Setup JAXP using identity transformer TransformerFactory factory = TransformerFactory.newInstance(); diff --git a/src/java/org/apache/fop/render/print/PrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java index e4c159815..b70bb21aa 100644 --- a/src/java/org/apache/fop/render/print/PrintRenderer.java +++ b/src/java/org/apache/fop/render/print/PrintRenderer.java @@ -27,9 +27,11 @@ import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.IOException; +import java.util.Map; import java.util.Vector; import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.render.java2d.Java2DRenderer; /** @@ -40,6 +42,13 @@ import org.apache.fop.render.java2d.Java2DRenderer; */ public class PrintRenderer extends Java2DRenderer implements Pageable { + /** + * Printing parameter: the preconfigured PrinterJob to use, + * datatype: java.awt.print.PrinterJob + */ + public static final String PRINTER_JOB = "printerjob"; + + private static final int EVEN_AND_ALL = 0; private static final int EVEN = 1; @@ -57,23 +66,42 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { private PrinterJob printerJob; /** - * Creates a new PrintRenderer with the options set from system properties. + * Creates a new PrintRenderer with the options set from system properties if a custom + * PrinterJob is not given in FOUserAgent's renderer options. */ public PrintRenderer() { - initializePrinterJob(); + setupFromSystemProperties(); } - + /** * Creates a new PrintRenderer and allows you to pass in a specific PrinterJob instance * that this renderer should work with. * @param printerJob the PrinterJob instance + * @deprecated Please use the rendering options on the user agent to pass in the PrinterJob! */ public PrintRenderer(PrinterJob printerJob) { + this(); this.printerJob = printerJob; printerJob.setPageable(this); } - private void initializePrinterJob() throws IllegalArgumentException { + private void initializePrinterJob() { + if (this.printerJob == null) { + printerJob = PrinterJob.getPrinterJob(); + printerJob.setJobName("FOP Document"); + printerJob.setCopies(copies); + if (System.getProperty("dialog") != null) { + if (!printerJob.printDialog()) { + throw new RuntimeException( + "Printing cancelled by operator"); + } + } + printerJob.setPageable(this); + } + } + + private void setupFromSystemProperties() { + //TODO Remove me! This is not a beautiful way to do this. // read from command-line options copies = getIntProperty("copies", 1); startNumber = getIntProperty("start", 1) - 1; @@ -82,19 +110,28 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { if (str != null) { mode = Boolean.valueOf(str).booleanValue() ? EVEN : ODD; } - - printerJob = PrinterJob.getPrinterJob(); - printerJob.setJobName("FOP Document"); - printerJob.setCopies(copies); - if (System.getProperty("dialog") != null) { - if (!printerJob.printDialog()) { + } + + /** {@inheritDoc} */ + public void setUserAgent(FOUserAgent agent) { + super.setUserAgent(agent); + + Map rendererOptions = agent.getRendererOptions(); + + Object printerJobO = rendererOptions.get(PrintRenderer.PRINTER_JOB); + if (printerJobO != null) { + if (!(printerJobO instanceof PrinterJob)) { throw new IllegalArgumentException( - "Printing cancelled by operator"); + "Renderer option " + PrintRenderer.PRINTER_JOB + + " must be an instance of java.awt.print.PrinterJob, but an instance of " + + printerJobO.getClass().getName() + " was given."); } + printerJob = (PrinterJob)printerJobO; + printerJob.setPageable(this); } - printerJob.setPageable(this); + initializePrinterJob(); } - + /** @return the PrinterJob instance that this renderer prints to */ public PrinterJob getPrinterJob() { return this.printerJob; @@ -126,6 +163,7 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { this.startNumber = start; } + /** {@inheritDoc} */ public void stopRenderer() throws IOException { super.stopRenderer(); @@ -149,7 +187,7 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { clearViewportList(); } - public static int getIntProperty(String name, int def) { + private static int getIntProperty(String name, int def) { String propValue = System.getProperty(name); if (propValue != null) { try { @@ -219,6 +257,7 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { } } + /** {@inheritDoc} */ public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException { return this; diff --git a/status.xml b/status.xml index a70aebb4d..640b2e8af 100644 --- a/status.xml +++ b/status.xml @@ -58,6 +58,10 @@ Added SVG support for AFP (GOCA). --> + + Added ability to pass a preconfigured PrinterJob instance to the PrintRenderer via + the rendering options map. + Added a public accessor for reference to the current page to PDFGraphics2D. -- cgit v1.2.3 From 2110cefe609d1ec729fb271e970809d2a84e5af4 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 17 Apr 2008 14:10:04 +0000 Subject: Fixed minor typo git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649119 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/embedding.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/embedding.xml b/src/documentation/content/xdocs/trunk/embedding.xml index 9ed42dd9d..95e96104b 100644 --- a/src/documentation/content/xdocs/trunk/embedding.xml +++ b/src/documentation/content/xdocs/trunk/embedding.xml @@ -183,7 +183,7 @@ try { how to configure alternative backends.

                                                                                        - As a result of the above we differentiate between to kinds of "logging": + As a result of the above we differentiate between two kinds of "logging":

                                                                                        • (FOP-)Developer-oriented logging
                                                                                        • -- cgit v1.2.3 From 5772532f675b18349b6c9262b1e5d8d645729fe6 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Apr 2008 15:12:23 +0000 Subject: Bugzilla #41687: Restored ability to specify from/to and odd/even pages as well as the number of copies for printing from the command-line. Note that this is no longer done via system properties but through the renderer options. Syntax is slightly different. See "fop -print help". git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649146 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/cli/CommandLineOptions.java | 61 +++++++++++--- src/java/org/apache/fop/cli/Main.java | 5 +- .../apache/fop/render/java2d/Java2DRenderer.java | 7 +- .../org/apache/fop/render/print/PagesMode.java | 69 ++++++++++++++++ .../org/apache/fop/render/print/PrintRenderer.java | 92 ++++++++++++++++++---- status.xml | 4 + 6 files changed, 207 insertions(+), 31 deletions(-) create mode 100644 src/java/org/apache/fop/render/print/PagesMode.java (limited to 'src') diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index 3bb0aae7f..4e5c8ae44 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -46,6 +46,8 @@ import org.apache.fop.pdf.PDFXMode; import org.apache.fop.render.Renderer; import org.apache.fop.render.awt.AWTRenderer; import org.apache.fop.render.pdf.PDFRenderer; +import org.apache.fop.render.print.PagesMode; +import org.apache.fop.render.print.PrintRenderer; import org.apache.fop.render.xml.XMLRenderer; import org.apache.fop.util.CommandLineLogger; @@ -133,8 +135,9 @@ public class CommandLineOptions { * @throws FOPException for general errors * @throws FileNotFoundException if an input file wasn't found * @throws IOException if the the configuration file could not be loaded + * @return true if the processing can continue, false to abort */ - public void parse(String[] args) + public boolean parse(String[] args) throws FOPException, IOException { boolean optionsParsed = true; @@ -155,6 +158,8 @@ public class CommandLineOptions { } addXSLTParameter("fop-output-format", getOutputFormat()); addXSLTParameter("fop-version", Version.getVersion()); + } else { + return false; } } catch (FOPException e) { printUsage(); @@ -193,6 +198,7 @@ public class CommandLineOptions { //Make sure the prepared XMLRenderer is used foUserAgent.setRendererOverride(xmlRenderer); } + return true; } /** @@ -268,7 +274,6 @@ public class CommandLineOptions { } else if (args[i].equals("-png")) { i = i + parsePNGOutputOption(args, i); } else if (args[i].equals("-print")) { - i = i + parsePrintOutputOption(args, i); // show print help if (i + 1 < args.length) { if (args[i + 1].equals("help")) { @@ -276,6 +281,9 @@ public class CommandLineOptions { return false; } } + i = i + parsePrintOutputOption(args, i); + } else if (args[i].equals("-copies")) { + i = i + parseCopiesOption(args, i); } else if (args[i].equals("-pcl")) { i = i + parsePCLOutputOption(args, i); } else if (args[i].equals("-ps")) { @@ -302,7 +310,7 @@ public class CommandLineOptions { String expression = args[++i]; addXSLTParameter(name, expression); } else { - throw new FOPException("invalid param usage: use -param "); + throw new FOPException("invalid param usage: use -param "); } } else if (args[i].equals("-o")) { i = i + parsePDFOwnerPassword(args, i); @@ -461,7 +469,37 @@ public class CommandLineOptions { private int parsePrintOutputOption(String[] args, int i) throws FOPException { setOutputMode(MimeConstants.MIME_FOP_PRINT); - return 0; + if ((i + 1 <= args.length) + && (args[i + 1].charAt(0) != '-')) { + String arg = args[i + 1]; + String[] parts = arg.split(","); + for (int j = 0; j < parts.length; j++) { + String s = parts[j]; + if (s.matches("\\d+")) { + renderingOptions.put(PrintRenderer.START_PAGE, new Integer(s)); + } else if (s.matches("\\d+-\\d+")) { + String[] startend = s.split("-"); + renderingOptions.put(PrintRenderer.START_PAGE, new Integer(startend[0])); + renderingOptions.put(PrintRenderer.END_PAGE, new Integer(startend[1])); + } else { + PagesMode mode = PagesMode.byName(s); + renderingOptions.put(PrintRenderer.PAGES_MODE, mode); + } + } + return 1; + } else { + return 0; + } + } + + private int parseCopiesOption(String[] args, int i) throws FOPException { + if ((i + 1 == args.length) + || (args[i + 1].charAt(0) == '-')) { + throw new FOPException("you must specify the number of copies"); + } else { + renderingOptions.put(PrintRenderer.COPIES, new Integer(args[i + 1])); + return 1; + } } private int parsePCLOutputOption(String[] args, int i) throws FOPException { @@ -991,18 +1029,21 @@ public class CommandLineOptions { + " Fop -xml foo.xml -xsl foo.xsl -foout foo.fo\n" + " Fop foo.fo -mif foo.mif\n" + " Fop foo.fo -rtf foo.rtf\n" - + " Fop foo.fo -print or Fop -print foo.fo \n" - + " Fop foo.fo -awt \n"); + + " Fop foo.fo -print\n" + + " Fop foo.fo -awt\n"); } /** * shows the options for print output */ private void printUsagePrintOutput() { - System.err.println("USAGE: -print [-Dstart=i] [-Dend=i] [-Dcopies=i] [-Deven=true|false] " - + " org.apache.fop.apps.Fop (..) -print \n" - + "Example:\n" - + "java -Dstart=1 -Dend=2 org.apache.Fop.apps.Fop infile.fo -print "); + System.err.println("USAGE: -print [from[-to][,even|odd]] [-copies numCopies]\n\n" + + "Example:\n" + + "all pages: Fop infile.fo -print\n" + + "all pages with two copies: Fop infile.fo -print -copies 2\n" + + "all pages starting with page 7: Fop infile.fo -print 7\n" + + "pages 2 to 3: Fop infile.fo -print 2-3\n" + + "only even page between 10 and 20: Fop infile.fo -print 10-20,even\n"); } /** diff --git a/src/java/org/apache/fop/cli/Main.java b/src/java/org/apache/fop/cli/Main.java index e2297380d..43da8d966 100644 --- a/src/java/org/apache/fop/cli/Main.java +++ b/src/java/org/apache/fop/cli/Main.java @@ -28,6 +28,7 @@ import java.net.URL; import java.util.List; import org.apache.commons.io.IOUtils; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; @@ -151,7 +152,9 @@ public class Main { try { options = new CommandLineOptions(); - options.parse(args); + if (!options.parse(args)) { + System.exit(1); + } foUserAgent = options.getFOUserAgent(); String outputFormat = options.getOutputFormat(); diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 0ffe3307a..1f3194949 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -121,9 +121,6 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** The 0-based current page number */ private int currentPageNumber = 0; - /** The 0-based total number of rendered pages */ - private int numberOfPages; - /** true if antialiasing is set */ protected boolean antialiasing = true; @@ -208,7 +205,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem public void stopRenderer() throws IOException { log.debug("Java2DRenderer stopped"); renderingDone = true; - numberOfPages = currentPageNumber; + int numberOfPages = currentPageNumber; // TODO set all vars to null for gc if (numberOfPages == 0) { new FOPException("No page could be rendered"); @@ -238,7 +235,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem * @return The 0-based total number of rendered pages */ public int getNumberOfPages() { - return numberOfPages; + return pageViewportList.size(); } /** diff --git a/src/java/org/apache/fop/render/print/PagesMode.java b/src/java/org/apache/fop/render/print/PagesMode.java new file mode 100644 index 000000000..6879aa68d --- /dev/null +++ b/src/java/org/apache/fop/render/print/PagesMode.java @@ -0,0 +1,69 @@ +/* + * 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.render.print; + +/** Enum class for pages mode (all, even, odd pages). */ +public final class PagesMode { + + /** the all pages mode */ + public static final PagesMode ALL = new PagesMode("all"); + /** the even pages mode */ + public static final PagesMode EVEN = new PagesMode("even"); + /** the odd pages mode */ + public static final PagesMode ODD = new PagesMode("odd"); + + private String name; + + /** + * Constructor to add a new named item. + * @param name Name of the item. + */ + private PagesMode(String name) { + this.name = name; + } + + /** @return the name of the enum */ + public String getName() { + return this.name; + } + + /** + * Returns a PagesMode instance by name. + * @param name the name of the pages mode + * @return the pages mode + */ + public static PagesMode byName(String name) { + if (PagesMode.ALL.getName().equalsIgnoreCase(name)) { + return PagesMode.ALL; + } else if (PagesMode.EVEN.getName().equalsIgnoreCase(name)) { + return PagesMode.EVEN; + } else if (PagesMode.ODD.getName().equalsIgnoreCase(name)) { + return PagesMode.ODD; + } else { + throw new IllegalArgumentException("Invalid value for PagesMode: " + name); + } + } + + /** {@inheritDoc} */ + public String toString() { + return "PagesMode:" + name; + } + +} diff --git a/src/java/org/apache/fop/render/print/PrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java index b70bb21aa..2774b5373 100644 --- a/src/java/org/apache/fop/render/print/PrintRenderer.java +++ b/src/java/org/apache/fop/render/print/PrintRenderer.java @@ -48,18 +48,35 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { */ public static final String PRINTER_JOB = "printerjob"; - - private static final int EVEN_AND_ALL = 0; - - private static final int EVEN = 1; + /** + * Printing parameter: the pages to be printed (all, even or odd), + * datatype: the strings "all", "even" or "odd" or one of PagesMode.* + */ + public static final String PAGES_MODE = "even-odd"; - private static final int ODD = 2; + /** + * Printing parameter: the page number (1-based) of the first page to be printed, + * datatype: a positive Integer + */ + public static final String START_PAGE = "start-page"; + /** + * Printing parameter: the page number (1-based) of the last page to be printed, + * datatype: a positive Integer + */ + public static final String END_PAGE = "end-page"; + + /** + * Printing parameter: the number of copies of the document to be printed, + * datatype: a positive Integer + */ + public static final String COPIES = "copies"; + + private int startNumber = 0; - private int endNumber = -1; - private int mode = EVEN_AND_ALL; + private PagesMode mode = PagesMode.ALL; private int copies = 1; @@ -104,11 +121,11 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { //TODO Remove me! This is not a beautiful way to do this. // read from command-line options copies = getIntProperty("copies", 1); - startNumber = getIntProperty("start", 1) - 1; + startNumber = getIntProperty("start", 1); endNumber = getIntProperty("end", -1); String str = System.getProperty("even"); if (str != null) { - mode = Boolean.valueOf(str).booleanValue() ? EVEN : ODD; + mode = Boolean.valueOf(str).booleanValue() ? PagesMode.EVEN : PagesMode.ODD; } } @@ -129,9 +146,53 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { printerJob = (PrinterJob)printerJobO; printerJob.setPageable(this); } + Object o = rendererOptions.get(PrintRenderer.PAGES_MODE); + if (o != null) { + if (o instanceof PagesMode) { + this.mode = (PagesMode)o; + } else if (o instanceof String) { + this.mode = PagesMode.byName((String)o); + } else { + throw new IllegalArgumentException( + "Renderer option " + PrintRenderer.PAGES_MODE + + " must be an 'all', 'even', 'odd' or a PagesMode instance."); + } + } + + o = rendererOptions.get(PrintRenderer.START_PAGE); + if (o != null) { + this.startNumber = getPositiveInteger(o); + } + o = rendererOptions.get(PrintRenderer.END_PAGE); + if (o != null) { + this.endNumber = getPositiveInteger(o); + } + if (this.endNumber >= 0 && this.endNumber < this.endNumber) { + this.endNumber = this.startNumber; + } + o = rendererOptions.get(PrintRenderer.COPIES); + if (o != null) { + this.copies = getPositiveInteger(o); + } initializePrinterJob(); } + private int getPositiveInteger(Object o) { + if (o instanceof Integer) { + Integer i = (Integer)o; + if (i.intValue() < 1) { + throw new IllegalArgumentException( + "Value must be a positive Integer"); + } + return i.intValue(); + } else if (o instanceof String) { + return Integer.parseInt((String)o); + } else { + throw new IllegalArgumentException( + "Value must be a positive integer"); + } + } + /** @return the PrinterJob instance that this renderer prints to */ public PrinterJob getPrinterJob() { return this.printerJob; @@ -174,7 +235,8 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { Vector numbers = getInvalidPageNumbers(); for (int i = numbers.size() - 1; i > -1; i--) { - // removePage(Integer.parseInt((String)numbers.elementAt(i))); + int page = ((Integer)numbers.elementAt(i)).intValue(); + pageViewportList.remove(page - 1); } try { @@ -204,20 +266,20 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { Vector vec = new Vector(); int max = getNumberOfPages(); boolean isValid; - for (int i = 0; i < max; i++) { + for (int i = 1; i <= max; i++) { isValid = true; if (i < startNumber || i > endNumber) { isValid = false; - } else if (mode != EVEN_AND_ALL) { - if (mode == EVEN && ((i + 1) % 2 != 0)) { + } else if (mode != PagesMode.ALL) { + if (mode == PagesMode.EVEN && (i % 2 != 0)) { isValid = false; - } else if (mode == ODD && ((i + 1) % 2 != 1)) { + } else if (mode == PagesMode.ODD && (i % 2 == 0)) { isValid = false; } } if (!isValid) { - vec.add(Integer.toString(i)); + vec.add(new Integer(i)); } } return vec; diff --git a/status.xml b/status.xml index 640b2e8af..5fd349180 100644 --- a/status.xml +++ b/status.xml @@ -58,6 +58,10 @@ Added SVG support for AFP (GOCA). --> + + Restored ability to specify from/to and odd/even pages as well as the number of copies + for printing from the command-line. + Added ability to pass a preconfigured PrinterJob instance to the PrintRenderer via the rendering options map. -- cgit v1.2.3 From e7c4e9837b27b08c619533a0946697a65fa66284 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Apr 2008 15:14:26 +0000 Subject: Bugzilla #43383: Made sure the pages don't appear out of order in AWT preview. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649149 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/awt/AWTRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java index e646f9b9c..2f2631786 100644 --- a/src/java/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java @@ -43,8 +43,8 @@ import org.apache.fop.apps.MimeConstants; import org.apache.fop.area.Area; import org.apache.fop.area.PageViewport; import org.apache.fop.render.awt.viewer.PreviewDialog; -import org.apache.fop.render.awt.viewer.StatusListener; import org.apache.fop.render.awt.viewer.Renderable; +import org.apache.fop.render.awt.viewer.StatusListener; import org.apache.fop.render.java2d.Java2DRenderer; /** @@ -202,7 +202,7 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { /** {@inheritDoc} */ public boolean supportsOutOfOrder() { - return true; // TODO true? + return false; } /** {@inheritDoc} */ -- cgit v1.2.3 From 867bded418d667d3d5889b8ac66169a676623f86 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Apr 2008 21:23:15 +0000 Subject: clone() did not propagate the page's page index. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649279 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/PageViewport.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java index da7ef1def..745160d44 100644 --- a/src/java/org/apache/fop/area/PageViewport.java +++ b/src/java/org/apache/fop/area/PageViewport.java @@ -124,6 +124,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl if (original.extensionAttachments != null) { this.extensionAttachments = new java.util.ArrayList(original.extensionAttachments); } + this.pageIndex = original.pageIndex; this.pageNumber = original.pageNumber; this.pageNumberString = original.pageNumberString; this.page = (Page)original.page.clone(); -- cgit v1.2.3 From c7cf9e0dd189de4960bcc44d9a10d217bbd13896 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Apr 2008 21:25:02 +0000 Subject: Throw a useful exception when the user agent isn't set on the renderer. This has been a problem for more than one person setting up their own renderer using FOUserAgent.setRendererOverride(). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649283 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/AbstractRenderer.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index ca3d007d0..816fa4067 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -124,12 +124,19 @@ public abstract class AbstractRenderer /** {@inheritDoc} */ public FOUserAgent getUserAgent() { + if (userAgent == null) { + throw new IllegalStateException("FOUserAgent has not been set on Renderer"); + } return userAgent; } /** {@inheritDoc} */ public void startRenderer(OutputStream outputStream) - throws IOException { } + throws IOException { + if (userAgent == null) { + throw new IllegalStateException("FOUserAgent has not been set on Renderer"); + } + } /** {@inheritDoc} */ public void stopRenderer() -- cgit v1.2.3 From 58ca051e721f34639915b469b9f3275b610c71ec Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Apr 2008 21:27:46 +0000 Subject: Split PrintRenderer into PageableRenderer and PrintRenderer (extends PageableRenderer). This allows the use of FOP with JPS. A new example illustrates how this is done. Removed the code that sets start/end/copies from system properties (now done through renderer options). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649285 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/embedding/ExampleFO2JPSPrint.java | 143 ++++++++++++++ .../apache/fop/render/java2d/Java2DRenderer.java | 30 ++- .../apache/fop/render/print/PageableRenderer.java | 214 +++++++++++++++++++++ .../org/apache/fop/render/print/PrintRenderer.java | 176 +---------------- 4 files changed, 382 insertions(+), 181 deletions(-) create mode 100644 examples/embedding/java/embedding/ExampleFO2JPSPrint.java create mode 100644 src/java/org/apache/fop/render/print/PageableRenderer.java (limited to 'src') diff --git a/examples/embedding/java/embedding/ExampleFO2JPSPrint.java b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java new file mode 100644 index 000000000..a67e2bdad --- /dev/null +++ b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java @@ -0,0 +1,143 @@ +/* + * 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 embedding; + +// Java +import java.io.File; +import java.io.IOException; + +import javax.print.Doc; +import javax.print.DocFlavor; +import javax.print.DocPrintJob; +import javax.print.PrintException; +import javax.print.PrintService; +import javax.print.PrintServiceLookup; +import javax.print.ServiceUI; +import javax.print.SimpleDoc; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.render.print.PageableRenderer; + +/** + * This class demonstrates printing an FO file using JPS (Java Printing System). + */ +public class ExampleFO2JPSPrint { + + // configure fopFactory as desired + private FopFactory fopFactory = FopFactory.newInstance(); + + private DocPrintJob createDocPrintJob() { + PrintService[] services = PrintServiceLookup.lookupPrintServices( + DocFlavor.SERVICE_FORMATTED.PAGEABLE, null); + PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet(); + PrintService printService = ServiceUI.printDialog(null, 50, 50, + services, services[0], null, attributes); + if (printService != null) { + return printService.createPrintJob(); + } else { + return null; + } + } + + /** + * Prints an FO file using JPS. + * @param fo the FO file + * @throws IOException In case of an I/O problem + * @throws FOPException In case of a FOP problem + * @throws TransformerException In case of a problem during XSLT processing + * @throws PrintException If an error occurs while printing + */ + public void printFO(File fo) + throws IOException, FOPException, TransformerException, PrintException { + + //Set up DocPrintJob instance + DocPrintJob printJob = createDocPrintJob(); + + //Set up a custom user agent so we can supply our own renderer instance + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + PageableRenderer renderer = new PageableRenderer(); + renderer.setUserAgent(userAgent); + userAgent.setRendererOverride(renderer); + + // Construct FOP with desired output format + Fop fop = fopFactory.newFop(userAgent); + + // Setup JAXP using identity transformer + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(); // identity transformer + + // Setup input stream + Source src = new StreamSource(fo); + + // Resulting SAX events (the generated FO) must be piped through to FOP + Result res = new SAXResult(fop.getDefaultHandler()); + + // Start XSLT transformation and FOP processing + transformer.transform(src, res); + + Doc doc = new SimpleDoc(renderer, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null); + printJob.print(doc, null); + } + + /** + * Main method. + * @param args command-line arguments + */ + public static void main(String[] args) { + try { + System.out.println("FOP ExampleFO2JPSPrint\n"); + System.out.println("Preparing..."); + + //Setup directories + File baseDir = new File("."); + File outDir = new File(baseDir, "out"); + outDir.mkdirs(); + + //Setup input and output files + File fofile = new File(baseDir, "xml/fo/helloworld.fo"); + + System.out.println("Input: XSL-FO (" + fofile + ")"); + System.out.println("Output: JPS (Java Printing System)"); + System.out.println(); + System.out.println("Transforming..."); + + ExampleFO2JPSPrint app = new ExampleFO2JPSPrint(); + app.printFO(fofile); + + System.out.println("Success!"); + } catch (Exception e) { + e.printStackTrace(System.err); + System.exit(-1); + } + } +} diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 1f3194949..db8ed6250 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -198,6 +198,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** {@inheritDoc} */ public void startRenderer(OutputStream out) throws IOException { + super.startRenderer(out); // do nothing by default } @@ -232,7 +233,9 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } /** + * Returns the number of pages available. This method is also part of the Pageable interface. * @return The 0-based total number of rendered pages + * @see java.awt.print.Pageable */ public int getNumberOfPages() { return pageViewportList.size(); @@ -250,7 +253,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** * This method override only stores the PageViewport in a List. No actual * rendering is performed here. A renderer override renderPage() to get the - * freshly produced PageViewport, and rendere them on the fly (producing the + * freshly produced PageViewport, and render them on the fly (producing the * desired BufferedImages by calling getPageImage(), which lazily starts the * rendering process). * @@ -260,11 +263,22 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem * @see org.apache.fop.render.Renderer */ public void renderPage(PageViewport pageViewport) throws IOException { - // TODO clone? - pageViewportList.add(pageViewport.clone()); + rememberPage((PageViewport)pageViewport.clone()); + //The clone() call is necessary as we store the page for later. Otherwise, the + //RenderPagesModel calls PageViewport.clear() to release memory as early as possible. currentPageNumber++; } + /** + * Stores the pageViewport in a list of page viewports so they can be rendered later. + * Subclasses can override this method to filter pages, for example. + * @param pageViewport the page viewport + */ + protected void rememberPage(PageViewport pageViewport) { + assert pageViewport.getPageIndex() >= 0; + pageViewportList.add(pageViewport); + } + /** * Generates a desired page from the renderer's page viewport list. * @@ -362,17 +376,17 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** * Returns a page viewport. - * @param pageNum the page number + * @param pageIndex the page index (zero-based) * @return the requested PageViewport instance * @exception FOPException If the page is out of range. */ - public PageViewport getPageViewport(int pageNum) throws FOPException { - if (pageNum < 0 || pageNum >= pageViewportList.size()) { - throw new FOPException("Requested page number is out of range: " + pageNum + public PageViewport getPageViewport(int pageIndex) throws FOPException { + if (pageIndex < 0 || pageIndex >= pageViewportList.size()) { + throw new FOPException("Requested page number is out of range: " + pageIndex + "; only " + pageViewportList.size() + " page(s) available."); } - return (PageViewport) pageViewportList.get(pageNum); + return (PageViewport) pageViewportList.get(pageIndex); } /** diff --git a/src/java/org/apache/fop/render/print/PageableRenderer.java b/src/java/org/apache/fop/render/print/PageableRenderer.java new file mode 100644 index 000000000..947708cef --- /dev/null +++ b/src/java/org/apache/fop/render/print/PageableRenderer.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.render.print; + +import java.awt.geom.Rectangle2D; +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.io.IOException; +import java.util.Map; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.area.PageViewport; +import org.apache.fop.render.java2d.Java2DRenderer; + +/** + * Renderer that prints through java.awt.PrintJob. + * The actual printing is handled by Java2DRenderer + * since both PrintRenderer and AWTRenderer need to + * support printing. + */ +public class PageableRenderer extends Java2DRenderer implements Pageable { + + /** + * Printing parameter: the pages to be printed (all, even or odd), + * datatype: the strings "all", "even" or "odd" or one of PagesMode.* + */ + public static final String PAGES_MODE = "even-odd"; + + /** + * Printing parameter: the page number (1-based) of the first page to be printed, + * datatype: a positive Integer + */ + public static final String START_PAGE = "start-page"; + + /** + * Printing parameter: the page number (1-based) of the last page to be printed, + * datatype: a positive Integer + */ + public static final String END_PAGE = "end-page"; + + + /** first valid page number (1-based) */ + protected int startNumber = 0; + /** last valid page number (1-based) */ + protected int endNumber = -1; + + /** indicates which pages are valid: odd, even or all */ + protected PagesMode mode = PagesMode.ALL; + + private PageFilter pageFilter; + + /** + * Creates a new PageableRenderer. + */ + public PageableRenderer() { + } + + /** {@inheritDoc} */ + public void setUserAgent(FOUserAgent agent) { + super.setUserAgent(agent); + + Map rendererOptions = agent.getRendererOptions(); + processOptions(rendererOptions); + this.pageFilter = new DefaultPageFilter(); + } + + private void processOptions(Map rendererOptions) { + Object o = rendererOptions.get(PageableRenderer.PAGES_MODE); + if (o != null) { + if (o instanceof PagesMode) { + this.mode = (PagesMode)o; + } else if (o instanceof String) { + this.mode = PagesMode.byName((String)o); + } else { + throw new IllegalArgumentException( + "Renderer option " + PageableRenderer.PAGES_MODE + + " must be an 'all', 'even', 'odd' or a PagesMode instance."); + } + } + + o = rendererOptions.get(PageableRenderer.START_PAGE); + if (o != null) { + this.startNumber = getPositiveInteger(o); + } + o = rendererOptions.get(PageableRenderer.END_PAGE); + if (o != null) { + this.endNumber = getPositiveInteger(o); + } + if (this.endNumber >= 0 && this.endNumber < this.endNumber) { + this.endNumber = this.startNumber; + } + } + + /** + * Converts an object into a positive integer value if possible. The method throws an + * {@link IllegalArgumentException} if the value is invalid. + * @param o the object to be converted + * @return the positive integer + */ + protected int getPositiveInteger(Object o) { + if (o instanceof Integer) { + Integer i = (Integer)o; + if (i.intValue() < 1) { + throw new IllegalArgumentException( + "Value must be a positive Integer"); + } + return i.intValue(); + } else if (o instanceof String) { + return Integer.parseInt((String)o); + } else { + throw new IllegalArgumentException( + "Value must be a positive integer"); + } + } + + /** {@inheritDoc} */ + public void stopRenderer() throws IOException { + super.stopRenderer(); + + if (endNumber == -1) { + // was not set on command line + endNumber = getNumberOfPages(); + } + } + + /** {@inheritDoc} */ + protected void rememberPage(PageViewport pageViewport) { + if (this.pageFilter.isValid(pageViewport)) { + super.rememberPage(pageViewport); + } + } + + private interface PageFilter { + boolean isValid(PageViewport page); + } + + private class DefaultPageFilter implements PageFilter { + + public boolean isValid(PageViewport page) { + int pageNum = page.getPageIndex() + 1; + assert pageNum >= 0; + if (pageNum < startNumber || (endNumber >= 0 && pageNum > endNumber)) { + return false; + } else if (mode != PagesMode.ALL) { + if (mode == PagesMode.EVEN && (pageNum % 2 != 0)) { + return false; + } else if (mode == PagesMode.ODD && (pageNum % 2 == 0)) { + return false; + } + } + return true; + } + } + + /** {@inheritDoc} */ + public PageFormat getPageFormat(int pageIndex) + throws IndexOutOfBoundsException { + try { + if (pageIndex >= getNumberOfPages()) { + return null; + } + + PageFormat pageFormat = new PageFormat(); + + Paper paper = new Paper(); + + Rectangle2D dim = getPageViewport(pageIndex).getViewArea(); + double width = dim.getWidth(); + double height = dim.getHeight(); + + // if the width is greater than the height assume landscape mode + // and swap the width and height values in the paper format + if (width > height) { + paper.setImageableArea(0, 0, height / 1000d, width / 1000d); + paper.setSize(height / 1000d, width / 1000d); + pageFormat.setOrientation(PageFormat.LANDSCAPE); + } else { + paper.setImageableArea(0, 0, width / 1000d, height / 1000d); + paper.setSize(width / 1000d, height / 1000d); + pageFormat.setOrientation(PageFormat.PORTRAIT); + } + pageFormat.setPaper(paper); + return pageFormat; + } catch (FOPException fopEx) { + throw new IndexOutOfBoundsException(fopEx.getMessage()); + } + } + + /** {@inheritDoc} */ + public Printable getPrintable(int pageIndex) + throws IndexOutOfBoundsException { + return this; + } +} diff --git a/src/java/org/apache/fop/render/print/PrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java index 2774b5373..888776ecb 100644 --- a/src/java/org/apache/fop/render/print/PrintRenderer.java +++ b/src/java/org/apache/fop/render/print/PrintRenderer.java @@ -19,20 +19,12 @@ package org.apache.fop.render.print; -import java.awt.geom.Rectangle2D; -import java.awt.print.PageFormat; -import java.awt.print.Pageable; -import java.awt.print.Paper; -import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.IOException; import java.util.Map; -import java.util.Vector; -import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.render.java2d.Java2DRenderer; /** * Renderer that prints through java.awt.PrintJob. @@ -40,7 +32,7 @@ import org.apache.fop.render.java2d.Java2DRenderer; * since both PrintRenderer and AWTRenderer need to * support printing. */ -public class PrintRenderer extends Java2DRenderer implements Pageable { +public class PrintRenderer extends PageableRenderer { /** * Printing parameter: the preconfigured PrinterJob to use, @@ -48,24 +40,6 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { */ public static final String PRINTER_JOB = "printerjob"; - /** - * Printing parameter: the pages to be printed (all, even or odd), - * datatype: the strings "all", "even" or "odd" or one of PagesMode.* - */ - public static final String PAGES_MODE = "even-odd"; - - /** - * Printing parameter: the page number (1-based) of the first page to be printed, - * datatype: a positive Integer - */ - public static final String START_PAGE = "start-page"; - - /** - * Printing parameter: the page number (1-based) of the last page to be printed, - * datatype: a positive Integer - */ - public static final String END_PAGE = "end-page"; - /** * Printing parameter: the number of copies of the document to be printed, * datatype: a positive Integer @@ -73,21 +47,15 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { public static final String COPIES = "copies"; - private int startNumber = 0; - private int endNumber = -1; - - private PagesMode mode = PagesMode.ALL; - private int copies = 1; private PrinterJob printerJob; /** - * Creates a new PrintRenderer with the options set from system properties if a custom + * Creates a new PrintRenderer with the options set through the renderer options if a custom * PrinterJob is not given in FOUserAgent's renderer options. */ public PrintRenderer() { - setupFromSystemProperties(); } /** @@ -117,18 +85,6 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { } } - private void setupFromSystemProperties() { - //TODO Remove me! This is not a beautiful way to do this. - // read from command-line options - copies = getIntProperty("copies", 1); - startNumber = getIntProperty("start", 1); - endNumber = getIntProperty("end", -1); - String str = System.getProperty("even"); - if (str != null) { - mode = Boolean.valueOf(str).booleanValue() ? PagesMode.EVEN : PagesMode.ODD; - } - } - /** {@inheritDoc} */ public void setUserAgent(FOUserAgent agent) { super.setUserAgent(agent); @@ -146,53 +102,13 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { printerJob = (PrinterJob)printerJobO; printerJob.setPageable(this); } - Object o = rendererOptions.get(PrintRenderer.PAGES_MODE); - if (o != null) { - if (o instanceof PagesMode) { - this.mode = (PagesMode)o; - } else if (o instanceof String) { - this.mode = PagesMode.byName((String)o); - } else { - throw new IllegalArgumentException( - "Renderer option " + PrintRenderer.PAGES_MODE - + " must be an 'all', 'even', 'odd' or a PagesMode instance."); - } - } - - o = rendererOptions.get(PrintRenderer.START_PAGE); - if (o != null) { - this.startNumber = getPositiveInteger(o); - } - o = rendererOptions.get(PrintRenderer.END_PAGE); - if (o != null) { - this.endNumber = getPositiveInteger(o); - } - if (this.endNumber >= 0 && this.endNumber < this.endNumber) { - this.endNumber = this.startNumber; - } - o = rendererOptions.get(PrintRenderer.COPIES); + Object o = rendererOptions.get(PrintRenderer.COPIES); if (o != null) { this.copies = getPositiveInteger(o); } initializePrinterJob(); } - private int getPositiveInteger(Object o) { - if (o instanceof Integer) { - Integer i = (Integer)o; - if (i.intValue() < 1) { - throw new IllegalArgumentException( - "Value must be a positive Integer"); - } - return i.intValue(); - } else if (o instanceof String) { - return Integer.parseInt((String)o); - } else { - throw new IllegalArgumentException( - "Value must be a positive integer"); - } - } - /** @return the PrinterJob instance that this renderer prints to */ public PrinterJob getPrinterJob() { return this.printerJob; @@ -228,17 +144,6 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { public void stopRenderer() throws IOException { super.stopRenderer(); - if (endNumber == -1) { - // was not set on command line - endNumber = getNumberOfPages(); - } - - Vector numbers = getInvalidPageNumbers(); - for (int i = numbers.size() - 1; i > -1; i--) { - int page = ((Integer)numbers.elementAt(i)).intValue(); - pageViewportList.remove(page - 1); - } - try { printerJob.print(); } catch (PrinterException e) { @@ -249,79 +154,4 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { clearViewportList(); } - private static int getIntProperty(String name, int def) { - String propValue = System.getProperty(name); - if (propValue != null) { - try { - return Integer.parseInt(propValue); - } catch (Exception e) { - return def; - } - } else { - return def; - } - } - - private Vector getInvalidPageNumbers() { - Vector vec = new Vector(); - int max = getNumberOfPages(); - boolean isValid; - for (int i = 1; i <= max; i++) { - isValid = true; - if (i < startNumber || i > endNumber) { - isValid = false; - } else if (mode != PagesMode.ALL) { - if (mode == PagesMode.EVEN && (i % 2 != 0)) { - isValid = false; - } else if (mode == PagesMode.ODD && (i % 2 == 0)) { - isValid = false; - } - } - - if (!isValid) { - vec.add(new Integer(i)); - } - } - return vec; - } - - /** {@inheritDoc} */ - public PageFormat getPageFormat(int pageIndex) - throws IndexOutOfBoundsException { - try { - if (pageIndex >= getNumberOfPages()) { - return null; - } - - PageFormat pageFormat = new PageFormat(); - - Paper paper = new Paper(); - - Rectangle2D dim = getPageViewport(pageIndex).getViewArea(); - double width = dim.getWidth(); - double height = dim.getHeight(); - - // if the width is greater than the height assume lanscape mode - // and swap the width and height values in the paper format - if (width > height) { - paper.setImageableArea(0, 0, height / 1000d, width / 1000d); - paper.setSize(height / 1000d, width / 1000d); - pageFormat.setOrientation(PageFormat.LANDSCAPE); - } else { - paper.setImageableArea(0, 0, width / 1000d, height / 1000d); - paper.setSize(width / 1000d, height / 1000d); - pageFormat.setOrientation(PageFormat.PORTRAIT); - } - pageFormat.setPaper(paper); - return pageFormat; - } catch (FOPException fopEx) { - throw new IndexOutOfBoundsException(fopEx.getMessage()); - } - } - - /** {@inheritDoc} */ - public Printable getPrintable(int pageIndex) - throws IndexOutOfBoundsException { - return this; - } } -- cgit v1.2.3 From 88e5a6ee83a4d3a88617b872992adc082856c8ee Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 18 Apr 2008 07:44:32 +0000 Subject: Introduced PageProductionException and fixed exception throwing for the event related to this exception. It's a RuntimeException descendant as making it a checked exception would have made changes necessary to at least a dozen more classes. Our overall exception style is still not so good. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649396 13f79535-47bb-0310-9956-ffa450edef68 --- ...p.events.EventExceptionManager$ExceptionFactory | 1 + src/java/org/apache/fop/apps/FOPException.java | 2 +- src/java/org/apache/fop/area/RenderPagesModel.java | 9 +- .../fop/fo/pagination/PageProductionException.java | 106 +++++++++++++++++++++ .../org/apache/fop/fo/pagination/PageSequence.java | 4 +- .../fop/fo/pagination/PageSequenceMaster.java | 4 +- .../fop/fo/pagination/SubSequenceSpecifier.java | 5 +- .../fop/layoutmgr/BlockLevelEventProducer.java | 14 +-- .../org/apache/fop/layoutmgr/PageProvider.java | 51 +++++----- 9 files changed, 150 insertions(+), 46 deletions(-) create mode 100644 src/java/org/apache/fop/fo/pagination/PageProductionException.java (limited to 'src') diff --git a/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory b/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory index 9fa7b8d04..1ad959188 100644 --- a/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory +++ b/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory @@ -2,3 +2,4 @@ org.apache.fop.events.ValidationExceptionFactory org.apache.fop.events.PropertyExceptionFactory org.apache.fop.events.UnsupportedOperationExceptionFactory org.apache.fop.layoutmgr.LayoutException$LayoutExceptionFactory +org.apache.fop.fo.pagination.PageProductionException$PageProductionExceptionFactory diff --git a/src/java/org/apache/fop/apps/FOPException.java b/src/java/org/apache/fop/apps/FOPException.java index 851712b09..d8ac2e2f7 100644 --- a/src/java/org/apache/fop/apps/FOPException.java +++ b/src/java/org/apache/fop/apps/FOPException.java @@ -103,7 +103,7 @@ public class FOPException extends SAXException { * @param systemId the system id of the FO document which is associated with the exception; * may be null. * @param line line number in the FO document which is associated with the exception. - * @param column clolumn number in the line which is associated with the exception. + * @param column column number in the line which is associated with the exception. */ public void setLocation(String systemId, int line, int column) { this.systemId = systemId; diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java index b21566902..64159cca7 100644 --- a/src/java/org/apache/fop/area/RenderPagesModel.java +++ b/src/java/org/apache/fop/area/RenderPagesModel.java @@ -31,6 +31,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererEventProducer; /** * This uses the AreaTreeModel to store the pages @@ -115,8 +116,12 @@ public class RenderPagesModel extends AreaTreeModel { String err = "Error while rendering page " + page.getPageNumberString(); log.error(err, re); throw re; - } catch (Exception e) { - //TODO use error handler to handle this FOP or IO Exception or propagate exception + } catch (IOException ioe) { + RendererEventProducer eventProducer = RendererEventProducer.Provider.get( + renderer.getUserAgent().getEventBroadcaster()); + eventProducer.ioError(this, ioe); + } catch (FOPException e) { + //TODO use error handler to handle this FOPException or propagate exception String err = "Error while rendering page " + page.getPageNumberString(); log.error(err, e); throw new IllegalStateException("Fatal error occurred. Cannot continue. " diff --git a/src/java/org/apache/fop/fo/pagination/PageProductionException.java b/src/java/org/apache/fop/fo/pagination/PageProductionException.java new file mode 100644 index 000000000..068e38ff8 --- /dev/null +++ b/src/java/org/apache/fop/fo/pagination/PageProductionException.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo.pagination; + +import java.util.Locale; + +import org.xml.sax.Locator; +import org.xml.sax.helpers.LocatorImpl; + +import org.apache.fop.events.Event; +import org.apache.fop.events.EventFormatter; +import org.apache.fop.events.EventExceptionManager.ExceptionFactory; + +/** + * Exception thrown by FOP if there is a problem while producing new pages. + */ +public class PageProductionException extends RuntimeException { + + private static final long serialVersionUID = -5126033718398975158L; + + private String localizedMessage; + private Locator locator; + + /** + * Creates a new PageProductionException. + * @param message the message + * @param locator the optional locator that points to the error in the source file + */ + public PageProductionException(String message, Locator locator) { + super(message); + setLocator(locator); + } + + /** + * Set a location associated with the exception. + * @param locator the locator holding the location. + */ + public void setLocator(Locator locator) { + this.locator = new LocatorImpl(locator); + } + + + /** + * Returns the locattion associated with the exception. + * @return the locator or null if the location information is not available + */ + public Locator getLocator() { + return this.locator; + } + + /** + * Sets the localized message for this exception. + * @param msg the localized message + */ + public void setLocalizedMessage(String msg) { + this.localizedMessage = msg; + } + + /** {@inheritDoc} */ + public String getLocalizedMessage() { + if (this.localizedMessage != null) { + return this.localizedMessage; + } else { + return super.getLocalizedMessage(); + } + } + + /** Exception factory for {@link PageProductionException}. */ + public static class PageProductionExceptionFactory implements ExceptionFactory { + + /** {@inheritDoc} */ + public Throwable createException(Event event) { + Object obj = event.getParam("loc"); + Locator loc = (obj instanceof Locator ? (Locator)obj : null); + String msg = EventFormatter.format(event, Locale.ENGLISH); + PageProductionException ex = new PageProductionException(msg, loc); + if (!Locale.ENGLISH.equals(Locale.getDefault())) { + ex.setLocalizedMessage(EventFormatter.format(event)); + } + return ex; + } + + /** {@inheritDoc} */ + public Class getExceptionClass() { + return PageProductionException.class; + } + + } +} diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java index 3d155a1da..3c7cfb197 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java @@ -371,13 +371,13 @@ public class PageSequence extends AbstractPageSequence { * page sequence * @param isBlank indicator whether the page will be blank * @return the SimplePageMaster to use for this page - * @throws FOPException if there's a problem determining the page master + * @throws PageProductionException if there's a problem determining the page master */ public SimplePageMaster getNextSimplePageMaster(int page, boolean isFirstPage, boolean isLastPage, boolean isOnlyPage, - boolean isBlank) throws FOPException { + boolean isBlank) throws PageProductionException { if (pageSequenceMaster == null) { return simplePageMaster; diff --git a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java index 4258a1139..b6c8c0f6b 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java @@ -189,14 +189,14 @@ public class PageSequenceMaster extends FObj { * @param isOnlyPage True if the next page is the only page * @param isBlankPage True if the next page is blank * @return the requested page master - * @throws FOPException if there's a problem determining the next page master + * @throws PageProductionException if there's a problem determining the next page master */ public SimplePageMaster getNextSimplePageMaster(boolean isOddPage, boolean isFirstPage, boolean isLastPage, boolean isOnlyPage, boolean isBlankPage) - throws FOPException { + throws PageProductionException { if (currentSubSequence == null) { currentSubSequence = getNextSubSequence(); if (currentSubSequence == null) { diff --git a/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java b/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java index 5da4945f1..0bad65a7c 100644 --- a/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java +++ b/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java @@ -19,7 +19,6 @@ package org.apache.fop.fo.pagination; -import org.apache.fop.apps.FOPException; /** * Classes that implement this interface can be added to a PageSequenceMaster, @@ -35,14 +34,14 @@ public interface SubSequenceSpecifier { * @param isOnlyPage True if the next page is the only page * @param isBlankPage True if the next page is blank * @return the page master name - * @throws FOPException if there's a problem determining the next page master + * @throws PageProductionException if there's a problem determining the next page master */ String getNextPageMasterName(boolean isOddPage, boolean isFirstPage, boolean isLastPage, boolean isOnlyPage, boolean isBlankPage) - throws FOPException; + throws PageProductionException; /** * Called before a new page sequence is rendered so subsequences can reset diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java index c31a70477..b1dd7ef5d 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java @@ -21,9 +21,9 @@ package org.apache.fop.layoutmgr; import org.xml.sax.Locator; -import org.apache.fop.apps.FOPException; import org.apache.fop.events.EventBroadcaster; import org.apache.fop.events.EventProducer; +import org.apache.fop.fo.pagination.PageProductionException; /** * Event producer interface for block-level layout managers. @@ -136,22 +136,22 @@ public interface BlockLevelEventProducer extends EventProducer { * @param pageSequenceMasterName the name of the page sequence master * @param canRecover indicates whether FOP can recover from this problem and continue working * @param loc the location of the error or null - * @throws FOPException the error provoked by the method call + * @throws PageProductionException the error provoked by the method call * @event.severity FATAL */ void pageSequenceMasterExhausted(Object source, String pageSequenceMasterName, - boolean canRecover, Locator loc) throws FOPException; + boolean canRecover, Locator loc) throws PageProductionException; /** * No subsequences in page sequence master. * @param source the event source * @param pageSequenceMasterName the name of the page sequence master * @param loc the location of the error or null - * @throws FOPException the error provoked by the method call + * @throws PageProductionException the error provoked by the method call * @event.severity FATAL */ void missingSubsequencesInPageSequenceMaster(Object source, String pageSequenceMasterName, - Locator loc) throws FOPException; + Locator loc) throws PageProductionException; /** * No single-page-master matching in page sequence master. @@ -159,10 +159,10 @@ public interface BlockLevelEventProducer extends EventProducer { * @param pageSequenceMasterName the name of the page sequence master * @param pageMasterName the name of the page master not matching * @param loc the location of the error or null - * @throws FOPException the error provoked by the method call + * @throws PageProductionException the error provoked by the method call * @event.severity FATAL */ void noMatchingPageMaster(Object source, String pageSequenceMasterName, - String pageMasterName, Locator loc) throws FOPException; + String pageMasterName, Locator loc) throws PageProductionException; } diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java index 037f02094..a7918db6e 100644 --- a/src/java/org/apache/fop/layoutmgr/PageProvider.java +++ b/src/java/org/apache/fop/layoutmgr/PageProvider.java @@ -24,7 +24,6 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.apps.FOPException; import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.fo.Constants; import org.apache.fop.fo.pagination.PageSequence; @@ -196,10 +195,10 @@ public class PageProvider implements Constants { } /** - * - * @param isBlank true if the Page should be a blank one + * Returns a Page. + * @param isBlank true if the Page should be a blank one * @param index the Page's index - * @return a Page instance + * @return a Page instance */ protected Page getPage(boolean isBlank, int index) { boolean isLastPage = (lastPageIndex >= 0) && (index == lastPageIndex); @@ -251,31 +250,25 @@ public class PageProvider implements Constants { } private Page cacheNextPage(int index, boolean isBlank, boolean isLastPage) { - try { - String pageNumberString = pageSeq.makeFormattedPageNumber(index); - SimplePageMaster spm = pageSeq.getNextSimplePageMaster( - index, (startPageOfPageSequence == index), isLastPage, false, isBlank); - - Region body = spm.getRegion(FO_REGION_BODY); - if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) { - // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to - // any region), but we don't support it yet. - BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( - pageSeq.getUserAgent().getEventBroadcaster()); - eventProducer.flowNotMappingToRegionBody(this, - pageSeq.getMainFlow().getFlowName(), spm.getMasterName(), spm.getLocator()); - } - Page page = new Page(spm, index, pageNumberString, isBlank); - //Set unique key obtained from the AreaTreeHandler - page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey()); - page.getPageViewport().setForeignAttributes(spm.getForeignAttributes()); - cachedPages.add(page); - return page; - } catch (FOPException e) { - //TODO Maybe improve. It'll mean to propagate this exception up several - //methods calls. - throw new IllegalStateException(e.getMessage()); + String pageNumberString = pageSeq.makeFormattedPageNumber(index); + SimplePageMaster spm = pageSeq.getNextSimplePageMaster( + index, (startPageOfPageSequence == index), isLastPage, false, isBlank); + + Region body = spm.getRegion(FO_REGION_BODY); + if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) { + // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to + // any region), but we don't support it yet. + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + pageSeq.getUserAgent().getEventBroadcaster()); + eventProducer.flowNotMappingToRegionBody(this, + pageSeq.getMainFlow().getFlowName(), spm.getMasterName(), spm.getLocator()); } + Page page = new Page(spm, index, pageNumberString, isBlank); + //Set unique key obtained from the AreaTreeHandler + page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey()); + page.getPageViewport().setForeignAttributes(spm.getForeignAttributes()); + cachedPages.add(page); + return page; } - + } \ No newline at end of file -- cgit v1.2.3 From 85946488d7551416767aaa896680f6bd5fe9827b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 18 Apr 2008 09:16:28 +0000 Subject: Fixed build problem. FOPException is no longer thrown there. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649420 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/rtf/RTFHandler.java | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 88e34e17a..05aade551 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -242,9 +242,6 @@ public class RTFHandler extends FOEventHandler { bFooterSpecified = false; } catch (IOException ioe) { handleIOTrouble(ioe); - } catch (FOPException fope) { - // TODO could we throw Exception in all FOEventHandler events? - log.error("startPageSequence: " + fope.getMessage(), fope); } } -- cgit v1.2.3 From 070382fa9bc83afed2acabb5fc1f37e5762ed9f9 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 18 Apr 2008 12:03:24 +0000 Subject: Bugfix: If the first event is not issued over an event producer, the fallback logging event listener was not installed. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649477 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/apps/FOUserAgent.java | 34 ++++++++++++++------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index 307087f74..eea7f3926 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -39,7 +39,7 @@ import org.apache.fop.Version; import org.apache.fop.events.DefaultEventBroadcaster; import org.apache.fop.events.Event; import org.apache.fop.events.EventBroadcaster; -import org.apache.fop.events.EventProducer; +import org.apache.fop.events.EventListener; import org.apache.fop.events.FOPEventListenerProxy; import org.apache.fop.events.LoggingEventListener; import org.apache.fop.fo.FOEventHandler; @@ -549,11 +549,25 @@ public class FOUserAgent { private class FOPEventBroadcaster extends DefaultEventBroadcaster { - private FOPEventListenerProxy rootListener; + private EventListener rootListener; public FOPEventBroadcaster() { - this.rootListener = new FOPEventListenerProxy( - this.listeners, FOUserAgent.this); + //Install a temporary event listener that catches the first event to + //do some initialization. + this.rootListener = new EventListener() { + public void processEvent(Event event) { + if (!listeners.hasEventListeners()) { + //Backwards-compatibility: Make sure at least the LoggingEventListener is + //plugged in so no events are just silently swallowed. + addEventListener( + new LoggingEventListener(LogFactory.getLog(FOUserAgent.class))); + } + //Replace with final event listener + rootListener = new FOPEventListenerProxy( + listeners, FOUserAgent.this); + rootListener.processEvent(event); + } + }; } /** {@inheritDoc} */ @@ -561,18 +575,6 @@ public class FOUserAgent { rootListener.processEvent(event); } - /** {@inheritDoc} */ - protected EventProducer createProxyFor(Class clazz) { - if (!this.listeners.hasEventListeners()) { - //Backwards-compatibility: Make sure at least the LoggingEventListener is plugged - //in so no events are just silently swallowed. - addEventListener( - new LoggingEventListener(LogFactory.getLog(FOUserAgent.class))); - - } - return super.createProxyFor(clazz); - } - } } -- cgit v1.2.3 From fa13f5c3f1434e4d0413ed418236b355018679ed Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 18 Apr 2008 14:40:56 +0000 Subject: Remember the missing glyphs also if an event listener is registered so they don't get warned about twice. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649552 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/SingleByteFont.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index 0a47d52ab..feb1b440c 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -117,15 +117,15 @@ public class SingleByteFont extends CustomFont { } //Give up, character is not available - if (this.eventListener != null) { - this.eventListener.glyphNotAvailable(this, c, getFontName()); - } else { - Character ch = new Character(c); - if (warnedChars == null) { - warnedChars = new java.util.HashSet(); - } - if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { - warnedChars.add(ch); + Character ch = new Character(c); + if (warnedChars == null) { + warnedChars = new java.util.HashSet(); + } + if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { + warnedChars.add(ch); + if (this.eventListener != null) { + this.eventListener.glyphNotAvailable(this, c, getFontName()); + } else { if (warnedChars.size() == 8) { log.warn("Many requested glyphs are not available in font " + getFontName()); } else { -- cgit v1.2.3 From a0a75029b98d18c23601745bad7669fb60503fe8 Mon Sep 17 00:00:00 2001 From: Simon Pepping Date: Fri, 18 Apr 2008 19:07:57 +0000 Subject: An implementation of a positive integer property maker. It implements convertProperty, which is the correct method to implement if one wants to add to the make process. This fixes bug 44619. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@649657 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 14 ++++----- .../org/apache/fop/fo/flow/table/TableFObj.java | 20 +------------ .../apache/fop/fo/properties/NumberProperty.java | 34 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 539648f5a..db19d6515 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1095,13 +1095,13 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("hyphenation-character", m); // hyphenation-push-character-count - m = new NumberProperty.Maker(PR_HYPHENATION_PUSH_CHARACTER_COUNT); + m = new NumberProperty.PositiveIntegerMaker(PR_HYPHENATION_PUSH_CHARACTER_COUNT); m.setInherited(true); m.setDefault("2"); addPropertyMaker("hyphenation-push-character-count", m); // hyphenation-remain-character-count - m = new NumberProperty.Maker(PR_HYPHENATION_REMAIN_CHARACTER_COUNT); + m = new NumberProperty.PositiveIntegerMaker(PR_HYPHENATION_REMAIN_CHARACTER_COUNT); m.setInherited(true); m.setDefault("2"); addPropertyMaker("hyphenation-remain-character-count", m); @@ -2137,7 +2137,7 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("blank-or-not-blank", m); // column-count - m = new NumberProperty.Maker(PR_COLUMN_COUNT); + m = new NumberProperty.PositiveIntegerMaker(PR_COLUMN_COUNT); m.setInherited(false); m.setDefault("1"); addPropertyMaker("column-count", m); @@ -2175,7 +2175,7 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("force-page-count", m); // initial-page-number - m = new NumberProperty.Maker(PR_INITIAL_PAGE_NUMBER); + m = new NumberProperty.PositiveIntegerMaker(PR_INITIAL_PAGE_NUMBER); m.setInherited(false); m.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); m.addEnum("auto-odd", getEnumProperty(EN_AUTO_ODD, "AUTO_ODD")); @@ -2359,19 +2359,19 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("ends-row", m); // number-columns-repeated - m = new NumberProperty.Maker(PR_NUMBER_COLUMNS_REPEATED); + m = new NumberProperty.PositiveIntegerMaker(PR_NUMBER_COLUMNS_REPEATED); m.setInherited(false); m.setDefault("1"); addPropertyMaker("number-columns-repeated", m); // number-columns-spanned - m = new NumberProperty.Maker(PR_NUMBER_COLUMNS_SPANNED); + m = new NumberProperty.PositiveIntegerMaker(PR_NUMBER_COLUMNS_SPANNED); m.setInherited(false); m.setDefault("1"); addPropertyMaker("number-columns-spanned", m); // number-rows-spanned - m = new NumberProperty.Maker(PR_NUMBER_ROWS_SPANNED); + m = new NumberProperty.PositiveIntegerMaker(PR_NUMBER_ROWS_SPANNED); m.setInherited(false); m.setDefault("1"); addPropertyMaker("number-rows-spanned", m); diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 24528f622..9b60de740 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -117,7 +117,7 @@ public abstract class TableFObj extends FObj { * PropertyMaker subclass for the column-number property * */ - public static class ColumnNumberPropertyMaker extends NumberProperty.Maker { + public static class ColumnNumberPropertyMaker extends NumberProperty.PositiveIntegerMaker { /** * Constructor @@ -153,24 +153,6 @@ public abstract class TableFObj extends FObj { = (ColumnNumberManagerHolder) propertyList.getParentFObj(); ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); int columnIndex = p.getNumeric().getValue(); - if (columnIndex <= 0) { - /* No warning necessary as the spec clearly defines how to handle these cases. - log.warn("Specified negative or zero value for " - + "column-number on " + fo.getName() + ": " - + columnIndex + " forced to " - + columnIndexManager.getCurrentColumnNumber());*/ - return NumberProperty.getInstance(columnIndexManager.getCurrentColumnNumber()); - } else { - double tmpIndex = p.getNumeric().getNumericValue(); - if (tmpIndex - columnIndex > 0.0) { - columnIndex = (int) Math.round(tmpIndex); - /* No warning necessary as the spec clearly defines how to handle these cases. - log.warn("Rounding specified column-number of " - + tmpIndex + " to " + columnIndex);*/ - p = NumberProperty.getInstance(columnIndex); - } - } - int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED) .getNumeric().getValue(); int i = -1; diff --git a/src/java/org/apache/fop/fo/properties/NumberProperty.java b/src/java/org/apache/fop/fo/properties/NumberProperty.java index 6f8d8a1d2..58400d76e 100644 --- a/src/java/org/apache/fop/fo/properties/NumberProperty.java +++ b/src/java/org/apache/fop/fo/properties/NumberProperty.java @@ -68,6 +68,40 @@ public final class NumberProperty extends Property implements Numeric { } + public static class PositiveIntegerMaker extends PropertyMaker { + + /** + * Constructor for NumberProperty.PositiveIntegerMaker + * @param propId the id of the property for which a PositiveIntegerMaker should be created + */ + public PositiveIntegerMaker(int propId) { + super(propId); + } + + /** + * If the value is not positive, return a property with value 1 + * + * {@inheritDoc} + */ + public Property convertProperty(Property p, + PropertyList propertyList, FObj fo) + throws PropertyException { + if (p instanceof EnumProperty) { + return EnumNumber.getInstance(p); + } + Number val = p.getNumber(); + if (val != null) { + int i = val.intValue(); + if (i <= 0) { + i = 1; + } + return getInstance(i); + } + return convertPropertyDatatype(p, propertyList, fo); + } + + } + /** cache holding all canonical NumberProperty instances */ private static final PropertyCache cache = new PropertyCache(); -- cgit v1.2.3 From ec0cb2d2d4e0aecbc066837dd62d5da8249a27e6 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 21 Apr 2008 08:32:02 +0000 Subject: Partially reverted my revision 641827: The yellow tint of certain JPEG images came from badly extracted ICC color profiles. This is fixed in XML Graphics Commons Trunk (revision 650048). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@650050 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/pdf/ImageRawJPEGAdapter.java | 17 ----------------- status.xml | 5 ----- 2 files changed, 22 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java index 1c8fceb50..1e505daed 100644 --- a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java +++ b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java @@ -18,7 +18,6 @@ /* $Id$ */ package org.apache.fop.render.pdf; -import java.awt.color.ICC_Profile; import java.io.DataInput; import java.io.IOException; import java.io.InputStream; @@ -36,7 +35,6 @@ import org.apache.fop.pdf.PDFDeviceColorSpace; import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFFilter; import org.apache.fop.pdf.PDFFilterList; -import org.apache.fop.util.ColorProfileUtil; /** * PDFImage implementation for the PDF renderer which handles raw JPEG images. @@ -81,21 +79,6 @@ public class ImageRawJPEGAdapter extends AbstractImageAdapter { return toPDFColorSpace(getImageColorSpace()); } - /** {@inheritDoc} */ - protected ICC_Profile getEffectiveICCProfile() { - ICC_Profile profile = super.getEffectiveICCProfile(); - if (profile != null - && profile.getNumComponents() == 3 - && !ColorProfileUtil.isDefaultsRGB(profile)) { - //RGB profiles which are not sRGB don't seem to work. - //Without this override, the image drifts into yellow for an unknown reason. - //TODO Find out why this happens. - //Test using a JPEG images with, for example, "Adobe RGB 1998" color profile. - profile = null; - } - return profile; - } - /** {@inheritDoc} */ public int getBitsPerComponent() { return 8; diff --git a/status.xml b/status.xml index bbd073f9a..6d55b69d4 100644 --- a/status.xml +++ b/status.xml @@ -81,11 +81,6 @@ When a JPEG image is embedded, an optionally embedded color profile is filtered out as it's already embedded separately in the PDF file. - - Worked around a problem (PDF renderer) with JPEG image containing RGB color profiles which - are not sRGB. The images drifted into yellow. The color profile is simply disabled in this - case. Please let us know if you know what the problem could be. - Added support for addressing all glyphs available in a Type 1 font, not just the ones in the font's primary encoding. -- cgit v1.2.3 From 5cded0d5c204d6c5a49b1915d7595b2c67a20881 Mon Sep 17 00:00:00 2001 From: Simon Pepping Date: Thu, 24 Apr 2008 17:46:31 +0000 Subject: Improve table-unit computation if proportional-column-width() is used as a subexpression. Fixes bug 44658. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651323 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/fo/expr/RelativeNumericProperty.java | 53 ++++++++++++++++++- .../apache/fop/fo/properties/LengthProperty.java | 16 ------ .../apache/fop/layoutmgr/table/ColumnSetup.java | 5 +- .../table-cell_table-units_mixed.xml | 61 ++++++++++++++++++++++ 4 files changed, 116 insertions(+), 19 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table-cell_table-units_mixed.xml (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java b/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java index ae140b6b7..dc7ab902f 100755 --- a/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java +++ b/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java @@ -23,6 +23,7 @@ import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.properties.Property; +import org.apache.fop.fo.properties.TableColLength; /** @@ -31,7 +32,7 @@ import org.apache.fop.fo.properties.Property; * to delay evaluation of the operation until the time where getNumericValue() * or getValue() is called. */ -public class RelativeNumericProperty extends Property implements Numeric, Length { +public class RelativeNumericProperty extends Property implements Length { public static final int ADDITION = 1; public static final int SUBTRACTION = 2; public static final int MULTIPLY = 3; @@ -56,7 +57,7 @@ public class RelativeNumericProperty extends Property implements Numeric, Length /** * The second operand. */ - private Numeric op2; + private Numeric op2 = null; /** * The dimension of the result. */ @@ -99,6 +100,7 @@ public class RelativeNumericProperty extends Property implements Numeric, Length /** * Return a resolved (calculated) Numeric with the value of the expression. * @param context Evaluation context + * @return the resolved {@link Numeric} corresponding to the value of the expression * @throws PropertyException when an exception occur during evaluation. */ private Numeric getResolved(PercentBaseContext context) throws PropertyException { @@ -195,6 +197,53 @@ public class RelativeNumericProperty extends Property implements Numeric, Length return 0; } + /** + * Return the number of table units which are included in this + * length specification. + * This will always be 0 unless the property specification used + * the proportional-column-width() function (only on table + * column FOs). + *

                                                                                          If this value is not 0, the actual value of the Length cannot + * be known without looking at all of the columns in the table to + * determine the value of a "table-unit". + * @return The number of table units which are included in this + * length specification. + */ + public double getTableUnits() { + double tu1 = 0.0, tu2 = 0.0; + if (op1 instanceof RelativeNumericProperty) { + tu1 = ((RelativeNumericProperty) op1).getTableUnits(); + } else if (op1 instanceof TableColLength) { + tu1 = ((TableColLength) op1).getTableUnits(); + } + if (op2 instanceof RelativeNumericProperty) { + tu2 = ((RelativeNumericProperty) op2).getTableUnits(); + } else if (op2 instanceof TableColLength) { + tu2 = ((TableColLength) op2).getTableUnits(); + } + if (tu1 != 0.0 && tu2 != 0.0) { + switch (operation) { + case ADDITION: return tu1 + tu2; + case SUBTRACTION: return tu1 - tu2; + case MULTIPLY: return tu1 * tu2; + case DIVIDE: return tu1 / tu2; + case MODULO: return tu1 % tu2; + case MIN: return Math.min(tu1, tu2); + case MAX: return Math.max(tu1, tu2); + default: assert false; + } + } else if (tu1 != 0.0) { + switch (operation) { + case NEGATE: return -tu1; + case ABS: return Math.abs(tu1); + default: return tu1; + } + } else if (tu2 != 0.0){ + return tu2; + } + return 0.0; + } + /** * Return a string represention of the expression. Only used for debugging. * @return the string representation. diff --git a/src/java/org/apache/fop/fo/properties/LengthProperty.java b/src/java/org/apache/fop/fo/properties/LengthProperty.java index 495e8d8ea..697aa75a7 100644 --- a/src/java/org/apache/fop/fo/properties/LengthProperty.java +++ b/src/java/org/apache/fop/fo/properties/LengthProperty.java @@ -71,22 +71,6 @@ public abstract class LengthProperty extends Property } - /** - * Return the number of table units which are included in this - * length specification. - * This will always be 0 unless the property specification used - * the proportional-column-width() function (only only table - * column FOs). - *

                                                                                          If this value is not 0, the actual value of the Length cannot - * be known without looking at all of the columns in the table to - * determine the value of a "table-unit". - * @return The number of table units which are included in this - * length specification. - */ - public double getTableUnits() { - return 0.0; - } - /** @return the numeric dimension. Length always a dimension of 1 */ public int getDimension() { return 1; diff --git a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java index bd032e610..9dbd31653 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java +++ b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java @@ -29,6 +29,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.expr.RelativeNumericProperty; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.properties.TableColLength; @@ -196,7 +197,9 @@ public class ColumnSetup { Length colWidth = (Length) i.next(); if (colWidth != null) { sumCols += colWidth.getValue(tlm); - if (colWidth instanceof TableColLength) { + if (colWidth instanceof RelativeNumericProperty) { + factors += ((RelativeNumericProperty) colWidth).getTableUnits(); + } else if (colWidth instanceof TableColLength) { factors += ((TableColLength) colWidth).getTableUnits(); } } diff --git a/test/layoutengine/standard-testcases/table-cell_table-units_mixed.xml b/test/layoutengine/standard-testcases/table-cell_table-units_mixed.xml new file mode 100644 index 000000000..868b14388 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_table-units_mixed.xml @@ -0,0 +1,61 @@ + + + + + +

                                                                                          + This test checks the calculation of table units when the column + widths are a mixture of fixed and proportional widths. +

                                                                                          + + + + + + + + + + + + + + + + + Cell 1.1 + + + Cell 2.2 + + + Cell 3.3 + + + + + + + + + + + + + -- cgit v1.2.3 From 4e61617403d6e13de6a295d5272449dbdf7fab3c Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Apr 2008 08:42:02 +0000 Subject: Javadocs git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651538 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/tools/EventConventionException.java | 9 +++++ .../apache/fop/tools/EventProducerCollector.java | 27 +++++++++++++- .../fop/tools/EventProducerCollectorTask.java | 43 +++++++++++++++++++++- 3 files changed, 76 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/codegen/java/org/apache/fop/tools/EventConventionException.java b/src/codegen/java/org/apache/fop/tools/EventConventionException.java index 675f4a0ca..27a7fcd50 100644 --- a/src/codegen/java/org/apache/fop/tools/EventConventionException.java +++ b/src/codegen/java/org/apache/fop/tools/EventConventionException.java @@ -19,8 +19,17 @@ package org.apache.fop.tools; +/** + * This exception is used to indicate a violation of the conventions for event producers. + */ public class EventConventionException extends Exception { + private static final long serialVersionUID = 117244726033986628L; + + /** + * Creates a new EventConventionException + * @param message the error message + */ public EventConventionException(String message) { super(message); } diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java index e42395ae7..f7e320ee7 100644 --- a/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java @@ -63,15 +63,29 @@ public class EventProducerCollector { private DocletTagFactory tagFactory; private EventModel model = new EventModel(); + /** + * Creates a new EventProducerCollector. + */ public EventProducerCollector() { this.tagFactory = createDocletTagFactory(); } + /** + * Creates the {@link DocletTagFactory} to be used by the collector. + * @return the doclet tag factory + */ protected DocletTagFactory createDocletTagFactory() { return new DefaultDocletTagFactory(); } - public void scanFile(File src, String filename) + /** + * Scans a file and processes it if it extends the {@link EventProducer} interface. + * @param src the source file (a Java source file) + * @throws IOException if an I/O error occurs + * @throws EventConventionException if the EventProducer conventions are violated + * @throws ClassNotFoundException if a required class cannot be found + */ + public void scanFile(File src) throws IOException, EventConventionException, ClassNotFoundException { JavaDocBuilder builder = new JavaDocBuilder(this.tagFactory); builder.addSource(src); @@ -79,7 +93,7 @@ public class EventProducerCollector { for (int i = 0, c = classes.length; i < c; i++) { JavaClass clazz = classes[i]; if (clazz.isInterface() && implementsInterface(clazz, CLASSNAME_EVENT_PRODUCER)) { - processEventProducerInterface(clazz, filename); + processEventProducerInterface(clazz, src.getName()); } } } @@ -172,10 +186,19 @@ public class EventProducerCollector { return methodMeta; } + /** + * Returns the event model that has been accumulated. + * @return the event model. + */ public EventModel getModel() { return this.model; } + /** + * Saves the accumulated event model to an XML file. + * @param modelFile the target model file + * @throws IOException if an I/O error occurs + */ public void saveModelToXML(File modelFile) throws IOException { getModel().saveToXML(modelFile); } diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java index 755e3da0b..60ffaf103 100644 --- a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java @@ -45,6 +45,12 @@ import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.selectors.FilenameSelector; +/** + * Ant task which inspects a file set for Java interfaces which extend the + * {@link org.apache.fop.events.EventProducer} interface. For all such interfaces an event model + * file and a translation file for the human-readable messages generated by the events is + * created and/or updated. + */ public class EventProducerCollectorTask extends Task { private List filesets = new java.util.ArrayList(); @@ -74,6 +80,10 @@ public class EventProducerCollectorTask extends Task { private static final String MODEL2TRANSLATION = "model2translation.xsl"; private static final String MERGETRANSLATION = "merge-translation.xsl"; + /** + * Updates the translation file with new entries for newly found event producer methods. + * @throws IOException if an I/O error occurs + */ protected void updateTranslationFile() throws IOException { try { boolean resultExists = getTranslationFile().exists(); @@ -136,6 +146,13 @@ public class EventProducerCollectorTask extends Task { } } + /** + * Processes the file sets defined for the task. + * @param collector the collector to use for collecting the event producers + * @throws IOException if an I/O error occurs + * @throws EventConventionException if the EventProducer conventions are violated + * @throws ClassNotFoundException if a required class cannot be found + */ protected void processFileSets(EventProducerCollector collector) throws IOException, EventConventionException, ClassNotFoundException { Iterator iter = filesets.iterator(); @@ -147,31 +164,55 @@ public class EventProducerCollectorTask extends Task { for (int i = 0, c = srcFiles.length; i < c; i++) { String filename = srcFiles[i]; File src = new File(directory, filename); - collector.scanFile(src, filename); + collector.scanFile(src); } } } + /** + * Adds a file set. + * @param set the file set + */ public void addFileset(FileSet set) { filesets.add(set); } + /** + * Sets the model file to be written. + * @param f the model file + */ public void setModelFile(File f) { this.modelFile = f; } + /** + * Returns the model file to be written. + * @return the model file + */ public File getModelFile() { return this.modelFile; } + /** + * Sets the translation file for the event producer methods. + * @param f the translation file + */ public void setTranslationFile(File f) { this.translationFile = f; } + /** + * Returns the translation file for the event producer methods. + * @return the translation file + */ public File getTranslationFile() { return this.translationFile; } + /** + * Command-line interface for testing purposes. + * @param args the command-line arguments + */ public static void main(String[] args) { try { Project project = new Project(); -- cgit v1.2.3 From a33539b1533bd7f1c1a110f9c435d283660de257 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Apr 2008 08:44:39 +0000 Subject: Cleanup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651540 13f79535-47bb-0310-9956-ffa450edef68 --- src/codegen/java/org/apache/fop/tools/EventProducerCollector.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java index f7e320ee7..ebb960a8e 100644 --- a/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java @@ -93,7 +93,7 @@ public class EventProducerCollector { for (int i = 0, c = classes.length; i < c; i++) { JavaClass clazz = classes[i]; if (clazz.isInterface() && implementsInterface(clazz, CLASSNAME_EVENT_PRODUCER)) { - processEventProducerInterface(clazz, src.getName()); + processEventProducerInterface(clazz); } } } @@ -112,11 +112,10 @@ public class EventProducerCollector { /** * Processes an EventProducer interface and creates an EventProducerModel from it. * @param clazz the EventProducer interface - * @param javaFilename the filename of the Java source of the interface * @throws EventConventionException if the event producer conventions are violated * @throws ClassNotFoundException if a required class cannot be found */ - protected void processEventProducerInterface(JavaClass clazz, String javaFilename) + protected void processEventProducerInterface(JavaClass clazz) throws EventConventionException, ClassNotFoundException { EventProducerModel prodMeta = new EventProducerModel(clazz.getFullyQualifiedName()); JavaMethod[] methods = clazz.getMethods(true); -- cgit v1.2.3 From a6d5390ee3682016f82a5344f5a20b77596abaf7 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 25 Apr 2008 08:59:56 +0000 Subject: Removed TODO: New validation event to generate an error in case an fo:marker appears as a child of an fo:block-container with absolutely positioned areas. Additionally: some javadoc updates in BlockContainer.java git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651543 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/EventFormatter.xml | 1 + .../apache/fop/fo/FOValidationEventProducer.java | 9 +++ .../org/apache/fop/fo/flow/BlockContainer.java | 87 +++++++++------------- 3 files changed, 45 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml index f17da1161..f5e4609e9 100644 --- a/src/java/org/apache/fop/events/EventFormatter.xml +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -33,6 +33,7 @@ Required content model: {contentModel}]{{locator}} Element "{elementName}" is missing required property "{propertyName}"!{{locator}} Property ID "{id}" (found on "{elementName}") previously used; ID values must be unique within a document!{severity,equals,EventSeverity:FATAL,, Any reference to it will be considered a reference to the first occurrence in the document.}{{locator}} + Only an fo:block-container that does not generate absolutely positioned areas may have one or more fo:markers as its initial children.{{locator}} fo:marker must be an initial child: {mcname}{{locator}} fo:marker "marker-class-name" must be unique for same parent: {mcname}{{locator}} Invalid property encountered on "{elementName}": {attr}{{locator}} diff --git a/src/java/org/apache/fop/fo/FOValidationEventProducer.java b/src/java/org/apache/fop/fo/FOValidationEventProducer.java index aa7b14941..61bd68340 100644 --- a/src/java/org/apache/fop/fo/FOValidationEventProducer.java +++ b/src/java/org/apache/fop/fo/FOValidationEventProducer.java @@ -149,6 +149,15 @@ public interface FOValidationEventProducer extends EventProducer { void masterNameNotUnique(Object source, String elementName, String name, Locator loc) throws ValidationException; + /** + * An fo:marker appears as initial descendant in an fo:block-container + * that generates absolutely positioned areas + * @param source the event source + * @param loc the location of the error (possibly null) + * @event.severity ERROR + */ + void markerBlockContainerAbsolutePosition(Object source, Locator loc); + /** * A marker is not an initial child on a node. * @param source the event source diff --git a/src/java/org/apache/fop/fo/flow/BlockContainer.java b/src/java/org/apache/fop/fo/flow/BlockContainer.java index f1180ac16..5e8957299 100644 --- a/src/java/org/apache/fop/fo/flow/BlockContainer.java +++ b/src/java/org/apache/fop/fo/flow/BlockContainer.java @@ -35,7 +35,8 @@ import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; /** - * Class modelling the fo:block-container object. + * Class modelling the + * fo:block-container object. */ public class BlockContainer extends FObj { // The value of properties relevant for fo:block-container. @@ -66,15 +67,16 @@ public class BlockContainer extends FObj { private boolean blockItemFound = false; /** - * @param parent FONode that is the parent of this object + * Creates a new BlockContainer instance as a child of + * the given {@link FONode}. + * + * @param parent {@link FONode} that is the parent of this object */ public BlockContainer(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonAbsolutePosition = pList.getAbsolutePositionProps(); @@ -97,9 +99,7 @@ public class BlockContainer extends FObj { writingMode = pList.get(PR_WRITING_MODE).getEnum(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startBlockContainer(this); @@ -107,30 +107,34 @@ public class BlockContainer extends FObj { /** * {@inheritDoc} - * XSL Content Model: marker* (%block;)+ - * But: "In addition an fo:block-container that does not generate an + *
                                                                                          XSL Content Model: marker* (%block;)+ + *
                                                                                          BUT: "In addition an fo:block-container that does not generate an * absolutely positioned area may have a sequence of zero or more * fo:markers as its initial children." - * @todo - implement above restriction if possible + * The latter refers to block-containers with absolute-position="absolute" + * or absolute-position="fixed". */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { - if (localName.equals("marker")) { + if ("marker".equals(localName)) { + if (commonAbsolutePosition.absolutePosition == EN_ABSOLUTE + || commonAbsolutePosition.absolutePosition == EN_FIXED) { + getFOValidationEventProducer() + .markerBlockContainerAbsolutePosition(this, locator); + } if (blockItemFound) { nodesOutOfOrderError(loc, "fo:marker", "(%block;)"); } - } else if (!isBlockItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); + } else if (!isBlockItem(FO_URI, localName)) { + invalidChildError(loc, FO_URI, localName); } else { blockItemFound = true; } } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (!blockItemFound) { missingChildElementError("marker* (%block;)+"); @@ -139,30 +143,22 @@ public class BlockContainer extends FObj { getFOEventHandler().endBlockContainer(this); } - /** - * @return true (BlockContainer can generate Reference Areas) - */ + /** @return true (BlockContainer can generate Reference Areas) */ public boolean generatesReferenceAreas() { return true; } - /** - * @return the Common Absolute Position Properties. - */ + /** @return the {@link CommonAbsolutePosition} */ public CommonAbsolutePosition getCommonAbsolutePosition() { return commonAbsolutePosition; } - /** - * @return the Common Margin Properties-Block. - */ + /** @return the {@link CommonMarginBlock} */ public CommonMarginBlock getCommonMarginBlock() { return commonMarginBlock; } - /** - * @return the Common Border, Padding, and Background Properties. - */ + /** @return the {@link CommonBorderPaddingBackground} */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } @@ -174,7 +170,7 @@ public class BlockContainer extends FObj { return blockProgressionDimension; } - /** @return the display-align property. */ + /** @return the "display-align" property. */ public int getDisplayAlign() { return displayAlign; } @@ -204,51 +200,37 @@ public class BlockContainer extends FObj { return keepTogether; } - /** - * @return the "inline-progression-dimension" property. - */ + /** @return the "inline-progression-dimension" property */ public LengthRangeProperty getInlineProgressionDimension() { return inlineProgressionDimension; } - /** - * @return the "overflow" property. - */ + /** @return the "overflow" property */ public int getOverflow() { return overflow; } - /** - * @return the "reference-orientation" property. - */ + /** @return the "reference-orientation" property */ public int getReferenceOrientation() { return referenceOrientation.getValue(); } - /** - * @return the "span" property. - */ + /** @return the "span" property */ public int getSpan() { return this.span; } - /** - * @return the "writing-mode" property. - */ + /** @return the "writing-mode" property */ public int getWritingMode() { return writingMode; } - /** - * @return the width property - */ + /** @return the "width" property */ public Length getWidth() { return width; } - /** - * @return the height property - */ + /** @return the "height" property */ public Length getHeight() { return height; } @@ -260,6 +242,7 @@ public class BlockContainer extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_BLOCK_CONTAINER} */ public int getNameId() { return FO_BLOCK_CONTAINER; -- cgit v1.2.3 From 09abeb4758f979199ec28eeb57c788289831cfda Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 25 Apr 2008 09:04:06 +0000 Subject: Removed the tab characters that were causing a big moan from eclipse git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651544 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/fo/expr/RelativeNumericProperty.java | 95 ++++++++++++---------- 1 file changed, 53 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java b/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java index dc7ab902f..647528692 100755 --- a/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java +++ b/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java @@ -198,50 +198,61 @@ public class RelativeNumericProperty extends Property implements Length { } /** - * Return the number of table units which are included in this - * length specification. - * This will always be 0 unless the property specification used - * the proportional-column-width() function (only on table - * column FOs). - *

                                                                                          If this value is not 0, the actual value of the Length cannot - * be known without looking at all of the columns in the table to - * determine the value of a "table-unit". - * @return The number of table units which are included in this - * length specification. + * Return the number of table units which are included in this length + * specification. This will always be 0 unless the property specification + * used the proportional-column-width() function (only on table column FOs). + *

                                                                                          + * If this value is not 0, the actual value of the Length cannot be known + * without looking at all of the columns in the table to determine the value + * of a "table-unit". + * + * @return The number of table units which are included in this length + * specification. */ public double getTableUnits() { - double tu1 = 0.0, tu2 = 0.0; - if (op1 instanceof RelativeNumericProperty) { - tu1 = ((RelativeNumericProperty) op1).getTableUnits(); - } else if (op1 instanceof TableColLength) { - tu1 = ((TableColLength) op1).getTableUnits(); - } - if (op2 instanceof RelativeNumericProperty) { - tu2 = ((RelativeNumericProperty) op2).getTableUnits(); - } else if (op2 instanceof TableColLength) { - tu2 = ((TableColLength) op2).getTableUnits(); - } - if (tu1 != 0.0 && tu2 != 0.0) { - switch (operation) { - case ADDITION: return tu1 + tu2; - case SUBTRACTION: return tu1 - tu2; - case MULTIPLY: return tu1 * tu2; - case DIVIDE: return tu1 / tu2; - case MODULO: return tu1 % tu2; - case MIN: return Math.min(tu1, tu2); - case MAX: return Math.max(tu1, tu2); - default: assert false; - } - } else if (tu1 != 0.0) { - switch (operation) { - case NEGATE: return -tu1; - case ABS: return Math.abs(tu1); - default: return tu1; - } - } else if (tu2 != 0.0){ - return tu2; - } - return 0.0; + double tu1 = 0.0, tu2 = 0.0; + if (op1 instanceof RelativeNumericProperty) { + tu1 = ((RelativeNumericProperty) op1).getTableUnits(); + } else if (op1 instanceof TableColLength) { + tu1 = ((TableColLength) op1).getTableUnits(); + } + if (op2 instanceof RelativeNumericProperty) { + tu2 = ((RelativeNumericProperty) op2).getTableUnits(); + } else if (op2 instanceof TableColLength) { + tu2 = ((TableColLength) op2).getTableUnits(); + } + if (tu1 != 0.0 && tu2 != 0.0) { + switch (operation) { + case ADDITION: + return tu1 + tu2; + case SUBTRACTION: + return tu1 - tu2; + case MULTIPLY: + return tu1 * tu2; + case DIVIDE: + return tu1 / tu2; + case MODULO: + return tu1 % tu2; + case MIN: + return Math.min(tu1, tu2); + case MAX: + return Math.max(tu1, tu2); + default: + assert false; + } + } else if (tu1 != 0.0) { + switch (operation) { + case NEGATE: + return -tu1; + case ABS: + return Math.abs(tu1); + default: + return tu1; + } + } else if (tu2 != 0.0) { + return tu2; + } + return 0.0; } /** -- cgit v1.2.3 From 69f2bb15e9268dae8440e5254e89b6914c8c46c3 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 25 Apr 2008 09:30:09 +0000 Subject: Cleanup: removal of commented block/methods + some javadoc updates git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651551 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/pagination/PageSequence.java | 160 ++++----------------- 1 file changed, 25 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java index 3c7cfb197..c8f7c66d7 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java @@ -30,7 +30,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Abstract base implementation for page sequences. + * Class modelling the + * fo:page-sequence object. */ public class PageSequence extends AbstractPageSequence { @@ -70,9 +71,10 @@ public class PageSequence extends AbstractPageSequence { private Flow mainFlow = null; /** - * Create a page sequence FO node. + * Create a PageSequence instance that is a child of the + * given {@link FONode}. * - * @param parent the parent FO node + * @param parent the parent {@link FONode} */ public PageSequence(FONode parent) { super(parent); @@ -172,6 +174,9 @@ public class PageSequence extends AbstractPageSequence { * The flow-name is used to associate the flow with a region on a page, * based on the region-names given to the regions in the page-master * used to generate that page. + * @param flow the {@link Flow} instance to be added + * @throws org.apache.fop.fo.ValidationException if the fo:flow maps + * to an invalid page-region */ private void addFlow(Flow flow) throws ValidationException { String flowName = flow.getFlowName(); @@ -189,133 +194,6 @@ public class PageSequence extends AbstractPageSequence { } } -// /** -// * Returns true when there is more flow elements left to lay out. -// */ -// private boolean flowsAreIncomplete() { -// boolean isIncomplete = false; - -// for (Iterator e = flowMap.values().iterator(); e.hasNext(); ) { -// Flow flow = (Flow)e.next(); -// if (flow instanceof StaticContent) { -// continue; -// } - -// Status status = flow.getStatus(); -// isIncomplete |= status.isIncomplete(); -// } -// return isIncomplete; -// } - -// /** -// * Returns the flow that maps to the given region class for the current -// * page master. -// */ -// private Flow getCurrentFlow(String regionClass) { -// Region region = getCurrentSimplePageMaster().getRegion(regionClass); -// if (region != null) { -// Flow flow = (Flow)flowMap.get(region.getRegionName()); -// return flow; - -// } else { - -// getLogger().error("flow is null. regionClass = '" + regionClass -// + "' currentSPM = " -// + getCurrentSimplePageMaster()); - -// return null; -// } - -// } - -// private boolean isFlowForMasterNameDone(String masterName) { -// // parameter is master-name of PMR; we need to locate PM -// // referenced by this, and determine whether flow(s) are OK -// if (isForcing) -// return false; -// if (masterName != null) { - -// SimplePageMaster spm = -// root.getLayoutMasterSet().getSimplePageMaster(masterName); -// Region region = spm.getRegion(FO_REGION_BODY); - - -// Flow flow = (Flow)flowMap.get(region.getRegionName()); -// /*if ((null == flow) || flow.getStatus().isIncomplete()) -// return false; -// else -// return true;*/ -// } -// return false; -// } - -// private void forcePage(AreaTree areaTree, int firstAvailPageNumber) { -// boolean makePage = false; -// if (this.forcePageCount == ForcePageCount.AUTO) { -// PageSequence nextSequence = -// this.root.getSucceedingPageSequence(this); -// if (nextSequence != null) { -// if (nextSequence.getIpnValue().equals("auto")) { -// // do nothing special -// } -// else if (nextSequence.getIpnValue().equals("auto-odd")) { -// if (firstAvailPageNumber % 2 == 0) { -// makePage = true; -// } -// } else if (nextSequence.getIpnValue().equals("auto-even")) { -// if (firstAvailPageNumber % 2 != 0) { -// makePage = true; -// } -// } else { -// int nextSequenceStartPageNumber = -// nextSequence.getCurrentPageNumber(); -// if ((nextSequenceStartPageNumber % 2 == 0) -// && (firstAvailPageNumber % 2 == 0)) { -// makePage = true; -// } else if ((nextSequenceStartPageNumber % 2 != 0) -// && (firstAvailPageNumber % 2 != 0)) { -// makePage = true; -// } -// } -// } -// } else if ((this.forcePageCount == ForcePageCount.EVEN) -// && (this.pageCount % 2 != 0)) { -// makePage = true; -// } else if ((this.forcePageCount == ForcePageCount.ODD) -// && (this.pageCount % 2 == 0)) { -// makePage = true; -// } else if ((this.forcePageCount == ForcePageCount.END_ON_EVEN) -// && (firstAvailPageNumber % 2 == 0)) { -// makePage = true; -// } else if ((this.forcePageCount == ForcePageCount.END_ON_ODD) -// && (firstAvailPageNumber % 2 != 0)) { -// makePage = true; -// } else if (this.forcePageCount == ForcePageCount.NO_FORCE) { -// // do nothing -// } - -// if (makePage) { -// try { -// this.isForcing = true; -// this.currentPageNumber++; -// firstAvailPageNumber = this.currentPageNumber; -// currentPage = makePage(areaTree, firstAvailPageNumber, false, -// true); -// String formattedPageNumber = -// pageNumberGenerator.makeFormattedPageNumber(this.currentPageNumber); -// currentPage.setFormattedNumber(formattedPageNumber); -// currentPage.setPageSequence(this); -// formatStaticContent(areaTree); -// log.debug("[forced-" + firstAvailPageNumber + "]"); -// areaTree.addPage(currentPage); -// this.root.setRunningPageNumberCounter(this.currentPageNumber); -// this.isForcing = false; -// } catch (FOPException fopex) { -// log.debug("'force-page-count' failure"); -// } -// } -// } - /** * Get the static content FO node from the flow map. * This gets the static content flow for the given flow name. @@ -328,7 +206,7 @@ public class PageSequence extends AbstractPageSequence { } /** - * Accessor method for titleFO + * Accessor method for the fo:title associated with this fo:page-sequence * @return titleFO for this object */ public Title getTitleFO() { @@ -425,7 +303,10 @@ public class PageSequence extends AbstractPageSequence { } } - /** @return the "master-reference" property. */ + /** + * Get the value of the master-reference property. + * @return the "master-reference" property + */ public String getMasterReference() { return masterReference; } @@ -435,17 +316,26 @@ public class PageSequence extends AbstractPageSequence { return "page-sequence"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_PAGE_SEQUENCE} + */ public int getNameId() { return FO_PAGE_SEQUENCE; } - /** @return the country property value */ + /** + * Get the value of the country property. + * @return the country property value + */ public String getCountry() { return this.country; } - /** @return the language property value */ + /** + * Get the value of the language property. + * @return the language property value + */ public String getLanguage() { return this.language; } -- cgit v1.2.3 From c47f87ac1bc127389597c979e1e4a344b3e9fe88 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Apr 2008 10:07:58 +0000 Subject: Second part of the implementation of stage 1 for advanced keeps (see Wiki): Integer values are treated differently from "always" values in keep-with-next/previous.within-column for all block-level FOs. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651558 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/EffRow.java | 44 ++--- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 31 ++-- .../fop/layoutmgr/BlockContainerLayoutManager.java | 39 +++-- .../apache/fop/layoutmgr/BlockLayoutManager.java | 19 +-- .../fop/layoutmgr/BlockLevelLayoutManager.java | 12 ++ .../fop/layoutmgr/BlockStackingLayoutManager.java | 39 ++--- .../apache/fop/layoutmgr/FlowLayoutManager.java | 46 ++---- .../fop/layoutmgr/FootnoteBodyLayoutManager.java | 10 ++ src/java/org/apache/fop/layoutmgr/KeepUtil.java | 39 +++++ .../org/apache/fop/layoutmgr/LayoutContext.java | 82 ++++++++- .../fop/layoutmgr/StaticContentLayoutManager.java | 10 ++ .../fop/layoutmgr/inline/InlineLayoutManager.java | 10 +- .../fop/layoutmgr/inline/LineLayoutManager.java | 26 +-- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 18 +- .../list/ListItemContentLayoutManager.java | 16 +- .../fop/layoutmgr/list/ListItemLayoutManager.java | 65 +++----- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 14 +- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 7 +- .../table/TableAndCaptionLayoutManager.java | 32 +++- .../layoutmgr/table/TableCaptionLayoutManager.java | 24 ++- .../layoutmgr/table/TableCellLayoutManager.java | 31 ++-- .../layoutmgr/table/TableContentLayoutManager.java | 34 ++-- .../fop/layoutmgr/table/TableLayoutManager.java | 35 ++-- .../apache/fop/layoutmgr/table/TableStepper.java | 45 +++-- status.xml | 5 + test/layoutengine/disabled-testcases.xml | 12 -- .../block-container_keep-with-next_1.xml | 101 +++++++++++ .../block-container_keep-with-previous_1.xml | 101 +++++++++++ .../block_keep-with-next_integers_1.xml | 99 +++++++++++ .../block_keep-with-previous_integers_1.xml | 116 +++++++++++++ .../list-block_keep-with-next_integers_1.xml | 155 +++++++++++++++++ .../list-block_keep-with-previous.xml | 3 - .../list-block_keep-with-previous_integers_1.xml | 127 ++++++++++++++ .../list-item_block_keep-with-previous.xml | 3 - .../table_keep-with-next_integers_1.xml | 184 +++++++++++++++++++++ .../table_keep-with-previous_integers_1.xml | 146 ++++++++++++++++ 36 files changed, 1465 insertions(+), 315 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block-container_keep-with-next_1.xml create mode 100644 test/layoutengine/standard-testcases/block-container_keep-with-previous_1.xml create mode 100644 test/layoutengine/standard-testcases/block_keep-with-next_integers_1.xml create mode 100644 test/layoutengine/standard-testcases/block_keep-with-previous_integers_1.xml create mode 100644 test/layoutengine/standard-testcases/list-block_keep-with-next_integers_1.xml create mode 100644 test/layoutengine/standard-testcases/list-block_keep-with-previous_integers_1.xml create mode 100644 test/layoutengine/standard-testcases/table_keep-with-next_integers_1.xml create mode 100644 test/layoutengine/standard-testcases/table_keep-with-previous_integers_1.xml (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java index 31a8260cc..fc8209b01 100644 --- a/src/java/org/apache/fop/fo/flow/table/EffRow.java +++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java @@ -165,55 +165,47 @@ public class EffRow { } /** - * Returns true if the enclosing (if any) fo:table-row element of this row, or if any - * of the cells starting on this row, have keep-with-previous set. + * Returns the strength of the keep constraint if the enclosing (if any) fo:table-row element + * of this row, or if any of the cells starting on this row, have keep-with-previous set. * - * @return true if this row must be kept with the previous content + * @return the strength of the keep-with-previous constraint */ - public boolean mustKeepWithPrevious() { - boolean keepWithPrevious = false; + public int getKeepWithPreviousStrength() { + int strength = BlockLevelLayoutManager.KEEP_AUTO; TableRow row = getTableRow(); if (row != null) { - keepWithPrevious = row.mustKeepWithPrevious(); + strength = Math.max(strength, + KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithPrevious())); } for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); if (gu.isPrimary()) { - keepWithPrevious |= gu.getPrimary().mustKeepWithPrevious(); + strength = Math.max(strength, gu.getPrimary().getKeepWithPreviousStrength()); } } - return keepWithPrevious; + return strength; } /** - * Returns true if the enclosing (if any) fo:table-row element of this row, or if any - * of the cells ending on this row, have keep-with-next set. + * Returns the strength of the keep constraint if the enclosing (if any) fo:table-row element + * of this row, or if any of the cells ending on this row, have keep-with-next set. * - * @return true if this row must be kept with the next content + * @return the strength of the keep-with-next constraint */ - public boolean mustKeepWithNext() { - boolean keepWithNext = false; + public int getKeepWithNextStrength() { + int strength = BlockLevelLayoutManager.KEEP_AUTO; TableRow row = getTableRow(); if (row != null) { - keepWithNext = row.mustKeepWithNext(); + strength = Math.max(strength, + KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithNext())); } for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) { - keepWithNext |= gu.getPrimary().mustKeepWithNext(); + strength = Math.max(strength, gu.getPrimary().getKeepWithNextStrength()); } } - return keepWithNext; - } - - /** - * Returns true if this row is enclosed by an fo:table-row element that has - * keep-together set. - * - * @return true if this row must be kept together - */ - public boolean mustKeepTogether() { - return getKeepTogetherStrength() != BlockLevelLayoutManager.KEEP_AUTO; + return strength; } /** diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 8af896fa2..55bcfa44e 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -25,6 +25,7 @@ import java.util.List; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.table.TableCellLayoutManager; @@ -53,8 +54,8 @@ public class PrimaryGridUnit extends GridUnit { private boolean isSeparateBorderModel; private int halfBorderSeparationBPD; - private boolean keepWithPrevious; - private boolean keepWithNext; + private int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; + private int keepWithNext = BlockLevelLayoutManager.KEEP_AUTO; private int breakBefore = Constants.EN_AUTO; private int breakAfter = Constants.EN_AUTO; @@ -328,37 +329,39 @@ public class PrimaryGridUnit extends GridUnit { } /** - * Returns true if the first child block (or its descendants) of this cell has - * keep-with-previous. + * Returns the strength of the keep constraint if the first child block (or its descendants) + * of this cell has keep-with-previous. * - * @return the value of keep-with-previous + * @return the keep-with-previous strength */ - public boolean mustKeepWithPrevious() { + public int getKeepWithPreviousStrength() { return keepWithPrevious; } /** * Don't use, reserved for TableCellLM. TODO + * @param strength the keep strength */ - public void setKeepWithPrevious() { - this.keepWithPrevious = true; + public void setKeepWithPreviousStrength(int strength) { + this.keepWithPrevious = strength; } /** - * Returns true if the last child block (or its descendants) of this cell has - * keep-with-next. + * Returns the strength of the keep constraint if the last child block (or its descendants) of + * this cell has keep-with-next. * - * @return the value of keep-with-next + * @return the keep-with-next strength */ - public boolean mustKeepWithNext() { + public int getKeepWithNextStrength() { return keepWithNext; } /** * Don't use, reserved for TableCellLM. TODO + * @param strength the keep strength */ - public void setKeepWithNext() { - this.keepWithNext = true; + public void setKeepWithNextStrength(int strength) { + this.keepWithNext = strength; } /** diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index c0220e75e..a44669371 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -263,6 +263,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (!firstVisibleMarkServed) { addKnuthElementsForSpaceBefore(returnList, alignment); + context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); } addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); @@ -284,6 +285,11 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // get elements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); + if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { + //Propagate keep-with-previous up from the first child + context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + childLC.clearKeepWithPreviousPending(); + } if (returnedList.size() == 1 && ((ListElement)returnedList.getFirst()).isForcedBreak()) { // a descendant of this block has break-before @@ -329,6 +335,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return returnList; } } + // propagate and clear + context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); + childLC.clearKeepsPending(); prevLM = curLM; } @@ -377,6 +386,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager context.clearPendingMarks(); addKnuthElementsForBreakAfter(returnList, context); + context.updateKeepWithNextPending(getKeepWithNextStrength()); + setFinished(true); return returnList; } @@ -990,26 +1001,22 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; - strength = Math.max(strength, KeepUtil.getKeepStrength( - getBlockContainerFO().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - getBlockContainerFO().getKeepTogether().getWithinColumn())); + int strength = KeepUtil.getCombinedBlockLevelKeepStrength( + getBlockContainerFO().getKeepTogether()); strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; } /** {@inheritDoc} */ - public boolean mustKeepWithPrevious() { - //TODO Keeps will have to be more sophisticated sooner or later - return !getBlockContainerFO().getKeepWithPrevious().getWithinPage().isAuto() - || !getBlockContainerFO().getKeepWithPrevious().getWithinColumn().isAuto(); + public int getKeepWithNextStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength( + getBlockContainerFO().getKeepWithNext()); } /** {@inheritDoc} */ - public boolean mustKeepWithNext() { - return !getBlockContainerFO().getKeepWithNext().getWithinPage().isAuto() - || !getBlockContainerFO().getKeepWithNext().getWithinColumn().isAuto(); + public int getKeepWithPreviousStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength( + getBlockContainerFO().getKeepWithPrevious()); } /** @@ -1021,16 +1028,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // --------- Property Resolution related functions --------- // - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean getGeneratesReferenceArea() { return true; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean getGeneratesBlockArea() { return true; } diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 253ec2af1..48bf47caf 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -30,6 +30,7 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.LineArea; import org.apache.fop.datatypes.Length; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; @@ -209,26 +210,20 @@ public class BlockLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; - strength = Math.max(strength, KeepUtil.getKeepStrength( - getBlockFO().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - getBlockFO().getKeepTogether().getWithinColumn())); + KeepProperty keep = getBlockFO().getKeepTogether(); + int strength = KeepUtil.getCombinedBlockLevelKeepStrength(keep); strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; } /** {@inheritDoc} */ - public boolean mustKeepWithPrevious() { - //TODO Keeps will have to be more sophisticated sooner or later - return !getBlockFO().getKeepWithPrevious().getWithinPage().isAuto() - || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto(); + public int getKeepWithNextStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithNext()); } /** {@inheritDoc} */ - public boolean mustKeepWithNext() { - return !getBlockFO().getKeepWithNext().getWithinPage().isAuto() - || !getBlockFO().getKeepWithNext().getWithinColumn().isAuto(); + public int getKeepWithPreviousStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithPrevious()); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java index 3dc7ed46e..765bb1086 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java @@ -55,11 +55,23 @@ public interface BlockLevelLayoutManager extends LayoutManager { */ boolean mustKeepTogether(); + /** + * Returns the keep-with-previous strength for this element. + * @return the keep-with-previous strength + */ + int getKeepWithPreviousStrength(); + /** * @return true if this element must be kept with the previous element. */ boolean mustKeepWithPrevious(); + /** + * Returns the keep-with-next strength for this element. + * @return the keep-with-next strength + */ + int getKeepWithNextStrength(); + /** * @return true if this element must be kept with the next element. */ diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index c6ead8d59..e9d529ebe 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -265,6 +265,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (!firstVisibleMarkServed) { addKnuthElementsForSpaceBefore(returnList, alignment); + context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); } addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); @@ -296,8 +297,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // get elements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); + //Propagate keep-with-previous up from the first child + context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + childLC.clearKeepWithPreviousPending(); } if (returnedList != null && returnedList.size() == 1 @@ -364,9 +366,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } } // propagate and clear - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, childLC.isKeepWithNextPending()); - childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); + context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); + childLC.clearKeepsPending(); prevLM = curLM; } @@ -400,12 +401,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager wrapPositionElement(forcedBreakAfterLast, returnList, false); } - if (mustKeepWithNext()) { - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); - } - if (mustKeepWithPrevious()) { - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); - } + context.updateKeepWithNextPending(getKeepWithNextStrength()); setFinished(true); @@ -425,14 +421,15 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager || childLC.isKeepWithPreviousPending()) { int strength = getKeepTogetherStrength(); - if (context.isKeepWithNextPending()) { - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - strength = KEEP_ALWAYS; - } - if (childLC.isKeepWithPreviousPending()) { - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); - strength = KEEP_ALWAYS; - } + + //Handle pending keep-with-next + strength = Math.max(strength, context.getKeepWithNextPending()); + context.clearKeepWithNextPending(); + + //Handle pending keep-with-previous from child LM + strength = Math.max(strength, childLC.getKeepWithPreviousPending()); + childLC.clearKeepWithPreviousPending(); + int penalty = KeepUtil.getPenaltyForKeep(strength); // add a penalty to forbid or discourage a break between blocks @@ -823,12 +820,12 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { - return false; + return getKeepWithPreviousStrength() > KEEP_AUTO; } /** {@inheritDoc} */ public boolean mustKeepWithNext() { - return false; + return getKeepWithNextStrength() > KEEP_AUTO; } /** diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index ecfcbe2b4..c54f0ce12 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -107,8 +107,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager returnedList = curLM.getNextKnuthElements(childLC, alignment); //log.debug("FLM.getNextKnuthElements> returnedList.size() = " + returnedList.size()); if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) { - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); + context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + childLC.clearKeepWithPreviousPending(); } // "wrap" the Position inside each element @@ -124,20 +124,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager return returnList; } else { if (returnList.size() > 0) { - // there is a block before this one - if (context.isKeepWithNextPending() - || childLC.isKeepWithPreviousPending()) { - //Clear pending keep flag - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); - // add an infinite penalty to forbid a break between blocks - returnList.add(new BreakElement( - new Position(this), KnuthElement.INFINITE, context)); - } else if (!((ListElement) returnList.getLast()).isGlue()) { - // add a null penalty to allow a break between blocks - returnList.add(new BreakElement( - new Position(this), 0, context)); - } + addInBetweenBreak(returnList, context, childLC); } if (returnedList.size() > 0) { returnList.addAll(returnedList); @@ -155,11 +142,12 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } } } - if (childLC.isKeepWithNextPending()) { - //Clear and propagate - childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); - } + + //Propagate and clear + context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); + childLC.clearKeepWithNextPending(); + + context.updateKeepWithNextPending(getKeepWithNextStrength()); } SpaceResolver.resolveElementList(returnList); @@ -213,18 +201,16 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public boolean mustKeepWithPrevious() { - return false; + public int getKeepWithNextStrength() { + return KEEP_AUTO; } /** {@inheritDoc} */ - public boolean mustKeepWithNext() { - return false; + public int getKeepWithPreviousStrength() { + return KEEP_AUTO; } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ public LinkedList getChangedKnuthElements(List oldList, /*int flaggedPenalty,*/ int alignment) { ListIterator oldListIterator = oldList.listIterator(); KnuthElement returnedElement; @@ -357,6 +343,6 @@ public class FlowLayoutManager extends BlockStackingLayoutManager public int getContentAreaBPD() { return (int) getCurrentPV().getBodyRegion().getBPD(); } - + } diff --git a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java index 351504cd7..34b931c03 100644 --- a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java @@ -96,4 +96,14 @@ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { return getParentKeepTogetherStrength(); } + /** {@inheritDoc} */ + public int getKeepWithNextStrength() { + return KEEP_AUTO; + } + + /** {@inheritDoc} */ + public int getKeepWithPreviousStrength() { + return KEEP_AUTO; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/KeepUtil.java b/src/java/org/apache/fop/layoutmgr/KeepUtil.java index 1fd595ae0..8c80a1b10 100644 --- a/src/java/org/apache/fop/layoutmgr/KeepUtil.java +++ b/src/java/org/apache/fop/layoutmgr/KeepUtil.java @@ -20,6 +20,7 @@ package org.apache.fop.layoutmgr; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.Property; /** @@ -46,6 +47,29 @@ public class KeepUtil { } } + /** + * Returns the combined block-level keep strength from a keep property. + *

                                                                                          + * Note: This is a temporary method to be used until it is possible to differentiate between + * page and column keeps! + * @param keep the keep property + * @return the combined keep strength + */ + public static int getCombinedBlockLevelKeepStrength(KeepProperty keep) { + return Math.max( + getKeepStrength(keep.getWithinPage()), + getKeepStrength(keep.getWithinColumn())); + } + + /** + * Indicates whether a keep strength indicates a keep constraint. + * @param strength the keep strength + * @return true if the keep is not "auto" + */ + public static boolean hasKeep(int strength) { + return strength > BlockLevelLayoutManager.KEEP_AUTO; + } + /** * Returns the penalty value to be used for a certain keep strength. *

                                                                                            @@ -67,4 +91,19 @@ public class KeepUtil { return penalty; } + /** + * Returns a string representation of a keep strength value. + * @param keepStrength the keep strength + * @return the string representation + */ + public static String keepStrengthToString(int keepStrength) { + if (keepStrength == BlockLevelLayoutManager.KEEP_AUTO) { + return "auto"; + } else if (keepStrength == BlockLevelLayoutManager.KEEP_ALWAYS) { + return "always"; + } else { + return Integer.toString(keepStrength); + } + } + } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 79b5e232f..5ac9808f2 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -63,12 +63,12 @@ public class LayoutContext { * This flag indicates that there's a keep-with-next that hasn't * been processed, yet. */ - public static final int KEEP_WITH_NEXT_PENDING = 0x200; + //public static final int KEEP_WITH_NEXT_PENDING = 0x200; /** * This flag indicates that there's a keep-with-previous that hasn't * been processed, yet. */ - public static final int KEEP_WITH_PREVIOUS_PENDING = 0x400; + //public static final int KEEP_WITH_PREVIOUS_PENDING = 0x400; private int flags; // Contains some set of flags defined above @@ -135,7 +135,6 @@ public class LayoutContext { /** Amount of space before / start */ private int spaceBefore = 0; - /** Amount of space after / end */ private int spaceAfter = 0; @@ -145,9 +144,11 @@ public class LayoutContext { private int lineEndBorderAndPaddingWidth = 0; private int breakBefore; - private int breakAfter; + private int pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO; + private int pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; + /** * Copy constructor for creating child layout contexts. * @param parentLC the parent layout context to copy from @@ -167,6 +168,8 @@ public class LayoutContext { this.lineStartBorderAndPaddingWidth = parentLC.lineStartBorderAndPaddingWidth; this.lineEndBorderAndPaddingWidth = parentLC.lineEndBorderAndPaddingWidth; copyPendingMarksFrom(parentLC); + this.pendingKeepWithNext = parentLC.pendingKeepWithNext; + this.pendingKeepWithPrevious = parentLC.pendingKeepWithPrevious; // Copy other fields as necessary. } @@ -228,12 +231,74 @@ public class LayoutContext { return ((this.flags & SUPPRESS_LEADING_SPACE) != 0); } + /** + * Returns the strength of a keep-with-next currently pending. + * @return the keep-with-next strength + */ + public int getKeepWithNextPending() { + return this.pendingKeepWithNext; + } + + /** + * Returns the strength of a keep-with-previous currently pending. + * @return the keep-with-previous strength + */ + public int getKeepWithPreviousPending() { + return this.pendingKeepWithPrevious; + } + + /** + * Clears any pending keep-with-next strength. + */ + public void clearKeepWithNextPending() { + this.pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO; + } + + /** + * Clears any pending keep-with-previous strength. + */ + public void clearKeepWithPreviousPending() { + this.pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; + } + + /** + * Clears both keep-with-previous and keep-with-next strengths. + */ + public void clearKeepsPending() { + clearKeepWithPreviousPending(); + clearKeepWithNextPending(); + } + + /** + * Updates the currently pending keep-with-next strength. + * @param strength the new strength to consider + */ + public void updateKeepWithNextPending(int strength) { + this.pendingKeepWithNext = Math.max(this.pendingKeepWithNext, strength); + } + + /** + * Updates the currently pending keep-with-previous strength. + * @param strength the new strength to consider + */ + public void updateKeepWithPreviousPending(int strength) { + this.pendingKeepWithPrevious = Math.max(this.pendingKeepWithPrevious, strength); + } + + /** + * Indicates whether a keep-with-next constraint is pending. + * @return true if a keep-with-next constraint is pending + */ public boolean isKeepWithNextPending() { - return ((this.flags & KEEP_WITH_NEXT_PENDING) != 0); + return getKeepWithNextPending() != BlockLevelLayoutManager.KEEP_AUTO; } + /** + * Indicates whether a keep-with-previous constraint is pending. + * @return true if a keep-with-previous constraint is pending + */ public boolean isKeepWithPreviousPending() { - return ((this.flags & KEEP_WITH_PREVIOUS_PENDING) != 0); + return getKeepWithPreviousPending() != BlockLevelLayoutManager.KEEP_AUTO; } public void setLeadingSpace(SpaceSpecifier space) { @@ -595,8 +660,9 @@ public class LayoutContext { + "\nStarts New Area: \t" + startsNewArea() + "\nIs Last Area: \t" + isLastArea() + "\nTry Hyphenate: \t" + tryHyphenate() - + "\nKeeps: \t[" + (isKeepWithNextPending() ? "keep-with-next" : "") + "][" - + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending" + + "\nKeeps: \t[keep-with-next=" + KeepUtil.keepStrengthToString(getKeepWithNextPending()) + + "][keep-with-previous=" + + KeepUtil.keepStrengthToString(getKeepWithPreviousPending()) + "] pending" + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]"; } diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 0d88f2a1d..42ddcc220 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -410,5 +410,15 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { return KEEP_AUTO; } + /** {@inheritDoc} */ + public int getKeepWithNextStrength() { + return KEEP_AUTO; + } + + /** {@inheritDoc} */ + public int getKeepWithPreviousStrength() { + return KEEP_AUTO; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index e9919e02f..f3bb66022 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -314,7 +314,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // get KnuthElements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) { - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); + childLC.clearKeepWithPreviousPending(); } if (returnedList == null || returnedList.size() == 0) { @@ -324,7 +324,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } if (curLM instanceof InlineLevelLayoutManager) { - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); + context.clearKeepWithNextPending(); // "wrap" the Position stored in each element of returnedList ListIterator seqIter = returnedList.listIterator(); while (seqIter.hasNext()) { @@ -365,10 +365,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { returnList.add(sequence); } // propagate and clear - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, - childLC.isKeepWithNextPending()); - childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); + context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); + childLC.clearKeepsPending(); } lastSequence = (KnuthSequence) returnList.getLast(); lastChildLM = curLM; diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 08a3f3eff..8c46796eb 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -1281,23 +1281,27 @@ public class LineLayoutManager extends InlineStackingLayoutManager return ((BlockLevelLayoutManager) getParent()).getKeepTogetherStrength(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { - return false; + return getKeepWithPreviousStrength() > KEEP_AUTO; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean mustKeepWithNext() { - return false; + return getKeepWithNextStrength() > KEEP_AUTO; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ + public int getKeepWithNextStrength() { + return KEEP_AUTO; + } + + /** {@inheritDoc} */ + public int getKeepWithPreviousStrength() { + return KEEP_AUTO; + } + + /** {@inheritDoc} */ public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) { LeafPosition pos = (LeafPosition)lastElement.getPosition(); int totalAdj = adj; diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index eb64e0bf0..57114eee2 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -280,26 +280,20 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; - strength = Math.max(strength, KeepUtil.getKeepStrength( - getListBlockFO().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - getListBlockFO().getKeepTogether().getWithinColumn())); + int strength = KeepUtil.getCombinedBlockLevelKeepStrength( + getListBlockFO().getKeepTogether()); strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; } /** {@inheritDoc} */ - public boolean mustKeepWithPrevious() { - //TODO Keeps will have to be more sophisticated sooner or later - return !getListBlockFO().getKeepWithPrevious().getWithinPage().isAuto() - || !getListBlockFO().getKeepWithPrevious().getWithinColumn().isAuto(); + public int getKeepWithNextStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithNext()); } /** {@inheritDoc} */ - public boolean mustKeepWithNext() { - return !getListBlockFO().getKeepWithNext().getWithinPage().isAuto() - || !getListBlockFO().getKeepWithNext().getWithinColumn().isAuto(); + public int getKeepWithPreviousStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithPrevious()); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index be7dbdbba..e3b88b0ac 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -222,14 +222,20 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { /** {@inheritDoc} */ public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; - strength = Math.max(strength, KeepUtil.getKeepStrength( - getPartFO().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - getPartFO().getKeepTogether().getWithinColumn())); + int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getPartFO().getKeepTogether()); strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; } + /** {@inheritDoc} */ + public int getKeepWithNextStrength() { + return KEEP_AUTO; + } + + /** {@inheritDoc} */ + public int getKeepWithPreviousStrength() { + return KEEP_AUTO; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index b727f8860..5e7288f04 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -32,6 +32,7 @@ import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListItem; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; +import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ConditionalElementListener; @@ -80,8 +81,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager private MinOptMax effSpaceBefore; private MinOptMax effSpaceAfter; - private boolean keepWithNextPendingOnLabel; - private boolean keepWithNextPendingOnBody; + private int keepWithNextPendingOnLabel; + private int keepWithNextPendingOnBody; private int listItemHeight; @@ -223,10 +224,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager SpaceResolver.resolveElementList(labelList); ElementListObserver.observe(labelList, "list-item-label", label.getPartFO().getId()); - if (childLC.isKeepWithPreviousPending()) { - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); - } - this.keepWithNextPendingOnLabel = childLC.isKeepWithNextPending(); + context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + this.keepWithNextPendingOnLabel = childLC.getKeepWithNextPending(); // body childLC = new LayoutContext(0); @@ -239,10 +238,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager SpaceResolver.resolveElementList(bodyList); ElementListObserver.observe(bodyList, "list-item-body", body.getPartFO().getId()); - if (childLC.isKeepWithPreviousPending()) { - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); - } - this.keepWithNextPendingOnBody = childLC.isKeepWithNextPending(); + context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + this.keepWithNextPendingOnBody = childLC.getKeepWithNextPending(); // create a combined list LinkedList returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList, context); @@ -254,12 +251,10 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager addKnuthElementsForSpaceAfter(returnList, alignment); addKnuthElementsForBreakAfter(returnList, context); - if (keepWithNextPendingOnLabel || keepWithNextPendingOnBody || mustKeepWithNext()) { - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); - } - if (mustKeepWithPrevious()) { - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); - } + context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel); + context.updateKeepWithNextPending(this.keepWithNextPendingOnBody); + context.updateKeepWithNextPending(getKeepWithNextStrength()); + context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); setFinished(true); resetSpaces(); @@ -281,21 +276,17 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int totalHeight = Math.max(fullHeights[0], fullHeights[1]); int step; int addedBoxHeight = 0; - boolean keepWithNextActive = false; + int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO; LinkedList returnList = new LinkedList(); while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { if (end[0] + 1 == elementLists[0].size()) { - if (keepWithNextPendingOnLabel) { - keepWithNextActive = true; - } + keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel); } if (end[1] + 1 == elementLists[1].size()) { - if (keepWithNextPendingOnBody) { - keepWithNextActive = true; - } + keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnBody); } // compute penalty height and box height @@ -327,12 +318,12 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager start[0], end[0], start[1], end[1]); returnList.add(new KnuthBox(boxHeight, stepPosition, false)); if (addedBoxHeight < totalHeight) { + int strength = BlockLevelLayoutManager.KEEP_AUTO; + strength = Math.max(strength, keepWithNextActive); + strength = Math.max(strength, getKeepTogetherStrength()); int p = stepPenalty; - if (keepWithNextActive) { - p = KnuthPenalty.INFINITE; - } - if (mustKeepTogether()) { - p = Math.max(p, KeepUtil.getPenaltyForKeep(getKeepTogetherStrength())); + if (p > -KnuthElement.INFINITE) { + p = Math.max(p, KeepUtil.getPenaltyForKeep(strength)); } returnList.add(new BreakElement(stepPosition, penaltyHeight, p, -1, context)); } @@ -637,26 +628,20 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; - strength = Math.max(strength, KeepUtil.getKeepStrength( - getListItemFO().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - getListItemFO().getKeepTogether().getWithinColumn())); + int strength = KeepUtil.getCombinedBlockLevelKeepStrength( + getListItemFO().getKeepTogether()); strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; } /** {@inheritDoc} */ - public boolean mustKeepWithPrevious() { - //TODO Keeps will have to be more sophisticated sooner or later - return !getListItemFO().getKeepWithPrevious().getWithinPage().isAuto() - || !getListItemFO().getKeepWithPrevious().getWithinColumn().isAuto(); + public int getKeepWithNextStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithNext()); } /** {@inheritDoc} */ - public boolean mustKeepWithNext() { - return !getListItemFO().getKeepWithNext().getWithinPage().isAuto() - || !getListItemFO().getKeepWithNext().getWithinColumn().isAuto(); + public int getKeepWithPreviousStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithPrevious()); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index ab65a1d28..70e2b2330 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -24,11 +24,13 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -70,7 +72,7 @@ class ActiveCell { /** True if the next CellPart that will be created will be the last one for this cell. */ private boolean lastCellPart; - private boolean keepWithNextSignal; + private int keepWithNextStrength; private int spanIndex = 0; @@ -202,7 +204,7 @@ class ActiveCell { includedLength = -1; // Avoid troubles with cells having content of zero length totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1; - keepWithNextSignal = false; + keepWithNextStrength = BlockLevelLayoutManager.KEEP_AUTO; remainingLength = totalLength - previousRowsLength; afterNextStep = new Step(previousRowsLength); @@ -506,14 +508,14 @@ class ActiveCell { */ CellPart createCellPart() { if (nextStep.end + 1 == elementList.size()) { - keepWithNextSignal = pgu.mustKeepWithNext(); + keepWithNextStrength = pgu.getKeepWithNextStrength(); // TODO if keep-with-next is set on the row, must every cell of the row // contribute some content from children blocks? // see http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200802.mbox/ // %3c47BDA379.4050606@anyware-tech.com%3e // Assuming no, but if yes the following code should enable this behaviour // if (pgu.getRow() != null && pgu.getRow().mustKeepWithNext()) { -// keepWithNextSignal = true; +// keepWithNextSignal = true; //to be converted to integer strengths // } } int bpBeforeFirst; @@ -536,8 +538,8 @@ class ActiveCell { } } - boolean keepWithNextSignal() { - return keepWithNextSignal; + int getKeepWithNextStrength() { + return keepWithNextStrength; } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 72e78b84f..19b97322c 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -33,7 +33,6 @@ import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; -import org.apache.fop.layoutmgr.BlockLevelEventProducer; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.MinOptMaxUtil; @@ -61,10 +60,8 @@ class RowGroupLayoutManager { LinkedList returnList = new LinkedList(); createElementsForRowGroup(context, alignment, bodyType, returnList); - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, - rowGroup[0].mustKeepWithPrevious()); - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, - rowGroup[rowGroup.length - 1].mustKeepWithNext()); + context.updateKeepWithPreviousPending(rowGroup[0].getKeepWithPreviousStrength()); + context.updateKeepWithNextPending(rowGroup[rowGroup.length - 1].getKeepWithNextStrength()); int breakBefore = Constants.EN_AUTO; TableRow firstRow = rowGroup[0].getTableRow(); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index fc0d587ff..c20060723 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -48,6 +48,14 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { super(node); } + /** + * Returns the table-and-caption formatting object. + * @return the table-and-caption formatting object + */ + public TableAndCaption getTableAndCaptionFO() { + return (TableAndCaption)this.fobj; + } + /** * Get the next break possibility. * @@ -196,13 +204,29 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { public int getKeepTogetherStrength() { int strength = KEEP_AUTO; /* TODO Complete me! - strength = Math.max(strength, KeepUtil.getKeepStrength( - getTableAndCaption().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - getTableAndCaption().getKeepTogether().getWithinColumn())); + int strength = KeepUtil.getCombinedBlockLevelKeepStrength( + getTableAndCaptionFO().getKeepTogether()); */ strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; } + /** {@inheritDoc} */ + public int getKeepWithNextStrength() { + return KEEP_AUTO; + /* TODO Complete me! + return KeepUtil.getCombinedBlockLevelKeepStrength( + getTableAndCaptionFO().getKeepWithNext()); + */ + } + + /** {@inheritDoc} */ + public int getKeepWithPreviousStrength() { + return KEEP_AUTO; + /* TODO Complete me! + return KeepUtil.getCombinedBlockLevelKeepStrength( + getTableAndCaptionFO().getKeepWithPrevious()); + */ + } + } \ No newline at end of file diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 8c4908547..615145fa1 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -47,7 +47,7 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { } /** @return the table-caption FO */ - public TableCaption getTableCaption() { + public TableCaption getTableCaptionFO() { return (TableCaption)this.fobj; } @@ -201,13 +201,31 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { int strength = KEEP_AUTO; /* TODO Complete me! strength = Math.max(strength, KeepUtil.getKeepStrength( - getTableCaption().getKeepTogether().getWithinPage())); + getTableCaptionFO().getKeepTogether().getWithinPage())); strength = Math.max(strength, KeepUtil.getKeepStrength( - getTableCaption().getKeepTogether().getWithinColumn())); + getTableCaptionFO().getKeepTogether().getWithinColumn())); */ strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; } + /** {@inheritDoc} */ + public int getKeepWithNextStrength() { + return KEEP_AUTO; + /* TODO Complete me! + return KeepUtil.getCombinedBlockLevelKeepStrength( + getTableCaptionFO().getKeepWithNext()); + */ + } + + /** {@inheritDoc} */ + public int getKeepWithPreviousStrength() { + return KEEP_AUTO; + /* TODO Complete me! + return KeepUtil.getCombinedBlockLevelKeepStrength( + getTableCaptionFO().getKeepWithPrevious()); + */ + } + } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 291e27ae2..6067af4bc 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -153,8 +153,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager log.debug("child LM signals pending keep with next"); } if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { - primaryGridUnit.setKeepWithPrevious(); - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); + primaryGridUnit.setKeepWithPreviousStrength(childLC.getKeepWithPreviousPending()); + childLC.clearKeepWithPreviousPending(); } if (prevLM != null) { @@ -169,14 +169,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } if (childLC.isKeepWithNextPending()) { //Clear and propagate - childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); + context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); + childLC.clearKeepWithNextPending(); } prevLM = curLM; } - if (context.isKeepWithNextPending()) { - primaryGridUnit.setKeepWithNext(); - } + primaryGridUnit.setKeepWithNextStrength(context.getKeepWithNextPending()); returnedList = new LinkedList(); if (contentList.size() > 0) { @@ -569,24 +567,15 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public boolean mustKeepWithPrevious() { - //TODO Keeps will have to be more sophisticated sooner or later - return false; //TODO FIX ME - /* - return !fobj.getKeepWithPrevious().getWithinPage().isAuto() - || !fobj.getKeepWithPrevious().getWithinColumn().isAuto(); - */ + public int getKeepWithNextStrength() { + return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-next!) } /** {@inheritDoc} */ - public boolean mustKeepWithNext() { - return false; //TODO FIX ME - /* - return !fobj.getKeepWithNext().getWithinPage().isAuto() - || !fobj.getKeepWithNext().getWithinColumn().isAuto(); - */ + public int getKeepWithPreviousStrength() { + return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!) } - + // --------- Property Resolution related functions --------- // /** diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 235bc1fd2..7a2ee171c 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -35,6 +35,7 @@ import org.apache.fop.fo.flow.table.EffRow; 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.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KeepUtil; @@ -208,31 +209,37 @@ public class TableContentLayoutManager implements PercentBaseContext { LinkedList returnList = new LinkedList(); 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.clearKeepsPending(); context.setBreakBefore(Constants.EN_AUTO); context.setBreakAfter(Constants.EN_AUTO); - boolean keepWithPrevious = false; + int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; int breakBefore = Constants.EN_AUTO; if (rowGroup != null) { RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, stepper); List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); - keepWithPrevious = context.isKeepWithPreviousPending(); - boolean keepBetween = context.isKeepWithNextPending(); + keepWithPrevious = Math.max(keepWithPrevious, context.getKeepWithPreviousPending()); breakBefore = context.getBreakBefore(); int breakBetween = context.getBreakAfter(); returnList.addAll(nextRowGroupElems); while ((rowGroup = iter.getNextRowGroup()) != null) { rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, stepper); + + //Note previous pending keep-with-next and clear the strength + //(as the layout context is reused) + int keepWithNextPending = context.getKeepWithNextPending(); + context.clearKeepWithNextPending(); + + //Get elements for next row group nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); - int penaltyValue = 0; - keepBetween |= context.isKeepWithPreviousPending(); - if (keepBetween) { - penaltyValue = KnuthElement.INFINITE; - } - penaltyValue = Math.max(penaltyValue, - KeepUtil.getPenaltyForKeep(getTableLM().getKeepTogetherStrength())); + + //Determine keep constraints + int penaltyStrength = BlockLevelLayoutManager.KEEP_AUTO; + penaltyStrength = Math.max(penaltyStrength, keepWithNextPending); + penaltyStrength = Math.max(penaltyStrength, context.getKeepWithPreviousPending()); + context.clearKeepWithPreviousPending(); + penaltyStrength = Math.max(penaltyStrength, getTableLM().getKeepTogetherStrength()); + int penaltyValue = KeepUtil.getPenaltyForKeep(penaltyStrength); breakBetween = BreakUtil.compareBreakClasses(breakBetween, context.getBreakBefore()); @@ -255,10 +262,9 @@ public class TableContentLayoutManager implements PercentBaseContext { penaltyLen, penaltyValue, breakBetween, context)); returnList.addAll(nextRowGroupElems); breakBetween = context.getBreakAfter(); - keepBetween = context.isKeepWithNextPending(); } } - context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, keepWithPrevious); + context.updateKeepWithPreviousPending(keepWithPrevious); context.setBreakBefore(breakBefore); //fox:widow-content-limit diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 5738a027c..75189a6b9 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -256,12 +256,11 @@ public class TableLayoutManager extends BlockStackingLayoutManager log.debug(contentKnuthElements); 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); - } + context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); + context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + + context.updateKeepWithNextPending(getKeepWithNextStrength()); + context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); if (getTable().isSeparateBorderModel()) { addKnuthElementsForBorderPaddingAfter(returnList, true); @@ -448,29 +447,19 @@ public class TableLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; - strength = Math.max(strength, KeepUtil.getKeepStrength( - getTable().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - getTable().getKeepTogether().getWithinColumn())); + int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepTogether()); strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; } - /** - * {@inheritDoc} - */ - public boolean mustKeepWithPrevious() { - return !getTable().getKeepWithPrevious().getWithinPage().isAuto() - || !getTable().getKeepWithPrevious().getWithinColumn().isAuto(); + /** {@inheritDoc} */ + public int getKeepWithNextStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithNext()); } - /** - * {@inheritDoc} - */ - public boolean mustKeepWithNext() { - return !getTable().getKeepWithNext().getWithinPage().isAuto() - || !getTable().getKeepWithNext().getWithinColumn().isAuto(); + /** {@inheritDoc} */ + public int getKeepWithPreviousStrength() { + return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithPrevious()); } // --------- Property Resolution related functions --------- // diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 07894a07b..2d3c990f8 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -30,9 +30,11 @@ import org.apache.fop.fo.Constants; 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.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.KeepUtil; 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 org.apache.fop.layoutmgr.LayoutContext; @@ -198,11 +200,20 @@ public class TableStepper { } //Put all involved grid units into a list + int stepPenalty = 0; 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); + + //Record highest penalty value of part + if (part.end >= 0) { + KnuthElement endEl = (KnuthElement)part.pgu.getElements().get(part.end); + if (endEl instanceof KnuthPenalty) { + stepPenalty = Math.max(stepPenalty, endEl.getP()); + } + } } //Create elements for step @@ -230,39 +241,37 @@ public class TableStepper { } } - int p = 0; - boolean keepWithNext = false; + int strength = BlockLevelLayoutManager.KEEP_AUTO; for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); - keepWithNext |= activeCell.keepWithNextSignal(); - } - if (keepWithNext) { - p = KnuthPenalty.INFINITE; + strength = Math.max(strength, activeCell.getKeepWithNextStrength()); } if (!rowFinished) { - p = Math.max(p, KeepUtil.getPenaltyForKeep( - rowGroup[activeRowIndex].getKeepTogetherStrength())); + strength = Math.max(strength, rowGroup[activeRowIndex].getKeepTogetherStrength()); //The above call doesn't take the penalty from the table into account, so... - p = Math.max(p, KeepUtil.getPenaltyForKeep( - getTableLM().getKeepTogetherStrength())); + strength = Math.max(strength, getTableLM().getKeepTogetherStrength()); } else if (activeRowIndex < rowGroup.length - 1) { - if (rowGroup[activeRowIndex].mustKeepWithNext() - || rowGroup[activeRowIndex + 1].mustKeepWithPrevious()) { - p = KnuthPenalty.INFINITE; - } + strength = Math.max(strength, + rowGroup[activeRowIndex].getKeepWithNextStrength()); + strength = Math.max(strength, + rowGroup[activeRowIndex + 1].getKeepWithPreviousStrength()); 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) - } + int p = KeepUtil.getPenaltyForKeep(strength); if (rowHeightSmallerThanFirstStep) { rowHeightSmallerThanFirstStep = false; p = KnuthPenalty.INFINITE; } + if (p > -KnuthElement.INFINITE) { + p = Math.max(p, stepPenalty); + } + 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, nextBreakClass, context)); if (penaltyOrGlueLen < 0) { returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true)); diff --git a/status.xml b/status.xml index 6d55b69d4..d6b3c6941 100644 --- a/status.xml +++ b/status.xml @@ -58,6 +58,11 @@ Added SVG support for AFP (GOCA). --> + + Added minimal support for integer keep values on the various keep properties on block-level + FOs. For now, all integer values are treated the same (i.e. without strength distinction). + Using integers allows to avoid overflows that can happen when "always" is used extensively. + Added support for rendering pages using JPS (Java Printing System). See new example: examples/embedding/java/ExamplesFO2JPSPrint.java diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index b4de16ef4..12d7ed1aa 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -164,18 +164,6 @@ line. http://www.nabble.com/leaders-with-leader-pattern%3D%22use-content%22-t546244.html - - keep-with-previous doesn't work in lists - list-block_keep-with-previous.xml - Keep-with-previous doesn't work inside tables and - lists, yet. - - - keep-with-previous doesn't work in lists - list-item_block_keep-with-previous.xml - Keep-with-previous doesn't work inside tables and - lists, yet. - Page breaking doesn't deal with IPD changes page-breaking_4.xml diff --git a/test/layoutengine/standard-testcases/block-container_keep-with-next_1.xml b/test/layoutengine/standard-testcases/block-container_keep-with-next_1.xml new file mode 100644 index 000000000..c43e06359 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_keep-with-next_1.xml @@ -0,0 +1,101 @@ + + + + + +

                                                                                            + This test checks keep-with-next on fo:block-container. +

                                                                                            +

                                                                                            + Widows and Orphans are disabled in this test to avoid side-effects. +

                                                                                            +
                                                                                            + + + + + + + + + + + block1 + block2 + + + block3 + block4 + + + block5 + + + block6 + block7 + + block8 + + block9 + block10 + + block11 + + block12 + block13 + + block14 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + +
                                                                                            diff --git a/test/layoutengine/standard-testcases/block-container_keep-with-previous_1.xml b/test/layoutengine/standard-testcases/block-container_keep-with-previous_1.xml new file mode 100644 index 000000000..1c318ca0c --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_keep-with-previous_1.xml @@ -0,0 +1,101 @@ + + + + + +

                                                                                            + This test checks keep-with-previous on fo:block-container. +

                                                                                            +

                                                                                            + Widows and Orphans are disabled in this test to avoid side-effects. +

                                                                                            +
                                                                                            + + + + + + + + + + block1 + + block2 + block3 + + + block4 + block5 + + + block6 + + + block7 + block8 + + block9 + + block10 + block11 + + block12 + + block13 + block14 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + +
                                                                                            diff --git a/test/layoutengine/standard-testcases/block_keep-with-next_integers_1.xml b/test/layoutengine/standard-testcases/block_keep-with-next_integers_1.xml new file mode 100644 index 000000000..a1e89f3c2 --- /dev/null +++ b/test/layoutengine/standard-testcases/block_keep-with-next_integers_1.xml @@ -0,0 +1,99 @@ + + + + + +

                                                                                            + This test checks keep-with-next.wuithin-column with integer values. +

                                                                                            +

                                                                                            + Widows and Orphans are disabled in this test to avoid side-effects. +

                                                                                            +
                                                                                            + + + + + + + + + + block1 + block2 + block3 + block4 + + block5 + block6 + + block7 + + block8 + block9 + + block10 + + block11 + block12 + + block13 + + block14 + block15 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + +
                                                                                            diff --git a/test/layoutengine/standard-testcases/block_keep-with-previous_integers_1.xml b/test/layoutengine/standard-testcases/block_keep-with-previous_integers_1.xml new file mode 100644 index 000000000..d43d45608 --- /dev/null +++ b/test/layoutengine/standard-testcases/block_keep-with-previous_integers_1.xml @@ -0,0 +1,116 @@ + + + + + +

                                                                                            + This test checks keep-with-previous.wuithin-column with integer values. +

                                                                                            +

                                                                                            + Widows and Orphans are disabled in this test to avoid side-effects. +

                                                                                            +
                                                                                            + + + + + + + + + + block1 + block2 + block3 + block4 + + block5 + block6 + + block7 + + block8 + block9 + + block10 + + block11 + block12 + + block13 + + block14 + block15 + + block16 + + block17 + block18 + block19 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + 3 + + +
                                                                                            diff --git a/test/layoutengine/standard-testcases/list-block_keep-with-next_integers_1.xml b/test/layoutengine/standard-testcases/list-block_keep-with-next_integers_1.xml new file mode 100644 index 000000000..2c02806a3 --- /dev/null +++ b/test/layoutengine/standard-testcases/list-block_keep-with-next_integers_1.xml @@ -0,0 +1,155 @@ + + + + + +

                                                                                            + This test checks keep-with-next with lists. +

                                                                                            +
                                                                                            + + + + + + + + + + block1 + + + + label1 + + + item1 + + + + + label2 + + + item2 + + + + block2 + + + + label1 + + + item1 + item1 + item1 + item1 + + + + + label2 + + + item2 + + + + block3 + + + + label1 + + + item1 + + + + block4 + + + + label1 + + + item1 + item1 + + + + block5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + +
                                                                                            diff --git a/test/layoutengine/standard-testcases/list-block_keep-with-previous.xml b/test/layoutengine/standard-testcases/list-block_keep-with-previous.xml index 62b0f634c..cec98836a 100644 --- a/test/layoutengine/standard-testcases/list-block_keep-with-previous.xml +++ b/test/layoutengine/standard-testcases/list-block_keep-with-previous.xml @@ -63,7 +63,6 @@ item1 - item1 @@ -117,8 +116,6 @@ - - diff --git a/test/layoutengine/standard-testcases/list-block_keep-with-previous_integers_1.xml b/test/layoutengine/standard-testcases/list-block_keep-with-previous_integers_1.xml new file mode 100644 index 000000000..7b9c9fb0f --- /dev/null +++ b/test/layoutengine/standard-testcases/list-block_keep-with-previous_integers_1.xml @@ -0,0 +1,127 @@ + + + + + +

                                                                                            + This test checks keep-with-previous with lists. +

                                                                                            +
                                                                                            + + + + + + + + + + block1 + + + + label1 + + + item1 + + + + + label2 + + + item2 + + + + block2 + + + + label1 + + + item1 + item1 + + + + + label2 + + + item2 + + + + block3 + + + + label1 + + + item1 + + + + block4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + +
                                                                                            diff --git a/test/layoutengine/standard-testcases/list-item_block_keep-with-previous.xml b/test/layoutengine/standard-testcases/list-item_block_keep-with-previous.xml index 5c0a5da16..d2f5a18a8 100644 --- a/test/layoutengine/standard-testcases/list-item_block_keep-with-previous.xml +++ b/test/layoutengine/standard-testcases/list-item_block_keep-with-previous.xml @@ -41,7 +41,6 @@ item1 - item2
                                                                                            @@ -88,8 +87,6 @@ - - diff --git a/test/layoutengine/standard-testcases/table_keep-with-next_integers_1.xml b/test/layoutengine/standard-testcases/table_keep-with-next_integers_1.xml new file mode 100644 index 000000000..9774feb53 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_keep-with-next_integers_1.xml @@ -0,0 +1,184 @@ + + + + + +

                                                                                            + This test checks that keep-with-next works on tables. +

                                                                                            +
                                                                                            + + + + + + + + + + block1 + + + + + + cell1/1 + + + cell1/2 + + + + + block2 + + + + + + cell1/1 + + + cell1/2 + + + + + cell1/1 + + + cell1/2 + + + + + cell1/1 + + + cell1/2 + + + + + block3 + + + + + + cell1/1 + + + cell1/2 + + + + + block4 + + + + + + cell1/1 + + + cell1/2 + + + + + block5 + + + + + + cell1/1 + + + + cell1/2 + cell1/2 + + + + + + cell1/1 + + + cell1/2 + cell1/2 + + + + + block6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + +
                                                                                            diff --git a/test/layoutengine/standard-testcases/table_keep-with-previous_integers_1.xml b/test/layoutengine/standard-testcases/table_keep-with-previous_integers_1.xml new file mode 100644 index 000000000..ea5fada5f --- /dev/null +++ b/test/layoutengine/standard-testcases/table_keep-with-previous_integers_1.xml @@ -0,0 +1,146 @@ + + + + + +

                                                                                            + This test checks that keep-with-previous works on tables. +

                                                                                            +
                                                                                            + + + + + + + + + + block1 + + + + + + cell1/1 + + + cell1/2 + + + + + block2 + + + + + + cell1/1 + + + cell1/2 + + + + + cell1/1 + + + cell1/2 + + + + + cell1/1 + + + cell1/2 + + + + + block3 + + + + + + cell1/1 + + + cell1/2 + + + + + block4 + + + + + + cell1/1 + + + cell1/2 + + + + + block5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + +
                                                                                            -- cgit v1.2.3 From 6a5f719385be496af9d8fede33a8af0b5e2c7815 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 25 Apr 2008 11:27:19 +0000 Subject: Bugzilla 44634: Added partial implementation for show-destination. Only works for PDF output, when the PDF is opened in a standalone viewer, and for links that point to destinations in another PDF document. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651575 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 11 +- src/java/org/apache/fop/area/AreaTreeParser.java | 4 +- src/java/org/apache/fop/area/Trait.java | 192 +++++++++------------ src/java/org/apache/fop/fo/Constants.java | 8 +- src/java/org/apache/fop/fo/FOPropertyMapping.java | 11 +- src/java/org/apache/fop/fo/flow/BasicLink.java | 62 ++++--- .../layoutmgr/inline/BasicLinkLayoutManager.java | 14 +- .../fop/layoutmgr/inline/InlineLayoutManager.java | 11 +- src/java/org/apache/fop/pdf/PDFFactory.java | 38 ++-- src/java/org/apache/fop/pdf/PDFGoToRemote.java | 34 +++- .../org/apache/fop/render/pdf/PDFRenderer.java | 21 ++- status.xml | 9 +- .../basic-link_external-destination.xml | 4 +- 13 files changed, 222 insertions(+), 197 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 2b25b89d7..2c1af46c3 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -5276,9 +5276,16 @@ no - no + partial -   + +
                                                                                              +
                                                                                            • [FOP Trunk] only has effect in PDF output, for external PDF destinations (links pointing to destinations + in another PDF), and only works reliably when the PDF is viewed in a standalone PDF viewer. +

                                                                                              Adobe's browser plugin, for example, ignores the /NewWindow flag. +

                                                                                              For links pointing to non-PDF destinations (e.g.

                                                                                            • +
                                                                                            + diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index 19edd3d5e..d48221c0a 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -1018,7 +1018,7 @@ public class AreaTreeParser { Trait.IS_REFERENCE_AREA, Trait.IS_VIEWPORT_AREA}; private void setTraits(Attributes attributes, Area area, Object[] traitSubset) { - for (int i = 0, c = traitSubset.length; i < c; i++) { + for (int i = traitSubset.length; --i >= 0;) { Object trait = traitSubset[i]; String traitName = Trait.getTraitName(trait); String value = attributes.getValue(traitName); @@ -1044,6 +1044,8 @@ public class AreaTreeParser { } } else if (cl == InternalLink.class) { area.addTrait(trait, new InternalLink(value)); + } else if (cl == Trait.ExternalLink.class) { + area.addTrait(trait, Trait.ExternalLink.makeFromTraitValue(value)); } else if (cl == Background.class) { Background bkg = new Background(); try { diff --git a/src/java/org/apache/fop/area/Trait.java b/src/java/org/apache/fop/area/Trait.java index 98bed098c..9599d8833 100644 --- a/src/java/org/apache/fop/area/Trait.java +++ b/src/java/org/apache/fop/area/Trait.java @@ -194,7 +194,7 @@ public class Trait implements Serializable { public static final Integer OVERLINE_COLOR = new Integer(35); /** Trait for color of linethrough decorations when rendering inline parent. */ public static final Integer LINETHROUGH_COLOR = new Integer(36); - + /** Maximum value used by trait keys */ public static final int MAX_TRAIT_KEY = 36; @@ -226,7 +226,7 @@ public class Trait implements Serializable { // Create a hashmap mapping trait code to name for external representation //put(ID_LINK, new TraitInfo("id-link", String.class)); put(INTERNAL_LINK, new TraitInfo("internal-link", InternalLink.class)); - put(EXTERNAL_LINK, new TraitInfo("external-link", String.class)); + put(EXTERNAL_LINK, new TraitInfo("external-link", ExternalLink.class)); put(FONT, new TraitInfo("font", FontTriplet.class)); put(FONT_SIZE, new TraitInfo("font-size", Integer.class)); put(COLOR, new TraitInfo("color", Color.class)); @@ -277,7 +277,7 @@ public class Trait implements Serializable { new TraitInfo("is-reference-area", Boolean.class)); put(IS_VIEWPORT_AREA, new TraitInfo("is-viewport-area", Boolean.class)); - + } /** @@ -290,25 +290,6 @@ public class Trait implements Serializable { return TRAIT_INFO[((Integer)traitCode).intValue()].getName(); } - /** - * Get the trait code for a trait name. - * - * @param sTraitName the name of the trait to find - * @return the trait code object - */ - /* - public static Object getTraitCode(String sTraitName) { - Iterator iter = TRAIT_INFO.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = (Map.Entry) iter.next(); - TraitInfo ti = (TraitInfo) entry.getValue(); - if (ti != null && ti.getName().equals(sTraitName)) { - return entry.getKey(); - } - } - return null; - }*/ - /** * Get the data storage class for the trait. * @@ -319,99 +300,6 @@ public class Trait implements Serializable { return TRAIT_INFO[((Integer)traitCode).intValue()].getClazz(); } - /** - * The type of trait for an area. - */ - private Object propType; - - /** - * The data value of the trait. - */ - private Object data; - - /** - * Create a new empty trait. - */ - public Trait() { - this.propType = null; - this.data = null; - } - - /** - * Create a trait with the value and type. - * - * @param propType the type of trait - * @param data the data value - */ - public Trait(Object propType, Object data) { - this.propType = propType; - this.data = data; - } - - /** - * Returns the trait data value. - * @return the trait data value - */ - public Object getData() { - return this.data; - } - - /** - * Returns the property type. - * @return the property type - */ - public Object getPropType() { - return this.propType; - } - - /** - * Return the string for debugging. - * {@inheritDoc} - */ - public String toString() { - return data.toString(); - } - - /** - * Make a trait value. - * - * @param oCode trait code - * @param sTraitValue trait value as String - * @return the trait value as object - */ - /* - public static Object makeTraitValue(Object oCode, String sTraitValue) { - // Get the code from the name - // See what type of object it is - // Convert string value to an object of that type - Class tclass = getTraitClass(oCode); - if (tclass == null) { - return null; - } - if (tclass.equals(String.class)) { - return sTraitValue; - } - if (tclass.equals(Integer.class)) { - return new Integer(sTraitValue); - } - // See if the class has a constructor from string or can read from a string - try { - Object o = tclass.newInstance(); - //return o.fromString(sTraitValue); - } catch (IllegalAccessException e1) { - log.error("Can't create instance of " - + tclass.getName()); - return null; - } catch (InstantiationException e2) { - log.error("Can't create instance of " - + tclass.getName()); - return null; - } - - - return null; - }*/ - /** * Class for internal link traits. * Stores PageViewport key and producer ID @@ -547,6 +435,80 @@ public class Trait implements Serializable { } } + /** + * External Link trait structure + */ + public static class ExternalLink implements Serializable { + + private String destination; + private boolean newWindow; + + /** + * Constructs an ExternalLink object with the given destination + * + * @param destination target of the link + * @param newWindow true if the target should be opened in a new window + */ + public ExternalLink(String destination, boolean newWindow) { + this.destination = destination; + this.newWindow = newWindow; + } + + /** + * Create an ExternalLink from a trait value/attribute value in the + * area tree + * @param traitValue the value to use (should match the result of {@link #toString()} + * @return an ExternalLink instance corresponding to the given value + */ + protected static ExternalLink makeFromTraitValue(String traitValue) { + if (traitValue.indexOf(ExternalLink.class.getName()) == -1 + || traitValue.indexOf("dest=") == -1) { + throw new IllegalArgumentException( + "Malformed trait value for Trait.ExternalLink: " + traitValue); + } + int startIndex = traitValue.indexOf("dest=") + 5; + int endIndex = traitValue.indexOf(',', startIndex); + if (endIndex == -1) { + endIndex = traitValue.indexOf(']'); + } + String dest = traitValue.substring(startIndex, endIndex); + startIndex = traitValue.indexOf("newWindow=", endIndex) + 10; + endIndex = traitValue.indexOf(']', startIndex); + boolean newWindow = Boolean.parseBoolean( + traitValue.substring(startIndex, endIndex)); + return new ExternalLink(dest, newWindow); + } + + /** + * Get the target/destination of the link + * @return the destination of the link + */ + public String getDestination() { + return this.destination; + } + + /** + * Check if the target has to be displayed in a new window + * @return true if the target has to be displayed in a new window + */ + public boolean newWindow() { + return this.newWindow; + } + + /** + * Return a String representation of the object. + * @return a String of the form + * "org.apache.fop.area.Trait.ExternalLink[dest=someURL,newWindow=false]" + */ + public String toString() { + StringBuffer sb = new StringBuffer(64); + sb.append(super.toString()); + sb.append("[dest=").append(this.destination); + sb.append(",newWindow=").append(newWindow).append("]"); + return sb.toString(); + } + } + /** * Background trait structure. * Used for storing back trait information which are related. diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java index edfa68c1a..25c2fe371 100644 --- a/src/java/org/apache/fop/fo/Constants.java +++ b/src/java/org/apache/fop/fo/Constants.java @@ -1092,7 +1092,11 @@ public interface Constants { /** Enumeration constant -- for instream-foreign-object and external-graphic, XSL 1.1 */ int EN_SCALE_DOWN_TO_FIT = 187; /** Enumeration constant -- for instream-foreign-object and external-graphic, XSL 1.1 */ - int EN_SCALE_UP_TO_FIT = 188; + int EN_SCALE_UP_TO_FIT = 188; + /** Enumeration constant -- for fo:basic-link show-destination */ + int EN_REPLACE = 189; + /** Enumeration constant -- for fo:basic-link show-destination */ + int EN_NEW = 190; /** Number of enumeration constants defined */ - int ENUM_COUNT = 188; + int ENUM_COUNT = 190; } diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index db19d6515..5d4185d68 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -258,7 +258,7 @@ public final class FOPropertyMapping implements Constants { /** * Return a (possibly cached) enum property based in the enum value. - * @param enum A enum value from Constants.java. + * @param enumValue A enum value from Constants.java. * @param text the text value by which this enum property is known * @return An EnumProperty instance. */ @@ -371,9 +371,8 @@ public final class FOPropertyMapping implements Constants { || ((id & Constants.PROPERTY_MASK) == 0)) { return (String) s_htPropIds.get(new Integer(id)); } else { - return (String) s_htPropIds.get(new Integer( - id & Constants.PROPERTY_MASK)) + "." + s_htPropIds.get( - new Integer(id & Constants.COMPOUND_MASK)); + return s_htPropIds.get(new Integer(id & Constants.PROPERTY_MASK)) + + "." + s_htPropIds.get(new Integer(id & Constants.COMPOUND_MASK)); } } @@ -2019,8 +2018,10 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("internal-destination", m); // show-destination - m = new ToBeImplementedProperty.Maker(PR_SHOW_DESTINATION); + m = new EnumProperty.Maker(PR_SHOW_DESTINATION); m.setInherited(false); + m.addEnum("new", getEnumProperty(EN_NEW, "NEW")); + m.addEnum("replace", getEnumProperty(EN_REPLACE, "REPLACE")); m.setDefault("replace"); addPropertyMaker("show-destination", m); diff --git a/src/java/org/apache/fop/fo/flow/BasicLink.java b/src/java/org/apache/fop/fo/flow/BasicLink.java index b3ef48012..82d0134bd 100644 --- a/src/java/org/apache/fop/fo/flow/BasicLink.java +++ b/src/java/org/apache/fop/fo/flow/BasicLink.java @@ -27,19 +27,21 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:basic-link object. + * Class modelling the + * fo:basic-link object. * * This class contains the logic to determine the link represented by this FO, * and whether that link is external (uses a URI) or internal (an id * reference). */ public class BasicLink extends Inline { + // The value of properties relevant for fo:basic-link. // private ToBeImplementedProperty destinationPlacementOffset; private String externalDestination; // private ToBeImplementedProperty indicateDestination; private String internalDestination; - // private ToBeImplementedProperty showDestination; + private int showDestination; // private ToBeImplementedProperty targetProcessingContext; // private ToBeImplementedProperty targetPresentationContext; // private ToBeImplementedProperty targetStylesheet; @@ -51,22 +53,23 @@ public class BasicLink extends Inline { private boolean blockOrInlineItemFound = false; /** - * @param parent FONode that is the parent of this object + * Construct a BasicLink instance with the given {@link FONode} + * as its parent. + * + * @param parent {@link FONode} that is the parent of this object */ public BasicLink(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); // destinationPlacementOffset = pList.get(PR_DESTINATION_PLACEMENT_OFFSET); externalDestination = pList.get(PR_EXTERNAL_DESTINATION).getString(); // indicateDestination = pList.get(PR_INDICATE_DESTINATION); internalDestination = pList.get(PR_INTERNAL_DESTINATION).getString(); - // showDestination = pList.get(PR_SHOW_DESTINATION); + showDestination = pList.get(PR_SHOW_DESTINATION).getEnum(); // targetProcessingContext = pList.get(PR_TARGET_PROCESSING_CONTEXT); // targetPresentationContext = pList.get(PR_TARGET_PRESENTATION_CONTEXT); // targetStylesheet = pList.get(PR_TARGET_STYLESHEET); @@ -80,26 +83,19 @@ public class BasicLink extends Inline { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startLink(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { super.endOfNode(); getFOEventHandler().endLink(); } - /** - * {@inheritDoc} String, String) - * XSL Content Model: marker* (#PCDATA|%inline;|%block;)* - */ + /** {@inheritDoc} */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { @@ -116,39 +112,61 @@ public class BasicLink extends Inline { } /** - * @return the "internal-destination" property. + * Get the value of the internal-destination property. + * + * @return the "internal-destination" property */ public String getInternalDestination() { return internalDestination; } /** - * @return the "external-destination" property. + * Get the value of the external-destination property. + * + * @return the "external-destination" property */ public String getExternalDestination() { return externalDestination; } /** - * @return whether or not this basic link has an internal destination or not + * Convenience method to check if this instance has an internal destination. + * + * @return true if this basic link has an internal destination; + * false otherwise */ public boolean hasInternalDestination() { return internalDestination != null && internalDestination.length() > 0; } /** - * @return whether or not this basic link has an external destination or not + * Convenience method to check if this instance has an external destination + * + * @return true if this basic link has an external destination; + * false otherwise */ public boolean hasExternalDestination() { return externalDestination != null && externalDestination.length() > 0; } + /** + * Get the value of the show-destination property. + * + * @return the "show-destination" property + */ + public int getShowDestination() { + return this.showDestination; + } + /** {@inheritDoc} */ public String getLocalName() { return "basic-link"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_BASIC_LINK} + */ public int getNameId() { return FO_BASIC_LINK; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java index e7339034c..b8979e187 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java @@ -21,7 +21,7 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.flow.BasicLink; -import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.fo.Constants; import org.apache.fop.layoutmgr.PageSequenceLayoutManager; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.Trait; @@ -31,7 +31,6 @@ import org.apache.fop.area.LinkResolver; * LayoutManager for the fo:basic-link formatting object */ public class BasicLinkLayoutManager extends InlineLayoutManager { - private BasicLink fobj; /** * Create an fo:basic-link layout manager. @@ -40,23 +39,22 @@ public class BasicLinkLayoutManager extends InlineLayoutManager { */ public BasicLinkLayoutManager(BasicLink node) { super(node); - fobj = node; } /** {@inheritDoc} */ protected InlineArea createArea(boolean bInlineParent) { InlineArea area = super.createArea(bInlineParent); - setupBasicLinkArea(parentLM, area); + setupBasicLinkArea(area); return area; } /* * Detect internal or external link and add it as an area trait * - * @param parentLM the parent LayoutManager * @param area the basic-link's area */ - private void setupBasicLinkArea(LayoutManager parentLM, InlineArea area) { + private void setupBasicLinkArea(InlineArea area) { + BasicLink fobj = (BasicLink) this.fobj; // internal destinations take precedence: if (fobj.hasInternalDestination()) { String idref = fobj.getInternalDestination(); @@ -70,8 +68,10 @@ public class BasicLinkLayoutManager extends InlineLayoutManager { } } else if (fobj.hasExternalDestination()) { String url = URISpecification.getURL(fobj.getExternalDestination()); + boolean newWindow = (fobj.getShowDestination() == Constants.EN_NEW); if (url.length() > 0) { - area.addTrait(Trait.EXTERNAL_LINK, url); + area.addTrait(Trait.EXTERNAL_LINK, + new Trait.ExternalLink(url, newWindow)); } } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index f3bb66022..b59f0466a 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -68,8 +68,6 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { */ private static Log log = LogFactory.getLog(InlineLayoutManager.class); - private InlineLevel fobj; - private CommonMarginInline inlineProps = null; private CommonBorderPaddingBackground borderProps = null; @@ -105,7 +103,6 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // The node should be FObjMixed public InlineLayoutManager(InlineLevel node) { super(node); - fobj = node; } private Inline getInlineFO() { @@ -114,6 +111,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { /** {@inheritDoc} */ public void initialize() { + InlineLevel fobj = (InlineLevel) this.fobj; + int padding = 0; FontInfo fi = fobj.getFOEventHandler().getFontInfo(); FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); @@ -555,7 +554,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { if (returnList instanceof BlockKnuthSequence) { return; } - CommonBorderPaddingBackground borderAndPadding = fobj.getCommonBorderPaddingBackground(); + CommonBorderPaddingBackground borderAndPadding = + ((InlineLevel)fobj).getCommonBorderPaddingBackground(); if (borderAndPadding != null) { int ipStart = borderAndPadding.getBorderStartWidth(false) + borderAndPadding.getPaddingStart(false, this); @@ -579,7 +579,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { if (returnList instanceof BlockKnuthSequence) { return; } - CommonBorderPaddingBackground borderAndPadding = fobj.getCommonBorderPaddingBackground(); + CommonBorderPaddingBackground borderAndPadding = + ((InlineLevel)fobj).getCommonBorderPaddingBackground(); if (borderAndPadding != null) { int ipEnd = borderAndPadding.getBorderEndWidth(false) + borderAndPadding.getPaddingEnd(false, this); diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index f4474331f..02f0c2cdb 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -724,6 +724,7 @@ public class PDFFactory { * @param theColors the list of colors for the gradient * @param theBounds the list of bounds associated with the colors * @param theCoords the coordinates for the gradient + * @param theMatrix the coordinate-transformation matrix * @return the PDF pattern that was created */ public PDFPattern makeGradient(PDFResourceContext res, boolean radial, @@ -737,7 +738,7 @@ public class PDFFactory { List theCone; PDFPattern myPattern; //PDFColorSpace theColorSpace; - double interpolation = (double)1.000; + double interpolation = 1.000; List theFunctions = new ArrayList(); int currentPosition; @@ -874,7 +875,8 @@ public class PDFFactory { */ public PDFDests makeDests(List destinationList) { PDFDests dests; - + + //TODO: Check why the below conditional branch is needed. Condition is always true... final boolean deep = true; //true for a "deep" structure (one node per entry), true for a "flat" structure if (deep) { @@ -961,7 +963,7 @@ public class PDFFactory { } /** - * make a link object + * Make a {@link PDFLink} object * * @param rect the clickable rectangle * @param destination the destination file @@ -976,7 +978,7 @@ public class PDFFactory { PDFLink link = new PDFLink(rect); if (linkType == PDFLink.EXTERNAL) { - link.setAction(getExternalAction(destination)); + link.setAction(getExternalAction(destination, false)); } else { // linkType is internal String goToReference = getGoToReference(destination, yoffset); @@ -999,9 +1001,11 @@ public class PDFFactory { * * @param target The external target. This may be a PDF file name * (optionally with internal page number or destination) or any type of URI. + * @param newWindow boolean indicating whether the target should be + * displayed in a new window * @return the PDFAction thus created or found */ - public PDFAction getExternalAction(String target) { + public PDFAction getExternalAction(String target, boolean newWindow) { int index; String targetLo = target.toLowerCase(); // HTTP URL? @@ -1009,17 +1013,17 @@ public class PDFFactory { return new PDFUri(target); // Bare PDF file name? } else if (targetLo.endsWith(".pdf")) { - return getGoToPDFAction(target, null, -1); + return getGoToPDFAction(target, null, -1, newWindow); // PDF file + page? } else if ((index = targetLo.indexOf(".pdf#page=")) > 0) { String filename = target.substring(0, index + 4); int page = Integer.parseInt(target.substring(index + 10)); - return getGoToPDFAction(filename, null, page); + return getGoToPDFAction(filename, null, page, newWindow); // PDF file + destination? } else if ((index = targetLo.indexOf(".pdf#dest=")) > 0) { String filename = target.substring(0, index + 4); String dest = target.substring(index + 10); - return getGoToPDFAction(filename, dest, -1); + return getGoToPDFAction(filename, dest, -1, newWindow); // None of the above? Default to URI: } else { return new PDFUri(target); @@ -1069,9 +1073,11 @@ public class PDFFactory { * @param file the pdf file name * @param dest the remote name destination, may be null * @param page the remote page number, -1 means not specified + * @param newWindow boolean indicating whether the target should be + * displayed in a new window * @return the pdf goto remote object */ - private PDFGoToRemote getGoToPDFAction(String file, String dest, int page) { + private PDFGoToRemote getGoToPDFAction(String file, String dest, int page, boolean newWindow) { getDocument().getProfile().verifyActionAllowed(); PDFFileSpec fileSpec = new PDFFileSpec(file); PDFFileSpec oldspec = getDocument().findFileSpec(fileSpec); @@ -1083,11 +1089,11 @@ public class PDFFactory { PDFGoToRemote remote; if (dest == null && page == -1) { - remote = new PDFGoToRemote(fileSpec); + remote = new PDFGoToRemote(fileSpec, newWindow); } else if (dest != null) { - remote = new PDFGoToRemote(fileSpec, dest); + remote = new PDFGoToRemote(fileSpec, dest, newWindow); } else { - remote = new PDFGoToRemote(fileSpec, page); + remote = new PDFGoToRemote(fileSpec, page, newWindow); } PDFGoToRemote oldremote = getDocument().findGoToRemote(remote); if (oldremote == null) { @@ -1197,8 +1203,7 @@ public class PDFFactory { PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor); PDFFont font = null; - font = (PDFFont)PDFFont.createFont(fontname, fonttype, - basefont, encoding); + font = PDFFont.createFont(fontname, fonttype, basefont, encoding); getDocument().registerObject(font); if (fonttype == FontType.TYPE0) { @@ -1298,6 +1303,7 @@ public class PDFFactory { /** * Creates a PDFEncoding instance from a CodePointMapping instance. * @param encoding the code point mapping (encoding) + * @param fontNameHint ... * @return the PDF Encoding dictionary (or a String with the predefined encoding) */ public Object createPDFEncoding(SingleByteEncoding encoding, String fontNameHint) { @@ -1458,6 +1464,7 @@ public class PDFFactory { try { in = new java.net.URL(source.getSystemId()).openStream(); } catch (MalformedURLException e) { + //TODO: Why construct a new exception here, when it is not thrown? new FileNotFoundException( "File not found. URL could not be resolved: " + e.getMessage()); @@ -1514,7 +1521,7 @@ public class PDFFactory { log.error( "Failed to embed font [" + desc + "] " + desc.getEmbedFontName(), ioe); - return (PDFStream) null; + return null; } } @@ -1563,7 +1570,6 @@ public class PDFFactory { /** * Create a PDFICCStream * @see PDFImageXObject - * @see org.apache.fop.image.JpegImage * @see org.apache.fop.pdf.PDFDeviceColorSpace * @return the new PDF ICC stream object */ diff --git a/src/java/org/apache/fop/pdf/PDFGoToRemote.java b/src/java/org/apache/fop/pdf/PDFGoToRemote.java index 71cae5ba6..2cd937df3 100644 --- a/src/java/org/apache/fop/pdf/PDFGoToRemote.java +++ b/src/java/org/apache/fop/pdf/PDFGoToRemote.java @@ -20,7 +20,7 @@ package org.apache.fop.pdf; /** - * class representing a /GoToR object. + * Class representing a /GoToR object. */ public class PDFGoToRemote extends PDFAction { @@ -30,17 +30,21 @@ public class PDFGoToRemote extends PDFAction { private PDFFileSpec pdfFileSpec; private int pageReference = 0; private String destination = null; + private boolean newWindow = false; /** - * create an GoToR object. + * Create an GoToR object. * * @param pdfFileSpec the fileSpec associated with the action + * @param newWindow boolean indicating whether the target should be + * displayed in a new window */ - public PDFGoToRemote(PDFFileSpec pdfFileSpec) { + public PDFGoToRemote(PDFFileSpec pdfFileSpec, boolean newWindow) { /* generic creation of object */ super(); this.pdfFileSpec = pdfFileSpec; + this.newWindow = newWindow; } /** @@ -48,13 +52,16 @@ public class PDFGoToRemote extends PDFAction { * * @param pdfFileSpec the fileSpec associated with the action * @param page a page reference within the remote document + * @param newWindow boolean indicating whether the target should be + * displayed in a new window */ - public PDFGoToRemote(PDFFileSpec pdfFileSpec, int page) { + public PDFGoToRemote(PDFFileSpec pdfFileSpec, int page, boolean newWindow) { /* generic creation of object */ super(); this.pdfFileSpec = pdfFileSpec; this.pageReference = page; + this.newWindow = newWindow; } /** @@ -62,13 +69,16 @@ public class PDFGoToRemote extends PDFAction { * * @param pdfFileSpec the fileSpec associated with the action * @param dest a named destination within the remote document + * @param newWindow boolean indicating whether the target should be + * displayed in a new window */ - public PDFGoToRemote(PDFFileSpec pdfFileSpec, String dest) { + public PDFGoToRemote(PDFFileSpec pdfFileSpec, String dest, boolean newWindow) { /* generic creation of object */ super(); this.pdfFileSpec = pdfFileSpec; this.destination = dest; + this.newWindow = newWindow; } /** @@ -86,12 +96,18 @@ public class PDFGoToRemote extends PDFAction { public String toPDFString() { StringBuffer sb = new StringBuffer(64); sb.append(getObjectID()); - sb.append("<<\n/S /GoToR\n/F " + pdfFileSpec.referencePDF() + "\n"); + sb.append("<<\n/S /GoToR\n/F "); + sb.append(pdfFileSpec.referencePDF()); + sb.append("\n"); if (destination != null) { - sb.append("/D (" + this.destination + ")"); + sb.append("/D (").append(this.destination).append(")"); } else { - sb.append("/D [ " + this.pageReference + " /XYZ null null null ]"); + sb.append("/D [ ").append(this.pageReference).append(" /XYZ null null null ]"); + } + + if (newWindow) { + sb.append("/NewWindow true"); } sb.append(" \n>>\nendobj\n"); @@ -142,7 +158,7 @@ public class PDFGoToRemote extends PDFAction { } } - return true; + return (this.newWindow == remote.newWindow); } } diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 936bf4384..06f5921cc 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -837,7 +837,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * @param value the value * @return the formatted value */ - protected static final String format(float value) { + protected static String format(float value) { return PDFNumber.doubleOut(value); } @@ -1134,9 +1134,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * (i.e. if the area qualifies as a link target). * Otherwise, or if the area has no id, null is returned. * - * NOTE : area must be on currentPageViewport, otherwise result may be wrong! + * NOTE: area must be on currentPageViewport, otherwise result may be wrong! * * @param area the area for which to return the id + * @return the area's id (null if the area has no id or + * other preceding areas have the same id) */ protected String getTargetableID(Area area) { String id = (String) area.getTrait(Trait.PROD_ID); @@ -1374,11 +1376,14 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { // no INTERNAL_LINK, look for EXTERNAL_LINK if (!linkTraitFound) { - String extDest = (String) ip.getTrait(Trait.EXTERNAL_LINK); - if (extDest != null && extDest.length() > 0) { - linkTraitFound = true; - if (annotsAllowed) { - action = factory.getExternalAction(extDest); + Trait.ExternalLink extLink = (Trait.ExternalLink) ip.getTrait(Trait.EXTERNAL_LINK); + if (extLink != null) { + String extDest = extLink.getDestination(); + if (extDest != null && extDest.length() > 0) { + linkTraitFound = true; + if (annotsAllowed) { + action = factory.getExternalAction(extDest, extLink.newWindow()); + } } } } @@ -1610,7 +1615,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced. * @param uri URL of the bitmap * @param pos Position of the bitmap - * @deprecated Use {@link @putImage(String, Rectangle2D, Map)} instead. + * @deprecated Use {@link #putImage(String, Rectangle2D, Map)} instead. */ protected void putImage(String uri, Rectangle2D pos) { putImage(uri, pos, null); diff --git a/status.xml b/status.xml index d6b3c6941..a289dadc9 100644 --- a/status.xml +++ b/status.xml @@ -54,10 +54,13 @@ +
                                                                                            + + Add partial support for the "show-destination" property on fo:basic-link + (PDF output only; see limitations on the compliance page) + Added minimal support for integer keep values on the various keep properties on block-level FOs. For now, all integer values are treated the same (i.e. without strength distinction). diff --git a/test/layoutengine/standard-testcases/basic-link_external-destination.xml b/test/layoutengine/standard-testcases/basic-link_external-destination.xml index 6f7ba77d6..690248d19 100644 --- a/test/layoutengine/standard-testcases/basic-link_external-destination.xml +++ b/test/layoutengine/standard-testcases/basic-link_external-destination.xml @@ -38,7 +38,7 @@ - - + + -- cgit v1.2.3 From 0aef8c31937a71a49686bf8d32f279aa5309fb85 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 25 Apr 2008 11:37:11 +0000 Subject: Correction: remove unfinished sentence... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651577 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 2c1af46c3..535bb41bc 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -5283,7 +5283,7 @@
                                                                                          • [FOP Trunk] only has effect in PDF output, for external PDF destinations (links pointing to destinations in another PDF), and only works reliably when the PDF is viewed in a standalone PDF viewer.

                                                                                            Adobe's browser plugin, for example, ignores the /NewWindow flag. -

                                                                                            For links pointing to non-PDF destinations (e.g.

                                                                                          • +
                                                                                          -- cgit v1.2.3 From 2647dfd93fbd240c4b653cc2b7f8a5348842a134 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Apr 2008 12:31:44 +0000 Subject: Update for advanced keeps. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651591 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 535bb41bc..a704ee791 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -4764,7 +4764,8 @@
                                                                                          • [0.20.5] works only in table rows
                                                                                          • -
                                                                                          • [0.94 and later] <integer> values are not supported.
                                                                                          • +
                                                                                          • [0.95 and earlier] <integer> values are not supported.
                                                                                          • +
                                                                                          • [Trunk] minimal support for <integer> value.
                                                                                          @@ -4793,7 +4794,8 @@
                                                                                        • [0.94 and later] works on all implemented block-level FOs, but not on inline-level FOs.
                                                                                        • -
                                                                                        • [0.94 and later] <integer> values are not supported.
                                                                                        • +
                                                                                        • [0.95 and earlier] <integer> values are not supported.
                                                                                        • +
                                                                                        • [Trunk] minimal support for <integer> value.
                                                                                        @@ -4824,8 +4826,10 @@
                                                                                      • [0.95] works on all implemented FOs, except list- and inline-level FOs.
                                                                                      • - -
                                                                                      • [0.94 and later] <integer> values are not supported.
                                                                                      • +
                                                                                      • [Trunk] does not work on inline-level FOs.
                                                                                      • + +
                                                                                      • [0.95 and earlier] <integer> values are not supported.
                                                                                      • +
                                                                                      • [Trunk] minimal support for <integer> value.
                                                                                      -- cgit v1.2.3 From 7b7345085ea92bdca57b8d8aeeba8d716a35a1eb Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 25 Apr 2008 14:13:08 +0000 Subject: Added missing file from r651575 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651613 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/Area.java | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index 73b167b99..ff9f5c7d0 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -367,18 +367,6 @@ public class Area extends AreaTreeObject implements Serializable { public void addChildArea(Area child) { } - /** - * Add a trait property to this area. - * - * @param prop the Trait to add - */ - public void addTrait(Trait prop) { - if (props == null) { - props = new java.util.HashMap(20); - } - props.put(prop.getPropType(), prop.getData()); - } - /** * Add a trait to this area. * -- cgit v1.2.3 From 417f880fb993de6302e5a9e1a51cbaf0ed7a61bc Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 25 Apr 2008 14:59:49 +0000 Subject: Renamed method. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651622 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index ce33bc5b6..484710d1a 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -139,7 +139,7 @@ public class FontInfoFinder { * @param fontCache font cache (may be null) * @return */ - private EmbedFontInfo fontInfoFromCustomFont( + private EmbedFontInfo getFontInfoFromCustomFont( URL fontUrl, CustomFont customFont, FontCache fontCache) { List fontTripletList = new java.util.ArrayList(); generateTripletsFromFont(customFont, fontTripletList); @@ -237,7 +237,7 @@ public class FontInfoFinder { } continue; } - EmbedFontInfo fi = fontInfoFromCustomFont(fontUrl, customFont, fontCache); + EmbedFontInfo fi = getFontInfoFromCustomFont(fontUrl, customFont, fontCache); if (fi != null) { embedFontInfoList.add(fi); } @@ -260,7 +260,7 @@ public class FontInfoFinder { } return null; } - EmbedFontInfo fi = fontInfoFromCustomFont(fontUrl, customFont, fontCache); + EmbedFontInfo fi = getFontInfoFromCustomFont(fontUrl, customFont, fontCache); if (fi != null) { return new EmbedFontInfo[] {fi}; } else { -- cgit v1.2.3 From 46ddb807a234655e106f4949d1474e857a025d17 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Apr 2008 15:03:17 +0000 Subject: Restored Java 1.4 compatibility (Boolean.parseBoolean() is a Java 5 method). Simplified the ExternalLink's string representation to follow the pattern used by Trait.Background. Added a check to test for the effect of the show-destination property. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651623 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/Trait.java | 32 ++++++++++------------ .../basic-link_external-destination.xml | 8 ++++-- 2 files changed, 21 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/area/Trait.java b/src/java/org/apache/fop/area/Trait.java index 9599d8833..e7b39ad2b 100644 --- a/src/java/org/apache/fop/area/Trait.java +++ b/src/java/org/apache/fop/area/Trait.java @@ -461,21 +461,20 @@ public class Trait implements Serializable { * @return an ExternalLink instance corresponding to the given value */ protected static ExternalLink makeFromTraitValue(String traitValue) { - if (traitValue.indexOf(ExternalLink.class.getName()) == -1 - || traitValue.indexOf("dest=") == -1) { - throw new IllegalArgumentException( - "Malformed trait value for Trait.ExternalLink: " + traitValue); - } - int startIndex = traitValue.indexOf("dest=") + 5; - int endIndex = traitValue.indexOf(',', startIndex); - if (endIndex == -1) { - endIndex = traitValue.indexOf(']'); + String dest = null; + boolean newWindow = false; + String[] values = traitValue.split(","); + for (int i = 0, c = values.length; i < c; i++) { + String v = values[i]; + if (v.startsWith("dest=")) { + dest = v.substring(5); + } else if (v.startsWith("newWindow=")) { + newWindow = Boolean.valueOf(v.substring(10)).booleanValue(); + } else { + throw new IllegalArgumentException( + "Malformed trait value for Trait.ExternalLink: " + traitValue); + } } - String dest = traitValue.substring(startIndex, endIndex); - startIndex = traitValue.indexOf("newWindow=", endIndex) + 10; - endIndex = traitValue.indexOf(']', startIndex); - boolean newWindow = Boolean.parseBoolean( - traitValue.substring(startIndex, endIndex)); return new ExternalLink(dest, newWindow); } @@ -502,9 +501,8 @@ public class Trait implements Serializable { */ public String toString() { StringBuffer sb = new StringBuffer(64); - sb.append(super.toString()); - sb.append("[dest=").append(this.destination); - sb.append(",newWindow=").append(newWindow).append("]"); + sb.append("newWindow=").append(newWindow); + sb.append(",dest=").append(this.destination); return sb.toString(); } } diff --git a/test/layoutengine/standard-testcases/basic-link_external-destination.xml b/test/layoutengine/standard-testcases/basic-link_external-destination.xml index 690248d19..4a1929a62 100644 --- a/test/layoutengine/standard-testcases/basic-link_external-destination.xml +++ b/test/layoutengine/standard-testcases/basic-link_external-destination.xml @@ -33,12 +33,16 @@ FOP FOP + FOP + FOP - - + + + + -- cgit v1.2.3 From 5b92a2b32f19f208ab1313339a141efc15e35a3e Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 26 Apr 2008 20:06:04 +0000 Subject: Bugzilla 44203: Fixed a logic error in Hyphenator.java where an UnsupportedOperationException was erroneously thrown if the supplied source had an associated InputStream. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651853 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/hyphenation/Hyphenator.java | 10 ++++++---- status.xml | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/hyphenation/Hyphenator.java b/src/java/org/apache/fop/hyphenation/Hyphenator.java index 3d9ef9eb8..a537a9d01 100644 --- a/src/java/org/apache/fop/hyphenation/Hyphenator.java +++ b/src/java/org/apache/fop/hyphenation/Hyphenator.java @@ -255,11 +255,13 @@ public class Hyphenator { if (source instanceof StreamSource) { in = ((StreamSource) source).getInputStream(); } - if (in == null && source.getSystemId() != null) { - in = new java.net.URL(source.getSystemId()).openStream(); - } else { - throw new UnsupportedOperationException("Cannot load hyphenation pattern file" + if (in == null) { + if (source.getSystemId() != null) { + in = new java.net.URL(source.getSystemId()).openStream(); + } else { + throw new UnsupportedOperationException("Cannot load hyphenation pattern file" + " with the supplied Source object: " + source); + } } in = new BufferedInputStream(in); try { diff --git a/status.xml b/status.xml index a289dadc9..ca4768446 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,11 @@ Added SVG support for AFP (GOCA). + + Fixed a logic error in Hyphenator.java: + If the source had an associated InputStream, an UnsupportedOperationException was + triggered. + Add partial support for the "show-destination" property on fo:basic-link (PDF output only; see limitations on the compliance page) -- cgit v1.2.3 From a5c961841124731be6c531a6b12a1d8673e7f4f6 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 26 Apr 2008 20:19:59 +0000 Subject: Basic activation of keep-* properties on Character and AbstractGraphics + javadoc updates git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651855 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/AbstractGraphics.java | 93 +++++++++---------- src/java/org/apache/fop/fo/flow/Character.java | 103 ++++++++------------- 2 files changed, 79 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java index a58cc08f2..19cea1510 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java +++ b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java @@ -26,15 +26,18 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.GraphicsProperties; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.fo.properties.SpaceProperty; /** - * Common base class for instream-foreign-object and external-graphics - * flow formatting objects. + * Common base class for the + * fo:instream-foreign-object + * and + * fo:external-graphic flow formatting objects. */ public abstract class AbstractGraphics extends FObj implements GraphicsProperties { - + // The value of properties relevant for fo:instream-foreign-object // and external-graphics. private CommonBorderPaddingBackground commonBorderPaddingBackground; @@ -50,6 +53,8 @@ public abstract class AbstractGraphics extends FObj implements GraphicsPropertie private Length height; private String id; private LengthRangeProperty inlineProgressionDimension; + private KeepProperty keepWithNext; + private KeepProperty keepWithPrevious; private SpaceProperty lineHeight; private int overflow; private int scaling; @@ -61,8 +66,6 @@ public abstract class AbstractGraphics extends FObj implements GraphicsPropertie // private CommonMarginInline commonMarginInline; // private CommonRelativePosition commonRelativePosition; // private String contentType; - // private KeepProperty keepWithNext; - // private KeepProperty keepWithPrevious; // private int scalingMethod; // End of property values @@ -77,9 +80,7 @@ public abstract class AbstractGraphics extends FObj implements GraphicsPropertie super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength(); @@ -94,6 +95,8 @@ public abstract class AbstractGraphics extends FObj implements GraphicsPropertie height = pList.get(PR_HEIGHT).getLength(); id = pList.get(PR_ID).getString(); inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange(); + keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep(); + keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); lineHeight = pList.get(PR_LINE_HEIGHT).getSpace(); overflow = pList.get(PR_OVERFLOW).getEnum(); scaling = pList.get(PR_SCALING).getEnum(); @@ -108,60 +111,52 @@ public abstract class AbstractGraphics extends FObj implements GraphicsPropertie return id; } - /** - * @return the Common Border, Padding, and Background Properties. - */ + /** @return the {@link CommonBorderPaddingBackground} */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } - /** - * @return the "line-height" property. - */ + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } - /** {@inheritDoc} */ + /** @return the "inline-progression-dimension" property */ public LengthRangeProperty getInlineProgressionDimension() { return inlineProgressionDimension; } - /** {@inheritDoc} */ + /** @return the "block-progression-dimension" property */ public LengthRangeProperty getBlockProgressionDimension() { return blockProgressionDimension; } - /** - * @return the "height" property. - */ + /** @return the "height" property */ public Length getHeight() { return height; } - /** - * @return the "width" property. - */ + /** @return the "width" property */ public Length getWidth() { return width; } - /** {@inheritDoc} */ + /** @return the "content-height" property */ public Length getContentHeight() { return contentHeight; } - /** {@inheritDoc} */ + /** @return the "content-width" property */ public Length getContentWidth() { return contentWidth; } - /** {@inheritDoc} */ + /** @return the "scaling" property */ public int getScaling() { return scaling; } - /** {@inheritDoc} */ + /** @return the "overflow" property */ public int getOverflow() { return overflow; } @@ -176,9 +171,7 @@ public abstract class AbstractGraphics extends FObj implements GraphicsPropertie return textAlign; } - /** - * @return the "alignment-adjust" property - */ + /** @return the "alignment-adjust" property */ public Length getAlignmentAdjust() { if (alignmentAdjust.getEnum() == EN_AUTO) { final Length intrinsicAlignmentAdjust = this.getIntrinsicAlignmentAdjust(); @@ -188,40 +181,38 @@ public abstract class AbstractGraphics extends FObj implements GraphicsPropertie } return alignmentAdjust; } - - /** - * @return the "alignment-baseline" property - */ + + /** @return the "alignment-baseline" property */ public int getAlignmentBaseline() { return alignmentBaseline; } - - /** - * @return the "baseline-shift" property - */ + + /** @return the "baseline-shift" property */ public Length getBaselineShift() { return baselineShift; } - - /** - * @return the "dominant-baseline" property - */ + + /** @return the "dominant-baseline" property */ public int getDominantBaseline() { return dominantBaseline; } - - /** - * @return the graphics intrinsic width in millipoints - */ + + /** @return the "keep-with-next" property */ + public KeepProperty getKeepWithNext() { + return keepWithNext; + } + + /** @return the "keep-with-previous" property */ + public KeepProperty getKeepWithPrevious() { + return keepWithPrevious; + } + + /** @return the graphic's intrinsic width in millipoints */ public abstract int getIntrinsicWidth(); - /** - * @return the graphics intrinsic height in millipoints - */ + /** @return the graphic's intrinsic height in millipoints */ public abstract int getIntrinsicHeight(); - /** - * @return the graphics intrinsic alignment-adjust - */ + /** @return the graphic's intrinsic alignment-adjust */ public abstract Length getIntrinsicAlignmentAdjust(); } diff --git a/src/java/org/apache/fop/fo/flow/Character.java b/src/java/org/apache/fop/fo/flow/Character.java index aad4209f9..7fd98b0ef 100644 --- a/src/java/org/apache/fop/fo/flow/Character.java +++ b/src/java/org/apache/fop/fo/flow/Character.java @@ -35,22 +35,13 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonFont; import org.apache.fop.fo.properties.CommonHyphenation; import org.apache.fop.fo.properties.CommonTextDecoration; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.SpaceProperty; /** - * Class modelling the fo:character object. - * Its use is defined by the spec: - * "The fo:character flow object represents a character that is mapped to - * a glyph for presentation. It is an atomic unit to the formatter. - * When the result tree is interpreted as a tree of formatting objects, - * a character in the result tree is treated as if it were an empty - * element of type fo:character with a character attribute - * equal to the Unicode representation of the character. - * The semantics of an "auto" value for character properties, which is - * typically their initial value, are based on the Unicode codepoint. - * Overrides may be specified in an implementation-specific manner." (6.6.3) - * + * Class modelling the + * fo:character object. */ public class Character extends FObj { // The value of properties relevant for fo:character. @@ -63,8 +54,8 @@ public class Character extends FObj { private char character; private Color color; private int dominantBaseline; - // private ToBeImplementedProperty glyphOrientationHorizontal; - // private ToBeImplementedProperty glyphOrientationVertical; + private KeepProperty keepWithNext; + private KeepProperty keepWithPrevious; private Property letterSpacing; private SpaceProperty lineHeight; /** Holds the text decoration values. May be null */ @@ -75,11 +66,11 @@ public class Character extends FObj { // private CommonAural commonAural; // private CommonMarginInline commonMarginInline; // private CommonRelativePosition commonRelativePosition; + // private ToBeImplementedProperty glyphOrientationHorizontal; + // private ToBeImplementedProperty glyphOrientationVertical; // private int treatAsWordSpace; // private Length textDepth; // private Length textAltitude; - // private KeepProperty keepWithNext; - // private KeepProperty keepWithPrevious; // private int scoreSpaces; // private int suppressAtLineBreak; // private int textTransform; @@ -92,15 +83,13 @@ public class Character extends FObj { public static final int DOESNOT_FIT = 1; /** - * @param parent FONode that is the parent of this object + * @param parent {@link FONode} that is the parent of this object */ public Character(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); @@ -113,18 +102,15 @@ public class Character extends FObj { character = pList.get(PR_CHARACTER).getCharacter(); color = pList.get(PR_COLOR).getColor(getUserAgent()); dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum(); - // glyphOrientationHorizontal = pList.get(PR_GLYPH_ORIENTATION_HORIZONTAL); - // glyphOrientationVertical = pList.get(PR_GLYPH_ORIENTATION_VERTICAL); + keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep(); + keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); letterSpacing = pList.get(PR_LETTER_SPACING); lineHeight = pList.get(PR_LINE_HEIGHT).getSpace(); textDecoration = pList.getTextDecorationProps(); - // textShadow = pList.get(PR_TEXT_SHADOW); wordSpacing = pList.get(PR_WORD_SPACING); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().character(this); @@ -132,7 +118,7 @@ public class Character extends FObj { /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -141,86 +127,62 @@ public class Character extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public CharIterator charIterator() { return new FOCharIterator(this); } - /** - * @return the Common Border, Padding, and Background Properties. - */ + /** @return the Common Border, Padding, and Background Properties */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } - /** - * @return the Common Font Properties. - */ + /** @return the Common Font Properties */ public CommonFont getCommonFont() { return commonFont; } - /** - * @return the Common Hyphenation Properties. - */ + /** @return the Common Hyphenation Properties */ public CommonHyphenation getCommonHyphenation() { return commonHyphenation; } - /** - * @return the "character" property. - */ + /** @return the "character" property */ public char getCharacter() { return character; } - /** - * @return the "color" property. - */ + /** @return the "color" property */ public Color getColor() { return color; } - /** - * @return the "alignment-adjust" property - */ + /** @return the "alignment-adjust" property */ public Length getAlignmentAdjust() { return alignmentAdjust; } - /** - * @return the "alignment-baseline" property - */ + /** @return the "alignment-baseline" property */ public int getAlignmentBaseline() { return alignmentBaseline; } - /** - * @return the "baseline-shift" property - */ + /** @return the "baseline-shift" property */ public Length getBaselineShift() { return baselineShift; } - /** - * @return the "dominant-baseline" property - */ + /** @return the "dominant-baseline" property */ public int getDominantBaseline() { return dominantBaseline; } - /** - * @return the "letter-spacing" property. - */ + /** @return the "letter-spacing" property */ public Property getLetterSpacing() { return letterSpacing; } - /** - * @return the "line-height" property. - */ + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } @@ -230,13 +192,21 @@ public class Character extends FObj { return textDecoration; } - /** - * @return the "word-spacing" property. - */ + /** @return the "word-spacing" property */ public Property getWordSpacing() { return wordSpacing; } + /** @return the "keep-with-next" property */ + public KeepProperty getKeepWithNext() { + return keepWithNext; + } + + /** @return the "keep-with-previous" property */ + public KeepProperty getKeepWithPrevious() { + return keepWithPrevious; + } + /** {@inheritDoc} */ public String getLocalName() { return "character"; @@ -244,6 +214,7 @@ public class Character extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_CHARACTER} */ public int getNameId() { return FO_CHARACTER; -- cgit v1.2.3 From 83d3be0ad93e70213c4008e8aa1ccf326a9fae3b Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 26 Apr 2008 20:21:44 +0000 Subject: Basic activation on some widely used properties (prepare for implementation) + javadoc updates git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651856 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/InlineContainer.java | 116 +++++++++++++++------ 1 file changed, 82 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/InlineContainer.java b/src/java/org/apache/fop/fo/flow/InlineContainer.java index 3c142afe9..c26730b3a 100644 --- a/src/java/org/apache/fop/fo/flow/InlineContainer.java +++ b/src/java/org/apache/fop/fo/flow/InlineContainer.java @@ -23,14 +23,20 @@ import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.CommonMarginInline; +import org.apache.fop.fo.properties.KeepProperty; +import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.fo.properties.SpaceProperty; /** - * Class modelling the fo:inline-container object. + * Class modelling the + * fo:inline-container object. */ public class InlineContainer extends FObj { @@ -38,52 +44,60 @@ public class InlineContainer extends FObj { private Length alignmentAdjust; private int alignmentBaseline; private Length baselineShift; - // private ToBeImplementedProperty clip; + private LengthRangeProperty blockProgressionDimension; + private CommonBorderPaddingBackground commonBorderPaddingBackground; + private CommonMarginInline commonMarginInline; + private int clip; private int dominantBaseline; + private LengthRangeProperty inlineProgressionDimension; + private KeepProperty keepTogether; private SpaceProperty lineHeight; + private int overflow; + private Numeric referenceOrientation; + private int writingMode; // Unused but valid items, commented out for performance: - // private CommonBorderPaddingBackground commonBorderPaddingBackground; - // private CommonMarginInline commonMarginInline; // private CommonRelativePosition commonRelativePosition; - // private LengthRangeProperty blockProgressionDimension; // private int displayAlign; // private Length height; - // private LengthRangeProperty inlineProgressionDimension; - // private KeepProperty keepTogether; // private KeepProperty keepWithNext; // private KeepProperty keepWithPrevious; - // private int overflow; - // private Numeric referenceOrientation; // private Length width; - // private int writingMode; // End of property values /** used for FO validation */ private boolean blockItemFound = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public InlineContainer(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength(); alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum(); baselineShift = pList.get(PR_BASELINE_SHIFT).getLength(); - // clip = pList.get(PR_CLIP); + blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange(); + commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); + commonMarginInline = pList.getMarginInlineProps(); + clip = pList.get(PR_CLIP).getEnum(); dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum(); + inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange(); + keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); lineHeight = pList.get(PR_LINE_HEIGHT).getSpace(); + overflow = pList.get(PR_OVERFLOW).getEnum(); + referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); + writingMode = pList.get(PR_WRITING_MODE).getEnum(); } /** * {@inheritDoc} - * XSL Content Model: marker* (%block;)+ + *
                                                                                      XSL Content Model: marker* (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -100,50 +114,83 @@ public class InlineContainer extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (!blockItemFound) { missingChildElementError("marker* (%block;)+"); } } - /** - * @return the "alignment-adjust" property - */ + /** @return the "alignment-adjust" property */ public Length getAlignmentAdjust() { return alignmentAdjust; } - /** - * @return the "alignment-baseline" property - */ + /** @return the "alignment-baseline" property */ public int getAlignmentBaseline() { return alignmentBaseline; } - /** - * @return the "baseline-shift" property - */ + /** @return the "baseline-shift" property */ public Length getBaselineShift() { return baselineShift; } - /** - * @return the "dominant-baseline" property - */ + /** @return the "block-progression-dimension" property */ + public LengthRangeProperty getBlockProgressionDimension() { + return blockProgressionDimension; + } + + /** @return the "clip" property */ + public int getClip() { + return clip; + } + + /**@return Returns the {@link CommonBorderPaddingBackground} */ + public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { + return this.commonBorderPaddingBackground; + } + + /** @return Returns the {@link CommonMarginInline} */ + public CommonMarginInline getCommonMarginInline() { + return this.commonMarginInline; + } + + /** @return the "dominant-baseline" property */ public int getDominantBaseline() { return dominantBaseline; } - /** - * @return the "line-height" property. - */ + /** @return the "keep-together" property */ + public KeepProperty getKeepTogether() { + return keepTogether; + } + + /** @return the "inline-progression-dimension" property */ + public LengthRangeProperty getInlineProgressionDimension() { + return inlineProgressionDimension; + } + + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } + /** @return the "overflow" property */ + public int getOverflow() { + return overflow; + } + + /** @return the "reference-orientation" property */ + public int getReferenceOrientation() { + return referenceOrientation.getValue(); + } + + /** @return the "writing-mode" property */ + public int getWritingMode() { + return writingMode; + } + /** {@inheritDoc} */ public String getLocalName() { return "inline-container"; @@ -151,6 +198,7 @@ public class InlineContainer extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_INLINE_CONTAINER} */ public int getNameId() { return FO_INLINE_CONTAINER; -- cgit v1.2.3 From ac29c8eee27bd00826799d94c192e46459505007 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 26 Apr 2008 22:08:10 +0000 Subject: Javadoc updates: attempt at improving interactivity and consistency git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651866 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FONode.java | 287 +++++++++++++-------- src/java/org/apache/fop/fo/FOText.java | 9 +- src/java/org/apache/fop/fo/FObj.java | 89 ++----- src/java/org/apache/fop/fo/FObjMixed.java | 29 ++- src/java/org/apache/fop/fo/XMLObj.java | 19 +- .../org/apache/fop/fo/XMLWhiteSpaceHandler.java | 2 - .../apache/fop/fo/flow/AbstractListItemPart.java | 18 +- .../fop/fo/flow/AbstractPageNumberCitation.java | 39 ++- src/java/org/apache/fop/fo/flow/BidiOverride.java | 20 +- src/java/org/apache/fop/fo/flow/Block.java | 115 +++------ .../org/apache/fop/fo/flow/ExternalGraphic.java | 8 +- src/java/org/apache/fop/fo/flow/Float.java | 18 +- src/java/org/apache/fop/fo/flow/Footnote.java | 35 +-- src/java/org/apache/fop/fo/flow/FootnoteBody.java | 21 +- .../org/apache/fop/fo/flow/InitialPropertySet.java | 18 +- src/java/org/apache/fop/fo/flow/Inline.java | 46 ++-- src/java/org/apache/fop/fo/flow/InlineLevel.java | 60 ++--- .../apache/fop/fo/flow/InstreamForeignObject.java | 24 +- src/java/org/apache/fop/fo/flow/Leader.java | 54 ++-- src/java/org/apache/fop/fo/flow/ListBlock.java | 43 ++- src/java/org/apache/fop/fo/flow/ListItem.java | 50 ++-- src/java/org/apache/fop/fo/flow/ListItemBody.java | 12 +- src/java/org/apache/fop/fo/flow/ListItemLabel.java | 16 +- src/java/org/apache/fop/fo/flow/Marker.java | 108 +++----- src/java/org/apache/fop/fo/flow/MultiCase.java | 16 +- .../org/apache/fop/fo/flow/MultiProperties.java | 14 +- .../org/apache/fop/fo/flow/MultiPropertySet.java | 14 +- src/java/org/apache/fop/fo/flow/MultiSwitch.java | 18 +- src/java/org/apache/fop/fo/flow/MultiToggle.java | 14 +- src/java/org/apache/fop/fo/flow/PageNumber.java | 46 ++-- .../org/apache/fop/fo/flow/PageNumberCitation.java | 11 +- .../apache/fop/fo/flow/PageNumberCitationLast.java | 11 +- .../org/apache/fop/fo/flow/RetrieveMarker.java | 39 +-- src/java/org/apache/fop/fo/flow/Wrapper.java | 14 +- src/java/org/apache/fop/fo/flow/table/Table.java | 18 +- .../apache/fop/fo/flow/table/TableAndCaption.java | 8 +- .../org/apache/fop/fo/flow/table/TableBody.java | 34 ++- .../org/apache/fop/fo/flow/table/TableCaption.java | 18 +- .../org/apache/fop/fo/flow/table/TableCell.java | 43 ++- .../org/apache/fop/fo/flow/table/TableColumn.java | 39 ++- .../org/apache/fop/fo/flow/table/TableFooter.java | 24 +- .../org/apache/fop/fo/flow/table/TableHeader.java | 23 +- .../org/apache/fop/fo/flow/table/TableRow.java | 28 +- .../fop/fo/pagination/AbstractPageSequence.java | 31 ++- .../org/apache/fop/fo/pagination/ColorProfile.java | 26 +- .../pagination/ConditionalPageMasterReference.java | 34 ++- .../org/apache/fop/fo/pagination/Declarations.java | 16 +- src/java/org/apache/fop/fo/pagination/Flow.java | 19 +- .../apache/fop/fo/pagination/LayoutMasterSet.java | 18 +- .../fop/fo/pagination/PageSequenceMaster.java | 54 ++-- .../fop/fo/pagination/PageSequenceWrapper.java | 31 ++- src/java/org/apache/fop/fo/pagination/Region.java | 13 +- .../org/apache/fop/fo/pagination/RegionAfter.java | 14 +- .../org/apache/fop/fo/pagination/RegionBA.java | 13 +- .../org/apache/fop/fo/pagination/RegionBefore.java | 14 +- .../org/apache/fop/fo/pagination/RegionBody.java | 29 ++- .../org/apache/fop/fo/pagination/RegionEnd.java | 17 +- .../org/apache/fop/fo/pagination/RegionSE.java | 10 +- .../org/apache/fop/fo/pagination/RegionStart.java | 14 +- .../RepeatablePageMasterAlternatives.java | 23 +- .../pagination/RepeatablePageMasterReference.java | 27 +- src/java/org/apache/fop/fo/pagination/Root.java | 30 ++- .../apache/fop/fo/pagination/SimplePageMaster.java | 16 +- .../fo/pagination/SinglePageMasterReference.java | 16 +- .../apache/fop/fo/pagination/StaticContent.java | 11 +- .../fop/fo/pagination/SubSequenceSpecifier.java | 4 +- src/java/org/apache/fop/fo/pagination/Title.java | 13 +- .../fop/fo/pagination/bookmarks/Bookmark.java | 38 ++- .../fop/fo/pagination/bookmarks/BookmarkTitle.java | 27 +- .../fop/fo/pagination/bookmarks/BookmarkTree.java | 33 +-- 70 files changed, 1118 insertions(+), 1045 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index 197a2482d..951e4c430 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -59,19 +59,21 @@ public abstract class FONode implements Cloneable { /** pointer to the sibling nodes */ protected FONode[] siblings; - /** - * Marks location of this object from the input FO - * Call locator.getSystemId(), getLineNumber(), - * getColumnNumber() for file, line, column + /** + * Marks the location of this object from the input FO + *
                                                                                      Call locator.getSystemId(), + * getLineNumber(), + * getColumnNumber() for file, line, column * information */ protected Locator locator; /** Logger for fo-tree related messages **/ protected static Log log = LogFactory.getLog(FONode.class); - + /** - * Main constructor. + * Base constructor + * * @param parent parent of this node */ protected FONode(FONode parent) { @@ -79,8 +81,9 @@ public abstract class FONode implements Cloneable { } /** - * Perform a shallow cloning operation, - * set its parent, and optionally clean the list of child nodes + * Performs a shallow cloning operation, sets the clone's parent, + * and optionally cleans the list of child nodes + * * @param cloneparent the intended parent of the clone * @param removeChildren if true, clean the list of child nodes * @return the cloned FO node @@ -88,32 +91,31 @@ public abstract class FONode implements Cloneable { */ public FONode clone(FONode cloneparent, boolean removeChildren) throws FOPException { - FONode foNode = (FONode) clone(); - foNode.parent = cloneparent; - foNode.siblings = null; - return foNode; + try { + FONode foNode = (FONode) clone(); + foNode.parent = cloneparent; + foNode.siblings = null; + return foNode; + } catch (CloneNotSupportedException cnse) { + return null; + } } /** * Perform a shallow cloning operation - * + * * {@inheritDoc} - * @return the cloned object */ - protected Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - return null; - } + protected Object clone() throws CloneNotSupportedException { + return super.clone(); } /** * Bind the given PropertyList to this node - * Does nothing by default. Subclasses should override this method - * in case they want to use the properties available on the + * Does nothing by default. Subclasses should override this method + * in case they want to use the properties available on the * PropertyList. - * + * * @param propertyList the PropertyList * @throws FOPException if there was an error when * processing the PropertyList @@ -121,7 +123,7 @@ public abstract class FONode implements Cloneable { public void bind(PropertyList propertyList) throws FOPException { //nop } - + /** * Set the location information for this element * @param locator the org.xml.sax.Locator object @@ -134,20 +136,27 @@ public abstract class FONode implements Cloneable { } } - /** @return the location information for this element or null, if not available */ + /** + * Returns the Locator containing the location information for this + * element, or null if not available + * + * @return the location information for this element or null, if not available + */ public Locator getLocator() { return this.locator; } - + /** - * Recursively goes up the FOTree hierarchy until the fo:root is found, - * which returns the parent FOEventHandler. + * Recursively goes up the FOTree hierarchy until the fo:root + * is found, which returns the parent FOEventHandler. + *
                                                                                      (see also: {@link org.apache.fop.fo.pagination.Root#getFOEventHandler()}) + * * @return the FOEventHandler object that is the parent of the FO Tree */ public FOEventHandler getFOEventHandler() { return parent.getFOEventHandler(); } - + /** * Indicates whether this node is a child of an fo:marker. * @return true if this node is a child of an fo:marker @@ -157,8 +166,10 @@ public abstract class FONode implements Cloneable { } /** - * Returns the user agent for the node. - * @return FOUserAgent + * Returns the user agent that is associated with the + * tree's FOEventHandler. + * + * @return the user agent */ public FOUserAgent getUserAgent() { return getFOEventHandler().getUserAgent(); @@ -166,6 +177,7 @@ public abstract class FONode implements Cloneable { /** * Returns the logger for the node. + * * @return the logger */ public Log getLogger() { @@ -176,16 +188,17 @@ public abstract class FONode implements Cloneable { * Initialize the node with its name, location information, and attributes * The attributes must be used immediately as the sax attributes * will be altered for the next element. + * * @param elementName element name (e.g., "fo:block") * @param locator Locator object (ignored by default) * @param attlist Collection of attributes passed to us from the parser. * @param pList the property list of the parent node * @throws FOPException for errors or inconsistencies in the attributes */ - public void processNode(String elementName, Locator locator, + public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { if (log.isDebugEnabled()) { - log.debug("Unhandled element: " + elementName + log.debug("Unhandled element: " + elementName + (locator != null ? " at " + getLocatorString(locator) : "")); } } @@ -193,30 +206,36 @@ public abstract class FONode implements Cloneable { /** * Create a property list for this node. Return null if the node does not * need a property list. - * @param pList the closest parent propertylist. - * @param foEventHandler The FOEventHandler where the PropertyListMaker + * + * @param pList the closest parent propertylist. + * @param foEventHandler The FOEventHandler where the PropertyListMaker * instance can be found. * @return A new property list. * @throws FOPException if there's a problem during processing */ - protected PropertyList createPropertyList(PropertyList pList, FOEventHandler foEventHandler) + protected PropertyList createPropertyList( + PropertyList pList, + FOEventHandler foEventHandler) throws FOPException { return null; } /** * Checks to make sure, during SAX processing of input document, that the - * incoming node is valid for the this (parent) node (e.g., checking to + * incoming node is valid for this (parent) node (e.g., checking to * see that fo:table is not an immediate child of fo:root) * called from {@link FOTreeBuilder#startElement(String, String, String, Attributes)} * before constructing the child {@link FObj}. - * + * * @param loc location in the FO source file * @param namespaceURI namespace of incoming node * @param localName name of the incoming node (without namespace prefix) * @throws ValidationException if incoming node not valid for parent */ - protected void validateChildNode(Locator loc, String namespaceURI, String localName) + protected void validateChildNode( + Locator loc, + String namespaceURI, + String localName) throws ValidationException { //nop } @@ -224,30 +243,32 @@ public abstract class FONode implements Cloneable { /** * Static version of {@link FONode#validateChildNode(Locator, String, String)} that * can be used by subclasses that need to validate children against a different node - * (for example: fo:wrapper needs to check if the incoming node is a + * (for example: fo:wrapper needs to check if the incoming node is a * valid child to its parent) - * - * @param fo the FONode to validate against + * + * @param fo the {@link FONode} to validate against * @param loc location in the source file * @param namespaceURI namespace of the incoming node - * @param localName name of the incoming node (without namespace prefix) + * @param localName name of the incoming node (without namespace prefix) * @throws ValidationException if the incoming node is not a valid child for the given FO */ protected static void validateChildNode( - FONode fo, - Locator loc, - String namespaceURI, - String localName) + FONode fo, + Locator loc, + String namespaceURI, + String localName) throws ValidationException { fo.validateChildNode(loc, namespaceURI, localName); } - + /** - * Adds characters (does nothing here) + * Adds characters. Does nothing by default. To be overridden in subclasses + * that allow #PCDATA content. + * * @param data array of characters containing text to be added * @param start starting array element to add * @param end ending array element to add - * @param pList currently applicable PropertyList + * @param pList currently applicable PropertyList * @param locator location in the XSL-FO source file. * @throws FOPException if there's a problem during processing */ @@ -259,6 +280,7 @@ public abstract class FONode implements Cloneable { /** * Called after processNode() is called. Subclasses can do additional processing. + * * @throws FOPException if there's a problem during processing */ protected void startOfNode() throws FOPException { @@ -267,8 +289,9 @@ public abstract class FONode implements Cloneable { /** * Primarily used for making final content model validation checks - * and/or informing the FOEventHandler that the end of this FO + * and/or informing the {@link FOEventHandler} that the end of this FO * has been reached. + * * @throws FOPException if there's a problem during processing */ protected void endOfNode() throws FOPException { @@ -278,6 +301,7 @@ public abstract class FONode implements Cloneable { /** * Adds a node as a child of this node. The default implementation of this method * just ignores any child node being added. + * * @param child child node to be added to the childNodes of this node * @throws FOPException if there's a problem during processing */ @@ -288,6 +312,7 @@ public abstract class FONode implements Cloneable { /** * Removes a child node. Used by the child nodes to remove themselves, for * example table-body if it has no children. + * * @param child child node to be removed */ public void removeChild(FONode child) { @@ -295,6 +320,8 @@ public abstract class FONode implements Cloneable { } /** + * Return the parent node of this node + * * @return the parent node of this node */ public FONode getParent() { @@ -302,8 +329,9 @@ public abstract class FONode implements Cloneable { } /** - * Return an iterator over all the child nodes of this FObj. - * @return A ListIterator. + * Return an iterator over all the child nodes of this node. + * + * @return the iterator over the FO's childnodes */ public FONodeIterator getChildNodes() { return null; @@ -312,15 +340,18 @@ public abstract class FONode implements Cloneable { /** * Return an iterator over the object's child nodes starting * at the passed node. + * * @param childNode First node in the iterator - * @return A ListIterator or null if child node isn't a child of - * this FObj. + * @return the iterator, or null if + * the given node is not a child of this node. */ public FONodeIterator getChildNodes(FONode childNode) { return null; } /** + * Return a {@link CharIterator} over all characters in this node + * * @return an iterator for the characters in this node */ public CharIterator charIterator() { @@ -332,7 +363,7 @@ public abstract class FONode implements Cloneable { * name pairs in text messages. * For readability, using fo:, fox:, svg:, for those namespaces even * though that prefix may not have been chosen in the document. - * @param namespaceURI URI of node found + * @param namespaceURI URI of node found * (e.g., "http://www.w3.org/1999/XSL/Format") * @param localName local name of node, (e.g., "root" for "fo:root") * @return the prefix:localname, if fo/fox/svg, or a longer representation @@ -359,28 +390,29 @@ public abstract class FONode implements Cloneable { return FOValidationEventProducer.Provider.get( getUserAgent().getEventBroadcaster()); } - + /** * Helper function to standardize "too many" error exceptions * (e.g., two fo:declarations within fo:root) * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param nsURI namespace URI of incoming invalid node - * @param lName local name (i.e., no prefix) of incoming node + * @param lName local name (i.e., no prefix) of incoming node * @throws ValidationException the validation error provoked by the method call */ - protected void tooManyNodesError(Locator loc, String nsURI, String lName) + protected void tooManyNodesError(Locator loc, String nsURI, String lName) throws ValidationException { tooManyNodesError(loc, new QName(nsURI, lName)); } /** * Helper function to standardize "too many" error exceptions - * (e.g., two fo:declarations within fo:root) + * (e.g., two fo:declarations within fo:root) + * * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param offendingNode the qualified name of the offending node * @throws ValidationException the validation error provoked by the method call */ - protected void tooManyNodesError(Locator loc, QName offendingNode) + protected void tooManyNodesError(Locator loc, QName offendingNode) throws ValidationException { getFOValidationEventProducer().tooManyNodes(this, getName(), offendingNode, loc); } @@ -393,24 +425,25 @@ public abstract class FONode implements Cloneable { * @param offendingNode incoming node that would cause a duplication. * @throws ValidationException the validation error provoked by the method call */ - protected void tooManyNodesError(Locator loc, String offendingNode) + protected void tooManyNodesError(Locator loc, String offendingNode) throws ValidationException { tooManyNodesError(loc, new QName(FO_URI, offendingNode)); } /** * Helper function to standardize "out of order" exceptions - * (e.g., fo:layout-master-set appearing after fo:page-sequence) + * (e.g., fo:layout-master-set appearing after fo:page-sequence) + * * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param tooLateNode string name of node that should be earlier in document * @param tooEarlyNode string name of node that should be later in document * @throws ValidationException the validation error provoked by the method call */ - protected void nodesOutOfOrderError(Locator loc, String tooLateNode, + protected void nodesOutOfOrderError(Locator loc, String tooLateNode, String tooEarlyNode) throws ValidationException { nodesOutOfOrderError(loc, tooLateNode, tooEarlyNode, false); } - + /** * Helper function to standardize "out of order" exceptions * (e.g., fo:layout-master-set appearing after fo:page-sequence) @@ -420,28 +453,30 @@ public abstract class FONode implements Cloneable { * @param canRecover indicates whether FOP can recover from this problem and continue working * @throws ValidationException the validation error provoked by the method call */ - protected void nodesOutOfOrderError(Locator loc, String tooLateNode, + protected void nodesOutOfOrderError(Locator loc, String tooLateNode, String tooEarlyNode, boolean canRecover) throws ValidationException { getFOValidationEventProducer().nodeOutOfOrder(this, getName(), tooLateNode, tooEarlyNode, canRecover, loc); } - + /** * Helper function to return "invalid child" exceptions - * (e.g., fo:block appearing immediately under fo:root) + * (e.g., fo:block appearing immediately under fo:root) + * * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param nsURI namespace URI of incoming invalid node - * @param lName local name (i.e., no prefix) of incoming node + * @param lName local name (i.e., no prefix) of incoming node * @throws ValidationException the validation error provoked by the method call */ - protected void invalidChildError(Locator loc, String nsURI, String lName) + protected void invalidChildError(Locator loc, String nsURI, String lName) throws ValidationException { invalidChildError(loc, getName(), nsURI, lName, null); } - + /** * Helper function to return "invalid child" exceptions with more * complex validation rules (i.e., needing more explanation of the problem) + * * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param parentName the name of the parent element * @param nsURI namespace URI of incoming invalid node @@ -458,8 +493,10 @@ public abstract class FONode implements Cloneable { /** * Helper function to throw an error caused by missing mandatory child elements. - * E.g., fo:layout-master-set not having any page-master child element. - * @param contentModel The XSL Content Model for the fo: object or a similar description + * (e.g., fo:layout-master-set not having any fo:page-master + * child element. + * + * @param contentModel The XSL Content Model for the fo: object or a similar description * indicating the necessary child elements. * @throws ValidationException the validation error provoked by the method call */ @@ -472,7 +509,7 @@ public abstract class FONode implements Cloneable { /** * Helper function to throw an error caused by missing mandatory child elements. * E.g., fo:layout-master-set not having any page-master child element. - * @param contentModel The XSL Content Model for the fo: object or a similar description + * @param contentModel The XSL Content Model for the fo: object or a similar description * indicating the necessary child elements. * @param canRecover indicates whether FOP can recover from this problem and continue working * @throws ValidationException the validation error provoked by the method call @@ -485,6 +522,7 @@ public abstract class FONode implements Cloneable { /** * Helper function to throw an error caused by missing mandatory properties + * * @param propertyName the name of the missing property. * @throws ValidationException the validation error provoked by the method call */ @@ -496,6 +534,7 @@ public abstract class FONode implements Cloneable { /** * Helper function to return "Error(line#/column#)" string for * above exception messages + * * @param loc org.xml.sax.Locator object * @return String opening error text */ @@ -506,15 +545,17 @@ public abstract class FONode implements Cloneable { /** * Helper function to return "Warning(line#/column#)" string for * warning messages + * * @param loc org.xml.sax.Locator object * @return String opening warning text */ protected static String warningText(Locator loc) { return "Warning(" + getLocatorString(loc) + "): "; } - + /** * Helper function to format a Locator instance. + * * @param loc org.xml.sax.Locator object * @return String the formatted text */ @@ -528,6 +569,7 @@ public abstract class FONode implements Cloneable { /** * Decorates a log or warning message with context information on the given node. + * * @param text the original message * @param node the context node * @return the decorated text @@ -541,7 +583,7 @@ public abstract class FONode implements Cloneable { return text; } } - + /** * Returns a String containing as much context information as possible about a node. Call * this method only in exceptional conditions because this method may perform quite extensive @@ -573,7 +615,7 @@ public abstract class FONode implements Cloneable { } return sb.toString(); } - + /** * Returns a String containing as some context information about a node. It does not take the * locator into consideration and returns null if no useful context information can be found. @@ -598,7 +640,7 @@ public abstract class FONode implements Cloneable { return null; } } - + /** Function for AdvancedMessageFormat to retrieve context info from an FONode. */ public static class GatherContextInfoFunction implements Function { @@ -621,7 +663,7 @@ public abstract class FONode implements Cloneable { return "gatherContextInfo"; } } - + /** * Gathers context information for the getContextInfo() method. * @return the collected context information or null, if none is available @@ -629,9 +671,10 @@ public abstract class FONode implements Cloneable { protected String gatherContextInfo() { return null; } - + /** * Returns the root node of this tree + * * @return the root node */ public Root getRoot() { @@ -640,6 +683,7 @@ public abstract class FONode implements Cloneable { /** * Returns the fully qualified name of the node + * * @return the fully qualified name of this node */ public String getName() { @@ -648,6 +692,7 @@ public abstract class FONode implements Cloneable { /** * Returns the fully qualified name of the node + * * @param prefix the namespace prefix to build the name with (may be null) * @return the fully qualified name of this node */ @@ -663,22 +708,32 @@ public abstract class FONode implements Cloneable { /** * Returns the local name (i.e. without namespace prefix) of the node + * * @return the local name of this node */ public abstract String getLocalName(); - /** @return the normally ussed namespace prefix for this kind of node (ex. "fo" for XSL-FO) */ + /** + * Returns the normally used namespace prefix for this node + * + * @return the normally used namespace prefix for this kind of node (ex. "fo" for XSL-FO) + */ public abstract String getNormalNamespacePrefix(); - - /** @return the namespace URI for this node */ + + /** + * Returns the namespace URI for this node + * + * @return the namespace URI for this node + */ public String getNamespaceURI() { return null; } - + /** * Returns the {@link Constants} class integer value of this node - * @return the integer enumeration of this FO (e.g. FO_ROOT) - * if a formatting object, FO_UNKNOWN_NODE otherwise + * + * @return the integer enumeration of this FO (e.g. {@link Constants#FO_ROOT}) + * if a formatting object, {@link Constants#FO_UNKNOWN_NODE} otherwise */ public int getNameId() { return Constants.FO_UNKNOWN_NODE; @@ -687,25 +742,31 @@ public abstract class FONode implements Cloneable { /** * This method is overridden by extension elements and allows the extension element * to return a pass-through attachment which the parent formatting objects should simply - * carry with them but otherwise ignore. This mechanism is used to pass non-standard - * information from the FO tree through to the layout engine and the renderers. + * carry with them but otherwise ignore. This mechanism is used to pass non-standard + * information from the FO tree through to the layout engine and the renderers. + * * @return the extension attachment if one is created by the extension element, null otherwise. */ public ExtensionAttachment getExtensionAttachment() { return null; } - + /** * This method is overridden by extension elements and allows the extension element to return - * a ContentHandlerFactory. This factory can create ContentHandler implementations that handle + * a {@link ContentHandlerFactory}. This factory can create ContentHandler implementations that handle * foreign XML content by either building up a specific DOM, a Java object or something else. - * @return the ContentHandlerFactory or null if not applicable + * + * @return the ContentHandlerFactory or null if not applicable */ public ContentHandlerFactory getContentHandlerFactory() { return null; } - + /** + * Returns true if fo:marker is allowed as + * a child node. + *
                                                                                      To be overridden only in extension nodes that need it. + * * @return true if markers are valid children */ protected boolean canHaveMarkers() { @@ -735,16 +796,16 @@ public abstract class FONode implements Cloneable { return false; } } - + /** * This method is used when adding child nodes to a FO that already * contains at least one child. In this case, the new child becomes a * sibling to the previous one - * + * * @param precedingSibling the previous child * @param followingSibling the new child */ - protected static void attachSiblings(FONode precedingSibling, + protected static void attachSiblings(FONode precedingSibling, FONode followingSibling) { if (precedingSibling.siblings == null) { precedingSibling.siblings = new FONode[2]; @@ -755,52 +816,54 @@ public abstract class FONode implements Cloneable { precedingSibling.siblings[1] = followingSibling; followingSibling.siblings[0] = precedingSibling; } - + /** * Base iterator interface over a FO's children - * */ public interface FONodeIterator extends ListIterator { - + /** - * Returns the parent node for this iterator's list + * Returns the parent node for this iterator's list * of child nodes + * * @return the parent node */ FObj parentNode(); - + /** * Convenience method with return type of FONode - * (should be semantically equivalent to - * (FONode) next();) + * (semantically equivalent to: (FONode) next();) + * * @return the next node (if any), as a type FONode */ FONode nextNode(); - + /** * Convenience method with return type of FONode - * (should be semantically equivalent to - * (FONode) previous();) + * (semantically equivalent to: (FONode) previous();) + * * @return the previous node (if any), as a type FONode */ FONode previousNode(); - + /** * Returns the first node in the list, and decreases the index, - * so that a subsequent call to hasPrevious() will return false + * so that a subsequent call to hasPrevious() will + * return false + * * @return the first node in the list - * @throws NoSuchElementException if the list is empty */ FONode firstNode(); - + /** * Returns the last node in the list, and advances the - * current position, so that a subsequent call to hasNext() - * will return false + * current position, so that a subsequent call to hasNext() + * will return false + * * @return the last node in the list - * @throws NoSuchElementException if the list is empty */ FONode lastNode(); } + } diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index 99d37dba9..8c85bb039 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -114,7 +114,8 @@ public class FOText extends FONode { private static final int IS_WORD_CHAR_MAYBE = 2; /** - * Creates a now FO text node. + * Creates a new FO text node. + * * @param parent FONode that is the parent of this object */ public FOText(FONode parent) { @@ -127,7 +128,7 @@ public class FOText extends FONode { int length = end - start; int calength = 0; - char[] nca = null; + char[] nca; if (ca != null) { calength = ca.length; nca = new char[calength + length]; @@ -223,6 +224,7 @@ public class FOText extends FONode { /** * This method is run as part of the ancestor Block's flushText(), to * create xref pointers to the previous FOText objects within the same Block + * @param ancestorBlock the ancestor fo:block */ protected void createBlockPointers(Block ancestorBlock) { this.ancestorBlock = ancestorBlock; @@ -236,7 +238,6 @@ public class FOText extends FONode { prevFOTextThisBlock = null; } } - return; } /** @@ -410,7 +411,7 @@ public class FOText extends FONode { * depending on whether the character should be considered part of a word * or not. */ - public static int isWordChar(char inputChar) { + private static int isWordChar(char inputChar) { switch (Character.getType(inputChar)) { case Character.COMBINING_SPACING_MARK: return IS_WORD_CHAR_TRUE; diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index a03a351e0..a2b09640b 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -39,11 +39,12 @@ import org.apache.fop.fo.properties.PropertyMaker; /** * Base class for representation of formatting objects and their processing. + * All standard formatting object classes extend this class. */ public abstract class FObj extends FONode implements Constants { /** the list of property makers */ - private static PropertyMaker[] propertyListTable + private static final PropertyMaker[] propertyListTable = FOPropertyMapping.getGenericMappings(); /** @@ -71,7 +72,6 @@ public abstract class FObj extends FONode implements Constants { /** * Create a new formatting object. - * All formatting object classes extend this class. * * @param parent the parent node */ @@ -92,9 +92,7 @@ public abstract class FObj extends FONode implements Constants { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FONode clone(FONode parent, boolean removeChildren) throws FOPException { FObj fobj = (FObj) super.clone(parent, removeChildren); @@ -113,9 +111,7 @@ public abstract class FObj extends FONode implements Constants { return propertyListTable[propId]; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { @@ -182,15 +178,13 @@ public abstract class FObj extends FONode implements Constants { * Returns Out Of Line FO Descendant indicator. * @return true if Out of Line FO or Out Of Line descendant, false otherwise */ - public boolean getIsOutOfLineFODescendant() { + boolean getIsOutOfLineFODescendant() { return isOutOfLineFODescendant; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc}*/ protected void addChildNode(FONode child) throws FOPException { - if (canHaveMarkers() && child.getNameId() == FO_MARKER) { + if (child.getNameId() == FO_MARKER) { addMarker((Marker) child); } else { ExtensionAttachment attachment = child.getExtensionAttachment(); @@ -318,7 +312,7 @@ public abstract class FObj extends FONode implements Constants { * any areas (see addMarker()). * @param node the node that was removed */ - protected void notifyChildRemoval(FONode node) { + void notifyChildRemoval(FONode node) { //nop } @@ -464,7 +458,7 @@ public abstract class FObj extends FONode implements Constants { || lName.equals("page-number-citation-last") || lName.equals("basic-link") || (lName.equals("multi-toggle") - && (getNameId() == FO_MULTI_CASE + && (getNameId() == FO_MULTI_CASE || findAncestor(FO_MULTI_CASE) > 0)) || (lName.equals("footnote") && !isOutOfLineFODescendant) @@ -491,7 +485,7 @@ public abstract class FObj extends FONode implements Constants { * @param lName local name (i.e., no prefix) of incoming node * @return true if a member, false if not */ - protected boolean isNeutralItem(String nsURI, String lName) { + boolean isNeutralItem(String nsURI, String lName) { return (FO_URI.equals(nsURI) && (lName.equals("multi-switch") || lName.equals("multi-properties") @@ -546,7 +540,7 @@ public abstract class FObj extends FONode implements Constants { * * @param attachment the attachment to add. */ - public void addExtensionAttachment(ExtensionAttachment attachment) { + void addExtensionAttachment(ExtensionAttachment attachment) { if (attachment == null) { throw new NullPointerException( "Parameter attachment must not be null"); @@ -611,27 +605,23 @@ public abstract class FObj extends FONode implements Constants { private static final int F_REMOVE_ALLOWED = 2; private FONode currentNode; - private FObj parentNode; + private final FObj parentNode; private int currentIndex; private int flags = F_NONE_ALLOWED; - protected FObjIterator(FObj parent) { + FObjIterator(FObj parent) { this.parentNode = parent; this.currentNode = parent.firstChild; this.currentIndex = 0; this.flags = F_NONE_ALLOWED; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FObj parentNode() { return parentNode; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Object next() { if (currentNode != null) { if (currentIndex != 0) { @@ -650,9 +640,7 @@ public abstract class FObj extends FONode implements Constants { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public Object previous() { if (currentNode.siblings != null && currentNode.siblings[0] != null) { @@ -665,9 +653,7 @@ public abstract class FObj extends FONode implements Constants { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void set(Object o) { if ((flags & F_SET_ALLOWED) == F_SET_ALLOWED) { FONode newNode = (FONode) o; @@ -685,9 +671,7 @@ public abstract class FObj extends FONode implements Constants { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void add(Object o) { FONode newNode = (FONode) o; if (currentIndex == -1) { @@ -707,9 +691,7 @@ public abstract class FObj extends FONode implements Constants { flags &= F_NONE_ALLOWED; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean hasNext() { return (currentNode != null) && ((currentIndex == 0) @@ -717,32 +699,24 @@ public abstract class FObj extends FONode implements Constants { && currentNode.siblings[1] != null)); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean hasPrevious() { return (currentIndex != 0) || (currentNode.siblings != null && currentNode.siblings[0] != null); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int nextIndex() { return currentIndex + 1; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int previousIndex() { return currentIndex - 1; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void remove() { if ((flags & F_REMOVE_ALLOWED) == F_REMOVE_ALLOWED) { parentNode.removeChild(currentNode); @@ -762,9 +736,7 @@ public abstract class FObj extends FONode implements Constants { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FONode lastNode() { while (currentNode != null && currentNode.siblings != null @@ -775,28 +747,21 @@ public abstract class FObj extends FONode implements Constants { return currentNode; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FONode firstNode() { currentNode = parentNode.firstChild; currentIndex = 0; return currentNode; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FONode nextNode() { return (FONode) next(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FONode previousNode() { return (FONode) previous(); } } - } diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java index eb64c8f61..698fc58f2 100644 --- a/src/java/org/apache/fop/fo/FObjMixed.java +++ b/src/java/org/apache/fop/fo/FObjMixed.java @@ -24,23 +24,25 @@ import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; /** - * Base class for representation of mixed content formatting objects - * (i.e., those that can contain both child FO's and text nodes/PCDATA). - * It should not be instantiated directly. + * Abstract base class for representation of mixed content formatting objects + * (= those that can contain both child {@link FONode}s and #PCDATA). */ public abstract class FObjMixed extends FObj { - /** Represents accumulated, pending FO text. See flushText(). */ + /** Represents accumulated, pending FO text. See {@link #flushText()}. */ protected FOText ft = null; /** Used for white-space handling; start CharIterator at node ... */ protected FONode currentTextNode; - /** Used in creating pointers between subsequent FOText nodes - * in the same Block (for handling text-transform) */ + /** Used in creating pointers between subsequent {@link FOText} nodes + * in the same {@link org.apache.fop.fo.flow.Block} + * (for handling text-transform) */ protected FOText lastFOTextProcessed = null; /** + * Base constructor + * * @param parent FONode that is the parent of this object */ protected FObjMixed(FONode parent) { @@ -75,8 +77,9 @@ public abstract class FObjMixed extends FObj { /** * Handles white-space for the node that is passed in, * starting at its current text-node - * (used by RetrieveMarker to trigger 'end-of-node' white-space - * handling) + * (used by {@link org.apache.fop.fo.flow.RetrieveMarker} + * to trigger 'end-of-node' white-space handling) + * * @param fobj the node for which to handle white-space */ protected static void handleWhiteSpaceFor(FObjMixed fobj) { @@ -86,8 +89,8 @@ public abstract class FObjMixed extends FObj { /** * Adds accumulated text as one FOText instance, unless - * the one instance's char array contains more than - * Short.MAX_VALUE characters. In the latter case the + * the one instance's char array contains more than + * Short.MAX_VALUE characters. In the latter case the * instance is split up into more manageable chunks. * * @throws FOPException if there is a problem during processing @@ -145,9 +148,7 @@ public abstract class FObjMixed extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { flushText(); if (!inMarker()) { @@ -166,6 +167,8 @@ public abstract class FObjMixed extends FObj { } /** + * Returns a {@link CharIterator} over this FO's character content + * * @return iterator for this object */ public CharIterator charIterator() { diff --git a/src/java/org/apache/fop/fo/XMLObj.java b/src/java/org/apache/fop/fo/XMLObj.java index 42fb1b9a1..da610f0e3 100644 --- a/src/java/org/apache/fop/fo/XMLObj.java +++ b/src/java/org/apache/fop/fo/XMLObj.java @@ -54,7 +54,9 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { protected String name; /** - * @param parent the parent formatting object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public XMLObj(FONode parent) { super(parent); @@ -62,7 +64,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** * {@inheritDoc} - * here, blocks XSL FO's from having non-FO parents. + *
                                                                                      Here, blocks XSL-FO's from having non-FO parents. */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -71,9 +73,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException { setLocator(locator); @@ -90,6 +90,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** * Returns the dimensions of the generated area in pts. + * * @param view Point2D instance to receive the dimensions * @return the requested dimensions in pts. */ @@ -99,6 +100,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** * Retrieve the intrinsic alignment-adjust of the child element. + * * @return the intrinsic alignment-adjust. */ public Length getIntrinsicAlignmentAdjust() { @@ -150,6 +152,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** * Add the top-level element to the DOM document + * * @param doc DOM document * @param svgRoot non-XSL-FO element to be added as the root of this document */ @@ -160,6 +163,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** * Create an empty DOM document + * * @return DOM document */ public Document createBasicDocument() { @@ -187,9 +191,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { return doc; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void addChildNode(FONode child) { if (child instanceof XMLObj) { ((XMLObj)child).addElement(doc, element); @@ -203,6 +205,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** * Add parsed characters to this object + * * @param data array of characters contaning the text to add * @param start starting array element to add * @param length number of characters from the array to add diff --git a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java index 8e5e4f297..bfebf6233 100644 --- a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java +++ b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java @@ -220,8 +220,6 @@ public class XMLWhiteSpaceHandler { * firstTextNode (when a nested FO is encountered) * @param fo the FO for which to handle white-space * @param firstTextNode the node at which to start - * @param nextChild the child-node that will be added to the list after - * the last text-node */ public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode) { handleWhiteSpace(fo, firstTextNode, null); diff --git a/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java b/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java index f99f9d947..092358891 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java +++ b/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java @@ -29,7 +29,9 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.KeepProperty; /** - * Common superclass for list-item-label and list-item-body. + * Common superclass for + * fo:list-item-label and + * fo:list-item-body. */ public abstract class AbstractListItemPart extends FObj { // The value of properties relevant for fo:list-item-label and fo:list-item-body. @@ -42,15 +44,15 @@ public abstract class AbstractListItemPart extends FObj { private boolean blockItemFound = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public AbstractListItemPart(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); @@ -58,7 +60,7 @@ public abstract class AbstractListItemPart extends FObj { /** * {@inheritDoc} - * XSL Content Model: marker* (%block;)+ + *
                                                                                      XSL Content Model: marker* (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -75,9 +77,7 @@ public abstract class AbstractListItemPart extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (!this.blockItemFound) { String contentModel = "marker* (%block;)+"; diff --git a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java index e9a1176d6..b45f21348 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java +++ b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java @@ -36,7 +36,10 @@ import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.SpaceProperty; /** - * Base class modelling the fo:page-number-citation object. + * Common base class for the + * fo:page-number-citation and + * + * fo:page-number-citation-last objects. */ public abstract class AbstractPageNumberCitation extends FObj { @@ -73,15 +76,15 @@ public abstract class AbstractPageNumberCitation extends FObj { private Color color; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public AbstractPageNumberCitation(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); @@ -110,7 +113,7 @@ public abstract class AbstractPageNumberCitation extends FObj { /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -119,7 +122,7 @@ public abstract class AbstractPageNumberCitation extends FObj { } } - /** @return the Common Font Properties. */ + /** @return the {@link CommonFont} */ public CommonFont getCommonFont() { return commonFont; } @@ -134,42 +137,32 @@ public abstract class AbstractPageNumberCitation extends FObj { return textDecoration; } - /** - * @return the "alignment-adjust" property - */ + /** @return the "alignment-adjust" property */ public Length getAlignmentAdjust() { return alignmentAdjust; } - /** - * @return the "alignment-baseline" property - */ + /** @return the "alignment-baseline" property */ public int getAlignmentBaseline() { return alignmentBaseline; } - /** - * @return the "baseline-shift" property - */ + /** @return the "baseline-shift" property */ public Length getBaselineShift() { return baselineShift; } - /** - * @return the "dominant-baseline" property - */ + /** @return the "dominant-baseline" property */ public int getDominantBaseline() { return dominantBaseline; } - /** @return the Common Border, Padding, and Background Properties. */ + /** @return the {@link CommonBorderPaddingBackground} */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } - /** - * @return the "line-height" property - */ + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } diff --git a/src/java/org/apache/fop/fo/flow/BidiOverride.java b/src/java/org/apache/fop/fo/flow/BidiOverride.java index 892f4a3c5..492e6c4ba 100644 --- a/src/java/org/apache/fop/fo/flow/BidiOverride.java +++ b/src/java/org/apache/fop/fo/flow/BidiOverride.java @@ -29,7 +29,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.SpaceProperty; /** - * Class modelling the fo:bidi-override object. + * Class modelling the + * fo:bidi-override object. */ public class BidiOverride extends FObjMixed { @@ -52,6 +53,8 @@ public class BidiOverride extends FObjMixed { // End of property values /** + * Base constructor + * * @param parent FONode that is the parent of this object */ public BidiOverride(FONode parent) { @@ -77,9 +80,7 @@ public class BidiOverride extends FObjMixed { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { // prDirection = pList.get(PR_DIRECTION); // prLetterSpacing = pList.get(PR_LETTER_SPACING); @@ -90,11 +91,11 @@ public class BidiOverride extends FObjMixed { /** * {@inheritDoc} - * XSL Content Model: marker* (#PCDATA|%inline;|%block;)* - * Additionally: "An fo:bidi-override that is a descendant of an fo:leader + *
                                                                                      XSL Content Model: marker* (#PCDATA|%inline;|%block;)* + *
                                                                                      Additionally: "An fo:bidi-override that is a descendant of an fo:leader * or of the fo:inline child of an fo:footnote may not have block-level * children, unless it has a nearer ancestor that is an - * fo:inline-container." + * fo:inline-container." */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -115,9 +116,7 @@ public class BidiOverride extends FObjMixed { } } - /** - * @return the "line-height" property. - */ + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } @@ -129,6 +128,7 @@ public class BidiOverride extends FObjMixed { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_BIDI_OVERRIDE} */ public int getNameId() { return FO_BIDI_OVERRIDE; diff --git a/src/java/org/apache/fop/fo/flow/Block.java b/src/java/org/apache/fop/fo/flow/Block.java index 30b4c5495..40175ce49 100644 --- a/src/java/org/apache/fop/fo/flow/Block.java +++ b/src/java/org/apache/fop/fo/flow/Block.java @@ -41,7 +41,8 @@ import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.SpaceProperty; /** - * Class modelling the fo:block object. + * Class modelling the + * fo:block object. */ public class Block extends FObjMixed { @@ -87,6 +88,8 @@ public class Block extends FObjMixed { // End of property values /** + * Base constructor + * * @param parent FONode that is the parent of this object * */ @@ -94,9 +97,7 @@ public class Block extends FObjMixed { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); @@ -130,46 +131,35 @@ public class Block extends FObjMixed { wrapOption = pList.get(PR_WRAP_OPTION).getEnum(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startBlock(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { super.endOfNode(); getFOEventHandler().endBlock(this); } - /** - * @return the Common Margin Properties-Block. - */ + /** @return the {@link CommonMarginBlock} */ public CommonMarginBlock getCommonMarginBlock() { return commonMarginBlock; } - /** - * @return the Common Border, Padding, and Background Properties. - */ + /** @return the {@link CommonBorderPaddingBackground} */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } /** - * @return the Common Font Properties. - */ + * @return the {@link CommonFont} */ public CommonFont getCommonFont() { return commonFont; } - /** - * @return the Common Hyphenation Properties. - */ + /** @return the {@link CommonHyphenation} */ public CommonHyphenation getCommonHyphenation() { return commonHyphenation; } @@ -219,79 +209,63 @@ public class Block extends FObjMixed { return lineStackingStrategy; } - /** - * @return the "color" property. - */ + /** @return the "color" property */ public Color getColor() { return color; } - /** - * @return the "line-height" property. - */ + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } - /** - * @return the "span" property. - */ + /** @return the "span" property */ public int getSpan() { return this.span; } - /** - * @return the "text-align" property. - */ + /** @return the "text-align" property */ public int getTextAlign() { return textAlign; } - /** - * @return the "text-align-last" property. - */ + /** @return the "text-align-last" property */ public int getTextAlignLast() { return textAlignLast; } - /** - * @return the "text-indent" property. - */ + /** @return the "text-indent" property */ public Length getTextIndent() { return textIndent; } - /** - * @return the "last-line-end-indent" property. - */ + /** @return the "last-line-end-indent" property */ public Length getLastLineEndIndent() { return lastLineEndIndent; } - /** - * @return the "wrap-option" property. - */ + /** @return the "wrap-option" property */ public int getWrapOption() { return wrapOption; } /** * {@inheritDoc} - * XSL Content Model: marker* initial-property-set? (#PCDATA|%inline;|%block;)* - * Additionally: "An fo:bidi-override that is a descendant of an fo:leader + *
                                                                                      XSL Content Model: marker* initial-property-set? (#PCDATA|%inline;|%block;)* + *
                                                                                      Additionally: "An fo:bidi-override that is a descendant of an fo:leader * or of the fo:inline child of an fo:footnote may not have block-level * children, unless it has a nearer ancestor that is an - * fo:inline-container." + * fo:inline-container." */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { - if (localName.equals("marker")) { + if ("marker".equals(localName)) { if (blockOrInlineItemFound || initialPropertySetFound) { nodesOutOfOrderError(loc, "fo:marker", "initial-property-set? (#PCDATA|%inline;|%block;)"); } - } else if (localName.equals("initial-property-set")) { + } else if ("initial-property-set".equals(localName)) { if (initialPropertySetFound) { tooManyNodesError(loc, "fo:initial-property-set"); } else if (blockOrInlineItemFound) { @@ -308,57 +282,37 @@ public class Block extends FObjMixed { } } - /** - * Accessor for the linefeed-treatment property - * - * @return the enum value of linefeed-treatment - */ + /** @return the "linefeed-treatment" property */ public int getLinefeedTreatment() { return linefeedTreatment; } - /** - * Accessor for the white-space-treatment property - * - * @return the enum value of white-space-treatment - */ + /** @return the "white-space-treatment" property */ public int getWhitespaceTreatment() { return whiteSpaceTreatment; } - /** - * Accessor for the white-space-collapse property - * - * @return the enum value of white-space-collapse - */ + /** @return the "white-space-collapse" property */ public int getWhitespaceCollapse() { return whiteSpaceCollapse; } - /** - * @return Returns the commonRelativePosition. - */ + /** @return the {@link CommonRelativePosition} */ public CommonRelativePosition getCommonRelativePosition() { return this.commonRelativePosition; } - /** - * @return Returns the hyphenationKeep. - */ + /** @return the "hyphenation-keep" property */ public int getHyphenationKeep() { return this.hyphenationKeep; } - /** - * @return Returns the intrusionDisplace. - */ + /** @return the "intrusion-displace" property */ public int getIntrusionDisplace() { return this.intrusionDisplace; } - /** - * @return Returns the lineHeightShiftAdjustment. - */ + /** @return the "line-height-shift-adjustment" property */ public int getLineHeightShiftAdjustment() { return this.lineHeightShiftAdjustment; } @@ -373,9 +327,10 @@ public class Block extends FObjMixed { return "block"; } - /** - * {@inheritDoc} - */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_BLOCK} + */ public int getNameId() { return FO_BLOCK; } diff --git a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java index 07f765e52..bfe54cbd9 100644 --- a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java +++ b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java @@ -58,7 +58,8 @@ public class ExternalGraphic extends AbstractGraphics { private Length intrinsicAlignmentAdjust; /** - * Create a new External graphic node. + * Create a new ExternalGraphic node that is a child + * of the given {@link FONode}. * * @param parent the parent of this node */ @@ -134,7 +135,10 @@ public class ExternalGraphic extends AbstractGraphics { return "external-graphic"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_EXTERNAL_GRAPHIC} + */ public int getNameId() { return FO_EXTERNAL_GRAPHIC; } diff --git a/src/java/org/apache/fop/fo/flow/Float.java b/src/java/org/apache/fop/fo/flow/Float.java index 57d3b4ee1..90bc423fd 100644 --- a/src/java/org/apache/fop/fo/flow/Float.java +++ b/src/java/org/apache/fop/fo/flow/Float.java @@ -29,7 +29,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:float object. + * Class modelling the + * fo:float object. */ public class Float extends FObj { // The value of properties relevant for fo:float (commented out for performance. @@ -40,7 +41,9 @@ public class Float extends FObj { static boolean notImplementedWarningGiven = false; /** - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Base constructor + * + * @param parent the parent {@link FONode} */ public Float(FONode parent) { super(parent); @@ -52,16 +55,14 @@ public class Float extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { // No active properties -> Nothing to do. } /** * {@inheritDoc} - * XSL Content Model: (%block;)+ + *
                                                                                      XSL Content Model: (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -72,9 +73,7 @@ public class Float extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (firstChild == null) { missingChildElementError("(%block;)+"); @@ -88,6 +87,7 @@ public class Float extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_FLOAT} */ public int getNameId() { return FO_FLOAT; diff --git a/src/java/org/apache/fop/fo/flow/Footnote.java b/src/java/org/apache/fop/fo/flow/Footnote.java index c15a7e0ee..54e457db8 100644 --- a/src/java/org/apache/fop/fo/flow/Footnote.java +++ b/src/java/org/apache/fop/fo/flow/Footnote.java @@ -28,7 +28,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:footnote object. + * Class modelling the + * fo:footnote object. */ public class Footnote extends FObj { // The value of properties relevant for fo:footnote (commented out for performance). @@ -39,29 +40,28 @@ public class Footnote extends FObj { private FootnoteBody footnoteBody; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public Footnote(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { // No active properties -> do nothing. } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { getFOEventHandler().startFootnote(this); } /** * Make sure content model satisfied, if so then tell the - * FOEventHandler that we are at the end of the flow. + * {@link org.apache.fop.fo.FOEventHandler} that we are at the end of the footnote. + * * {@inheritDoc} */ protected void endOfNode() throws FOPException { @@ -74,7 +74,7 @@ public class Footnote extends FObj { /** * {@inheritDoc} - * XSL Content Model: (inline,footnote-body) + *
                                                                                      XSL Content Model: (inline,footnote-body) * @todo implement additional constraint: A fo:footnote is not permitted * to have a fo:float, fo:footnote, or fo:marker as a descendant. * @todo implement additional constraint: A fo:footnote is not @@ -100,20 +100,19 @@ public class Footnote extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void addChildNode(FONode child) { - if (((FObj)child).getNameId() == FO_INLINE) { + if (child.getNameId() == FO_INLINE) { footnoteCitation = (Inline) child; - } else if (((FObj)child).getNameId() == FO_FOOTNOTE_BODY) { + } else if (child.getNameId() == FO_FOOTNOTE_BODY) { footnoteBody = (FootnoteBody) child; } } /** * Public accessor for inline FO - * @return the Inline child + * + * @return the {@link Inline} child */ public Inline getFootnoteCitation() { return footnoteCitation; @@ -121,7 +120,8 @@ public class Footnote extends FObj { /** * Public accessor for footnote-body FO - * @return the FootnoteBody child + * + * @return the {@link FootnoteBody} child */ public FootnoteBody getFootnoteBody() { return footnoteBody; @@ -134,6 +134,7 @@ public class Footnote extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_FOOTNOTE} */ public int getNameId() { return FO_FOOTNOTE; diff --git a/src/java/org/apache/fop/fo/flow/FootnoteBody.java b/src/java/org/apache/fop/fo/flow/FootnoteBody.java index 967d15215..21c5a3efd 100644 --- a/src/java/org/apache/fop/fo/flow/FootnoteBody.java +++ b/src/java/org/apache/fop/fo/flow/FootnoteBody.java @@ -29,7 +29,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:footnote-body object. + * Class modelling the + * fo:footnote-body object. */ public class FootnoteBody extends FObj { // The value of properties relevant for fo:footnote-body (commented out for perforance). @@ -37,28 +38,27 @@ public class FootnoteBody extends FObj { // End of property values /** + * Base constructor + * * @param parent FONode that is the parent of this object */ public FootnoteBody(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { getFOEventHandler().startFootnoteBody(this); } /** - * Make sure content model satisfied, if so then tell the - * FOEventHandler that we are at the end of the flow. + * Make sure the content model is satisfied, if so then tell the + * {@link org.apache.fop.fo.FOEventHandler} that we are at the + * end of the footnote-body. * {@inheritDoc} */ protected void endOfNode() throws FOPException { @@ -70,7 +70,7 @@ public class FootnoteBody extends FObj { /** * {@inheritDoc} - * XSL Content Model: (%block;)+ + *
                                                                                      XSL Content Model: (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -88,6 +88,7 @@ public class FootnoteBody extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_FOOTNOTE_BODY} */ public int getNameId() { return FO_FOOTNOTE_BODY; diff --git a/src/java/org/apache/fop/fo/flow/InitialPropertySet.java b/src/java/org/apache/fop/fo/flow/InitialPropertySet.java index 6d0e495b7..6b2a1b50c 100644 --- a/src/java/org/apache/fop/fo/flow/InitialPropertySet.java +++ b/src/java/org/apache/fop/fo/flow/InitialPropertySet.java @@ -30,7 +30,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.SpaceProperty; /** - * Class modelling the fo:initial-property-set object. + * Class modelling the + * fo:initial-property-set object. */ public class InitialPropertySet extends FObj { // The value of properties relevant for fo:initial-property-set. @@ -51,15 +52,15 @@ public class InitialPropertySet extends FObj { // End of property values /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public InitialPropertySet(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); // letterSpacing = pList.get(PR_LETTER_SPACING); @@ -69,7 +70,7 @@ public class InitialPropertySet extends FObj { /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -78,9 +79,7 @@ public class InitialPropertySet extends FObj { } } - /** - * @return the "line-height" property. - */ + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } @@ -92,6 +91,7 @@ public class InitialPropertySet extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_INITIAL_PROPERTY_SET} */ public int getNameId() { return FO_INITIAL_PROPERTY_SET; diff --git a/src/java/org/apache/fop/fo/flow/Inline.java b/src/java/org/apache/fop/fo/flow/Inline.java index 50662d9f1..a770b0f06 100644 --- a/src/java/org/apache/fop/fo/flow/Inline.java +++ b/src/java/org/apache/fop/fo/flow/Inline.java @@ -28,7 +28,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:inline formatting object. + * Class modelling the + * fo:inline formatting object. */ public class Inline extends InlineLevel { // The value of properties relevant for fo:inline. @@ -50,15 +51,15 @@ public class Inline extends InlineLevel { private boolean canHaveBlockLevelChildren = true; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public Inline(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength(); @@ -67,9 +68,7 @@ public class Inline extends InlineLevel { dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); @@ -94,9 +93,7 @@ public class Inline extends InlineLevel { getFOEventHandler().startInline(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { super.endOfNode(); getFOEventHandler().endInline(this); @@ -104,10 +101,10 @@ public class Inline extends InlineLevel { /** * {@inheritDoc} - * XSL Content Model: marker* (#PCDATA|%inline;|%block;)* - * Additionally: " An fo:inline that is a descendant of an fo:leader + *
                                                                                      XSL Content Model: marker* (#PCDATA|%inline;|%block;)* + *
                                                                                      Additionally: " An fo:inline that is a descendant of an fo:leader * or fo:footnote may not have block-level children, unless it has a - * nearer ancestor that is an fo:inline-container." (paraphrased) + * nearer ancestor that is an fo:inline-container." (paraphrased) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -127,30 +124,22 @@ public class Inline extends InlineLevel { } } - /** - * @return the "alignment-adjust" property - */ + /** @return the "alignment-adjust" property */ public Length getAlignmentAdjust() { return alignmentAdjust; } - /** - * @return the "alignment-baseline" property - */ + /** @return the "alignment-baseline" property */ public int getAlignmentBaseline() { return alignmentBaseline; } - /** - * @return the "baseline-shift" property - */ + /** @return the "baseline-shift" property */ public Length getBaselineShift() { return baselineShift; } - /** - * @return the "dominant-baseline" property - */ + /** @return the "dominant-baseline" property */ public int getDominantBaseline() { return dominantBaseline; } @@ -160,7 +149,10 @@ public class Inline extends InlineLevel { return "inline"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_INLINE} + */ public int getNameId() { return FO_INLINE; } diff --git a/src/java/org/apache/fop/fo/flow/InlineLevel.java b/src/java/org/apache/fop/fo/flow/InlineLevel.java index 096a2ed66..92af98d3c 100644 --- a/src/java/org/apache/fop/fo/flow/InlineLevel.java +++ b/src/java/org/apache/fop/fo/flow/InlineLevel.java @@ -25,8 +25,6 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.properties.CommonAccessibility; -import org.apache.fop.fo.properties.CommonAural; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonFont; import org.apache.fop.fo.properties.CommonMarginInline; @@ -40,71 +38,69 @@ import org.apache.fop.fo.properties.SpaceProperty; public abstract class InlineLevel extends FObjMixed { // The value of properties relevant for inline-level FOs. - protected CommonBorderPaddingBackground commonBorderPaddingBackground; - protected CommonAccessibility commonAccessibility; - protected CommonMarginInline commonMarginInline; - protected CommonAural commonAural; - protected CommonFont commonFont; - protected Color color; - protected SpaceProperty lineHeight; - protected int visibility; + private CommonBorderPaddingBackground commonBorderPaddingBackground; + private CommonMarginInline commonMarginInline; + private CommonFont commonFont; + private Color color; + private KeepProperty keepWithNext; + private KeepProperty keepWithPrevious; + private SpaceProperty lineHeight; // End of property values /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ protected InlineLevel(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); - commonAccessibility = pList.getAccessibilityProps(); commonMarginInline = pList.getMarginInlineProps(); - commonAural = pList.getAuralProps(); commonFont = pList.getFontProps(); color = pList.get(PR_COLOR).getColor(getUserAgent()); + keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep(); + keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); lineHeight = pList.get(PR_LINE_HEIGHT).getSpace(); - visibility = pList.get(PR_VISIBILITY).getEnum(); } - /** - * @return the Common Margin Properties-Inline. - */ + /** @return the {@link CommonMarginInline} */ public CommonMarginInline getCommonMarginInline() { return commonMarginInline; } - /** - * @return the Common Border, Padding, and Background Properties. - */ + /** @return the {@link CommonBorderPaddingBackground} */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } - /** - * @return the Common Font Properties. - */ + /** @return the {@link CommonFont} */ public CommonFont getCommonFont() { return commonFont; } - /** - * @return the "color" property. - */ + /** @return the "color" property */ public Color getColor() { return color; } - /** - * @return the "line-height" property - */ + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } + /** @return the "keep-with-next" property */ + public KeepProperty getKeepWithNext() { + return keepWithNext; + } + + /** @return the "keep-with-previous" property */ + public KeepProperty getKeepWithPrevious() { + return keepWithPrevious; + } + } diff --git a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java index 802f59c30..3583087d4 100644 --- a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java +++ b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java @@ -33,7 +33,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.XMLObj; /** - * Class modelling the fo:instream-foreign-object object. + * Class modelling the + * fo:instream-foreign-object object. * This is an atomic inline object that contains XML data. */ public class InstreamForeignObject extends AbstractGraphics { @@ -45,13 +46,14 @@ public class InstreamForeignObject extends AbstractGraphics { //Additional value private Point2D intrinsicDimensions; private boolean instrisicSizeDetermined; - + private Length intrinsicAlignmentAdjust; /** - * constructs an instream-foreign-object object (called by Maker). + * Constructs an instream-foreign-object object + * (called by {@link org.apache.fop.fo.ElementMapping.Maker}). * - * @param parent the parent formatting object + * @param parent the parent {@link FONode} */ public InstreamForeignObject(FONode parent) { super(parent); @@ -59,7 +61,8 @@ public class InstreamForeignObject extends AbstractGraphics { /** * Make sure content model satisfied, if so then tell the - * FOEventHandler that we are at the end of the flow. + * {@link org.apache.fop.fo.FOEventHandler} that we are at + * the end of the instream-foreign-object. * {@inheritDoc} */ protected void endOfNode() throws FOPException { @@ -71,10 +74,10 @@ public class InstreamForeignObject extends AbstractGraphics { /** * {@inheritDoc} - * XSL Content Model: one (1) non-XSL namespace child + *
                                                                                      XSL Content Model: one (1) non-XSL namespace child */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); } else if (firstChild != null) { @@ -87,7 +90,10 @@ public class InstreamForeignObject extends AbstractGraphics { return "instream-foreign-object"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_INSTREAM_FOREIGN_OBJECT} + */ public int getNameId() { return FO_INSTREAM_FOREIGN_OBJECT; } @@ -139,7 +145,7 @@ public class InstreamForeignObject extends AbstractGraphics { super.addChildNode(child); } - /** @return the XMLObj child node of the instream-foreign-object. */ + /** @return the {@link XMLObj} child node of the instream-foreign-object. */ public XMLObj getChildXMLObj() { return (XMLObj) firstChild; } diff --git a/src/java/org/apache/fop/fo/flow/Leader.java b/src/java/org/apache/fop/fo/flow/Leader.java index 82584b614..b73534d87 100644 --- a/src/java/org/apache/fop/fo/flow/Leader.java +++ b/src/java/org/apache/fop/fo/flow/Leader.java @@ -26,8 +26,9 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.LengthRangeProperty; /** - * Class modelling fo:leader object. - * The main property of fo:leader is leader-pattern. + * Class modelling the + * fo:leader object. + * The main property of fo:leader is leader-pattern. * The following patterns are treated: rule, space, dots and use-content. * @todo implement validateChildNode() */ @@ -53,15 +54,15 @@ public class Leader extends InlineLevel { // End of property values /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public Leader(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength(); @@ -95,72 +96,52 @@ public class Leader extends InlineLevel { // textShadow = pList.get(PR_TEXT_SHADOW); } - /** - * @return the "rule-style" property. - */ + /** @return the "rule-style" property */ public int getRuleStyle() { return ruleStyle; } - /** - * @return the "rule-thickness" property. - */ + /** @return the "rule-thickness" property */ public Length getRuleThickness() { return ruleThickness; } - /** - * @return the "leader-alignment" property. - */ + /** @return the "leader-alignment" property */ public int getLeaderAlignment() { return leaderAlignment; } - /** - * @return the "leader-length" property. - */ + /** @return the "leader-length" property */ public LengthRangeProperty getLeaderLength() { return leaderLength; } - /** - * @return the "leader-pattern" property. - */ + /** @return the "leader-pattern" property */ public int getLeaderPattern() { return leaderPattern; } - /** - * @return the "leader-pattern-width" property. - */ + /** @return the "leader-pattern-width" property */ public Length getLeaderPatternWidth() { return leaderPatternWidth; } - /** - * @return the "alignment-adjust" property - */ + /** @return the "alignment-adjust" property */ public Length getAlignmentAdjust() { return alignmentAdjust; } - /** - * @return the "alignment-baseline" property - */ + /** @return the "alignment-baseline" property */ public int getAlignmentBaseline() { return alignmentBaseline; } - /** - * @return the "baseline-shift" property - */ + /** @return the "baseline-shift" property */ public Length getBaselineShift() { return baselineShift; } - /** - * @return the "dominant-baseline" property - */ + /** @return the "dominant-baseline" property */ public int getDominantBaseline() { return dominantBaseline; } @@ -172,6 +153,7 @@ public class Leader extends InlineLevel { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_LEADER} */ public int getNameId() { return FO_LEADER; diff --git a/src/java/org/apache/fop/fo/flow/ListBlock.java b/src/java/org/apache/fop/fo/flow/ListBlock.java index a196e92de..8c7777e6a 100644 --- a/src/java/org/apache/fop/fo/flow/ListBlock.java +++ b/src/java/org/apache/fop/fo/flow/ListBlock.java @@ -32,7 +32,8 @@ import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.KeepProperty; /** - * Class modelling the fo:list-block object. + * Class modelling the + * fo:list-block object. */ public class ListBlock extends FObj { // The value of properties relevant for fo:list-block. @@ -60,15 +61,15 @@ public class ListBlock extends FObj { private boolean hasListItem = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public ListBlock(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); @@ -83,17 +84,16 @@ public class ListBlock extends FObj { orphanContentLimit = pList.get(PR_X_ORPHAN_CONTENT_LIMIT).getLength(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startList(this); } /** - * Make sure content model satisfied, if so then tell the - * FOEventHandler that we are at the end of the flow. + * Make sure the content model is satisfied, if so then tell the + * {@link org.apache.fop.fo.FOEventHandler} that we are at the end + * of the list-block. * {@inheritDoc} */ protected void endOfNode() throws FOPException { @@ -105,7 +105,7 @@ public class ListBlock extends FObj { /** * {@inheritDoc} - * XSL Content Model: marker* (list-item)+ + *
                                                                                      XSL Content Model: marker* (list-item)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -122,30 +122,22 @@ public class ListBlock extends FObj { } } - /** - * @return the Common Margin Properties-Block. - */ + /** @return the {@link CommonMarginBlock} */ public CommonMarginBlock getCommonMarginBlock() { return commonMarginBlock; } - /** - * @return the Common Border, Padding, and Background Properties. - */ + /** @return the {@link CommonBorderPaddingBackground} */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } - /** - * @return the "break-after" property. - */ + /** @return the "break-after" property */ public int getBreakAfter() { return breakAfter; } - /** - * @return the "break-before" property. - */ + /** @return the "break-before" property */ public int getBreakBefore() { return breakBefore; } @@ -180,7 +172,10 @@ public class ListBlock extends FObj { return "list-block"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_LIST_BLOCK} + */ public int getNameId() { return FO_LIST_BLOCK; } diff --git a/src/java/org/apache/fop/fo/flow/ListItem.java b/src/java/org/apache/fop/fo/flow/ListItem.java index cf0e05c56..398d91558 100644 --- a/src/java/org/apache/fop/fo/flow/ListItem.java +++ b/src/java/org/apache/fop/fo/flow/ListItem.java @@ -31,7 +31,8 @@ import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.KeepProperty; /** - * Class modelling the fo:list-item object. + * Class modelling the + * fo:list-item object. */ public class ListItem extends FObj { // The value of properties relevant for fo:list-item. @@ -54,15 +55,15 @@ public class ListItem extends FObj { private ListItemBody body = null; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public ListItem(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); @@ -74,17 +75,13 @@ public class ListItem extends FObj { keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startListItem(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (label == null || body == null) { missingChildElementError("marker* (list-item-label,list-item-body)"); @@ -94,7 +91,7 @@ public class ListItem extends FObj { /** * {@inheritDoc} - * XSL Content Model: marker* (list-item-label,list-item-body) + *
                                                                                      XSL Content Model: marker* (list-item-label,list-item-body) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -125,7 +122,7 @@ public class ListItem extends FObj { * (i.e., add to childNodes instead) */ public void addChildNode(FONode child) { - int nameId = ((FObj)child).getNameId(); + int nameId = child.getNameId(); if (nameId == FO_LIST_ITEM_LABEL) { label = (ListItemLabel) child; @@ -136,52 +133,42 @@ public class ListItem extends FObj { } } - /** - * @return the Common Margin Properties-Block. - */ + /** @return the {@link CommonMarginBlock} */ public CommonMarginBlock getCommonMarginBlock() { return commonMarginBlock; } - /** - * @return the Common Border, Padding, and Background Properties. - */ + /** @return the {@link CommonBorderPaddingBackground} */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } - /** - * @return the "break-after" property. - */ + /** @return the "break-after" property */ public int getBreakAfter() { return breakAfter; } - /** - * @return the "break-before" property. - */ + /** @return the "break-before" property */ public int getBreakBefore() { return breakBefore; } - /** @return the "keep-with-next" property. */ + /** @return the "keep-with-next" property */ public KeepProperty getKeepWithNext() { return keepWithNext; } - /** @return the "keep-with-previous" property. */ + /** @return the "keep-with-previous" property */ public KeepProperty getKeepWithPrevious() { return keepWithPrevious; } - /** @return the "keep-together" property. */ + /** @return the "keep-together" property */ public KeepProperty getKeepTogether() { return keepTogether; } - /** - * @return the label of the list item - */ + /** @return the label of the list item */ public ListItemLabel getLabel() { return label; } @@ -200,6 +187,7 @@ public class ListItem extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_LIST_ITEM} */ public int getNameId() { return FO_LIST_ITEM; diff --git a/src/java/org/apache/fop/fo/flow/ListItemBody.java b/src/java/org/apache/fop/fo/flow/ListItemBody.java index 3d5d4562e..226cacd12 100644 --- a/src/java/org/apache/fop/fo/flow/ListItemBody.java +++ b/src/java/org/apache/fop/fo/flow/ListItemBody.java @@ -23,7 +23,8 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; /** - * Class modelling the fo:list-item-body object. + * Class modelling the + * fo:list-item-body object. */ public class ListItemBody extends AbstractListItemPart { @@ -34,17 +35,13 @@ public class ListItemBody extends AbstractListItemPart { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startListBody(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { super.endOfNode(); getFOEventHandler().endListBody(); @@ -57,6 +54,7 @@ public class ListItemBody extends AbstractListItemPart { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_LIST_ITEM_BODY} */ public int getNameId() { return FO_LIST_ITEM_BODY; diff --git a/src/java/org/apache/fop/fo/flow/ListItemLabel.java b/src/java/org/apache/fop/fo/flow/ListItemLabel.java index dcdf1b3a1..7fbbe77d3 100644 --- a/src/java/org/apache/fop/fo/flow/ListItemLabel.java +++ b/src/java/org/apache/fop/fo/flow/ListItemLabel.java @@ -23,28 +23,27 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; /** - * Class modelling the fo:list-item-label object. + * Class modelling the + * fo:list-item-label object. */ public class ListItemLabel extends AbstractListItemPart { /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public ListItemLabel(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startListLabel(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { super.endOfNode(); getFOEventHandler().endListLabel(); @@ -57,6 +56,7 @@ public class ListItemLabel extends AbstractListItemPart { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_LIST_ITEM_LABEL} */ public int getNameId() { return FO_LIST_ITEM_LABEL; diff --git a/src/java/org/apache/fop/fo/flow/Marker.java b/src/java/org/apache/fop/fo/flow/Marker.java index 168b18180..7eda2101e 100644 --- a/src/java/org/apache/fop/fo/flow/Marker.java +++ b/src/java/org/apache/fop/fo/flow/Marker.java @@ -36,7 +36,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.Property; /** - * Class modelling the fo:marker object. + * Class modelling the + * fo:marker object. */ public class Marker extends FObjMixed { // The value of properties relevant for fo:marker. @@ -48,15 +49,14 @@ public class Marker extends FObjMixed { /** * Create a marker fo. - * @param parent the parent fo node + * + * @param parent the parent {@link FONode} */ public Marker(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { if (findAncestor(FO_FLOW) < 0) { invalidChildError(locator, getParent().getName(), FO_URI, getName(), @@ -71,9 +71,11 @@ public class Marker extends FObjMixed { } /** - * retrieve the property list of foNode - * @param foNode the FO node whose property list is requested - * @return the MarkerPropertyList of foNode + * Retrieve the property list of the given {@link FONode} + * descendant + * + * @param foNode the {@link FONode} whose property list is requested + * @return the {@link MarkerPropertyList} for the given node */ protected MarkerPropertyList getPropertyListFor(FONode foNode) { return (MarkerPropertyList) @@ -104,10 +106,10 @@ public class Marker extends FObjMixed { /** * {@inheritDoc} - * XSL Content Model: (#PCDATA|%inline;|%block;)* - * Additionally: "An fo:marker may contain any formatting objects that + *
                                                                                      XSL Content Model: (#PCDATA|%inline;|%block;)* + *
                                                                                      Additionally: "An fo:marker may contain any formatting objects that * are permitted as a replacement of any fo:retrieve-marker that retrieves - * the fo:marker's children." + * the fo:marker's children." * @todo implement "additional" constraint, possibly within fo:retrieve-marker */ protected void validateChildNode(Locator loc, String nsURI, String localName) @@ -119,13 +121,12 @@ public class Marker extends FObjMixed { } } + /** {@inheritDoc} */ protected boolean inMarker() { return true; } - /** - * Return the "marker-class-name" property. - */ + /** @return the "marker-class-name" property */ public String getMarkerClassName() { return markerClassName; } @@ -137,6 +138,7 @@ public class Marker extends FObjMixed { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_MARKER} */ public int getNameId() { return FO_MARKER; @@ -150,7 +152,7 @@ public class Marker extends FObjMixed { } /** - * An implementation of PropertyList which only stores the explicitly + * An implementation of {@link PropertyList} which only stores the explicitly * specified properties/attributes as bundles of name-value-namespace * strings */ @@ -163,7 +165,7 @@ public class Marker extends FObjMixed { /** * Overriding default constructor * - * @param fobj the FObj to attach + * @param fobj the {@link FObj} to attach * @param parentPropertyList ignored */ public MarkerPropertyList(FObj fobj, PropertyList parentPropertyList) { @@ -175,10 +177,10 @@ public class Marker extends FObjMixed { } /** - * Override that doesn't convert the attributes to Property instances, - * but simply stores the attributes for later processing; + * Override that doesn't convert the attributes to {@link Property} + * instances, but simply stores the attributes for later processing. * - * @see org.apache.fop.fo.PropertyList#addAttributesToList(Attributes) + * {@inheritDoc} */ public void addAttributesToList(Attributes attributes) throws ValidationException { @@ -201,23 +203,17 @@ public class Marker extends FObjMixed { } } - /** - * Null implementation; not used by this type of PropertyList - */ + /** Null implementation; not used by this type of {@link PropertyList} */ public void putExplicit(int propId, Property value) { //nop } - /** - * Null implementation; not used by this type of PropertyList - */ + /** Null implementation; not used by this type of {@link PropertyList} */ public Property getExplicit(int propId) { return null; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getLength() { if (attribs == null) { return 0; @@ -226,9 +222,7 @@ public class Marker extends FObjMixed { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getURI(int index) { if (attribs != null && index < attribs.length @@ -240,9 +234,7 @@ public class Marker extends FObjMixed { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getLocalName(int index) { if (attribs != null && index < attribs.length @@ -254,9 +246,7 @@ public class Marker extends FObjMixed { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getQName(int index) { if (attribs != null && index < attribs.length @@ -268,16 +258,12 @@ public class Marker extends FObjMixed { } } - /** - * Default implementation; not used - */ + /** Default implementation; not used */ public String getType(int index) { return "CDATA"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getValue(int index) { if (attribs != null && index < attribs.length @@ -289,9 +275,7 @@ public class Marker extends FObjMixed { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getIndex(String name, String namespace) { int index = -1; if (attribs != null && name != null && namespace != null) { @@ -306,9 +290,7 @@ public class Marker extends FObjMixed { return index; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getIndex(String qname) { int index = -1; if (attribs != null && qname != null) { @@ -322,23 +304,17 @@ public class Marker extends FObjMixed { return index; } - /** - * Default implementation; not used - */ + /** Default implementation; not used */ public String getType(String name, String namespace) { return "CDATA"; } - /** - * Default implementation; not used - */ + /** Default implementation; not used */ public String getType(String qname) { return "CDATA"; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getValue(String name, String namespace) { int index = getIndex(name, namespace); if (index > 0) { @@ -347,9 +323,7 @@ public class Marker extends FObjMixed { return null; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getValue(String qname) { int index = getIndex(qname); if (index > 0) { @@ -359,9 +333,7 @@ public class Marker extends FObjMixed { } } - /** - * Convenience inner class - */ + /** Convenience inner class */ private static final class MarkerAttribute { private static Map attributeCache = @@ -390,7 +362,9 @@ public class Marker extends FObjMixed { /** * Convenience method, reduces the number * of distinct MarkerAttribute instances - * + * + * @param namespace the attribute namespace + * @param qname the fully qualified name of the attribute * @param name the attribute name * @param value the attribute value * @return the single MarkerAttribute instance corresponding to @@ -409,9 +383,7 @@ public class Marker extends FObjMixed { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean equals(Object o) { if (o instanceof MarkerAttribute) { MarkerAttribute attr = (MarkerAttribute) o; diff --git a/src/java/org/apache/fop/fo/flow/MultiCase.java b/src/java/org/apache/fop/fo/flow/MultiCase.java index e568fba46..284d82d63 100644 --- a/src/java/org/apache/fop/fo/flow/MultiCase.java +++ b/src/java/org/apache/fop/fo/flow/MultiCase.java @@ -25,7 +25,8 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; /** - * Class modelling the fo:multi-case object. + * Class modelling the + * fo:multi-case object. * @todo implement validateChildNode() */ public class MultiCase extends FObj { @@ -40,7 +41,9 @@ public class MultiCase extends FObj { static boolean notImplementedWarningGiven = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public MultiCase(FONode parent) { super(parent); @@ -52,9 +55,7 @@ public class MultiCase extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); startingState = pList.get(PR_STARTING_STATE).getEnum(); @@ -62,9 +63,7 @@ public class MultiCase extends FObj { // caseTitle = pList.get(PR_CASE_TITLE); } - /** - * Return the "starting-state" property. - */ + /** @return the "starting-state" property */ public int getStartingState() { return startingState; } @@ -76,6 +75,7 @@ public class MultiCase extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_MULTI_CASE} */ public int getNameId() { return FO_MULTI_CASE; diff --git a/src/java/org/apache/fop/fo/flow/MultiProperties.java b/src/java/org/apache/fop/fo/flow/MultiProperties.java index bd3bd893e..ef015a9c1 100644 --- a/src/java/org/apache/fop/fo/flow/MultiProperties.java +++ b/src/java/org/apache/fop/fo/flow/MultiProperties.java @@ -28,7 +28,8 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:multi-properties object. + * Class modelling the + * fo:multi-properties object. */ public class MultiProperties extends FObj { // The value of properties relevant for fo:multi-properties. @@ -43,7 +44,9 @@ public class MultiProperties extends FObj { boolean hasWrapper = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public MultiProperties(FONode parent) { super(parent); @@ -55,9 +58,7 @@ public class MultiProperties extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (!hasMultiPropertySet || !hasWrapper) { missingChildElementError("(multi-property-set+, wrapper)"); @@ -66,7 +67,7 @@ public class MultiProperties extends FObj { /** * {@inheritDoc} - * XSL Content Model: (multi-property-set+, wrapper) + *
                                                                                      XSL Content Model: (multi-property-set+, wrapper) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -96,6 +97,7 @@ public class MultiProperties extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_MULTI_PROPERTIES} */ public int getNameId() { return FO_MULTI_PROPERTIES; diff --git a/src/java/org/apache/fop/fo/flow/MultiPropertySet.java b/src/java/org/apache/fop/fo/flow/MultiPropertySet.java index caa31f7b9..0736976b4 100644 --- a/src/java/org/apache/fop/fo/flow/MultiPropertySet.java +++ b/src/java/org/apache/fop/fo/flow/MultiPropertySet.java @@ -29,7 +29,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:multi-property-set object. + * Class modelling the + * fo:multi-property-set object. */ public class MultiPropertySet extends FObj { // The value of properties relevant for fo:multi-property-set. @@ -39,7 +40,9 @@ public class MultiPropertySet extends FObj { static boolean notImplementedWarningGiven = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public MultiPropertySet(FONode parent) { super(parent); @@ -51,9 +54,7 @@ public class MultiPropertySet extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); // activeState = pList.get(PR_ACTIVE_STATE); @@ -61,7 +62,7 @@ public class MultiPropertySet extends FObj { /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -77,6 +78,7 @@ public class MultiPropertySet extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_MULTI_PROPERTY_SET} */ public int getNameId() { return FO_MULTI_PROPERTY_SET; diff --git a/src/java/org/apache/fop/fo/flow/MultiSwitch.java b/src/java/org/apache/fop/fo/flow/MultiSwitch.java index 03f404aa3..81cb2aff9 100644 --- a/src/java/org/apache/fop/fo/flow/MultiSwitch.java +++ b/src/java/org/apache/fop/fo/flow/MultiSwitch.java @@ -29,7 +29,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:multi-switch object. + * Class modelling the + * fo:multi-switch object. */ public class MultiSwitch extends FObj { // The value of properties relevant for fo:multi-switch. @@ -41,7 +42,9 @@ public class MultiSwitch extends FObj { static boolean notImplementedWarningGiven = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public MultiSwitch(FONode parent) { super(parent); @@ -53,18 +56,14 @@ public class MultiSwitch extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); // autoRestore = pList.get(PR_AUTO_RESTORE); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (firstChild == null) { missingChildElementError("(multi-case+)"); @@ -73,7 +72,7 @@ public class MultiSwitch extends FObj { /** * {@inheritDoc} - * XSL Content Model: (multi-case+) + *
                                                                                      XSL Content Model: (multi-case+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -91,6 +90,7 @@ public class MultiSwitch extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_MULTI_SWITCH} */ public int getNameId() { return FO_MULTI_SWITCH; diff --git a/src/java/org/apache/fop/fo/flow/MultiToggle.java b/src/java/org/apache/fop/fo/flow/MultiToggle.java index 66442c2a7..bcb1f806a 100644 --- a/src/java/org/apache/fop/fo/flow/MultiToggle.java +++ b/src/java/org/apache/fop/fo/flow/MultiToggle.java @@ -30,7 +30,8 @@ import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:multi-toggle property. + * Class modelling the + * fo:multi-toggle property. */ public class MultiToggle extends FObj { // The value of properties relevant for fo:multi-toggle (commented out for performance). @@ -41,7 +42,9 @@ public class MultiToggle extends FObj { static boolean notImplementedWarningGiven = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public MultiToggle(FONode parent) { super(parent); @@ -53,9 +56,7 @@ public class MultiToggle extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { // prSwitchTo = pList.get(PR_SWITCH_TO); @@ -63,7 +64,7 @@ public class MultiToggle extends FObj { /** * {@inheritDoc} - * XSL Content Model: (#PCDATA|%inline;|%block;)* + *
                                                                                      XSL Content Model: (#PCDATA|%inline;|%block;)* */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -81,6 +82,7 @@ public class MultiToggle extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_MULTI_TOGGLE} */ public int getNameId() { return FO_MULTI_TOGGLE; diff --git a/src/java/org/apache/fop/fo/flow/PageNumber.java b/src/java/org/apache/fop/fo/flow/PageNumber.java index cc51dd28a..3b91c6b44 100644 --- a/src/java/org/apache/fop/fo/flow/PageNumber.java +++ b/src/java/org/apache/fop/fo/flow/PageNumber.java @@ -36,7 +36,8 @@ import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.SpaceProperty; /** - * Class modelling the fo:page-number object. + * Class modelling the + * fo:page-number object. */ public class PageNumber extends FObj { // The value of properties relevant for fo:page-number. @@ -71,15 +72,15 @@ public class PageNumber extends FObj { private Color color; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public PageNumber(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); @@ -97,24 +98,20 @@ public class PageNumber extends FObj { color = pList.get(Constants.PR_COLOR).getColor(getUserAgent()); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startPageNumber(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { getFOEventHandler().endPageNumber(this); } /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -143,37 +140,27 @@ public class PageNumber extends FObj { return textDecoration; } - /** - * @return the "alignment-adjust" property - */ + /** @return the "alignment-adjust" property */ public Length getAlignmentAdjust() { return alignmentAdjust; } - /** - * @return the "alignment-baseline" property - */ + /** @return the "alignment-baseline" property */ public int getAlignmentBaseline() { return alignmentBaseline; } - /** - * @return the "baseline-shift" property - */ + /** @return the "baseline-shift" property */ public Length getBaselineShift() { return baselineShift; } - /** - * @return the "dominant-baseline" property - */ + /** @return the "dominant-baseline" property */ public int getDominantBaseline() { return dominantBaseline; } - /** - * @return the "line-height" property - */ + /** @return the "line-height" property */ public SpaceProperty getLineHeight() { return lineHeight; } @@ -183,7 +170,10 @@ public class PageNumber extends FObj { return "page-number"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_PAGE_NUMBER} + */ public int getNameId() { return FO_PAGE_NUMBER; } diff --git a/src/java/org/apache/fop/fo/flow/PageNumberCitation.java b/src/java/org/apache/fop/fo/flow/PageNumberCitation.java index feea07433..b31bc9a11 100644 --- a/src/java/org/apache/fop/fo/flow/PageNumberCitation.java +++ b/src/java/org/apache/fop/fo/flow/PageNumberCitation.java @@ -23,7 +23,8 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; /** - * Class modelling the fo:page-number-citation object. + * Class modelling the + * fo:page-number-citation object. * This inline fo is replaced with the text for a page number. * The page number used is the page that contains the start of the * block referenced with the ref-id attribute. @@ -32,7 +33,8 @@ public class PageNumberCitation extends AbstractPageNumberCitation { /** * Main constructor - * @param parent FONode that is the parent of this object + * + * @param parent {@link FONode} that is the parent of this object */ public PageNumberCitation(FONode parent) { super(parent); @@ -55,7 +57,10 @@ public class PageNumberCitation extends AbstractPageNumberCitation { return "page-number-citation"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_PAGE_NUMBER_CITATION} + */ public int getNameId() { return FO_PAGE_NUMBER_CITATION; } diff --git a/src/java/org/apache/fop/fo/flow/PageNumberCitationLast.java b/src/java/org/apache/fop/fo/flow/PageNumberCitationLast.java index a9b5b90df..9e98c06be 100644 --- a/src/java/org/apache/fop/fo/flow/PageNumberCitationLast.java +++ b/src/java/org/apache/fop/fo/flow/PageNumberCitationLast.java @@ -23,7 +23,8 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; /** - * Class modelling the fo:page-number-citation-last object from XSL 1.1. + * Class modelling the + * fo:page-number-citation-last object from XSL 1.1. * This inline fo is replaced with the text for a page number. * The page number used is the page that contains the end of the * block referenced with the ref-id attribute. @@ -33,7 +34,8 @@ public class PageNumberCitationLast extends AbstractPageNumberCitation { /** * Main constructor - * @param parent the parent FO node + * + * @param parent the parent {@link FONode} */ public PageNumberCitationLast(FONode parent) { super(parent); @@ -56,7 +58,10 @@ public class PageNumberCitationLast extends AbstractPageNumberCitation { return "page-number-citation-last"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_PAGE_NUMBER_CITATION_LAST} + */ public int getNameId() { return FO_PAGE_NUMBER_CITATION_LAST; } diff --git a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java index ea6b6f1c5..0283dc7da 100644 --- a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java @@ -21,8 +21,6 @@ package org.apache.fop.fo.flow; import java.util.Iterator; -import org.xml.sax.Locator; - import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FOText; @@ -32,6 +30,7 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableFObj; +import org.xml.sax.Locator; /** * Class modelling the fo:retrieve-marker object. @@ -48,9 +47,10 @@ public class RetrieveMarker extends FObjMixed { private PropertyList propertyList; /** - * Create a retrieve marker object. - * @param parent FONode that is the parent of this object - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a new RetrieveMarker instance that is a + * child of the given {@link FONode}. + * + * @param parent {@link FONode} that is the parent of this object */ public RetrieveMarker(FONode parent) { super(parent); @@ -59,26 +59,27 @@ public class RetrieveMarker extends FObjMixed { /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { if (findAncestor(FO_STATIC_CONTENT) < 0) { - invalidChildError(locator, getParent().getName(), FO_URI, getName(), + invalidChildError(locator, getParent().getName(), FO_URI, getName(), "rule.retrieveMarkerDescendatOfStaticContent"); } retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME).getString(); retrievePosition = pList.get(PR_RETRIEVE_POSITION).getEnum(); retrieveBoundary = pList.get(PR_RETRIEVE_BOUNDARY).getEnum(); - + if (retrieveClassName == null || retrieveClassName.equals("")) { missingPropertyError("retrieve-class-name"); } - + propertyList = pList.getParentPropertyList(); + super.bind(pList); } - + /** * {@inheritDoc} * XSL Content Model: empty */ - protected void validateChildNode(Locator loc, String nsURI, String localName) + protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); @@ -105,7 +106,7 @@ public class RetrieveMarker extends FObjMixed { public int getRetrieveBoundary() { return retrieveBoundary; } - + private PropertyList createPropertyListFor(FObj fo, PropertyList parent) { return getFOEventHandler().getPropertyListMaker().make(fo, parent); } @@ -120,7 +121,7 @@ public class RetrieveMarker extends FObjMixed { Marker.MarkerPropertyList pList; PropertyList newPropertyList = createPropertyListFor( (FObj) newChild, parentPropertyList); - + pList = marker.getPropertyListFor(child); newChild.processNode( child.getLocalName(), @@ -159,7 +160,7 @@ public class RetrieveMarker extends FObjMixed { } } } - + /** * Clone the FO nodes in the parent iterator, * attach the new nodes to the new parent, @@ -178,7 +179,7 @@ public class RetrieveMarker extends FObjMixed { FONode child; while (parentIter.hasNext()) { child = (FONode) parentIter.next(); - cloneSingleNode(child, newParent, + cloneSingleNode(child, newParent, marker, parentPropertyList); } } @@ -191,14 +192,14 @@ public class RetrieveMarker extends FObjMixed { currentTextNode = null; firstChild = null; } - cloneSubtree(marker.getChildNodes(), this, + cloneSubtree(marker.getChildNodes(), this, marker, propertyList); handleWhiteSpaceFor(this); } /** * Clone the subtree of the given marker - * + * * @param marker the marker that is to be cloned */ public void bindMarker(Marker marker) { @@ -213,7 +214,6 @@ public class RetrieveMarker extends FObjMixed { } else if (log.isDebugEnabled()) { log.debug("Empty marker retrieved..."); } - return; } /** {@inheritDoc} */ @@ -221,7 +221,10 @@ public class RetrieveMarker extends FObjMixed { return "retrieve-marker"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_RETRIEVE_MARKER} + */ public int getNameId() { return FO_RETRIEVE_MARKER; } diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index 87582fb47..4b1cfeeac 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -28,8 +28,9 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:wrapper object. - * The wrapper object serves as a property holder for + * Class modelling the + * fo:wrapper object. + * The fo:wrapper object serves as a property holder for * its child node objects. */ public class Wrapper extends FObjMixed { @@ -41,7 +42,9 @@ public class Wrapper extends FObjMixed { private boolean inlineChildrenAllowed = false; /** - * @param parent FONode that is the parent of this object + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public Wrapper(FONode parent) { super(parent); @@ -101,7 +104,10 @@ public class Wrapper extends FObjMixed { return "wrapper"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_WRAPPER} + */ public int getNameId() { return FO_WRAPPER; } diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index c1ef3857c..69d5fbb9d 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -39,7 +39,8 @@ import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.fo.properties.TableColLength; /** - * Class modelling the fo:table object. + * Class modelling the + * fo:table object. */ public class Table extends TableFObj implements ColumnNumberManagerHolder { @@ -96,7 +97,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { private PropertyList propList; /** - * @param parent FONode that is the parent of this object + * Construct a Table instance with the given {@link FONode} + * as parent. + * + * @param parent {@link FONode} that is the parent of this object */ public Table(FONode parent) { super(parent); @@ -163,7 +167,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { /** * {@inheritDoc} - * XSL Content Model: (marker*,table-column*,table-header?,table-footer?,table-body+) + *
                                                                                      XSL Content Model: (marker*,table-column*,table-header?,table-footer?,table-body+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -255,7 +259,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { if (!inMarker()) { addColumnNode((TableColumn) child); } else { - columns.add((TableColumn) child); + columns.add(child); } break; case FO_TABLE_HEADER: @@ -344,7 +348,6 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { * used for determining initial values for column-number * * @param col the column to add - * @throws FOPException */ private void addColumnNode(TableColumn col) { @@ -518,7 +521,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { return "table"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE} + */ public int getNameId() { return FO_TABLE; } diff --git a/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java b/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java index 6dabf37db..7c45c21f2 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java +++ b/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java @@ -28,7 +28,8 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:table-and-caption property. + * Class modelling the + * fo:table-and-caption property. * @todo needs implementation */ public class TableAndCaption extends FObj { @@ -56,6 +57,8 @@ public class TableAndCaption extends FObj { private boolean tableFound = false; /** + * Create a TableAndCaption instance with the given {@link FONode} + * as parent. * @param parent FONode that is the parent of this object */ public TableAndCaption(FONode parent) { @@ -81,7 +84,7 @@ public class TableAndCaption extends FObj { /** * {@inheritDoc} - * XSL Content Model: marker* table-caption? table + *
                                                                                      XSL Content Model: marker* table-caption? table */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -120,6 +123,7 @@ public class TableAndCaption extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_AND_CAPTION} */ public int getNameId() { return FO_TABLE_AND_CAPTION; diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index 4e1673568..0214e7336 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -33,7 +33,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; /** - * Class modelling the fo:table-body object. + * Class modelling the + * fo:table-body object. */ public class TableBody extends TableCellContainer { // The value of properties relevant for fo:table-body. @@ -63,23 +64,21 @@ public class TableBody extends TableCellContainer { private List rowGroups = new LinkedList(); /** + * Create a TableBody instance with the given {@link FONode} + * as parent. * @param parent FONode that is the parent of the object */ public TableBody(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); super.bind(pList); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { @@ -99,17 +98,13 @@ public class TableBody extends TableCellContainer { super.processNode(elementName, locator, attlist, pList); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startBody(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endOfNode() throws FOPException { if (!inMarker()) { @@ -150,8 +145,8 @@ public class TableBody extends TableCellContainer { } /** - * {@inheritDoc} String, String) - * XSL Content Model: marker* (table-row+|table-cell+) + * {@inheritDoc} + *
                                                                                      XSL Content Model: marker* (table-row+|table-cell+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -180,9 +175,7 @@ public class TableBody extends TableCellContainer { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { if (!inMarker()) { switch (child.getNameId()) { @@ -236,7 +229,9 @@ public class TableBody extends TableCellContainer { } /** - * @return the Common Border, Padding, and Background Properties. + * Get the {@link CommonBorderPaddingBackground} instance attached + * to this TableBody. + * @return the {@link CommonBorderPaddingBackground} instance. */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; @@ -249,6 +244,7 @@ public class TableBody extends TableCellContainer { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_BODY} */ public int getNameId() { return FO_TABLE_BODY; diff --git a/src/java/org/apache/fop/fo/flow/table/TableCaption.java b/src/java/org/apache/fop/fo/flow/table/TableCaption.java index 416ef16ed..80fccb236 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCaption.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCaption.java @@ -30,7 +30,8 @@ import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:table-caption object. + * Class modelling the + * fo:table-caption object. */ public class TableCaption extends FObj { // The value of properties relevant for fo:table-caption. @@ -51,7 +52,9 @@ public class TableCaption extends FObj { static boolean notImplementedWarningGiven = false; /** - * @param parent FONode that is the parent of this object + * Create a TableCaption instance with the given {@link FONode} + * as parent. + * @param parent {@link FONode} that is the parent of this object */ public TableCaption(FONode parent) { super(parent); @@ -63,16 +66,12 @@ public class TableCaption extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (firstChild == null) { missingChildElementError("marker* (%block;)"); @@ -81,7 +80,7 @@ public class TableCaption extends FObj { /** * {@inheritDoc} - * XSL Content Model: marker* (%block;) + *
                                                                                      XSL Content Model: marker* (%block;) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -105,6 +104,7 @@ public class TableCaption extends FObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_CAPTION} */ public int getNameId() { return FO_TABLE_CAPTION; diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java index 78e35eb52..b1dfd86c3 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCell.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java @@ -30,7 +30,8 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; /** - * Class modelling the fo:table-cell object. + * Class modelling the + * fo:table-cell object. */ public class TableCell extends TableFObj { // The value of properties relevant for fo:table-cell. @@ -60,7 +61,9 @@ public class TableCell extends TableFObj { private boolean blockItemFound = false; /** - * @param parent FONode that is the parent of this object + * Create a TableCell instance with the given {@link FONode} + * as parent. + * @param parent {@link FONode} that is the parent of this object */ public TableCell(FONode parent) { super(parent); @@ -87,9 +90,7 @@ public class TableCell extends TableFObj { width = pList.get(PR_WIDTH).getLength(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startCell(this); @@ -115,7 +116,7 @@ public class TableCell extends TableFObj { /** * {@inheritDoc} - * XSL Content Model: marker* (%block;)+ + *
                                                                                      XSL Content Model: marker* (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -146,25 +147,32 @@ public class TableCell extends TableFObj { } /** - * @return the Common Border, Padding, and Background Properties. + * Get the {@link CommonBorderPaddingBackground} instance + * attached to this TableCell. + * @return the {@link CommonBorderPaddingBackground} instance */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return this.commonBorderPaddingBackground; } /** + * Get the value for the column-number property. * @return the "column-number" property. */ public int getColumnNumber() { return columnNumber; } - /** @return true if "empty-cells" is "show" */ + /** + * Get the value for the empty-cells property. + * @return true if "empty-cells" is "show" + */ public boolean showEmptyCells() { return (this.emptyCells == EN_SHOW); } /** + * Get the value for the number-columns-spanned property * @return the "number-columns-spanned" property. */ public int getNumberColumnsSpanned() { @@ -172,6 +180,7 @@ public class TableCell extends TableFObj { } /** + * Get the value for the number-rows-spanned property * @return the "number-rows-spanned" property. */ public int getNumberRowsSpanned() { @@ -179,30 +188,41 @@ public class TableCell extends TableFObj { } /** + * Get the value for the block-progression-dimension property * @return the "block-progression-dimension" property. */ public LengthRangeProperty getBlockProgressionDimension() { return blockProgressionDimension; } - /** @return the display-align property. */ + /** + * Get the value for the display-align property + * @return the display-align property. + */ public int getDisplayAlign() { return displayAlign; } /** + * Get the value for the width property * @return the "width" property. */ public Length getWidth() { return width; } - /** @return true if the cell starts a row. */ + /** + * Get the value for the starts-row property + * @return true if the cell starts a row. + */ public boolean startsRow() { return (startsRow == EN_TRUE); } - /** @return true if the cell ends a row. */ + /** + * Get the value for the ends-row property + * @return true if the cell ends a row. + */ public boolean endsRow() { return (endsRow == EN_TRUE); } @@ -214,6 +234,7 @@ public class TableCell extends TableFObj { /** * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_CELL} */ public final int getNameId() { return FO_TABLE_CELL; diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java index e6f6b420e..0ace2c311 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java +++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java @@ -34,7 +34,8 @@ import org.apache.fop.fo.properties.TableColLength; import org.apache.fop.layoutmgr.table.CollapsingBorderModel; /** - * Class modelling the fo:table-column object. + * Class modelling the + * fo:table-column object. */ public class TableColumn extends TableFObj { // The value of properties relevant for fo:table-column. @@ -51,13 +52,19 @@ public class TableColumn extends TableFObj { private PropertyList pList = null; /** - * @param parent FONode that is the parent of this object + * Create a TableColumn instance with the given {@link FONode} + * as parent. + * + * @param parent {@link FONode} that is the parent of this object */ public TableColumn(FONode parent) { this(parent, false); } /** + * Create a TableColumn instance with the given {@link FONode} + * as parent + * * @param parent FONode that is the parent of this object * @param implicit true if this table-column has automatically been created (does not * correspond to an explicit fo:table-column in the input document) @@ -68,9 +75,7 @@ public class TableColumn extends TableFObj { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue(); @@ -117,9 +122,7 @@ public class TableColumn extends TableFObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startColumn(this); @@ -146,7 +149,7 @@ public class TableColumn extends TableFObj { /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) @@ -157,13 +160,17 @@ public class TableColumn extends TableFObj { } /** - * @return the Common Border, Padding, and Background Properties. + * Get the {@link CommonBorderPaddingBackground} instance + * attached to this TableColumn. + * @return the {@link CommonBorderPaddingBackground} instance */ public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { return commonBorderPaddingBackground; } /** + * Get a {@link Length} instance corresponding to the + * column-width property. * @return the "column-width" property. */ public Length getColumnWidth() { @@ -179,6 +186,7 @@ public class TableColumn extends TableFObj { } /** + * Get the value of the column-number property * @return the "column-number" property. */ public int getColumnNumber() { @@ -187,7 +195,7 @@ public class TableColumn extends TableFObj { /** * Used for setting the column-number for an implicit column - * @param columnNumber + * @param columnNumber the number to set */ protected void setColumnNumber(int columnNumber) { this.columnNumber = columnNumber; @@ -208,7 +216,10 @@ public class TableColumn extends TableFObj { return "table-column"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_COLUMN} + */ public int getNameId() { return FO_TABLE_COLUMN; } @@ -244,10 +255,10 @@ public class TableColumn extends TableFObj { /** * Retrieve a property value through its Id; used by * from-table-column() function - * + * * @param propId the id for the property to retrieve * @return the requested Property - * @throws PropertyException if there is a problem evaluating the property + * @throws PropertyException if there is a problem evaluating the property */ public Property getProperty(int propId) throws PropertyException { return this.pList.get(propId); diff --git a/src/java/org/apache/fop/fo/flow/table/TableFooter.java b/src/java/org/apache/fop/fo/flow/table/TableFooter.java index e886d2ee1..d05824e95 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFooter.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFooter.java @@ -25,36 +25,33 @@ import org.apache.fop.fo.FONode; /** - * Class modelling the fo:table-footer object. + * Class modelling the + * fo:table-footer object. */ public class TableFooter extends TableBody { /** - * @param parent FONode that is the parent of this object + * Create a TableFooter instance with the given {@link FONode} + * as parent. + * + * @param parent {@link FONode} that is the parent of this object */ public TableFooter(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startOfNode() throws FOPException { super.startOfNode(); - //getFOEventHandler().startBody(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endOfNode() throws FOPException { -// getFOEventHandler().endFooter(this); if (!(tableRowsFound || tableCellsFound)) { missingChildElementError("marker* (table-row+|table-cell+)"); } else { finishLastRowGroup(); } -// convertCellsToRows(); } /** {@inheritDoc} */ @@ -62,7 +59,10 @@ public class TableFooter extends TableBody { return "table-footer"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_FOOTER} + */ public int getNameId() { return FO_TABLE_FOOTER; } diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java index e248a0f7e..252ba1b8b 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java +++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java @@ -25,36 +25,32 @@ import org.apache.fop.fo.FONode; /** - * Class modelling the fo:table-header object. + * Class modelling the + * fo:table-header object. */ public class TableHeader extends TableBody { /** - * @param parent FONode that is the parent of this object + * Create a TableHeader instance with the given {@link FONode} + * as parent. + * @param parent {@link FONode} that is the parent of this object */ public TableHeader(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startOfNode() throws FOPException { super.startOfNode(); - //getFOEventHandler().startHeader(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endOfNode() throws FOPException { -// getFOEventHandler().endHeader(this); if (!(tableRowsFound || tableCellsFound)) { missingChildElementError("marker* (table-row+|table-cell+)"); } else { finishLastRowGroup(); } -// convertCellsToRows(); } /** {@inheritDoc} */ @@ -62,7 +58,10 @@ public class TableHeader extends TableBody { return "table-header"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_HEADER} + */ public int getNameId() { return FO_TABLE_HEADER; } diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java index e5261614b..bf7b16dca 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableRow.java +++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java @@ -32,7 +32,8 @@ import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; /** - * Class modelling the fo:table-row object. + * Class modelling the + * fo:table-row object. */ public class TableRow extends TableCellContainer { // The value of properties relevant for fo:table-row. @@ -52,7 +53,9 @@ public class TableRow extends TableCellContainer { // End of property values /** - * @param parent FONode that is the parent of this object + * Create a TableRow instance with the given {@link FONode} + * as parent. + * @param parent {@link FONode} that is the parent of this object */ public TableRow(FONode parent) { super(parent); @@ -83,9 +86,7 @@ public class TableRow extends TableCellContainer { super.processNode(elementName, locator, attlist, pList); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { if (!inMarker()) { TableCell cell = (TableCell) child; @@ -95,17 +96,13 @@ public class TableRow extends TableCellContainer { super.addChildNode(child); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startRow(this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endOfNode() throws FOPException { if (firstChild == null) { missingChildElementError("(table-cell+)"); @@ -119,7 +116,7 @@ public class TableRow extends TableCellContainer { /** * {@inheritDoc} String, String) - * XSL Content Model: (table-cell+) + *
                                                                                      XSL Content Model: (table-cell+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) @@ -141,7 +138,7 @@ public class TableRow extends TableCellContainer { return true; } - /** {inheritDoc} */ + /** {@inheritDoc} */ protected void setCollapsedBorders() { TableBody body = (TableBody) parent; createBorder(CommonBorderPaddingBackground.START, body); @@ -231,7 +228,10 @@ public class TableRow extends TableCellContainer { return "table-row"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_ROW} + */ public int getNameId() { return FO_TABLE_ROW; } diff --git a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java index 578d74c4d..f0928a8ca 100644 --- a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java @@ -26,15 +26,15 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; /** - * Abstract base class for the fo:page-sequence formatting object and the fox:external-document - * extension object. + * Abstract base class for the + * fo:page-sequence formatting object and the + * + * fox:external-document extension object. */ public abstract class AbstractPageSequence extends FObj { // The value of properties relevant for fo:page-sequence. - /** the initial-page-number value */ protected Numeric initialPageNumber; - /** the force-page-count value */ protected int forcePageCount; private String format; private int letterValue; @@ -45,13 +45,13 @@ public abstract class AbstractPageSequence extends FObj { private PageNumberGenerator pageNumberGenerator; - /** the first page number generated by the page sequence */ protected int startingPageNumber = 0; /** - * Create a page sequence FO node. + * Create an AbstractPageSequence that is a child + * of the given parent {@link FONode}. * - * @param parent the parent FO node + * @param parent the parent {@link FONode} */ public AbstractPageSequence(FONode parent) { super(parent); @@ -76,10 +76,6 @@ public abstract class AbstractPageSequence extends FObj { } - /** {@inheritDoc} */ - protected void endOfNode() throws FOPException { - } - /** * Initialize the current page number for the start of the page sequence. */ @@ -132,18 +128,25 @@ public abstract class AbstractPageSequence extends FObj { return (Root)this.getParent(); } - /** @return the force-page-count value */ + /** + * Get the value of the force-page-count property. + * @return the force-page-count value + */ public int getForcePageCount() { return forcePageCount; } - /** @return the initial-page-number property value */ + /** + * Get the value of the initial-page-number property. + * @return the initial-page-number property value + */ public Numeric getInitialPageNumber() { return initialPageNumber; } /** - * @return the "reference-orientation" property. + * Get the value of the reference-orientation property. + * @return the "reference-orientation" property * @since XSL 1.1 */ public int getReferenceOrientation() { diff --git a/src/java/org/apache/fop/fo/pagination/ColorProfile.java b/src/java/org/apache/fop/fo/pagination/ColorProfile.java index 6067b55c5..0af1aa42d 100644 --- a/src/java/org/apache/fop/fo/pagination/ColorProfile.java +++ b/src/java/org/apache/fop/fo/pagination/ColorProfile.java @@ -19,16 +19,18 @@ package org.apache.fop.fo.pagination; -import org.xml.sax.Locator; - import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.xml.sax.Locator; + /** - * The fo:color-profile formatting object. + * Class modelling the + * fo:color-profile object. + * * This loads the color profile when needed and resolves a requested color. */ public class ColorProfile extends FObj { @@ -39,9 +41,9 @@ public class ColorProfile extends FObj { // End of property values /** - * Creates a new color-profile element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public ColorProfile(FONode parent) { super(parent); @@ -56,7 +58,7 @@ public class ColorProfile extends FObj { /** * {@inheritDoc} - XSL 1.0/FOP: EMPTY (no child nodes permitted) + *
                                                                                      XSL 1.0/FOP: EMPTY (no child nodes permitted) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -66,8 +68,7 @@ public class ColorProfile extends FObj { } /** - * Return the "color-profile-name" property. - * @return the color-profile-name property + * @return the "color-profile-name" property. */ public String getColorProfileName() { return colorProfileName; @@ -78,7 +79,10 @@ public class ColorProfile extends FObj { return "color-profile"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_COLOR_PROFILE} + */ public int getNameId() { return FO_COLOR_PROFILE; } @@ -86,7 +90,7 @@ public class ColorProfile extends FObj { /** * Get src attribute * - * @return Value of color-profile src attribute + * @return value of color-profile src attribute */ public String getSrc() { return this.src; diff --git a/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java b/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java index a13808324..7c76109f4 100644 --- a/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/ConditionalPageMasterReference.java @@ -29,7 +29,9 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * A conditional-page-master-reference formatting object. + * Class modelling the + * fo:conditional-page-master-reference object. + * * This is a reference to a page master with a set of conditions. * The conditions must be satisfied for the referenced master to * be used. @@ -45,9 +47,10 @@ public class ConditionalPageMasterReference extends FObj { // End of property values /** - * Creates a new conditional-page-master-reference element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a ConditionalPageMasterReference instance that is a + * child of the given {@link FONode}. + * + * @param parent {@link FONode} that is the parent of this object */ public ConditionalPageMasterReference(FONode parent) { super(parent); @@ -76,13 +79,11 @@ public class ConditionalPageMasterReference extends FObj { /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI)) { - invalidChildError(loc, nsURI, localName); - } + throws ValidationException { + invalidChildError(loc, nsURI, localName); } /** @@ -150,12 +151,18 @@ public class ConditionalPageMasterReference extends FObj { return true; } - /** @return the "master-reference" property. */ + /** + * Get the value for the master-reference property. + * @return the "master-reference" property + */ public String getMasterReference() { return masterReference; } - /** @return the page-position property value */ + /** + * Get the value for the page-position property. + * @return the page-position property value + */ public int getPagePosition() { return this.pagePosition; } @@ -165,7 +172,10 @@ public class ConditionalPageMasterReference extends FObj { return "conditional-page-master-reference"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_CONDITIONAL_PAGE_MASTER_REFERENCE} + */ public int getNameId() { return FO_CONDITIONAL_PAGE_MASTER_REFERENCE; } diff --git a/src/java/org/apache/fop/fo/pagination/Declarations.java b/src/java/org/apache/fop/fo/pagination/Declarations.java index 3eec2897a..eb24cffe0 100644 --- a/src/java/org/apache/fop/fo/pagination/Declarations.java +++ b/src/java/org/apache/fop/fo/pagination/Declarations.java @@ -31,7 +31,9 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Declarations formatting object. + * Class modelling the + * fo:declarations object. + * * A declarations formatting object holds a set of color-profiles * and optionally additional non-XSL namespace elements. * The color-profiles are held in a hashmap for use with color-profile @@ -42,7 +44,6 @@ public class Declarations extends FObj { private Map colorProfiles = null; /** - * Creates a new declarations element. * @param parent FONode that is the parent of this object */ public Declarations(FONode parent) { @@ -57,13 +58,13 @@ public class Declarations extends FObj { /** * {@inheritDoc} - * XSL 1.0: (color-profile)+ (and non-XSL NS nodes) - * FOP/XSL 1.1: (color-profile)* (and non-XSL NS nodes) + *
                                                                                      XSL 1.0: (color-profile)+ (and non-XSL NS nodes) + *
                                                                                      FOP/XSL 1.1: (color-profile)* (and non-XSL NS nodes) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { - if (!localName.equals("color-profile")) { + if (!localName.equals("color-profile")) { invalidChildError(loc, nsURI, localName); } } // anything outside of XSL namespace is OK. @@ -112,7 +113,10 @@ public class Declarations extends FObj { return "declarations"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_DECLARATIONS} + */ public int getNameId() { return FO_DECLARATIONS; } diff --git a/src/java/org/apache/fop/fo/pagination/Flow.java b/src/java/org/apache/fop/fo/pagination/Flow.java index 2ee77ff0a..8e114c47f 100644 --- a/src/java/org/apache/fop/fo/pagination/Flow.java +++ b/src/java/org/apache/fop/fo/pagination/Flow.java @@ -28,7 +28,9 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the fo:flow object. + * Class modelling the + * fo:flow object. + * */ public class Flow extends FObj { // The value of properties relevant for fo:flow. @@ -39,7 +41,8 @@ public class Flow extends FObj { private boolean blockItemFound = false; /** - * @param parent FONode that is the parent of this object + * Create a Flow instance that is a child of the given {@link FONode}. + * @param parent the {@link FONode} that is the parent of this object */ public Flow(FONode parent) { super(parent); @@ -86,7 +89,7 @@ public class Flow extends FObj { /** * {@inheritDoc} - * XSL Content Model: marker* (%block;)+ + *
                                                                                      XSL Content Model: marker* (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -103,7 +106,10 @@ public class Flow extends FObj { } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return true (Flow can generate reference areas) + */ public boolean generatesReferenceAreas() { return true; } @@ -118,7 +124,10 @@ public class Flow extends FObj { return "flow"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_FLOW} + */ public int getNameId() { return FO_FLOW; } diff --git a/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java b/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java index 1b57be57d..7f081579d 100644 --- a/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java +++ b/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java @@ -32,7 +32,9 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * The layout-master-set formatting object. + * Class modelling the + * fo:layout-master-set object. + * * This class maintains the set of simple page master and * page sequence masters. * The masters are stored so that the page sequence can obtain @@ -46,9 +48,10 @@ public class LayoutMasterSet extends FObj { private Map pageSequenceMasters; /** - * Creates a new layout-master-set element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a LayoutMasterSet instance that is a child of the given + * parent {@link FONode}. + * + * @param parent {@link FONode} that is the parent of this object */ public LayoutMasterSet(FONode parent) { super(parent); @@ -76,7 +79,7 @@ public class LayoutMasterSet extends FObj { /** * {@inheritDoc} - XSL/FOP: (simple-page-master|page-sequence-master)+ + *
                                                                                      XSL/FOP: (simple-page-master|page-sequence-master)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -205,7 +208,10 @@ public class LayoutMasterSet extends FObj { return "layout-master-set"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_LAYOUT_MASTER_SET} + */ public int getNameId() { return FO_LAYOUT_MASTER_SET; } diff --git a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java index b6c8c0f6b..a16514705 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java @@ -32,7 +32,9 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.layoutmgr.BlockLevelEventProducer; /** - * The page-sequence-master formatting object. + * Class modelling the + * fo:page-sequence-master object. + * * This class handles a list of subsequence specifiers * which are simple or complex references to page-masters. */ @@ -54,17 +56,16 @@ public class PageSequenceMaster extends FObj { // but the actual FO's are MasterReferences. /** - * Creates a new page-sequence-master element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a PageSequenceMaster instance that is a child of the + * given {@link FONode}. + * + * @param parent {@link FONode} that is the parent of this object */ public PageSequenceMaster(FONode parent) { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { masterName = pList.get(PR_MASTER_NAME).getString(); @@ -73,18 +74,14 @@ public class PageSequenceMaster extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void startOfNode() throws FOPException { subSequenceSpecifiers = new java.util.ArrayList(); layoutMasterSet = parent.getRoot().getLayoutMasterSet(); layoutMasterSet.addPageSequenceMaster(masterName, this); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (firstChild == null) { missingChildElementError("(single-page-master-reference|" @@ -94,22 +91,22 @@ public class PageSequenceMaster extends FObj { /** * {@inheritDoc} - * XSL/FOP: (single-page-master-reference|repeatable-page-master-reference| + *
                                                                                      XSL/FOP: (single-page-master-reference|repeatable-page-master-reference| * repeatable-page-master-alternatives)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { - if (!localName.equals("single-page-master-reference") - && !localName.equals("repeatable-page-master-reference") - && !localName.equals("repeatable-page-master-alternatives")) { + if (!"single-page-master-reference".equals(localName) + && !"repeatable-page-master-reference".equals(localName) + && !"repeatable-page-master-alternatives".equals(localName)) { invalidChildError(loc, nsURI, localName); } } } /** - * Adds a new subsequence specifier to the page sequence master. + * Adds a new suqsequence specifier to the page sequence master. * @param pageMasterReference the subsequence to add */ protected void addSubsequenceSpecifier(SubSequenceSpecifier pageMasterReference) { @@ -165,20 +162,14 @@ public class PageSequenceMaster extends FObj { /** @return true if the page-sequence-master has a page-master with page-position="last" */ public boolean hasPagePositionLast() { - if (currentSubSequence != null) { - return currentSubSequence.hasPagePositionLast(); - } else { - return false; - } + return (currentSubSequence != null + && currentSubSequence.hasPagePositionLast()); } /** @return true if the page-sequence-master has a page-master with page-position="only" */ public boolean hasPagePositionOnly() { - if (currentSubSequence != null) { - return currentSubSequence.hasPagePositionOnly(); - } else { - return false; - } + return (currentSubSequence != null + && currentSubSequence.hasPagePositionOnly()); } /** @@ -240,7 +231,10 @@ public class PageSequenceMaster extends FObj { return "page-sequence-master"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_PAGE_SEQUENCE_MASTER} + */ public int getNameId() { return FO_PAGE_SEQUENCE_MASTER; } diff --git a/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java b/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java index 0b3cff276..f8a37d8c0 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java @@ -22,15 +22,15 @@ package org.apache.fop.fo.pagination; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * The fo:page-sequence-wrapper formatting object, first introduced - * in the XSL 1.1 WD. Prototype version only, subject to change as - * XSL 1.1 WD evolves. + * Class modelling the + * fo:page-sequence-wrapper object, first introduced + * in the XSL 1.1 WD. */ public class PageSequenceWrapper extends FObj { // The value of properties relevant for this FO @@ -39,8 +39,10 @@ public class PageSequenceWrapper extends FObj { // End of property values /** - * Creates a new page-sequence-wrapper element. - * @param parent FONode that is the parent of this object + * Create a PageSequenceWrapper instance that is a child of + * the given parent {@link FONode}. + * + * @param parent {@link FONode} that is the parent of this object */ public PageSequenceWrapper(FONode parent) { super(parent); @@ -55,7 +57,7 @@ public class PageSequenceWrapper extends FObj { /** * {@inheritDoc} - XSL/FOP: (bookmark+) + *
                                                                                      XSL/FOP: (bookmark+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -67,12 +69,18 @@ public class PageSequenceWrapper extends FObj { } } - /** @return the "index-class" property. */ + /** + * Get the value of the index-class property. + * @return the "index-class" property + */ public String getIndexClass() { return indexClass; } - /** @return the "index-key" property. */ + /** + * Get the value of the index-key property. + * @return the "index-key" property + */ public String getIndexKey() { return indexKey; } @@ -82,7 +90,10 @@ public class PageSequenceWrapper extends FObj { return "page-sequence-wrapper"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_PAGE_SEQUENCE_WRAPPER} + */ public int getNameId() { return FO_PAGE_SEQUENCE_WRAPPER; } diff --git a/src/java/org/apache/fop/fo/pagination/Region.java b/src/java/org/apache/fop/fo/pagination/Region.java index ded86514b..753e8f735 100644 --- a/src/java/org/apache/fop/fo/pagination/Region.java +++ b/src/java/org/apache/fop/fo/pagination/Region.java @@ -30,10 +30,11 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; /** - * This is an abstract base class for pagination regions + * This is an abstract base class for pagination regions. */ public abstract class Region extends FObj { // The value of properties relevant for fo:region @@ -49,9 +50,9 @@ public abstract class Region extends FObj { private SimplePageMaster layoutMaster; /** - * Creates a new Region. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ protected Region(FONode parent) { super(parent); @@ -81,7 +82,7 @@ public abstract class Region extends FObj { } //TODO do we need context for getBPPaddingAndBorder() and getIPPaddingAndBorder()? - if ((getCommonBorderPaddingBackground().getBPPaddingAndBorder(false, null) != 0 + if ((getCommonBorderPaddingBackground().getBPPaddingAndBorder(false, null) != 0 || getCommonBorderPaddingBackground().getIPPaddingAndBorder(false, null) != 0)) { getFOValidationEventProducer().nonZeroBorderPaddingOnRegion(this, getName(), regionName, true, getLocator()); @@ -90,7 +91,7 @@ public abstract class Region extends FObj { /** * {@inheritDoc} String, String) - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { diff --git a/src/java/org/apache/fop/fo/pagination/RegionAfter.java b/src/java/org/apache/fop/fo/pagination/RegionAfter.java index 2852358b5..91aadce76 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionAfter.java +++ b/src/java/org/apache/fop/fo/pagination/RegionAfter.java @@ -29,14 +29,15 @@ import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.SimplePercentBaseContext; /** - * The fo:region-after element. + * Class modelling the + * fo:region-after object. */ public class RegionAfter extends RegionBA { /** - * Creates a new region-after element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a RegionAfter instance that is a child of the + * given parent {@link FONode}. + * @param parent the {@link FONode} that is to be the parent */ public RegionAfter(FONode parent) { super(parent); @@ -92,7 +93,10 @@ public class RegionAfter extends RegionBA { return "region-after"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_REGION_AFTER} + */ public int getNameId() { return FO_REGION_AFTER; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionBA.java b/src/java/org/apache/fop/fo/pagination/RegionBA.java index 279164a96..4cedee6d1 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBA.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBA.java @@ -28,7 +28,9 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; /** - * Abstract base class for fo:region-before and fo:region-after. + * Abstract base class for + * fo:region-before and + * fo:region-after. */ public abstract class RegionBA extends SideRegion { // The value of properties relevant for fo:region-[before|after]. @@ -36,9 +38,9 @@ public abstract class RegionBA extends SideRegion { // End of property values /** - * Creates a new region (before or after). - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a RegionBA instance that is a child of the + * given parent {@link FONode}. + * @param parent the {@link FONode} that is to be the parent */ protected RegionBA(FONode parent) { super(parent); @@ -51,7 +53,8 @@ public abstract class RegionBA extends SideRegion { } /** - * @return the "precedence" property. + * Get the value of the precedence property. + * @return the "precedence" property */ public int getPrecedence() { return precedence; diff --git a/src/java/org/apache/fop/fo/pagination/RegionBefore.java b/src/java/org/apache/fop/fo/pagination/RegionBefore.java index 076737252..fbcf7e8e7 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBefore.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBefore.java @@ -29,14 +29,15 @@ import org.apache.fop.datatypes.SimplePercentBaseContext; import org.apache.fop.fo.FONode; /** - * The fo:region-before element. + * Class modelling the + * fo:region-before object. */ public class RegionBefore extends RegionBA { /** - * Creates a new region-before element. - * @param parent the parent element - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a RegionBefore instance that is a child of the + * given parent {@link FONode}. + * @param parent the {@link FONode} that is to be the parent */ public RegionBefore(FONode parent) { super(parent); @@ -90,7 +91,10 @@ public class RegionBefore extends RegionBA { return "region-before"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_REGION_BEFORE} + */ public int getNameId() { return FO_REGION_BEFORE; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionBody.java b/src/java/org/apache/fop/fo/pagination/RegionBody.java index 9700e72fc..e04ad1c3a 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBody.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBody.java @@ -33,7 +33,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.CommonMarginBlock; /** - * The fo:region-body element. + * Class modelling the + * fo:region-body object. */ public class RegionBody extends Region { // The value of properties relevant for fo:region-body. @@ -43,9 +44,9 @@ public class RegionBody extends Region { // End of property values /** - * Creates a new region-body element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a RegionBody instance that is a child of the + * given parent {@link FONode}. + * @param parent the {@link FONode} that is to be the parent */ public RegionBody(FONode parent) { super(parent); @@ -58,27 +59,28 @@ public class RegionBody extends Region { columnCount = pList.get(PR_COLUMN_COUNT).getNumeric(); columnGap = pList.get(PR_COLUMN_GAP).getLength(); - if ((getColumnCount() != 1) && (getOverflow() == EN_SCROLL)) { + if ((getColumnCount() > 1) && (getOverflow() == EN_SCROLL)) { /* This is an error (See XSL Rec, fo:region-body description). * The Rec allows for acting as if "1" is chosen in * these cases, but we will need to be able to change Numeric * values in order to do this. */ - getFOValidationEventProducer().columnCountErrorOnRegionBodyOverflowScroll(this, - getName(), getLocator()); + attributeError("If overflow property is set to \"scroll\"," + + " a column-count other than \"1\" may not be specified."); } } /** - * Return the Common Margin Properties-Block. - * @return the Common Margin Properties-Block. + * Return the {@link CommonMarginBlock} instance attached to + * this instance. + * @return the {@link CommonMarginBlock} instance */ public CommonMarginBlock getCommonMarginBlock() { return commonMarginBlock; } /** - * Return the "column-count" property. + * Return the value of the column-count property. * @return the "column-count" property. */ public int getColumnCount() { @@ -86,7 +88,7 @@ public class RegionBody extends Region { } /** - * Return the "column-gap" property. + * Return the value of the column-gap property. * @return the "column-gap" property. */ public int getColumnGap() { @@ -151,7 +153,10 @@ public class RegionBody extends Region { return "region-body"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_REGION_BODY} + */ public int getNameId() { return FO_REGION_BODY; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionEnd.java b/src/java/org/apache/fop/fo/pagination/RegionEnd.java index 13f65d71a..1b1abd53c 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionEnd.java +++ b/src/java/org/apache/fop/fo/pagination/RegionEnd.java @@ -22,20 +22,22 @@ package org.apache.fop.fo.pagination; // Java import java.awt.Rectangle; +// FOP +import org.apache.fop.fo.FONode; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.SimplePercentBaseContext; -import org.apache.fop.fo.FONode; /** - * The fo:region-end element. + * Class modelling the + * fo:region-end object. */ public class RegionEnd extends RegionSE { /** - * Creates a new region-end element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a RegionEnd instance that is a child of the + * given parent {@link FONode}. + * @param parent the {@link FONode} that is to be the parent */ public RegionEnd(FONode parent) { super(parent); @@ -90,7 +92,10 @@ public class RegionEnd extends RegionSE { return "region-end"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_REGION_END} + */ public int getNameId() { return FO_REGION_END; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionSE.java b/src/java/org/apache/fop/fo/pagination/RegionSE.java index 183b44342..15f61096b 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionSE.java +++ b/src/java/org/apache/fop/fo/pagination/RegionSE.java @@ -28,16 +28,18 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; /** - * Abstract base class for fo:region-start and fo:region-end. + * Abstract base class for + * fo:region-start and + * fo:region-end. */ public abstract class RegionSE extends SideRegion { // The value of properties relevant for fo:region-[start|end]. // End of property values /** - * Creates a new region (start or end). - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a RegionSE instance that is a child of the + * given parent {@link FONode}. + * @param parent the {@link FONode} that is to be the parent */ protected RegionSE(FONode parent) { super(parent); diff --git a/src/java/org/apache/fop/fo/pagination/RegionStart.java b/src/java/org/apache/fop/fo/pagination/RegionStart.java index 7a69cfdac..e11a8f201 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionStart.java +++ b/src/java/org/apache/fop/fo/pagination/RegionStart.java @@ -29,14 +29,15 @@ import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.SimplePercentBaseContext; /** - * The fo:region-start element. + * Class modelling the + * fo:region-start object. */ public class RegionStart extends RegionSE { /** - * Creates a new region-start element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a RegionStart instance that is a child of the + * given parent {@link FONode}. + * @param parent the {@link FONode} that is to be the parent */ public RegionStart(FONode parent) { super(parent); @@ -88,7 +89,10 @@ public class RegionStart extends RegionSE { return "region-start"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_REGION_START} + */ public int getNameId() { return FO_REGION_START; } diff --git a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java index 509b81f21..5c06dd40d 100644 --- a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java +++ b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java @@ -32,7 +32,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.Property; /** - * A repeatable-page-master-alternatives formatting object. + * Class modelling the + * fo:repeatable-page-master-alternatives object. * This contains a list of conditional-page-master-reference * and the page master is found from the reference that * matches the page number and emptyness. @@ -52,9 +53,9 @@ public class RepeatablePageMasterAlternatives extends FObj private boolean hasPagePositionOnly = false; /** - * Creates a new repeatable-page-master-alternatives element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public RepeatablePageMasterAlternatives(FONode parent) { super(parent); @@ -69,7 +70,7 @@ public class RepeatablePageMasterAlternatives extends FObj protected void startOfNode() throws FOPException { conditionalPageMasterRefs = new java.util.ArrayList(); - assert parent.getName().equals("fo:page-sequence-master"); //Validation by the parent + assert parent.getName().equals("fo:page-sequence-master"); //Validation by the parent PageSequenceMaster pageSequenceMaster = (PageSequenceMaster)parent; pageSequenceMaster.addSubsequenceSpecifier(this); } @@ -83,7 +84,7 @@ public class RepeatablePageMasterAlternatives extends FObj /** * {@inheritDoc} - XSL/FOP: (conditional-page-master-reference+) + *
                                                                                      XSL/FOP: (conditional-page-master-reference+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -94,7 +95,10 @@ public class RepeatablePageMasterAlternatives extends FObj } } - /** @return the "maximum-repeats" property. */ + /** + * Get the value of the maximum-repeats property? + * @return the "maximum-repeats" property + */ public int getMaximumRepeats() { if (maximumRepeats.getEnum() == EN_NO_LIMIT) { return INFINITE; @@ -180,7 +184,10 @@ public class RepeatablePageMasterAlternatives extends FObj return "repeatable-page-master-alternatives"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_REPEATABLE_PAGE_MASTER_ALTERNATIVES} + */ public int getNameId() { return FO_REPEATABLE_PAGE_MASTER_ALTERNATIVES; } diff --git a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java index 87dc248c0..1cf77675d 100644 --- a/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java @@ -30,7 +30,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.Property; /** - * A repeatable-page-master-reference formatting object. + * Class modelling the + * fo:repeatable-page-master-reference object. * This handles a reference with a specified number of repeating * instances of the referenced page master (may have no limit). */ @@ -47,9 +48,9 @@ public class RepeatablePageMasterReference extends FObj private int numberConsumed = 0; /** - * Creates a new repeatable-page-master-reference element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public RepeatablePageMasterReference(FONode parent) { super(parent); @@ -78,13 +79,11 @@ public class RepeatablePageMasterReference extends FObj /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI)) { - invalidChildError(loc, nsURI, localName); - } + throws ValidationException { + invalidChildError(loc, nsURI, localName); } /** {@inheritDoc} */ @@ -103,7 +102,10 @@ public class RepeatablePageMasterReference extends FObj return masterReference; } - /** @return the "maximum-repeats" property. */ + /** + * Get the value of the maximum-repeats property. + * @return the "maximum-repeats" property + */ public int getMaximumRepeats() { if (maximumRepeats.getEnum() == EN_NO_LIMIT) { return INFINITE; @@ -149,7 +151,10 @@ public class RepeatablePageMasterReference extends FObj return "repeatable-page-master-reference"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_REPEATABLE_PAGE_MASTER_REFERENCE} + */ public int getNameId() { return FO_REPEATABLE_PAGE_MASTER_REFERENCE; } diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java index 1cff9c3d6..04014f6fc 100644 --- a/src/java/org/apache/fop/fo/pagination/Root.java +++ b/src/java/org/apache/fop/fo/pagination/Root.java @@ -34,7 +34,9 @@ import org.apache.fop.fo.extensions.destination.Destination; import org.apache.fop.fo.pagination.bookmarks.BookmarkTree; /** - * The fo:root formatting object. Contains page masters, page-sequences. + * Class modeling the + * fo:root formatting object. + * Contains page masters, page-sequences. */ public class Root extends FObj { // The value of properties relevant for fo:root. @@ -62,16 +64,14 @@ public class Root extends FObj { private FOEventHandler foEventHandler = null; /** - * Creates a new root element. - * @param parent the parent node (must be null) - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object + * Note: parent should be null for the fo:root. */ public Root(FONode parent) { super(parent); pageSequences = new java.util.ArrayList(); - if (parent != null) { - //throw new FOPException("root must be root element"); - } } /** {@inheritDoc} */ @@ -89,8 +89,8 @@ public class Root extends FObj { /** * {@inheritDoc} - XSL 1.0 Spec: (layout-master-set,declarations?,page-sequence+) - FOP: (layout-master-set, declarations?, fox:bookmarks?, page-sequence+) + *
                                                                                      XSL 1.0 Spec: (layout-master-set,declarations?,page-sequence+) + *
                                                                                      FOP: (layout-master-set, declarations?, fox:bookmarks?, page-sequence+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -138,6 +138,13 @@ public class Root extends FObj { } + /** @inheritDoc */ + protected void validateChildNode(Locator loc, FONode child) throws ValidationException { + if (child instanceof AbstractPageSequence) { + pageSequenceFound = true; + } + } + /** * Sets the FOEventHandler object that this Root is attached to * @param foEventHandler the FOEventHandler object @@ -295,7 +302,10 @@ public class Root extends FObj { return "root"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_ROOT} + */ public int getNameId() { return FO_ROOT; } diff --git a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java index 85a5081c8..b296b8579 100644 --- a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java +++ b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java @@ -36,7 +36,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonMarginBlock; /** - * A simple-page-master formatting object. + * Class modelling the + * fo:simple-page-master object. * This creates a simple page from the specified regions * and attributes. */ @@ -63,9 +64,9 @@ public class SimplePageMaster extends FObj { private boolean hasRegionEnd = false; /** - * Creates a new simple-page-master element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Base constructor + * + * @param parent {@link FONode} that is the parent of this object */ public SimplePageMaster(FONode parent) { super(parent); @@ -109,7 +110,7 @@ public class SimplePageMaster extends FObj { /** * {@inheritDoc} - * XSL Content Model: (region-body,region-before?,region-after?,region-start?,region-end?) + *
                                                                                      XSL Content Model: (region-body,region-before?,region-after?,region-start?,region-end?) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -262,7 +263,10 @@ public class SimplePageMaster extends FObj { return "simple-page-master"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_SIMPLE_PAGE_MASTER} + */ public int getNameId() { return FO_SIMPLE_PAGE_MASTER; } diff --git a/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java b/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java index 119ec409e..f58f32d1f 100644 --- a/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java +++ b/src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java @@ -29,7 +29,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * A single-page-master-reference formatting object. + * Class modelling the + * fo:single-page-master-reference object. * This is a reference for a single page. It returns the * master name only once until reset. */ @@ -46,9 +47,9 @@ public class SinglePageMasterReference extends FObj private int state; /** - * Creates a new single-page-master-reference element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Creates a new SinglePageMasterReference instance that is + * a child of the given {@link FONode}. + * @param parent {@link FONode} that is the parent of this object */ public SinglePageMasterReference(FONode parent) { super(parent); @@ -72,7 +73,7 @@ public class SinglePageMasterReference extends FObj /** * {@inheritDoc} - * XSL Content Model: empty + *
                                                                                      XSL Content Model: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -127,7 +128,10 @@ public class SinglePageMasterReference extends FObj return "single-page-master-reference"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_SINGLE_PAGE_MASTER_REFERENCE} + */ public int getNameId() { return FO_SINGLE_PAGE_MASTER_REFERENCE; } diff --git a/src/java/org/apache/fop/fo/pagination/StaticContent.java b/src/java/org/apache/fop/fo/pagination/StaticContent.java index 184438b6f..9a5e47d8a 100644 --- a/src/java/org/apache/fop/fo/pagination/StaticContent.java +++ b/src/java/org/apache/fop/fo/pagination/StaticContent.java @@ -27,12 +27,12 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; /** - * Class modeling the fo:static-content object. + * Class modelling the + * fo:static-content object. */ public class StaticContent extends Flow { /** - * Creates a new static-content element. * @param parent FONode that is the parent of this object */ public StaticContent(FONode parent) { @@ -61,7 +61,7 @@ public class StaticContent extends Flow { /** * {@inheritDoc} - * XSL Content Model: (%block;)+ + *
                                                                                      XSL Content Model: (%block;)+ */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -77,7 +77,10 @@ public class StaticContent extends Flow { return "static-content"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_STATIC_CONTENT} + */ public int getNameId() { return FO_STATIC_CONTENT; } diff --git a/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java b/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java index 0bad65a7c..68c8ed9b9 100644 --- a/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java +++ b/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java @@ -21,8 +21,8 @@ package org.apache.fop.fo.pagination; /** - * Classes that implement this interface can be added to a PageSequenceMaster, - * and are capable of looking up an appropriate PageMaster. + * Classes that implement this interface can be added to a {@link PageSequenceMaster}, + * and are capable of looking up an appropriate {@link SimplePageMaster}. */ public interface SubSequenceSpecifier { diff --git a/src/java/org/apache/fop/fo/pagination/Title.java b/src/java/org/apache/fop/fo/pagination/Title.java index f6f625ea8..03afcf5f6 100644 --- a/src/java/org/apache/fop/fo/pagination/Title.java +++ b/src/java/org/apache/fop/fo/pagination/Title.java @@ -27,7 +27,8 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.flow.InlineLevel; /** - * Class modeling the fo:title object. + * Class modeling the + * fo:title object. */ public class Title extends InlineLevel { // The value of properties relevant for fo:title. @@ -35,7 +36,6 @@ public class Title extends InlineLevel { // End of property values /** - * Creates a new title element. * @param parent FONode that is the parent of this object */ public Title(FONode parent) { @@ -44,10 +44,10 @@ public class Title extends InlineLevel { /** * {@inheritDoc} String, String) - XSL/FOP: (#PCDATA|%inline;)* + *
                                                                                      XSL/FOP: (#PCDATA|%inline;)* */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { if (!isInlineItem(nsURI, localName)) { invalidChildError(loc, nsURI, localName); @@ -60,7 +60,10 @@ public class Title extends InlineLevel { return "title"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TITLE} + */ public int getNameId() { return FO_TITLE; } diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java b/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java index 7f55ec51b..ac1ef66de 100644 --- a/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java +++ b/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java @@ -20,21 +20,19 @@ package org.apache.fop.fo.pagination.bookmarks; import java.util.ArrayList; -import java.util.List; import org.xml.sax.Locator; - import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * The fo:bookmark formatting object, first introduced in the - * XSL 1.1 WD. Prototype version only, subject to change as - * XSL 1.1 WD evolves. + * Class modelling the + * fo:bookmark object, first introduced in the + * XSL 1.1 WD. */ public class Bookmark extends FObj { private BookmarkTitle bookmarkTitle; @@ -50,7 +48,8 @@ public class Bookmark extends FObj { /** - * Create a new bookmark object. + * Create a new Bookmark object that is a child of the + * given {@link FONode}. * * @param parent the parent fo node */ @@ -58,9 +57,7 @@ public class Bookmark extends FObj { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { externalDestination = pList.get(PR_EXTERNAL_DESTINATION).getString(); internalDestination = pList.get(PR_INTERNAL_DESTINATION).getString(); @@ -80,7 +77,7 @@ public class Bookmark extends FObj { /** * {@inheritDoc} - XSL/FOP: (bookmark-title, bookmark*) + *
                                                                                      XSL/FOP: (bookmark-title, bookmark*) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -99,18 +96,14 @@ public class Bookmark extends FObj { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endOfNode() throws FOPException { if (bookmarkTitle == null) { missingChildElementError("(bookmark-title, bookmark*)"); } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void addChildNode(FONode obj) { if (obj instanceof BookmarkTitle) { bookmarkTitle = (BookmarkTitle)obj; @@ -155,10 +148,10 @@ public class Bookmark extends FObj { } /** - * Returns a list of child bookmarks. - * @return the list of child bookmarks + * Get the child Bookmarks in an java.util.ArrayList. + * @return an ArrayList containing the child Bookmarks */ - public List getChildBookmarks() { + public ArrayList getChildBookmarks() { return childBookmarks; } @@ -167,7 +160,10 @@ public class Bookmark extends FObj { return "bookmark"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_BOOKMARK} + */ public int getNameId() { return FO_BOOKMARK; } diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java index c7024f2aa..c4cc73efc 100644 --- a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java +++ b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java @@ -21,23 +21,24 @@ package org.apache.fop.fo.pagination.bookmarks; import org.xml.sax.Locator; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * The fo:bookmark-title formatting object, first introduced in the - * XSL 1.1 WD. Prototype version only, subject to change as XSL 1.1 WD - * evolves. + * Class modelling the + * fo:bookmark-title object, first introduced in the + * XSL 1.1 WD. */ public class BookmarkTitle extends FObj { private String title = ""; /** - * Create a new BookmarkTitle object. + * Create a new BookmarkTitle object that is a child + * of the given {@link FONode}. * - * @param parent the fo node parent + * @param parent the {@link FONode} parent */ public BookmarkTitle(FONode parent) { super(parent); @@ -45,14 +46,13 @@ public class BookmarkTitle extends FObj { /** * Add the characters to this BookmarkTitle. - * The text data inside the BookmarkTitle XML element + * The text data inside the BookmarkTitle xml element * is used for the BookmarkTitle string. * * @param data the character data * @param start the start position in the data array * @param end the end position in the character array - * @param pList the currently valid property list - * @param locator location in FO source file. + * @param locator location in fo source file. */ protected void addCharacters(char[] data, int start, int end, PropertyList pList, @@ -62,10 +62,10 @@ public class BookmarkTitle extends FObj { /** * {@inheritDoc} - XSL/FOP: empty + *
                                                                                      XSL/FOP: empty */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { invalidChildError(loc, nsURI, localName); } @@ -85,7 +85,10 @@ public class BookmarkTitle extends FObj { return "bookmark-title"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_BOOKMARK_TITLE} + */ public int getNameId() { return FO_BOOKMARK_TITLE; } diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTree.java b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTree.java index 0f1d8a8b7..9df049251 100644 --- a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTree.java +++ b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTree.java @@ -21,7 +21,6 @@ package org.apache.fop.fo.pagination.bookmarks; // Java import java.util.ArrayList; -import java.util.List; import org.xml.sax.Locator; @@ -32,17 +31,18 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.pagination.Root; /** - * The fo:bookmark-tree formatting object, first introduced in the - * XSL 1.1 WD. Prototype version only, subject to change as XSL 1.1 WD - * evolves. + * Class modelling the + * fo:bookmark-tree object, first introduced in the + * XSL 1.1 WD. */ public class BookmarkTree extends FObj { private ArrayList bookmarks = new ArrayList(); /** - * Creates a new bookmark-tree element. - * @param parent the parent node - * @see org.apache.fop.fo.FONode#FONode(FONode) + * Create a new BookmarkTree object that is a child + * of the given {@link FONode}. + * + * @param parent the {@link FONode} parent */ public BookmarkTree(FONode parent) { super(parent); @@ -55,10 +55,8 @@ public class BookmarkTree extends FObj { } } - /** - * {@inheritDoc} - */ - protected void endOfNode() throws FOPException { + /** {@inheritDoc} */ + protected void endOfNode() throws FOPException { if (bookmarks == null) { missingChildElementError("(fo:bookmark+)"); } @@ -67,7 +65,7 @@ public class BookmarkTree extends FObj { /** * {@inheritDoc} - XSL/FOP: (bookmark+) + *
                                                                                      XSL/FOP: (bookmark+) */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -79,10 +77,10 @@ public class BookmarkTree extends FObj { } /** - * Returns the root bookmarks. - * @return the root bookmarks + * Get the descendant {@link Bookmark}s. + * @return an ArrayList containing the {@link Bookmark} objects. */ - public List getBookmarks() { + public ArrayList getBookmarks() { return bookmarks; } @@ -91,7 +89,10 @@ public class BookmarkTree extends FObj { return "bookmark-tree"; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_BOOKMARK_TREE} + */ public int getNameId() { return FO_BOOKMARK_TREE; } -- cgit v1.2.3 From d8494c1892c5849057ba19449baafcac80a55559 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 26 Apr 2008 23:07:51 +0000 Subject: Minor refactoring: consolidate getPSLM().notifyEndOfLayout(fobj.getId()) in AbstractLayoutManager.notifyEndOfLayout() git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651867 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/layoutmgr/AbstractLayoutManager.java | 16 +++++++++++++--- .../fop/layoutmgr/BlockContainerLayoutManager.java | 18 +++++++----------- .../org/apache/fop/layoutmgr/BlockLayoutManager.java | 5 +++-- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 2 +- .../layoutmgr/list/ListItemContentLayoutManager.java | 4 ++-- .../fop/layoutmgr/list/ListItemLayoutManager.java | 4 ++-- .../fop/layoutmgr/table/TableCellLayoutManager.java | 4 ++-- .../apache/fop/layoutmgr/table/TableLayoutManager.java | 2 +- 8 files changed, 31 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 656b5e2df..76c5ad4da 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -60,7 +60,6 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** child LM and child LM iterator during getNextKnuthElement phase */ protected LayoutManager curChildLM = null; - /** child LM and child LM iterator during getNextKnuthElement phase */ protected ListIterator childLMiter = null; private int lastGeneratedPosition = -1; @@ -231,6 +230,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** * @see PageSequenceLayoutManager#getCurrentPage() + * @return the {@link Page} instance corresponding to the current page */ public Page getCurrentPage() { return getPSLM().getCurrentPage(); @@ -344,7 +344,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager * @param targetArea the area to set the attributes on */ protected void transferForeignAttributes(Area targetArea) { - Map atts = getFObj().getForeignAttributes(); + Map atts = fobj.getForeignAttributes(); targetArea.setForeignAttributes(atts); } @@ -373,7 +373,17 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager getPSLM().addIDToPage(fobj.getId()); } } - + + /** + * Notifies the {@link PageSequenceLayoutManager} that layout + * for this LM has ended. + */ + protected void notifyEndOfLayout() { + if (fobj != null) { + getPSLM().notifyEndOfLayout(fobj.getId()); + } + } + /** {@inheritDoc} */ public String toString() { return (super.toString() + (fobj != null ? "[fobj=" + fobj.toString() + "]" : "")); diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index a44669371..0e6c2cb40 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -442,8 +442,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } } else { - int maxbpd = context.getStackLimitBP().opt; - allocBPD = maxbpd; + allocBPD = context.getStackLimitBP().opt; if (!switchedProgressionDirection) { autoHeight = true; } @@ -601,13 +600,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } public boolean isOverflow() { - if (isEmpty()) { - return false; - } else { - return (deferredAlg.getPageBreaks().size() > 1) - || (deferredAlg.totalWidth - deferredAlg.totalShrink) - > deferredAlg.getLineWidth(); - } + return !isEmpty() + && ((deferredAlg.getPageBreaks().size() > 1) + || (deferredAlg.totalWidth - deferredAlg.totalShrink) + > deferredAlg.getLineWidth()); } public int getOverflowAmount() { @@ -879,8 +875,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager viewportBlockArea = null; referenceArea = null; resetSpaces(); - - getPSLM().notifyEndOfLayout(fobj.getId()); + + notifyEndOfLayout(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 48bf47caf..d129be666 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -153,6 +153,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } /** + * @param pos ... * @return true if new child lms were added */ protected boolean createNextChildLMs(int pos) { @@ -210,7 +211,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public int getKeepTogetherStrength() { - KeepProperty keep = getBlockFO().getKeepTogether(); + KeepProperty keep = getBlockFO().getKeepTogether(); int strength = KeepUtil.getCombinedBlockLevelKeepStrength(keep); strength = Math.max(strength, getParentKeepTogetherStrength()); return strength; @@ -392,7 +393,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager resetSpaces(); // Notify end of block layout manager to the PSLM - getPSLM().notifyEndOfLayout(getBlockFO().getId()); + notifyEndOfLayout(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index 57114eee2..7be146d0d 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -219,7 +219,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(fobj.getId()); + notifyEndOfLayout(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index e3b88b0ac..edee772d6 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -172,7 +172,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { curBlockArea = null; - getPSLM().notifyEndOfLayout(fobj.getId()); + notifyEndOfLayout(); } /** @@ -236,6 +236,6 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { public int getKeepWithPreviousStrength() { return KEEP_AUTO; } - + } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 5e7288f04..d0e8665e7 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -288,7 +288,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager if (end[1] + 1 == elementLists[1].size()) { keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnBody); } - + // compute penalty height and box height int penaltyHeight = step + getMaxRemainingHeight(fullHeights, partialHeights) @@ -557,7 +557,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(fobj.getId()); + notifyEndOfLayout(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 6067af4bc..430356bec 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -199,7 +199,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager p.setP(0); } - getPSLM().notifyEndOfLayout(fobj.getId()); + notifyEndOfLayout(); setFinished(true); return returnList; @@ -575,7 +575,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager public int getKeepWithPreviousStrength() { return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!) } - + // --------- Property Resolution related functions --------- // /** diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 75189a6b9..0fe47d7b4 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -381,7 +381,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager resetSpaces(); curBlockArea = null; - getPSLM().notifyEndOfLayout(fobj.getId()); + notifyEndOfLayout(); } /** -- cgit v1.2.3 From 9a236f8501131da3e26b8e057bb83da1c3e2c429 Mon Sep 17 00:00:00 2001 From: Clay Leeds Date: Sun, 27 Apr 2008 03:27:39 +0000 Subject: Updated to include dev (0.95beta) release. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651880 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/doap.rdf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/documentation/content/doap.rdf b/src/documentation/content/doap.rdf index 1c4253cea..c677ecbc8 100644 --- a/src/documentation/content/doap.rdf +++ b/src/documentation/content/doap.rdf @@ -76,11 +76,18 @@ - Previous release + Previous stable release 2007-01-02 0.93 + + + Previous development release + 2008-25-08 + 0.95beta + + Latest stable release -- cgit v1.2.3 From 7dc0ea558a66ce24af23b22c859a27eb3fc46da5 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 27 Apr 2008 08:18:31 +0000 Subject: Correction of r651866 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@651898 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/pagination/RegionBody.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/pagination/RegionBody.java b/src/java/org/apache/fop/fo/pagination/RegionBody.java index e04ad1c3a..c9dd792db 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBody.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBody.java @@ -65,8 +65,8 @@ public class RegionBody extends Region { * these cases, but we will need to be able to change Numeric * values in order to do this. */ - attributeError("If overflow property is set to \"scroll\"," - + " a column-count other than \"1\" may not be specified."); + getFOValidationEventProducer().columnCountErrorOnRegionBodyOverflowScroll(this, + getName(), getLocator()); } } -- cgit v1.2.3 From 99d913e85de420ed51d5d83638876c316abcde0d Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 1 May 2008 09:16:05 +0000 Subject: Tweak: activate max-height/min-height and max-width/min-width git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652456 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 8 ++++---- src/java/org/apache/fop/fo/FOPropertyMapping.java | 14 +++++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index a704ee791..181f1fe1d 100644 --- a/src/documentation/content/xdocs/compliance.ihtml +++ b/src/documentation/content/xdocs/compliance.ihtml @@ -3995,7 +3995,7 @@ no - no + yes   @@ -4014,7 +4014,7 @@ no - no + yes   @@ -4033,7 +4033,7 @@ no - no + yes   @@ -4052,7 +4052,7 @@ no - no + yes   diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 5d4185d68..3d1a46709 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1423,27 +1423,31 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("inline-progression-dimension", m); // max-height - m = new ToBeImplementedProperty.Maker(PR_MAX_HEIGHT); + m = new LengthProperty.Maker(PR_MAX_HEIGHT); m.setInherited(false); m.setDefault("0pt"); + m.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT); addPropertyMaker("max-height", m); // max-width - m = new ToBeImplementedProperty.Maker(PR_MAX_WIDTH); + m = new LengthProperty.Maker(PR_MAX_WIDTH); m.setInherited(false); m.setDefault("none"); + m.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH); addPropertyMaker("max-width", m); // min-height - m = new ToBeImplementedProperty.Maker(PR_MIN_HEIGHT); + m = new LengthProperty.Maker(PR_MIN_HEIGHT); m.setInherited(false); m.setDefault("0pt"); + m.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT); addPropertyMaker("min-height", m); // min-width - m = new ToBeImplementedProperty.Maker(PR_MIN_WIDTH); + m = new LengthProperty.Maker(PR_MIN_WIDTH); m.setInherited(false); - m.setDefault(""); + m.setDefault(""); //UA dependent + m.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH); addPropertyMaker("min-width", m); // scaling -- cgit v1.2.3 From 2063c2997322531239cbe26acdd7aa097a72bfd2 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 1 May 2008 09:52:24 +0000 Subject: Added enum "none" as a legitimate value for max-height/min-height (behavior to be checked) Added small testcase to check the correspondence mapping. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652465 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 + test/fotree/testcases/ipd_bpd_corresponding.fo | 57 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 test/fotree/testcases/ipd_bpd_corresponding.fo (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 3d1a46709..6d136535b 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1424,6 +1424,7 @@ public final class FOPropertyMapping implements Constants { // max-height m = new LengthProperty.Maker(PR_MAX_HEIGHT); + m.addEnum("NONE", getEnumProperty(EN_NONE, "NONE")); m.setInherited(false); m.setDefault("0pt"); m.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT); @@ -1431,6 +1432,7 @@ public final class FOPropertyMapping implements Constants { // max-width m = new LengthProperty.Maker(PR_MAX_WIDTH); + m.addEnum("NONE", getEnumProperty(EN_NONE, "NONE")); m.setInherited(false); m.setDefault("none"); m.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH); diff --git a/test/fotree/testcases/ipd_bpd_corresponding.fo b/test/fotree/testcases/ipd_bpd_corresponding.fo new file mode 100644 index 000000000..e5232507f --- /dev/null +++ b/test/fotree/testcases/ipd_bpd_corresponding.fo @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + Hello World! + + + + + + + + + + + + Hello World! + + + + + -- cgit v1.2.3 From 292760ece2e6482f4020480c17a204aa1435e707 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 1 May 2008 10:01:51 +0000 Subject: Minor cleanup: remove height/width members and unused getHeight()/getWidth() accessors git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652467 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/BlockContainer.java | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/BlockContainer.java b/src/java/org/apache/fop/fo/flow/BlockContainer.java index 5e8957299..431dae954 100644 --- a/src/java/org/apache/fop/fo/flow/BlockContainer.java +++ b/src/java/org/apache/fop/fo/flow/BlockContainer.java @@ -48,7 +48,6 @@ public class BlockContainer extends FObj { private int breakBefore; // private ToBeImplementedProperty clip; private int displayAlign; - private Length height; private LengthRangeProperty inlineProgressionDimension; private KeepProperty keepTogether; private KeepProperty keepWithNext; @@ -56,7 +55,6 @@ public class BlockContainer extends FObj { private int overflow; private Numeric referenceOrientation; private int span; - private Length width; private int writingMode; // Unused but valid items, commented out for performance: // private int intrusionDisplace; @@ -87,7 +85,6 @@ public class BlockContainer extends FObj { breakBefore = pList.get(PR_BREAK_BEFORE).getEnum(); // clip = pList.get(PR_CLIP); displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum(); - height = pList.get(PR_HEIGHT).getLength(); inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange(); keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep(); @@ -95,7 +92,6 @@ public class BlockContainer extends FObj { overflow = pList.get(PR_OVERFLOW).getEnum(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); span = pList.get(PR_SPAN).getEnum(); - width = pList.get(PR_WIDTH).getLength(); writingMode = pList.get(PR_WRITING_MODE).getEnum(); } @@ -225,16 +221,6 @@ public class BlockContainer extends FObj { return writingMode; } - /** @return the "width" property */ - public Length getWidth() { - return width; - } - - /** @return the "height" property */ - public Length getHeight() { - return height; - } - /** {@inheritDoc} */ public String getLocalName() { return "block-container"; -- cgit v1.2.3 From 003e8e389cbd1a8139184938fc996f8c2b4e0632 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 1 May 2008 13:46:21 +0000 Subject: Renamed variable git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652520 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/AFPRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 83b8048f9..dc649685b 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -279,8 +279,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { public void setupFontInfo(FontInfo inFontInfo) { this.fontInfo = inFontInfo; int num = 1; - if (this.fontList != null && this.fontList.size() > 0) { - for (Iterator it = this.fontList.iterator(); it.hasNext();) { + if (this.embedFontInfoList != null && this.embedFontInfoList.size() > 0) { + for (Iterator it = this.embedFontInfoList.iterator(); it.hasNext();) { AFPFontInfo afi = (AFPFontInfo)it.next(); AFPFont bf = (AFPFont)afi.getAFPFont(); for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) { -- cgit v1.2.3 From 256567a245370877d5e1b7e52f8f0aec6b3ce9f6 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 1 May 2008 14:01:54 +0000 Subject: Forgot about dependency on PrintRenderer, last commit broke the build - will commit this rename later. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652525 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/AFPRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index dc649685b..83b8048f9 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -279,8 +279,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { public void setupFontInfo(FontInfo inFontInfo) { this.fontInfo = inFontInfo; int num = 1; - if (this.embedFontInfoList != null && this.embedFontInfoList.size() > 0) { - for (Iterator it = this.embedFontInfoList.iterator(); it.hasNext();) { + if (this.fontList != null && this.fontList.size() > 0) { + for (Iterator it = this.fontList.iterator(); it.hasNext();) { AFPFontInfo afi = (AFPFontInfo)it.next(); AFPFont bf = (AFPFont)afi.getAFPFont(); for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) { -- cgit v1.2.3 From c5bc9c65717846ca25c49925604825ca7b7a5b53 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 1 May 2008 16:15:44 +0000 Subject: Javadoc corrections git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652565 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/Footnote.java | 5 +++-- src/java/org/apache/fop/fo/flow/FootnoteBody.java | 2 +- src/java/org/apache/fop/fo/flow/InitialPropertySet.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/Footnote.java b/src/java/org/apache/fop/fo/flow/Footnote.java index 54e457db8..5b13b502c 100644 --- a/src/java/org/apache/fop/fo/flow/Footnote.java +++ b/src/java/org/apache/fop/fo/flow/Footnote.java @@ -28,7 +28,7 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the + * Class modelling the * fo:footnote object. */ public class Footnote extends FObj { @@ -40,7 +40,8 @@ public class Footnote extends FObj { private FootnoteBody footnoteBody; /** - * Base constructor + * Create a Footnote instance that is a child of the + * given {@link FONode} * * @param parent {@link FONode} that is the parent of this object */ diff --git a/src/java/org/apache/fop/fo/flow/FootnoteBody.java b/src/java/org/apache/fop/fo/flow/FootnoteBody.java index 21c5a3efd..711d56c60 100644 --- a/src/java/org/apache/fop/fo/flow/FootnoteBody.java +++ b/src/java/org/apache/fop/fo/flow/FootnoteBody.java @@ -29,7 +29,7 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** - * Class modelling the + * Class modelling the * fo:footnote-body object. */ public class FootnoteBody extends FObj { diff --git a/src/java/org/apache/fop/fo/flow/InitialPropertySet.java b/src/java/org/apache/fop/fo/flow/InitialPropertySet.java index 6b2a1b50c..a7f62535f 100644 --- a/src/java/org/apache/fop/fo/flow/InitialPropertySet.java +++ b/src/java/org/apache/fop/fo/flow/InitialPropertySet.java @@ -30,7 +30,7 @@ import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.SpaceProperty; /** - * Class modelling the + * Class modelling the * fo:initial-property-set object. */ public class InitialPropertySet extends FObj { -- cgit v1.2.3 From a58560c014fcf997c196aabce95491b1622919ca Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 1 May 2008 17:15:49 +0000 Subject: Website fixes. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652581 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/0.95/graphics.xml | 12 +++++++++ src/documentation/content/xdocs/news.xml | 30 ++++++++++------------ src/documentation/content/xdocs/trunk/graphics.xml | 12 +++++++++ 3 files changed, 38 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/0.95/graphics.xml b/src/documentation/content/xdocs/0.95/graphics.xml index 31e54d8fd..dce05aa47 100644 --- a/src/documentation/content/xdocs/0.95/graphics.xml +++ b/src/documentation/content/xdocs/0.95/graphics.xml @@ -324,6 +324,18 @@
    +
    + Image I/O +

    + The image loading framework in XML Graphics Commons + provides a wrapper to load images through the + JDK's Image I/O API (JSR 015). + Image I/O allows to dynamically add additional image codecs. An example of such an + add-on library are the + JAI Image I/O Tools + available from Sun. +

    +
    Details on image formats diff --git a/src/documentation/content/xdocs/news.xml b/src/documentation/content/xdocs/news.xml index c72d76129..0a4467e66 100644 --- a/src/documentation/content/xdocs/news.xml +++ b/src/documentation/content/xdocs/news.xml @@ -16,9 +16,7 @@ limitations under the License. --> - - +
    News @@ -87,7 +85,7 @@

    Please see also the - announcement. + announcement.

    @@ -99,7 +97,7 @@ 20 October 2004 - Creation of the Apache XML Graphics project

    The Apache Board of Directors agreed to the creation of the - Apache XML Graphics + Apache XML Graphics project which will be comprised of Batik and FOP. Both former Apache XML subprojects are in this way complying with the Board's desire to improve project oversight. Both project teams also see additional @@ -152,8 +150,8 @@

    See also the full text of the - - announcement. + + announcement.

    @@ -164,15 +162,15 @@
    23 May 2003 - FOP 0.20.5 Release Candidate 3 available

    - See the full text of the announcement. + See the full text of the announcement.

    18 February 2003 - FOP 0.20.5 Release Candidate 2 available

    - See the full text of the announcement. + See the full text of the announcement.

    @@ -189,16 +187,16 @@
    23 December 2002 - Official FOP Wiki

    - See FOP project pages at the ApacheWiki. + See FOP project pages at the ApacheWiki.

    10 December 2002 - FOP 0.20.5 Release Candidate available

    - See the full text of the announcement. + >announcement.

    @@ -206,7 +204,7 @@

    The EXSLFO project is a community effort to define functional extensions to thet XSL Formatting Objects specification. See the - EXSLFO website for details. + EXSLFO website for details.

    diff --git a/src/documentation/content/xdocs/trunk/graphics.xml b/src/documentation/content/xdocs/trunk/graphics.xml index 31e54d8fd..dce05aa47 100644 --- a/src/documentation/content/xdocs/trunk/graphics.xml +++ b/src/documentation/content/xdocs/trunk/graphics.xml @@ -324,6 +324,18 @@
    +
    + Image I/O +

    + The image loading framework in XML Graphics Commons + provides a wrapper to load images through the + JDK's Image I/O API (JSR 015). + Image I/O allows to dynamically add additional image codecs. An example of such an + add-on library are the + JAI Image I/O Tools + available from Sun. +

    +
    Details on image formats -- cgit v1.2.3 From 3d594ae70ccb3f629f61ba2d55915213cc1b34e7 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 1 May 2008 17:16:57 +0000 Subject: DSC = Document Structuring Conventions! git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652582 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/ps/PSRenderer.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index e4d582ba2..a94c8b0aa 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -170,7 +170,10 @@ public class PSRenderer extends AbstractPathOrientedRenderer /** Whether or not the safe set page device macro will be used or not */ private boolean safeSetPageDevice = false; - /** Whether or not Dublin Core Standard (dsc) compliant output is enforced */ + /** + * Whether or not PostScript Document Structuring Conventions (DSC) compliant output are + * enforced. + */ private boolean dscCompliant = true; /** Is used to determine the document's bounding box */ @@ -181,9 +184,8 @@ public class PSRenderer extends AbstractPathOrientedRenderer /** This is a collection holding all document footer comments */ private Collection footerComments; - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ public void setUserAgent(FOUserAgent agent) { super.setUserAgent(agent); Object obj; @@ -1703,13 +1705,14 @@ public class PSRenderer extends AbstractPathOrientedRenderer } /** - * Sets whether or not Dublin Core Standard (dsc) compliance is enforced. - * - * It can cause problems (unwanted postscript subsystem initgraphics/erasepage calls) + * Sets whether or not PostScript Document Structuring Conventions (dsc) compliance are + * enforced. + *

    + * It can cause problems (unwanted PostScript subsystem initgraphics/erasepage calls) * on some printers when the pagedevice is set. If this causes problems on a * particular implementation then use this setting with a 'false' value to try and * minimize the number of setpagedevice calls in the postscript document output. - * + *

    * Set this value to false if you experience unwanted blank pages in your * postscript output. * @param dscCompliant boolean value (default is true) -- cgit v1.2.3 From 1363d649560c5cc6f76a849aff880eb7c802cc45 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 1 May 2008 21:34:19 +0000 Subject: First steps towards fo:retrieve-table-marker git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652673 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/EventFormatter.xml | 3 +- src/java/org/apache/fop/fo/Constants.java | 22 ++- src/java/org/apache/fop/fo/FOElementMapping.java | 6 + src/java/org/apache/fop/fo/FOPropertyMapping.java | 19 +++ .../apache/fop/fo/flow/AbstractRetrieveMarker.java | 168 +++++++++++++++++++++ .../org/apache/fop/fo/flow/RetrieveMarker.java | 145 +++--------------- .../apache/fop/fo/flow/RetrieveTableMarker.java | 111 ++++++++++++++ .../apache/fop/layoutmgr/LayoutManagerMapping.java | 19 +-- .../testcases/table_retrieve-table-marker.fo | 68 +++++++++ 9 files changed, 418 insertions(+), 143 deletions(-) create mode 100644 src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java create mode 100644 src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java create mode 100644 test/fotree/testcases/table_retrieve-table-marker.fo (limited to 'src') diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml index f5e4609e9..74e120407 100644 --- a/src/java/org/apache/fop/events/EventFormatter.xml +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -19,7 +19,8 @@ [ (See position {loc})| (See {#gatherContextInfo})| (No context info available)] An fo:marker is permitted only as the descendant of an fo:flow. - An fo:retrieve-marker is permitted only as the descendant of an fo:static-content. + An fo:retrieve-marker is permitted only as the descendant of an fo:static-content. + An fo:retrieve-table-marker is permitted only as the descendant of an fo:table-header or an fo:table-footer. An fo:bidi-override that is a descendant of an fo:leader or of the fo:inline child of an fo:footnote may not have block-level children, unless it has a nearer ancestor that is an fo:inline-container. An fo:inline that is a descendant of an fo:leader or fo:footnote may not have block-level children, unless it has a nearer ancestor that is an fo:inline-container. The element must be a child of fo:simple-page-master. diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java index 25c2fe371..2a7f7e0c9 100644 --- a/src/java/org/apache/fop/fo/Constants.java +++ b/src/java/org/apache/fop/fo/Constants.java @@ -159,8 +159,10 @@ public interface Constants { int FO_PAGE_SEQUENCE_WRAPPER = 60; /** FO element constant - XSL 1.1 */ int FO_PAGE_NUMBER_CITATION_LAST = 61; + /** FO element constant - XSL 1.1 */ + int FO_RETRIEVE_TABLE_MARKER = 62; /** Number of FO element constants defined */ - int FRM_OBJ_COUNT = 61; + int FRM_OBJ_COUNT = 62; // Masks /** @@ -688,8 +690,12 @@ public interface Constants { 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; + /** Property constant */ + int PR_RETRIEVE_POSITION_WITHIN_TABLE = 254; + /** Property constant */ + int PR_RETRIEVE_BOUNDARY_WITHIN_TABLE = 255; /** Number of property constants defined */ - int PROPERTY_COUNT = 253; + int PROPERTY_COUNT = 255; // compound property constants @@ -1097,6 +1103,16 @@ public interface Constants { int EN_REPLACE = 189; /** Enumeration constant -- for fo:basic-link show-destination */ int EN_NEW = 190; + /** Enumeration constant -- for fo:retrieve-table-marker */ + int EN_FIRST_STARTING = 191; + /** Enumeration constant -- for fo:retrieve-table-marker */ + int EN_LAST_STARTING = 192; + /** Enumeration constant -- for fo:retrieve-table-marker */ + int EN_LAST_ENDING = 193; + /** Enumeration constant -- for fo:retrieve-table-marker */ + int EN_TABLE = 194; + /** Enumeration constant -- for fo:retrieve-table-marker */ + int EN_TABLE_FRAGMENT = 195; /** Number of enumeration constants defined */ - int ENUM_COUNT = 190; + int ENUM_COUNT = 195; } diff --git a/src/java/org/apache/fop/fo/FOElementMapping.java b/src/java/org/apache/fop/fo/FOElementMapping.java index 62721afeb..facb1c304 100644 --- a/src/java/org/apache/fop/fo/FOElementMapping.java +++ b/src/java/org/apache/fop/fo/FOElementMapping.java @@ -135,6 +135,7 @@ public class FOElementMapping extends ElementMapping { foObjs.put("wrapper", new WrapperMaker()); foObjs.put("marker", new MarkerMaker()); foObjs.put("retrieve-marker", new RetrieveMarkerMaker()); + foObjs.put("retrieve-table-marker", new RetrieveTableMarkerMaker()); } } @@ -514,4 +515,9 @@ public class FOElementMapping extends ElementMapping { } } + static class RetrieveTableMarkerMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new org.apache.fop.fo.flow.RetrieveTableMarker(parent); + } + } } diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 6d136535b..643fc7b73 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -2097,6 +2097,25 @@ public final class FOPropertyMapping implements Constants { m.addEnum("document", getEnumProperty(EN_DOCUMENT, "DOCUMENT")); m.setDefault("page-sequence"); addPropertyMaker("retrieve-boundary", m); + + // retrieve-position-within-table + m = new EnumProperty.Maker(PR_RETRIEVE_POSITION_WITHIN_TABLE); + m.setInherited(false); + m.addEnum("first-starting", getEnumProperty(EN_FIRST_STARTING, "FIRST_STARTING")); + m.addEnum("first-including-carryover", getEnumProperty(EN_FIC, "FIC")); + m.addEnum("last-starting", getEnumProperty(EN_LAST_STARTING, "LAST_STARTING")); + m.addEnum("last-ending", getEnumProperty(EN_LAST_ENDING, "LAST_ENDING")); + m.setDefault("first-starting"); + addPropertyMaker("retrieve-position-within-table", m); + + // retrieve-boundary-within-table + m = new EnumProperty.Maker(PR_RETRIEVE_BOUNDARY_WITHIN_TABLE); + m.setInherited(false); + m.addEnum("table", getEnumProperty(EN_TABLE, "TABLE")); + m.addEnum("table-fragment", getEnumProperty(EN_TABLE_FRAGMENT, "TABLE_FRAGMENT")); + m.addEnum("page", getEnumProperty(EN_DOCUMENT, "PAGE")); + m.setDefault("table"); + addPropertyMaker("retrieve-boundary-within-table", m); } private void createNumberToStringProperties() { diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java new file mode 100644 index 000000000..30bb3fbf1 --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id:$ */ +package org.apache.fop.fo.flow; + +import org.apache.fop.fo.*; +import org.apache.fop.fo.flow.table.TableFObj; +import org.apache.fop.fo.flow.table.Table; +import org.apache.fop.apps.FOPException; + +import java.util.Iterator; + +/** + * Abstract base class for the + * fo:retrieve-marker and + * + * fo:retrieve-table-marker formatting objects. + + */ +public abstract class AbstractRetrieveMarker extends FObjMixed { + + private PropertyList propertyList; + + /** + * Create a new AbstractRetrieveMarker instance that + * is a child of the given {@link FONode} + * + * @param parent the parent {@link FONode} + */ + public AbstractRetrieveMarker(FONode parent) { + super(parent); + } + + /** + * {@inheritDoc} + * Store a reference to the parent {@link PropertyList} + * to be used when the retrieve-marker is resolved. + */ + public void bind(PropertyList pList) throws FOPException { + super.bind(pList); + this.propertyList = pList.getParentPropertyList(); + } + + private PropertyList createPropertyListFor(FObj fo, PropertyList parent) { + return getFOEventHandler().getPropertyListMaker().make(fo, parent); + } + + private void cloneSingleNode(FONode child, FONode newParent, + Marker marker, PropertyList parentPropertyList) + throws FOPException { + + if (child != null) { + FONode newChild = child.clone(newParent, true); + if (child instanceof FObj) { + Marker.MarkerPropertyList pList; + PropertyList newPropertyList = createPropertyListFor( + (FObj) newChild, parentPropertyList); + + pList = marker.getPropertyListFor(child); + newChild.processNode( + child.getLocalName(), + getLocator(), + pList, + newPropertyList); + if (newChild instanceof TableFObj) { + // TODO calling startOfNode (and endOfNode, below) on other fobjs may + // have undesirable side-effects. This is really ugly and will need to + // be addressed sooner or later + ((TableFObj) newChild).startOfNode(); + } + addChildTo(newChild, (FObj) newParent); + if (newChild.getNameId() == FO_TABLE) { + Table t = (Table) child; + cloneSubtree(t.getColumns().listIterator(), + newChild, marker, newPropertyList); + cloneSingleNode(t.getTableHeader(), + newChild, marker, newPropertyList); + cloneSingleNode(t.getTableFooter(), + newChild, marker, newPropertyList); + } + cloneSubtree(child.getChildNodes(), newChild, + marker, newPropertyList); + if (newChild instanceof TableFObj) { + // TODO this is ugly + ((TableFObj) newChild).endOfNode(); + } + } else if (child instanceof FOText) { + FOText ft = (FOText) newChild; + ft.bind(parentPropertyList); + addChildTo(newChild, (FObj) newParent); + } + if (newChild instanceof FObjMixed) { + handleWhiteSpaceFor((FObjMixed) newChild); + } + } + } + + /** + * Clone the FO nodes in the parent iterator, + * attach the new nodes to the new parent, + * and map the new nodes to the existing property lists. + * FOText nodes are also in the new map, with a null value. + * Clone the subtree by a recursive call to this method. + * @param parentIter the iterator over the children of the old parent + * @param newParent the new parent for the cloned nodes + * @param marker the marker that contains the old property list mapping + * @param parentPropertyList the parent PropertyList + * @throws FOPException in case there was an error + */ + private void cloneSubtree(Iterator parentIter, FONode newParent, + Marker marker, PropertyList parentPropertyList) + throws FOPException { + if (parentIter != null) { + FONode child; + while (parentIter.hasNext()) { + child = (FONode) parentIter.next(); + cloneSingleNode(child, newParent, + marker, parentPropertyList); + } + } + } + + private void cloneFromMarker(Marker marker) + throws FOPException { + // clean up remnants from a possible earlier layout + if (firstChild != null) { + currentTextNode = null; + firstChild = null; + } + cloneSubtree(marker.getChildNodes(), this, + marker, propertyList); + handleWhiteSpaceFor(this); + } + + /** + * Clone the subtree of the given marker + * + * @param marker the marker that is to be cloned + */ + public void bindMarker(Marker marker) { + if (marker.getChildNodes() != null) { + try { + cloneFromMarker(marker); + } catch (FOPException exc) { + getFOValidationEventProducer().markerCloningFailed(this, + marker.getMarkerClassName(), exc, getLocator()); + } + } else if (log.isDebugEnabled()) { + log.debug("Empty marker retrieved..."); + } + } + +} diff --git a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java index 0283dc7da..b75e14664 100644 --- a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java @@ -23,29 +23,25 @@ import java.util.Iterator; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.FOText; -import org.apache.fop.fo.FObj; -import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.fo.flow.table.TableFObj; import org.xml.sax.Locator; +import org.xml.sax.Attributes; /** - * Class modelling the fo:retrieve-marker object. + * Class modelling the + * fo:retrieve-marker formatting object. * This will create a layout manager that will retrieve * a marker based on the information. */ -public class RetrieveMarker extends FObjMixed { +public class RetrieveMarker extends AbstractRetrieveMarker { + // The value of properties relevant for fo:retrieve-marker. private String retrieveClassName; private int retrievePosition; private int retrieveBoundary; // End of property values - private PropertyList propertyList; - /** * Create a new RetrieveMarker instance that is a * child of the given {@link FONode}. @@ -56,12 +52,26 @@ public class RetrieveMarker extends FObjMixed { super(parent); } - /** {@inheritDoc} */ - public void bind(PropertyList pList) throws FOPException { + /** + * {@inheritDoc} + * NOTE: An fo:retrieve-marker is only permitted as a descendant + * of an fo:static-content. + */ + public void processNode(String elementName, + Locator locator, + Attributes attlist, + PropertyList pList) + throws FOPException { if (findAncestor(FO_STATIC_CONTENT) < 0) { invalidChildError(locator, getParent().getName(), FO_URI, getName(), - "rule.retrieveMarkerDescendatOfStaticContent"); + "rule.retrieveMarkerDescendantOfStaticContent"); + } else { + super.processNode(elementName, locator, attlist, pList); } + } + + /** {@inheritDoc} */ + public void bind(PropertyList pList) throws FOPException { retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME).getString(); retrievePosition = pList.get(PR_RETRIEVE_POSITION).getEnum(); @@ -70,8 +80,6 @@ public class RetrieveMarker extends FObjMixed { if (retrieveClassName == null || retrieveClassName.equals("")) { missingPropertyError("retrieve-class-name"); } - - propertyList = pList.getParentPropertyList(); super.bind(pList); } @@ -107,115 +115,6 @@ public class RetrieveMarker extends FObjMixed { return retrieveBoundary; } - private PropertyList createPropertyListFor(FObj fo, PropertyList parent) { - return getFOEventHandler().getPropertyListMaker().make(fo, parent); - } - - private void cloneSingleNode(FONode child, FONode newParent, - Marker marker, PropertyList parentPropertyList) - throws FOPException { - - if (child != null) { - FONode newChild = child.clone(newParent, true); - if (child instanceof FObj) { - Marker.MarkerPropertyList pList; - PropertyList newPropertyList = createPropertyListFor( - (FObj) newChild, parentPropertyList); - - pList = marker.getPropertyListFor(child); - newChild.processNode( - child.getLocalName(), - getLocator(), - pList, - newPropertyList); - if (newChild instanceof TableFObj) { - // TODO calling startOfNode (and endOfNode, below) on other fobjs may - // have undesirable side-effects. This is really ugly and will need to - // be addressed sooner or later - ((TableFObj) newChild).startOfNode(); - } - addChildTo(newChild, (FObj) newParent); - if (newChild.getNameId() == FO_TABLE) { - Table t = (Table) child; - cloneSubtree(t.getColumns().listIterator(), - newChild, marker, newPropertyList); - cloneSingleNode(t.getTableHeader(), - newChild, marker, newPropertyList); - cloneSingleNode(t.getTableFooter(), - newChild, marker, newPropertyList); - } - cloneSubtree(child.getChildNodes(), newChild, - marker, newPropertyList); - if (newChild instanceof TableFObj) { - // TODO this is ugly - ((TableFObj) newChild).endOfNode(); - } - } else if (child instanceof FOText) { - FOText ft = (FOText) newChild; - ft.bind(parentPropertyList); - addChildTo(newChild, (FObj) newParent); - } - if (newChild instanceof FObjMixed) { - handleWhiteSpaceFor((FObjMixed) newChild); - } - } - } - - /** - * Clone the FO nodes in the parent iterator, - * attach the new nodes to the new parent, - * and map the new nodes to the existing property lists. - * FOText nodes are also in the new map, with a null value. - * Clone the subtree by a recursive call to this method. - * @param parentIter the iterator over the children of the old parent - * @param newParent the new parent for the cloned nodes - * @param marker the marker that contains the old property list mapping - * @param descPLists the map of the new nodes to property lists - */ - private void cloneSubtree(Iterator parentIter, FONode newParent, - Marker marker, PropertyList parentPropertyList) - throws FOPException { - if (parentIter != null) { - FONode child; - while (parentIter.hasNext()) { - child = (FONode) parentIter.next(); - cloneSingleNode(child, newParent, - marker, parentPropertyList); - } - } - } - - private void cloneFromMarker(Marker marker) - throws FOPException { - // clean up remnants from a possible earlier layout - if (firstChild != null) { - currentTextNode = null; - firstChild = null; - } - cloneSubtree(marker.getChildNodes(), this, - marker, propertyList); - handleWhiteSpaceFor(this); - } - - /** - * Clone the subtree of the given marker - * - * @param marker the marker that is to be cloned - */ - public void bindMarker(Marker marker) { - if (marker.getChildNodes() != null) { - try { - cloneFromMarker(marker); - } catch (FOPException exc) { - getFOValidationEventProducer().markerCloningFailed(this, - marker.getMarkerClassName(), exc, getLocator()); - return; - } - } else if (log.isDebugEnabled()) { - log.debug("Empty marker retrieved..."); - } - } - /** {@inheritDoc} */ public String getLocalName() { return "retrieve-marker"; diff --git a/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java new file mode 100644 index 000000000..4a7b8af0d --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id:$ */ +package org.apache.fop.fo.flow; + +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.apps.FOPException; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; + +/** + * Class modelling the + * fo:retrieve-table-marker formatting object. + */ +public class RetrieveTableMarker extends AbstractRetrieveMarker { + + // The value of properties relevant for fo:retrieve-marker. + private String retrieveClassName; + private int retrievePositionWithinTable; + private int retrieveBoundaryWithinTable; + // end property values + + /** + * Create a new RetrieveTableMarker instance that is + * a child of the given {@link FONode}. + * + * @param parent the parent {@link FONode} + */ + public RetrieveTableMarker(FONode parent) { + super(parent); + } + + /** {@inheritDoc} */ + public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + if (findAncestor(FO_TABLE_HEADER) < 0 + && findAncestor(FO_TABLE_FOOTER) < 0) { + invalidChildError(locator, getParent().getName(), FO_URI, getName(), + "rule.retrieveTableMarkerDescendantOfHeaderOrFooter"); + } else { + super.processNode(elementName, locator, attlist, pList); + } + } + + /** {@inheritDoc} */ + public void bind(PropertyList pList) throws FOPException { + this.retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME).getString(); + this.retrievePositionWithinTable + = pList.get(PR_RETRIEVE_POSITION_WITHIN_TABLE).getEnum(); + this.retrieveBoundaryWithinTable + = pList.get(PR_RETRIEVE_BOUNDARY_WITHIN_TABLE).getEnum(); + } + + /** {@inheritDoc} */ + public String getRetrieveClassName() { + return this.retrieveClassName; + } + + /** + * Return the value for the retrieve-position-within-table + * property + * @return the value for retrieve-position-within-table; one of + * {@link org.apache.fop.fo.Constants#EN_FIRST_STARTING}, + * {@link org.apache.fop.fo.Constants#EN_FIC}, + * {@link org.apache.fop.fo.Constants#EN_LAST_STARTING}, + * {@link org.apache.fop.fo.Constants#EN_LAST_ENDING}. + */ + public int getRetrievePositionWithinTable() { + return this.retrievePositionWithinTable; + } + + /** + * Return the value for the retrieve-boundary-within-table + * property + * @return the value for retrieve-boundary-within-table; one of + * {@link org.apache.fop.fo.Constants#EN_TABLE}, + * {@link org.apache.fop.fo.Constants#EN_TABLE_FRAGMENT}, + * {@link org.apache.fop.fo.Constants#EN_PAGE}. + */ + public int getRetrieveBoundaryWithinTable() { + return this.retrieveBoundaryWithinTable; + } + + /** {@inheritDoc} */ + public String getLocalName() { + return "retrieve-table-marker"; + } + + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_RETRIEVE_TABLE_MARKER} + */ + public int getNameId() { + return FO_RETRIEVE_TABLE_MARKER; + } +} diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java index ad7d48caf..087963013 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java @@ -51,6 +51,7 @@ import org.apache.fop.fo.flow.PageNumber; import org.apache.fop.fo.flow.PageNumberCitation; import org.apache.fop.fo.flow.PageNumberCitationLast; import org.apache.fop.fo.flow.RetrieveMarker; +import org.apache.fop.fo.flow.RetrieveTableMarker; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; @@ -117,6 +118,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { makers.put(Block.class, new BlockLayoutManagerMaker()); makers.put(Leader.class, new LeaderLayoutManagerMaker()); makers.put(RetrieveMarker.class, new RetrieveMarkerLayoutManagerMaker()); + makers.put(RetrieveTableMarker.class, new Maker()); makers.put(Character.class, new CharacterLayoutManagerMaker()); makers.put(ExternalGraphic.class, new ExternalGraphicLayoutManagerMaker()); @@ -207,9 +209,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { return new StaticContentLayoutManager(pslm, sc, reg); } - /* - * {@inheritDoc} - */ + /** {@inheritDoc} */ public StaticContentLayoutManager makeStaticContentLayoutManager( PageSequenceLayoutManager pslm, StaticContent sc, org.apache.fop.area.Block block) { return new StaticContentLayoutManager(pslm, sc, block); @@ -218,7 +218,6 @@ public class LayoutManagerMapping implements LayoutManagerMaker { public static class Maker { public void make(FONode node, List lms) { // no layout manager - return; } } @@ -231,18 +230,6 @@ public class LayoutManagerMapping implements LayoutManagerMaker { } } - /* - public static class FObjMixedLayoutManagerMaker extends Maker { - public void make(FONode node, List lms) { - if (node.getChildNodes() != null) { - InlineStackingLayoutManager lm; - lm = new InlineStackingLayoutManager((FObjMixed) node); - lms.add(lm); - } - } - } - */ - public static class BidiOverrideLayoutManagerMaker extends Maker { // public static class BidiOverrideLayoutManagerMaker extends FObjMixedLayoutManagerMaker { public void make(BidiOverride node, List lms) { diff --git a/test/fotree/testcases/table_retrieve-table-marker.fo b/test/fotree/testcases/table_retrieve-table-marker.fo new file mode 100644 index 000000000..3697fcd19 --- /dev/null +++ b/test/fotree/testcases/table_retrieve-table-marker.fo @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cell1 + + + cell2 + + + + + cell3 + + + cell4 + + + + + + + -- cgit v1.2.3 From 2c8c8c837c99a941abc36c396a0d1c64f9b3d71a Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 1 May 2008 21:39:17 +0000 Subject: Code style: single class imports only... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652674 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index 30bb3fbf1..334f98e2f 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -15,10 +15,14 @@ * limitations under the License. */ -/* $Id:$ */ +/* $Id$ */ package org.apache.fop.fo.flow; -import org.apache.fop.fo.*; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOText; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.FObjMixed; +import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.flow.table.TableFObj; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.apps.FOPException; -- cgit v1.2.3 From 8f3f8d05fc2ba1404a63d0bcf94959e34221e981 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 2 May 2008 16:58:26 +0000 Subject: Cleanup/Correction after r657673 -> added missing file FObj.java -> pushed retrieve-class-name upwards to AbstractRetrieveMarker as a common property -> corrected use of property-name "retrieve-class-name" in source and testcase -> improved consistency in code-style git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652821 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FObj.java | 49 ++++++++++---------- .../apache/fop/fo/flow/AbstractRetrieveMarker.java | 34 ++++++++++++-- .../org/apache/fop/fo/flow/RetrieveMarker.java | 53 ++++++++-------------- .../apache/fop/fo/flow/RetrieveTableMarker.java | 18 ++++---- .../testcases/table_retrieve-table-marker.fo | 4 +- 5 files changed, 82 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index a2b09640b..79b04c4d7 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -427,12 +427,12 @@ public abstract class FObj extends FONode implements Constants { */ protected boolean isBlockItem(String nsURI, String lName) { return (FO_URI.equals(nsURI) - && (lName.equals("block") - || lName.equals("table") - || lName.equals("table-and-caption") - || lName.equals("block-container") - || lName.equals("list-block") - || lName.equals("float") + && ("block".equals(lName) + || "table".equals(lName) + || "table-and-caption".equals(lName) + || "block-container".equals(lName) + || "list-block".equals(lName) + || "float".equals(lName) || isNeutralItem(nsURI, lName))); } @@ -446,21 +446,21 @@ public abstract class FObj extends FONode implements Constants { */ protected boolean isInlineItem(String nsURI, String lName) { return (FO_URI.equals(nsURI) - && (lName.equals("bidi-override") - || lName.equals("character") - || lName.equals("external-graphic") - || lName.equals("instream-foreign-object") - || lName.equals("inline") - || lName.equals("inline-container") - || lName.equals("leader") - || lName.equals("page-number") - || lName.equals("page-number-citation") - || lName.equals("page-number-citation-last") - || lName.equals("basic-link") - || (lName.equals("multi-toggle") + && ("bidi-override".equals(lName) + || "character".equals(lName) + || "external-graphic".equals(lName) + || "instream-foreign-object".equals(lName) + || "inline".equals(lName) + || "inline-container".equals(lName) + || "leader".equals(lName) + || "page-number".equals(lName) + || "page-number-citation".equals(lName) + || "page-number-citation-last".equals(lName) + || "basic-link".equals(lName) + || ("multi-toggle".equals(lName) && (getNameId() == FO_MULTI_CASE || findAncestor(FO_MULTI_CASE) > 0)) - || (lName.equals("footnote") + || ("footnote".equals(lName) && !isOutOfLineFODescendant) || isNeutralItem(nsURI, lName))); } @@ -487,11 +487,12 @@ public abstract class FObj extends FONode implements Constants { */ boolean isNeutralItem(String nsURI, String lName) { return (FO_URI.equals(nsURI) - && (lName.equals("multi-switch") - || lName.equals("multi-properties") - || lName.equals("wrapper") - || (!isOutOfLineFODescendant && lName.equals("float")) - || lName.equals("retrieve-marker"))); + && ("multi-switch".equals(lName) + || "multi-properties".equals(lName) + || "wrapper".equals(lName) + || (!isOutOfLineFODescendant && "float".equals(lName)) + || "retrieve-marker".equals(lName) + || "retrieve-table-marker".equals(lName))); } /** diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index 334f98e2f..9e4585d32 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -18,14 +18,11 @@ /* $Id$ */ package org.apache.fop.fo.flow; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.FOText; -import org.apache.fop.fo.FObj; -import org.apache.fop.fo.FObjMixed; -import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.*; import org.apache.fop.fo.flow.table.TableFObj; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.apps.FOPException; +import org.xml.sax.Locator; import java.util.Iterator; @@ -40,6 +37,8 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { private PropertyList propertyList; + private String retrieveClassName; + /** * Create a new AbstractRetrieveMarker instance that * is a child of the given {@link FONode} @@ -50,6 +49,17 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { super(parent); } + /** + * {@inheritDoc} + *

    XSL Content Model: empty + */ + protected void validateChildNode(Locator loc, String nsURI, String localName) + throws ValidationException { + if (FO_URI.equals(nsURI)) { + invalidChildError(loc, nsURI, localName); + } + } + /** * {@inheritDoc} * Store a reference to the parent {@link PropertyList} @@ -57,6 +67,10 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { */ public void bind(PropertyList pList) throws FOPException { super.bind(pList); + this.retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME).getString(); + if (retrieveClassName == null || retrieveClassName.equals("")) { + missingPropertyError("retrieve-class-name"); + } this.propertyList = pList.getParentPropertyList(); } @@ -169,4 +183,14 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { } } + /** + * Return the value for the retrieve-class-name + * property + * + * @return the value for retrieve-class-name + */ + public String getRetrieveClassName() { + return this.retrieveClassName; + } + } diff --git a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java index b75e14664..c696d3d14 100644 --- a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java @@ -19,12 +19,9 @@ package org.apache.fop.fo.flow; -import java.util.Iterator; - import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.ValidationException; import org.xml.sax.Locator; import org.xml.sax.Attributes; @@ -37,7 +34,6 @@ import org.xml.sax.Attributes; public class RetrieveMarker extends AbstractRetrieveMarker { // The value of properties relevant for fo:retrieve-marker. - private String retrieveClassName; private int retrievePosition; private int retrieveBoundary; // End of property values @@ -46,7 +42,7 @@ public class RetrieveMarker extends AbstractRetrieveMarker { * Create a new RetrieveMarker instance that is a * child of the given {@link FONode}. * - * @param parent {@link FONode} that is the parent of this object + * @param parent the parent {@link FONode} */ public RetrieveMarker(FONode parent) { super(parent); @@ -72,47 +68,34 @@ public class RetrieveMarker extends AbstractRetrieveMarker { /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { - - retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME).getString(); - retrievePosition = pList.get(PR_RETRIEVE_POSITION).getEnum(); - retrieveBoundary = pList.get(PR_RETRIEVE_BOUNDARY).getEnum(); - - if (retrieveClassName == null || retrieveClassName.equals("")) { - missingPropertyError("retrieve-class-name"); - } super.bind(pList); + this.retrievePosition = pList.get(PR_RETRIEVE_POSITION).getEnum(); + this.retrieveBoundary = pList.get(PR_RETRIEVE_BOUNDARY).getEnum(); } /** - * {@inheritDoc} - * XSL Content Model: empty - */ - protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI)) { - invalidChildError(loc, nsURI, localName); - } - } - - /** - * @return the "retrieve-class-name" property. - */ - public String getRetrieveClassName() { - return retrieveClassName; - } - - /** - * @return the "retrieve-position" property (enum value). + * Return the value for the retrieve-position + * property + * @return the value for retrieve-position-within-table; one of + * {@link org.apache.fop.fo.Constants#EN_FSWP}, + * {@link org.apache.fop.fo.Constants#EN_FIC}, + * {@link org.apache.fop.fo.Constants#EN_LSWP}, + * {@link org.apache.fop.fo.Constants#EN_LEWP}. */ public int getRetrievePosition() { - return retrievePosition; + return this.retrievePosition; } /** - * @return the "retrieve-boundary" property (enum value). + * Return the value for the retrieve-boundary + * property + * @return the value for retrieve-boundary-within-table; one of + * {@link org.apache.fop.fo.Constants#EN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_PAGE_SEQUENCE}, + * {@link org.apache.fop.fo.Constants#EN_DOCUMENT}. */ public int getRetrieveBoundary() { - return retrieveBoundary; + return this.retrieveBoundary; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java index 4a7b8af0d..9d04e308d 100644 --- a/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java +++ b/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id:$ */ +/* $Id$ */ package org.apache.fop.fo.flow; import org.apache.fop.fo.FONode; @@ -30,8 +30,7 @@ import org.xml.sax.Attributes; */ public class RetrieveTableMarker extends AbstractRetrieveMarker { - // The value of properties relevant for fo:retrieve-marker. - private String retrieveClassName; + // The value of properties relevant for fo:retrieve-table-marker. private int retrievePositionWithinTable; private int retrieveBoundaryWithinTable; // end property values @@ -46,7 +45,11 @@ public class RetrieveTableMarker extends AbstractRetrieveMarker { super(parent); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + * NOTE: An fo:retrieve-table-marker is only permitted as a descendant + * of an fo:table-header or an fo:table-footer. + */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { if (findAncestor(FO_TABLE_HEADER) < 0 && findAncestor(FO_TABLE_FOOTER) < 0) { @@ -59,18 +62,13 @@ public class RetrieveTableMarker extends AbstractRetrieveMarker { /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { - this.retrieveClassName = pList.get(PR_RETRIEVE_CLASS_NAME).getString(); + super.bind(pList); this.retrievePositionWithinTable = pList.get(PR_RETRIEVE_POSITION_WITHIN_TABLE).getEnum(); this.retrieveBoundaryWithinTable = pList.get(PR_RETRIEVE_BOUNDARY_WITHIN_TABLE).getEnum(); } - /** {@inheritDoc} */ - public String getRetrieveClassName() { - return this.retrieveClassName; - } - /** * Return the value for the retrieve-position-within-table * property diff --git a/test/fotree/testcases/table_retrieve-table-marker.fo b/test/fotree/testcases/table_retrieve-table-marker.fo index 3697fcd19..138d4d2fb 100644 --- a/test/fotree/testcases/table_retrieve-table-marker.fo +++ b/test/fotree/testcases/table_retrieve-table-marker.fo @@ -35,8 +35,8 @@ - - + + -- cgit v1.2.3 From 8055bd932a423e3da1c8f68d36a4afaa15cec85a Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 2 May 2008 17:00:33 +0000 Subject: Expand imports... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652822 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index 9e4585d32..83a0ddbdc 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -18,7 +18,12 @@ /* $Id$ */ package org.apache.fop.fo.flow; -import org.apache.fop.fo.*; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOText; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.FObjMixed; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.flow.table.TableFObj; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.apps.FOPException; -- cgit v1.2.3 From cecacaf0e4c2d925347c829121422068c95ea376 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 2 May 2008 17:28:25 +0000 Subject: Bugzilla 42703: Fixed a regression introduced by the fix for Bugzilla 44286 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@652835 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/XMLWhiteSpaceHandler.java | 5 ++-- status.xml | 9 ++++++- .../marker_white-space-treatment_bug42703.xml | 29 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java index bfebf6233..557a1778e 100644 --- a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java +++ b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java @@ -116,6 +116,7 @@ public class XMLWhiteSpaceHandler { if (ancestor.getNameId() == Constants.FO_BLOCK) { currentBlock = (Block) ancestor; + nestedBlockStack.push(currentBlock); } } else if (!nestedBlockStack.isEmpty()) { currentBlock = (Block) nestedBlockStack.peek(); @@ -206,9 +207,7 @@ public class XMLWhiteSpaceHandler { /* end of block: clear the references and pop the * nested block stack */ if (!nestedBlockStack.empty()) { - currentBlock = (Block) nestedBlockStack.pop(); - } else { - currentBlock = null; + nestedBlockStack.pop(); } charIter = null; } diff --git a/status.xml b/status.xml index ca4768446..fa3ee3c44 100644 --- a/status.xml +++ b/status.xml @@ -57,7 +57,14 @@ Added SVG support for AFP (GOCA). - + + Fixed a regression introduced by the fix for + Bugzilla 44286. + + + Activated min-height/max-height and min-width/max-width properties. + + Fixed a logic error in Hyphenator.java: If the source had an associated InputStream, an UnsupportedOperationException was triggered. diff --git a/test/layoutengine/standard-testcases/marker_white-space-treatment_bug42703.xml b/test/layoutengine/standard-testcases/marker_white-space-treatment_bug42703.xml index 0eb80f982..50ef57bb2 100644 --- a/test/layoutengine/standard-testcases/marker_white-space-treatment_bug42703.xml +++ b/test/layoutengine/standard-testcases/marker_white-space-treatment_bug42703.xml @@ -56,6 +56,33 @@ text with the marker + + + + + + + marker1 content: + + + marker1 content: + + + + + + + + Block with inline element . + + text with the marker + @@ -64,5 +91,7 @@ + + -- cgit v1.2.3 From e026c24034e1dfedb674d1b150cf790f2f0a1f22 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 3 May 2008 10:21:45 +0000 Subject: Cleanup: improve code-readibility git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653036 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/inline/TextLayoutManager.java | 764 +++++++++------------ 1 file changed, 320 insertions(+), 444 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 40e1c087a..9af0ba90d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -62,33 +62,40 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * Number of word-spaces? */ private class AreaInfo { - private short iStartIndex; - private short iBreakIndex; - private short iWScount; - private short iLScount; - private MinOptMax ipdArea; - private boolean bHyphenated; + private short startIndex; + private short breakIndex; + private short wordSpaceCount; + private short letterSpaceCount; + private MinOptMax areaIPD; + private boolean isHyphenated; private boolean isSpace; private boolean breakOppAfter; - public AreaInfo(short iSIndex, short iBIndex, short iWS, short iLS, - MinOptMax ipd, boolean bHyph, boolean isSpace, boolean breakOppAfter) { - iStartIndex = iSIndex; - iBreakIndex = iBIndex; - iWScount = iWS; - iLScount = iLS; - ipdArea = ipd; - bHyphenated = bHyph; + + AreaInfo(short startIndex, + short breakIndex, + short wordSpaceCount, + short letterSpaceCount, + MinOptMax areaIPD, + boolean isHyphenated, + boolean isSpace, + boolean breakOppAfter) { + this.startIndex = startIndex; + this.breakIndex = breakIndex; + this.wordSpaceCount = wordSpaceCount; + this.letterSpaceCount = letterSpaceCount; + this.areaIPD = areaIPD; + this.isHyphenated = isHyphenated; this.isSpace = isSpace; this.breakOppAfter = breakOppAfter; } public String toString() { - return "[ lscnt=" + iLScount - + ", wscnt=" + iWScount - + ", ipd=" + ipdArea.toString() - + ", sidx=" + iStartIndex - + ", bidx=" + iBreakIndex - + ", hyph=" + bHyphenated + return "[ lscnt=" + letterSpaceCount + + ", wscnt=" + wordSpaceCount + + ", ipd=" + areaIPD.toString() + + ", sidx=" + startIndex + + ", bidx=" + breakIndex + + ", hyph=" + isHyphenated + ", space=" + isSpace + "]"; } @@ -133,14 +140,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private static final char NEWLINE = '\n'; private Font font = null; - /** Start index of first character in this parent Area */ - private short iAreaStart = 0; /** Start index of next TextArea */ - private short iNextStart = 0; - /** Size since last makeArea call, except for last break */ - private MinOptMax ipdTotal; - /** Size including last break possibility returned */ - // private MinOptMax nextIPD = new MinOptMax(0); + private short nextStart = 0; /** size of a space character (U+0020) glyph in current font */ private int spaceCharIPD; private MinOptMax wordSpaceIPD; @@ -153,13 +154,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private SpaceVal halfWS; /** 1/2 of letter-spacing value */ private SpaceVal halfLS; - /** Number of space characters after previous possible break position. */ - private int iNbSpacesPending; - private boolean bChanged = false; - private int iReturnedIndex = 0; - private short iThisStart = 0; - private short iTempStart = 0; + private boolean hasChanged = false; + private int returnedIndex = 0; + private short thisStart = 0; + private short tempStart = 0; private LinkedList changeList = null; private AlignmentContext alignmentContext = null; @@ -185,7 +184,23 @@ public class TextLayoutManager extends LeafNodeLayoutManager { vecAreaInfo = new java.util.ArrayList(); } - + + private LeafPosition getAuxiliaryPosition() { + return new LeafPosition(this, -1); + } + + private KnuthPenalty makeInfinitePenalty() { + return new KnuthPenalty(0, KnuthElement.INFINITE, false, getAuxiliaryPosition(), true); + } + + private KnuthPenalty makeZeroPenalty() { + return new KnuthPenalty(0, 0, false, getAuxiliaryPosition(), true); + } + + private KnuthInlineBox makeZeroWidthBox() { + return new KnuthInlineBox(0, null, notifyPos(getAuxiliaryPosition()), true); + } + /** {@inheritDoc} */ public void initialize() { FontInfo fi = foText.getFOEventHandler().getFontInfo(); @@ -224,30 +239,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } - // TODO: see if we can use normal getNextBreakPoss for this with - // extra hyphenation information in LayoutContext - private boolean getHyphenIPD(HyphContext hc, MinOptMax hyphIPD) { - // Skip leading word-space before calculating count? - boolean bCanHyphenate = true; - int iStopIndex = iNextStart + hc.getNextHyphPoint(); - - if (textArray.length < iStopIndex) { - iStopIndex = textArray.length; - bCanHyphenate = false; - } - hc.updateOffset(iStopIndex - iNextStart); - - for (; iNextStart < iStopIndex; iNextStart++) { - char c = textArray[iNextStart]; - hyphIPD.opt += font.getCharWidth(c); - // letter-space? - } - // Need to include hyphen size too, but don't count it in the - // stored running total, since it would be double counted - // with later hyphenation points - return bCanHyphenate; - } - /** * Generate and add areas to parent area. * This can either generate an area for each TextArea and each space, or @@ -262,8 +253,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // Add word areas AreaInfo ai = null; - int iWScount = 0; - int iLScount = 0; + int wordSpaceCount = 0; + int letterSpaceCount = 0; int firstAreaInfoIndex = -1; int lastAreaInfoIndex = 0; MinOptMax realWidth = new MinOptMax(0); @@ -281,89 +272,89 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (firstAreaInfoIndex == -1) { firstAreaInfoIndex = tbpNext.getLeafPos(); } - iWScount += ai.iWScount; - iLScount += ai.iLScount; - realWidth.add(ai.ipdArea); + wordSpaceCount += ai.wordSpaceCount; + letterSpaceCount += ai.letterSpaceCount; + realWidth.add(ai.areaIPD); lastAreaInfoIndex = tbpNext.getLeafPos(); } } if (ai == null) { return; } - int textLength = ai.iBreakIndex - ai.iStartIndex; - if (ai.iLScount == textLength && !ai.bHyphenated + int textLength = ai.breakIndex - ai.startIndex; + if (ai.letterSpaceCount == textLength && !ai.isHyphenated && context.isLastArea()) { // the line ends at a character like "/" or "-"; // remove the letter space after the last character realWidth.add(MinOptMax.multiply(letterSpaceIPD, -1)); - iLScount--; + letterSpaceCount--; } - for (int i = ai.iStartIndex; i < ai.iBreakIndex; i++) { + for (int i = ai.startIndex; i < ai.breakIndex; i++) { MinOptMax ladj = letterAdjustArray[i + 1]; if (ladj != null && ladj.isElastic()) { - iLScount++; + letterSpaceCount++; } } // add hyphenation character if the last word is hyphenated - if (context.isLastArea() && ai.bHyphenated) { + if (context.isLastArea() && ai.isHyphenated) { realWidth.add(new MinOptMax(hyphIPD)); } // Calculate adjustments - int iDifference = 0; - int iTotalAdjust = 0; - int iWordSpaceDim = wordSpaceIPD.opt; - int iLetterSpaceDim = letterSpaceIPD.opt; - double dIPDAdjust = context.getIPDAdjust(); + int difference = 0; + int totalAdjust = 0; + int wordSpaceDim = wordSpaceIPD.opt; + int letterSpaceDim = letterSpaceIPD.opt; + double ipdAdjust = context.getIPDAdjust(); double dSpaceAdjust = context.getSpaceAdjust(); // not used // calculate total difference between real and available width - if (dIPDAdjust > 0.0) { - iDifference = (int) ((double) (realWidth.max - realWidth.opt) - * dIPDAdjust); + if (ipdAdjust > 0.0) { + difference = (int) ((double) (realWidth.max - realWidth.opt) + * ipdAdjust); } else { - iDifference = (int) ((double) (realWidth.opt - realWidth.min) - * dIPDAdjust); + difference = (int) ((double) (realWidth.opt - realWidth.min) + * ipdAdjust); } // set letter space adjustment - if (dIPDAdjust > 0.0) { - iLetterSpaceDim + if (ipdAdjust > 0.0) { + letterSpaceDim += (int) ((double) (letterSpaceIPD.max - letterSpaceIPD.opt) - * dIPDAdjust); + * ipdAdjust); } else { - iLetterSpaceDim + letterSpaceDim += (int) ((double) (letterSpaceIPD.opt - letterSpaceIPD.min) - * dIPDAdjust); + * ipdAdjust); } - iTotalAdjust += (iLetterSpaceDim - letterSpaceIPD.opt) * iLScount; + totalAdjust += (letterSpaceDim - letterSpaceIPD.opt) * letterSpaceCount; // set word space adjustment // - if (iWScount > 0) { - iWordSpaceDim += (int) ((iDifference - iTotalAdjust) / iWScount); + if (wordSpaceCount > 0) { + wordSpaceDim += (difference - totalAdjust) / wordSpaceCount; } else { // there are no word spaces in this area } - iTotalAdjust += (iWordSpaceDim - wordSpaceIPD.opt) * iWScount; - if (iTotalAdjust != iDifference) { + totalAdjust += (wordSpaceDim - wordSpaceIPD.opt) * wordSpaceCount; + if (totalAdjust != difference) { // the applied adjustment is greater or smaller than the needed one log.trace("TextLM.addAreas: error in word / letter space adjustment = " - + (iTotalAdjust - iDifference)); - // set iTotalAdjust = iDifference, so that the width of the TextArea + + (totalAdjust - difference)); + // set totalAdjust = difference, so that the width of the TextArea // will counterbalance the error and the other inline areas will be // placed correctly - iTotalAdjust = iDifference; + totalAdjust = difference; } - TextArea t = createTextArea(realWidth, iTotalAdjust, context, + TextArea t = createTextArea(realWidth, totalAdjust, context, wordSpaceIPD.opt - spaceCharIPD, firstAreaInfoIndex, lastAreaInfoIndex, context.isLastArea()); - // iWordSpaceDim is computed in relation to wordSpaceIPD.opt + // wordSpaceDim is computed in relation to wordSpaceIPD.opt // but the renderer needs to know the adjustment in relation // to the size of the space character in the current font; // moreover, the pdf renderer adds the character spacing even to @@ -373,10 +364,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // space width = // = "normal" space width + letterSpaceAdjust + wordSpaceAdjust // = spaceCharIPD + letterSpaceAdjust + - // + (iWordSpaceDim - spaceCharIPD - 2 * letterSpaceAdjust) - // = iWordSpaceDim - letterSpaceAdjust - t.setTextLetterSpaceAdjust(iLetterSpaceDim); - t.setTextWordSpaceAdjust(iWordSpaceDim - spaceCharIPD + // + (wordSpaceDim - spaceCharIPD - 2 * letterSpaceAdjust) + // = wordSpaceDim - letterSpaceAdjust + t.setTextLetterSpaceAdjust(letterSpaceDim); + t.setTextWordSpaceAdjust(wordSpaceDim - spaceCharIPD - 2 * t.getTextLetterSpaceAdjust()); if (context.getIPDAdjust() != 0) { // add information about space width @@ -431,7 +422,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (areaInfo.isSpace) { // areaInfo stores information about spaces // add the spaces - except zero-width spaces - to the TextArea - for (int j = areaInfo.iStartIndex; j < areaInfo.iBreakIndex; j++) { + for (int j = areaInfo.startIndex; j < areaInfo.breakIndex; j++) { char spaceChar = textArray[j]; if (!CharUtilities.isZeroWidthSpace(spaceChar)) { textArea.addSpace(spaceChar, 0, @@ -445,13 +436,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { wordStartIndex = i; len = 0; } - len += areaInfo.iBreakIndex - areaInfo.iStartIndex; + len += areaInfo.breakIndex - areaInfo.startIndex; if (i == lastIndex || ((AreaInfo) vecAreaInfo.get(i + 1)).isSpace) { // here ends a new word // add a word to the TextArea if (isLastArea && i == lastIndex - && areaInfo.bHyphenated) { + && areaInfo.isHyphenated) { len++; } StringBuffer wordChars = new StringBuffer(len); @@ -459,10 +450,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { int letter = 0; for (int j = wordStartIndex; j <= i; j++) { AreaInfo ai = (AreaInfo) vecAreaInfo.get(j); - int lsCount = ai.iLScount; - wordChars.append(textArray, ai.iStartIndex, ai.iBreakIndex - ai.iStartIndex); - for (int k = 0; k < ai.iBreakIndex - ai.iStartIndex; k++) { - MinOptMax adj = letterAdjustArray[ai.iStartIndex + k]; + int lsCount = ai.letterSpaceCount; + wordChars.append(textArray, ai.startIndex, ai.breakIndex - ai.startIndex); + for (int k = 0; k < ai.breakIndex - ai.startIndex; k++) { + MinOptMax adj = letterAdjustArray[ai.startIndex + k]; if (letter > 0) { letterAdjust[letter] = (adj != null ? adj.opt : 0); } @@ -476,7 +467,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // String wordChars = new String(textArray, wordStartIndex, len); if (isLastArea && i == lastIndex - && areaInfo.bHyphenated) { + && areaInfo.isHyphenated) { // add the hyphenation character wordChars.append(foText.getCommonHyphenation().getHyphChar(font)); } @@ -501,14 +492,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - private void addToLetterAdjust(int index, MinOptMax width) { - if (letterAdjustArray[index] == null) { - letterAdjustArray[index] = new MinOptMax(width); - } else { - letterAdjustArray[index].add(width); - } - } - /** * Indicates whether a character is a space in terms of this layout manager. * @param ch the character @@ -533,14 +516,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { returnList.add(sequence); LineBreakStatus lbs = new LineBreakStatus(); - iThisStart = iNextStart; + thisStart = nextStart; boolean inWord = false; boolean inWhitespace = false; char ch = 0; - while (iNextStart < textArray.length) { - ch = textArray[iNextStart]; + while (nextStart < textArray.length) { + ch = textArray[nextStart]; boolean breakOpportunity = false; - byte breakAction = keepTogether? LineBreakStatus.PROHIBITED_BREAK : lbs.nextChar(ch); + byte breakAction = keepTogether ? LineBreakStatus.PROHIBITED_BREAK : lbs.nextChar(ch); switch (breakAction) { case LineBreakStatus.COMBINING_PROHIBITED_BREAK: case LineBreakStatus.PROHIBITED_BREAK: @@ -558,14 +541,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (inWord) { if (breakOpportunity || isSpace(ch) || ch == NEWLINE) { //Word boundary found, process widths and kerning - int lastIndex = iNextStart; + short lastIndex = nextStart; while (lastIndex > 0 && textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { lastIndex--; } - int wordLength = lastIndex - iThisStart; + int wordLength = lastIndex - thisStart; boolean kerning = font.hasKerning(); MinOptMax wordIPD = new MinOptMax(0); - for (int i = iThisStart; i < lastIndex; i++) { + for (int i = thisStart; i < lastIndex; i++) { char c = textArray[i]; //character width @@ -575,11 +558,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //kerning if (kerning) { int kern = 0; - if (i > iThisStart) { + if (i > thisStart) { char previous = textArray[i - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } else if (prevAi != null && !prevAi.isSpace && prevAi.iBreakIndex > 0) { - char previous = textArray[prevAi.iBreakIndex - 1]; + } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { + char previous = textArray[prevAi.breakIndex - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } if (kern != 0) { @@ -605,27 +588,26 @@ public class TextLayoutManager extends LeafNodeLayoutManager { wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); // create the AreaInfo object - ai = new AreaInfo(iThisStart, (short)lastIndex, (short) 0, + ai = new AreaInfo(thisStart, lastIndex, (short) 0, (short) iLetterSpaces, wordIPD, textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, false, breakOpportunity); - vecAreaInfo.add(ai); prevAi = ai; - iTempStart = iNextStart; + vecAreaInfo.add(ai); + tempStart = nextStart; - // create the elements + //add the elements sequence.addAll(createElementsForAWordFragment(alignment, ai, vecAreaInfo.size() - 1, letterSpaceIPD)); ai = null; - - iThisStart = iNextStart; + thisStart = nextStart; } } else if (inWhitespace) { if (ch != CharUtilities.SPACE || breakOpportunity) { // End of whitespace // create the AreaInfo object - ai = new AreaInfo(iThisStart, (short) (iNextStart), - (short) (iNextStart - iThisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, iNextStart - iThisStart), + ai = new AreaInfo(thisStart, nextStart, + (short) (nextStart - thisStart), (short) 0, + MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), false, true, breakOpportunity); vecAreaInfo.add(ai); prevAi = ai; @@ -635,7 +617,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); ai = null; - iThisStart = iNextStart; + thisStart = nextStart; } } else { if (ai != null) { @@ -650,7 +632,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (lineEndBAP != 0) { sequence.add (new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), true)); + getAuxiliaryPosition(), true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -663,36 +645,36 @@ public class TextLayoutManager extends LeafNodeLayoutManager { || ch == CharUtilities.NBSPACE) { // preserved space or non-breaking space: // create the AreaInfo object - ai = new AreaInfo(iNextStart, (short) (iNextStart + 1), + ai = new AreaInfo(nextStart, (short) (nextStart + 1), (short) 1, (short) 0, wordSpaceIPD, false, true, breakOpportunity); - iThisStart = (short) (iNextStart + 1); + thisStart = (short) (nextStart + 1); } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) { // create the AreaInfo object MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); - ai = new AreaInfo(iNextStart, (short) (iNextStart + 1), + ai = new AreaInfo(nextStart, (short) (nextStart + 1), (short) 0, (short) 0, ipd, false, true, breakOpportunity); - iThisStart = (short) (iNextStart + 1); + thisStart = (short) (nextStart + 1); } else if (ch == NEWLINE) { // linefeed; this can happen when linefeed-treatment="preserve" - iThisStart = (short) (iNextStart + 1); + thisStart = (short) (nextStart + 1); } inWord = !isSpace(ch) && ch != NEWLINE; inWhitespace = ch == CharUtilities.SPACE && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; - iNextStart++; + nextStart++; } // end of while // Process any last elements if (inWord) { - int lastIndex = iNextStart; - if (textArray[iNextStart - 1] == CharUtilities.SOFT_HYPHEN) { + int lastIndex = nextStart; + if (textArray[nextStart - 1] == CharUtilities.SOFT_HYPHEN) { lastIndex--; } - int wordLength = lastIndex - iThisStart; + int wordLength = lastIndex - thisStart; boolean kerning = font.hasKerning(); MinOptMax wordIPD = new MinOptMax(0); - for (int i = iThisStart; i < lastIndex; i++) { + for (int i = thisStart; i < lastIndex; i++) { char c = textArray[i]; //character width @@ -702,11 +684,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //kerning if (kerning) { int kern = 0; - if (i > iThisStart) { + if (i > thisStart) { char previous = textArray[i - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } else if (prevAi != null && !prevAi.isSpace) { - char previous = textArray[prevAi.iBreakIndex - 1]; + char previous = textArray[prevAi.breakIndex - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } if (kern != 0) { @@ -720,20 +702,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager { wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); // create the AreaInfo object - ai = new AreaInfo(iThisStart, (short)lastIndex, (short) 0, + ai = new AreaInfo(thisStart, (short)lastIndex, (short) 0, (short) iLetterSpaces, wordIPD, false, false, false); vecAreaInfo.add(ai); - iTempStart = iNextStart; + tempStart = nextStart; // create the elements sequence.addAll(createElementsForAWordFragment(alignment, ai, vecAreaInfo.size() - 1, letterSpaceIPD)); ai = null; } else if (inWhitespace) { - ai = new AreaInfo(iThisStart, (short) (iNextStart), - (short) (iNextStart - iThisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, iNextStart - iThisStart), + ai = new AreaInfo(thisStart, (short) (nextStart), + (short) (nextStart - thisStart), (short) 0, + MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), false, true, true); vecAreaInfo.add(ai); @@ -751,7 +733,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (lineEndBAP != 0) { sequence.add (new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), true)); + getAuxiliaryPosition(), true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -782,29 +764,29 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //element could refer to '-1' position, for non-collapsed spaces (?) if (idx > -1) { AreaInfo ai = (AreaInfo) vecAreaInfo.get(idx); - ai.iLScount++; - ai.ipdArea.add(letterSpaceIPD); - if (BREAK_CHARS.indexOf(textArray[iTempStart - 1]) >= 0) { + ai.letterSpaceCount++; + ai.areaIPD.add(letterSpaceIPD); + if (BREAK_CHARS.indexOf(textArray[tempStart - 1]) >= 0) { // the last character could be used as a line break // append new elements to oldList oldListIterator = oldList.listIterator(oldList.size()); oldListIterator.add(new KnuthPenalty(0, KnuthPenalty.FLAGGED_PENALTY, true, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); oldListIterator.add(new KnuthGlue(letterSpaceIPD.opt, letterSpaceIPD.max - letterSpaceIPD.opt, letterSpaceIPD.opt - letterSpaceIPD.min, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } else if (letterSpaceIPD.min == letterSpaceIPD.max) { // constant letter space: replace the box - oldListIterator.set(new KnuthInlineBox(ai.ipdArea.opt, alignmentContext, pos, false)); + oldListIterator.set(new KnuthInlineBox(ai.areaIPD.opt, alignmentContext, pos, false)); } else { // adjustable letter space: replace the glue oldListIterator.next(); // this would return the penalty element oldListIterator.next(); // this would return the glue element - oldListIterator.set(new KnuthGlue(ai.iLScount * letterSpaceIPD.opt, - ai.iLScount * (letterSpaceIPD.max - letterSpaceIPD.opt), - ai.iLScount * (letterSpaceIPD.opt - letterSpaceIPD.min), - new LeafPosition(this, -1), true)); + oldListIterator.set(new KnuthGlue(ai.letterSpaceCount * letterSpaceIPD.opt, + ai.letterSpaceCount * (letterSpaceIPD.max - letterSpaceIPD.opt), + ai.letterSpaceCount * (letterSpaceIPD.opt - letterSpaceIPD.min), + getAuxiliaryPosition(), true)); } } return oldList; @@ -844,37 +826,37 @@ public class TextLayoutManager extends LeafNodeLayoutManager { public void hyphenate(Position pos, HyphContext hc) { AreaInfo ai = (AreaInfo) vecAreaInfo.get(((LeafPosition) pos).getLeafPos()); - int iStartIndex = ai.iStartIndex; - int iStopIndex; - boolean bNothingChanged = true; + int startIndex = ai.startIndex; + int stopIndex; + boolean nothingChanged = true; - while (iStartIndex < ai.iBreakIndex) { + while (startIndex < ai.breakIndex) { MinOptMax newIPD = new MinOptMax(0); - boolean bHyphenFollows; + boolean hyphenFollows; if (hc.hasMoreHyphPoints() - && (iStopIndex = iStartIndex + hc.getNextHyphPoint()) - <= ai.iBreakIndex) { - // iStopIndex is the index of the first character + && (stopIndex = startIndex + hc.getNextHyphPoint()) + <= ai.breakIndex) { + // stopIndex is the index of the first character // after a hyphenation point - bHyphenFollows = true; + hyphenFollows = true; } else { // there are no more hyphenation points, - // or the next one is after ai.iBreakIndex - bHyphenFollows = false; - iStopIndex = ai.iBreakIndex; + // or the next one is after ai.breakIndex + hyphenFollows = false; + stopIndex = ai.breakIndex; } - hc.updateOffset(iStopIndex - iStartIndex); + hc.updateOffset(stopIndex - startIndex); - //log.info("Word: " + new String(textArray, iStartIndex, iStopIndex - iStartIndex)); - for (int i = iStartIndex; i < iStopIndex; i++) { + //log.info("Word: " + new String(textArray, startIndex, stopIndex - startIndex)); + for (int i = startIndex; i < stopIndex; i++) { char c = textArray[i]; newIPD.add(new MinOptMax(font.getCharWidth(c))); - //if (i > iStartIndex) { - if (i < iStopIndex) { + //if (i > startIndex) { + if (i < stopIndex) { MinOptMax la = this.letterAdjustArray[i + 1]; - if ((i == iStopIndex - 1) && bHyphenFollows) { + if ((i == stopIndex - 1) && hyphenFollows) { //the letter adjust here needs to be handled further down during //element generation because it depends on hyph/no-hyph condition la = null; @@ -885,36 +867,36 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } // add letter spaces - boolean bIsWordEnd - = iStopIndex == ai.iBreakIndex - && ai.iLScount < (ai.iBreakIndex - ai.iStartIndex); + boolean isWordEnd + = stopIndex == ai.breakIndex + && ai.letterSpaceCount < (ai.breakIndex - ai.startIndex); newIPD.add(MinOptMax.multiply(letterSpaceIPD, - (bIsWordEnd - ? (iStopIndex - iStartIndex - 1) - : (iStopIndex - iStartIndex)))); + (isWordEnd + ? (stopIndex - startIndex - 1) + : (stopIndex - startIndex)))); - if (!(bNothingChanged - && iStopIndex == ai.iBreakIndex - && bHyphenFollows == false)) { + if (!(nothingChanged + && stopIndex == ai.breakIndex + && !hyphenFollows)) { // the new AreaInfo object is not equal to the old one if (changeList == null) { changeList = new LinkedList(); } changeList.add (new PendingChange - (new AreaInfo((short) iStartIndex, (short) iStopIndex, + (new AreaInfo((short) startIndex, (short) stopIndex, (short) 0, - (short) (bIsWordEnd - ? (iStopIndex - iStartIndex - 1) - : (iStopIndex - iStartIndex)), - newIPD, bHyphenFollows, false, false), + (short) (isWordEnd + ? (stopIndex - startIndex - 1) + : (stopIndex - startIndex)), + newIPD, hyphenFollows, false, false), ((LeafPosition) pos).getLeafPos())); - bNothingChanged = false; + nothingChanged = false; } - iStartIndex = iStopIndex; + startIndex = stopIndex; } - if (!bChanged && !bNothingChanged) { - bChanged = true; + if (!hasChanged && !nothingChanged) { + hasChanged = true; } } @@ -923,31 +905,31 @@ public class TextLayoutManager extends LeafNodeLayoutManager { setFinished(false); if (changeList != null) { - int iAddedAI = 0; - int iRemovedAI = 0; - int iOldIndex = -1; + int areaInfosAdded = 0; + int areaInfosRemoved = 0; + int oldIndex = -1; PendingChange currChange = null; ListIterator changeListIterator = changeList.listIterator(); while (changeListIterator.hasNext()) { currChange = (PendingChange) changeListIterator.next(); - if (currChange.index != iOldIndex) { - iRemovedAI++; - iAddedAI++; - iOldIndex = currChange.index; - vecAreaInfo.remove(currChange.index + iAddedAI - iRemovedAI); - vecAreaInfo.add(currChange.index + iAddedAI - iRemovedAI, + if (currChange.index != oldIndex) { + areaInfosRemoved++; + areaInfosAdded++; + oldIndex = currChange.index; + vecAreaInfo.remove(currChange.index + areaInfosAdded - areaInfosRemoved); + vecAreaInfo.add(currChange.index + areaInfosAdded - areaInfosRemoved, currChange.ai); } else { - iAddedAI++; - vecAreaInfo.add(currChange.index + iAddedAI - iRemovedAI, + areaInfosAdded++; + vecAreaInfo.add(currChange.index + areaInfosAdded - areaInfosRemoved, currChange.ai); } } changeList.clear(); } - iReturnedIndex = 0; - return bChanged; + returnedIndex = 0; + return hasChanged; } /** {@inheritDoc} */ @@ -959,18 +941,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { LinkedList returnList = new LinkedList(); - while (iReturnedIndex < vecAreaInfo.size()) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(iReturnedIndex); - if (ai.iWScount == 0) { + while (returnedIndex < vecAreaInfo.size()) { + AreaInfo ai = (AreaInfo) vecAreaInfo.get(returnedIndex); + if (ai.wordSpaceCount == 0) { // ai refers either to a word or a word fragment returnList.addAll - (createElementsForAWordFragment(alignment, ai, iReturnedIndex, letterSpaceIPD)); + (createElementsForAWordFragment(alignment, ai, returnedIndex, letterSpaceIPD)); } else { // ai refers to a space returnList.addAll - (createElementsForASpace(alignment, ai, iReturnedIndex)); + (createElementsForASpace(alignment, ai, returnedIndex)); } - iReturnedIndex++; + returnedIndex++; } // end of while setFinished(true); //ElementListObserver.observe(returnList, "text-changed", null); @@ -979,11 +961,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public void getWordChars(StringBuffer sbChars, Position pos) { - int iLeafValue = ((LeafPosition) pos).getLeafPos(); - if (iLeafValue != -1) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(iLeafValue); - sbChars.append(new String(textArray, ai.iStartIndex, - ai.iBreakIndex - ai.iStartIndex)); + int leafValue = ((LeafPosition) pos).getLeafPos(); + if (leafValue != -1) { + AreaInfo ai = (AreaInfo) vecAreaInfo.get(leafValue); + sbChars.append(new String(textArray, ai.startIndex, + ai.breakIndex - ai.startIndex)); } } @@ -991,26 +973,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { AreaInfo ai, int leafValue) { LinkedList spaceElements = new LinkedList(); LeafPosition mainPosition = new LeafPosition(this, leafValue); - + if (!ai.breakOppAfter) { // a non-breaking space if (alignment == EN_JUSTIFY) { // the space can stretch and shrink, and must be preserved // when starting a line - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), true)); - spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, - false, new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, ai.ipdArea.max - ai.ipdArea.opt, - ai.ipdArea.opt - ai.ipdArea.min, mainPosition, false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); + spaceElements.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, + ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); } else { // the space does not need to stretch or shrink, and must be // preserved when starting a line - spaceElements.add(new KnuthInlineBox(ai.ipdArea.opt, null, + spaceElements.add(new KnuthInlineBox(ai.areaIPD.opt, null, mainPosition, true)); } } else { - if (textArray[ai.iStartIndex] != CharUtilities.SPACE + if (textArray[ai.startIndex] != CharUtilities.SPACE || foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved switch (alignment) { @@ -1021,21 +1001,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // beginning of the next one, otherwise they don't add any stretch spaceElements.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements - .add(new KnuthPenalty( - 0, - 0, false, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); spaceElements.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, - false, new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt + lineStartBAP, + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); + spaceElements.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); break; @@ -1048,19 +1022,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // they don't add any stretch spaceElements.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); spaceElements.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt + lineStartBAP, 0, 0, + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); + spaceElements.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 0, 0, mainPosition, false)); break; @@ -1068,19 +1038,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // justified text: // the stretch and shrink depends on the space width spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); spaceElements.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), ai.ipdArea.max - - ai.ipdArea.opt, ai.ipdArea.opt - ai.ipdArea.min, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); - spaceElements.add(new KnuthGlue(lineStartBAP + ai.ipdArea.opt, 0, 0, + - (lineStartBAP + lineEndBAP), ai.areaIPD.max + - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); + spaceElements.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); break; @@ -1088,19 +1054,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // last line justified, the other lines unjustified: // use only the space stretch spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); spaceElements.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), ai.ipdArea.max - - ai.ipdArea.opt, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); - spaceElements.add(new KnuthGlue(lineStartBAP + ai.ipdArea.opt, 0, 0, + - (lineStartBAP + lineEndBAP), ai.areaIPD.max + - ai.areaIPD.opt, 0, + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); + spaceElements.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); } } else { @@ -1113,22 +1075,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // beginning of the next one, otherwise they don't add any stretch spaceElements.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements - .add(new KnuthPenalty( - 0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); + spaceElements.add(new KnuthGlue(ai.areaIPD.opt - (lineStartBAP + lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, KnuthElement.INFINITE, - false, new LeafPosition(this, -1), false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); spaceElements.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); break; case EN_START: // fall through @@ -1140,27 +1097,22 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (lineStartBAP != 0 || lineEndBAP != 0) { spaceElements.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); + spaceElements.add(new KnuthGlue(ai.areaIPD.opt - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } else { spaceElements.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, -3 + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); + spaceElements.add(new KnuthGlue(ai.areaIPD.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); } @@ -1171,25 +1123,21 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // the stretch and shrink depends on the space width if (lineStartBAP != 0 || lineEndBAP != 0) { spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); spaceElements.add(new KnuthGlue( - ai.ipdArea.opt - (lineStartBAP + lineEndBAP), - ai.ipdArea.max - ai.ipdArea.opt, - ai.ipdArea.opt - ai.ipdArea.min, + ai.areaIPD.opt - (lineStartBAP + lineEndBAP), + ai.areaIPD.max - ai.areaIPD.opt, + ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } else { - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, - ai.ipdArea.max - ai.ipdArea.opt, - ai.ipdArea.opt - ai.ipdArea.min, + spaceElements.add(new KnuthGlue(ai.areaIPD.opt, + ai.areaIPD.max - ai.areaIPD.opt, + ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); } break; @@ -1199,23 +1147,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // use only the space stretch if (lineStartBAP != 0 || lineEndBAP != 0) { spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); + spaceElements.add(makeZeroPenalty()); spaceElements.add(new KnuthGlue( - ai.ipdArea.opt - (lineStartBAP + lineEndBAP), - ai.ipdArea.max - ai.ipdArea.opt, + ai.areaIPD.opt - (lineStartBAP + lineEndBAP), + ai.areaIPD.max - ai.areaIPD.opt, 0, mainPosition, false)); - spaceElements.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - spaceElements.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, new LeafPosition( - this, -1), false)); + spaceElements.add(makeZeroWidthBox()); + spaceElements.add(makeInfinitePenalty()); spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } else { - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, - ai.ipdArea.max - ai.ipdArea.opt, 0, + spaceElements.add(new KnuthGlue(ai.areaIPD.opt, + ai.areaIPD.max - ai.areaIPD.opt, 0, mainPosition, false)); } } @@ -1233,54 +1177,50 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the last character of the word fragment is '-' or '/', // the fragment could end a line; in this case, it loses one // of its letter spaces; - boolean bSuppressibleLetterSpace = ai.breakOppAfter && !ai.bHyphenated; + boolean suppressibleLetterSpace = ai.breakOppAfter && !ai.isHyphenated; if (letterSpaceWidth.min == letterSpaceWidth.max) { // constant letter spacing wordElements.add (new KnuthInlineBox( - bSuppressibleLetterSpace - ? ai.ipdArea.opt - letterSpaceWidth.opt - : ai.ipdArea.opt, + suppressibleLetterSpace + ? ai.areaIPD.opt - letterSpaceWidth.opt + : ai.areaIPD.opt, alignmentContext, notifyPos(mainPosition), false)); } else { // adjustable letter spacing int unsuppressibleLetterSpaces - = bSuppressibleLetterSpace ? ai.iLScount - 1 : ai.iLScount; + = suppressibleLetterSpace ? ai.letterSpaceCount - 1 : ai.letterSpaceCount; wordElements.add - (new KnuthInlineBox(ai.ipdArea.opt - - ai.iLScount * letterSpaceWidth.opt, + (new KnuthInlineBox(ai.areaIPD.opt + - ai.letterSpaceCount * letterSpaceWidth.opt, alignmentContext, notifyPos(mainPosition), false)); - wordElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); + wordElements.add(makeInfinitePenalty()); wordElements.add (new KnuthGlue(unsuppressibleLetterSpaces * letterSpaceWidth.opt, unsuppressibleLetterSpaces * (letterSpaceWidth.max - letterSpaceWidth.opt), unsuppressibleLetterSpaces * (letterSpaceWidth.opt - letterSpaceWidth.min), - new LeafPosition(this, -1), true)); - wordElements.add - (new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), true)); + getAuxiliaryPosition(), true)); + wordElements.add(makeZeroWidthBox()); } // extra-elements if the word fragment is the end of a syllable, // or it ends with a character that can be used as a line break - if (ai.bHyphenated) { + if (ai.isHyphenated) { MinOptMax widthIfNoBreakOccurs = null; - if (ai.iBreakIndex < textArray.length) { + if (ai.breakIndex < textArray.length) { //Add in kerning in no-break condition - widthIfNoBreakOccurs = letterAdjustArray[ai.iBreakIndex]; + widthIfNoBreakOccurs = letterAdjustArray[ai.breakIndex]; } - //if (ai.iBreakIndex) + //if (ai.breakIndex) // the word fragment ends at the end of a syllable: // if a break occurs the content width increases, // otherwise nothing happens - wordElements.addAll(createElementsForAHyphen(alignment, hyphIPD, widthIfNoBreakOccurs, ai.breakOppAfter && ai.bHyphenated)); - } else if (bSuppressibleLetterSpace) { + wordElements.addAll(createElementsForAHyphen(alignment, hyphIPD, widthIfNoBreakOccurs, ai.breakOppAfter && ai.isHyphenated)); + } else if (suppressibleLetterSpace) { // the word fragment ends with a character that acts as a hyphen // if a break occurs the width does not increase, // otherwise there is one more letter space @@ -1301,132 +1241,74 @@ public class TextLayoutManager extends LeafNodeLayoutManager { switch (alignment) { case EN_CENTER : // centered text: - /* - hyphenElements.add - (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthPenalty(hyphIPD, - KnuthPenalty.FLAGGED_PENALTY, true, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthGlue(0, - - 6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthInlineBox(0, 0, 0, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, true, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - */ - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); + hyphenElements.add(makeInfinitePenalty()); hyphenElements.add (new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), true)); + getAuxiliaryPosition(), true)); hyphenElements.add (new KnuthPenalty(hyphIPD, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); hyphenElements.add (new KnuthGlue(-(lineEndBAP + lineStartBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), true)); - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); + getAuxiliaryPosition(), false)); + hyphenElements.add(makeZeroWidthBox()); + hyphenElements.add(makeInfinitePenalty()); hyphenElements.add (new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), true)); + getAuxiliaryPosition(), true)); break; case EN_START : // fall through case EN_END : // left- or right-aligned text: - /* - hyphenElements.add - (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, - KnuthPenalty.FLAGGED_PENALTY, true, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthGlue(widthIfNoBreakOccurs.opt, - - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - */ if (lineStartBAP != 0 || lineEndBAP != 0) { - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); + hyphenElements.add(makeInfinitePenalty()); hyphenElements.add (new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); hyphenElements.add (new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); hyphenElements.add (new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); + hyphenElements.add(makeZeroWidthBox()); + hyphenElements.add(makeInfinitePenalty()); hyphenElements.add (new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } else { - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); + hyphenElements.add(makeInfinitePenalty()); hyphenElements.add (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); hyphenElements.add (new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); hyphenElements.add (new KnuthGlue(widthIfNoBreakOccurs.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } break; default: // justified text, or last line justified: // just a flagged penalty - /* - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, - KnuthPenalty.FLAGGED_PENALTY, true, - new LeafPosition(this, -1), false)); - */ if (lineStartBAP != 0 || lineEndBAP != 0) { - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); - + hyphenElements.add(makeInfinitePenalty()); hyphenElements.add (new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); hyphenElements.add (new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 @@ -1435,26 +1317,22 @@ public class TextLayoutManager extends LeafNodeLayoutManager { (new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } else { hyphenElements.add (new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } - hyphenElements.add - (new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), false)); - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), false)); + hyphenElements.add(new KnuthInlineBox(0, null, notifyPos(getAuxiliaryPosition()), true)); + hyphenElements.add(makeInfinitePenalty()); hyphenElements.add (new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } else { hyphenElements.add (new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 @@ -1463,7 +1341,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { (new KnuthGlue(widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - new LeafPosition(this, -1), false)); + getAuxiliaryPosition(), false)); } } } @@ -1471,6 +1349,4 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return hyphenElements; } -} - - +} \ No newline at end of file -- cgit v1.2.3 From 6baa2824e1bbcc09ee4267c30b0456b5f70074e2 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 3 May 2008 10:51:16 +0000 Subject: Tweak/correction: save local hash-code (as originally intended...) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653045 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/properties/CommonHyphenation.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java index f47ddbe0c..dfafa3b16 100644 --- a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java +++ b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java @@ -203,7 +203,7 @@ public final class CommonHyphenation { /** {@inheritDoc} */ public int hashCode() { - if (hash == 0) { + if (this.hash == 0) { int hash = 17; hash = 37 * hash + (language == null ? 0 : language.hashCode()); hash = 37 * hash + (script == null ? 0 : script.hashCode()); @@ -215,8 +215,9 @@ public final class CommonHyphenation { (hyphenationPushCharacterCount == null ? 0 : hyphenationPushCharacterCount.hashCode()); hash = 37 * hash + (hyphenationRemainCharacterCount == null ? 0 : hyphenationRemainCharacterCount.hashCode()); + this.hash = hash; } - return hash; + return this.hash; } } -- cgit v1.2.3 From df1a55e4c7d582228dda8a527ff288d6d44b8958 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 3 May 2008 10:55:07 +0000 Subject: Tweaks: make fobj member final; have default implementations for some methods throw an UnsupportedOperationException instead of merely logging an error git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653048 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/AbstractBaseLayoutManager.java | 51 +++++++++------------- 1 file changed, 20 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java index c5e0ddfc9..a5af4c167 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java @@ -29,7 +29,7 @@ import org.apache.fop.fo.FObj; * The base class for nearly all LayoutManagers. * Provides the functionality for merging the {@link LayoutManager} * and the {@link org.apache.fop.datatypes.PercentBaseContext} interfaces - * into a common base calls for all higher LayoutManagers. + * into a common base class for all higher LayoutManagers. */ public abstract class AbstractBaseLayoutManager implements LayoutManager, PercentBaseContext { @@ -39,7 +39,7 @@ public abstract class AbstractBaseLayoutManager /** Indicator if this LM generates block areas */ protected boolean generatesBlockArea = false; /** The formatting object for this LM */ - protected FObj fobj = null; + protected final FObj fobj; /** * logging instance @@ -50,6 +50,7 @@ public abstract class AbstractBaseLayoutManager * Abstract base layout manager. */ public AbstractBaseLayoutManager() { + fobj = null; } /** @@ -67,9 +68,7 @@ public abstract class AbstractBaseLayoutManager // --------- Property Resolution related functions --------- // - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getBaseLength(int lengthBase, FObj fobj) { if (fobj == this.fobj) { switch (lengthBase) { @@ -82,7 +81,7 @@ public abstract class AbstractBaseLayoutManager case LengthBase.CONTAINING_REFAREA_WIDTH: return getReferenceAreaIPD(); default: - log.error(new Exception("Unknown base type for LengthBase:" + lengthBase)); + log.error("Unknown base type for LengthBase:" + lengthBase); return 0; } } else { @@ -112,9 +111,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - if (lm == null) { - log.error("No parent LM found"); - } + log.error("No parent LM found"); return 0; } @@ -131,9 +128,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - if (lm == null) { - log.error("No parent LM found"); - } + log.error("No parent LM found"); return 0; } @@ -176,9 +171,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - if (lm == null) { - log.error("No parent LM found"); - } + log.error("No parent LM found"); return 0; } @@ -195,31 +188,31 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - if (lm == null) { - log.error("No parent LM found"); - } + log.error("No parent LM found"); return 0; } /** * {@inheritDoc} + * NOTE: Should be overridden by subclasses. + * Default implementation throws an UnsupportedOperationException. */ public int getContentAreaIPD() { - log.error("getContentAreaIPD called when it should have been overwritten"); - return 0; + throw new UnsupportedOperationException( + "getContentAreaIPD() called when it should have been overridden"); } /** * {@inheritDoc} + * NOTE: Should be overridden by subclasses. + * Default implementation throws an UnsupportedOperationException. */ public int getContentAreaBPD() { - log.error("getContentAreaBPD called when it should have been overwritten"); - return 0; + throw new UnsupportedOperationException( + "getContentAreaBPD() called when it should have been overridden"); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean getGeneratesReferenceArea() { return generatesReferenceArea; } @@ -234,9 +227,7 @@ public abstract class AbstractBaseLayoutManager this.generatesReferenceArea = generatesReferenceArea; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean getGeneratesBlockArea() { return generatesBlockArea; } @@ -250,9 +241,7 @@ public abstract class AbstractBaseLayoutManager this.generatesBlockArea = generatesBlockArea; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean getGeneratesLineArea() { return false; } -- cgit v1.2.3 From ad7d7b3b8074bb142bf02e3f0de58acbb3a7069f Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Sat, 3 May 2008 19:07:18 +0000 Subject: Fixed the build. Assignment on final variable fobj. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653106 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java index a5af4c167..67ef4d911 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java @@ -39,7 +39,7 @@ public abstract class AbstractBaseLayoutManager /** Indicator if this LM generates block areas */ protected boolean generatesBlockArea = false; /** The formatting object for this LM */ - protected final FObj fobj; + protected FObj fobj; /** * logging instance -- cgit v1.2.3 From 3337d89c3ed0df06e69c0658c200c78c2ae88d77 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Sat, 3 May 2008 21:29:09 +0000 Subject: Fix that preserves the final status of the fobj member variable. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653144 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java | 4 ++-- src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java index 67ef4d911..7fd289c05 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java @@ -39,7 +39,7 @@ public abstract class AbstractBaseLayoutManager /** Indicator if this LM generates block areas */ protected boolean generatesBlockArea = false; /** The formatting object for this LM */ - protected FObj fobj; + protected final FObj fobj; /** * logging instance @@ -59,7 +59,7 @@ public abstract class AbstractBaseLayoutManager * @param fo the formatting object for this layout manager */ public AbstractBaseLayoutManager(FObj fo) { - fobj = fo; + this.fobj = fo; setGeneratesReferenceArea(fo.generatesReferenceAreas()); if (getGeneratesReferenceArea()) { setGeneratesBlockArea(true); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 430356bec..6afb57dca 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -83,7 +83,6 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager */ public TableCellLayoutManager(TableCell node, PrimaryGridUnit pgu) { super(node); - fobj = node; this.primaryGridUnit = pgu; } -- cgit v1.2.3 From c8cb0583fc806ea8f5ee56e670092f44066fbcd7 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 4 May 2008 11:37:31 +0000 Subject: Change private element-generating methods to add the elements to a passed List (improves code-readability and reduces the amount of temporary LinkedList instances) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653202 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/inline/TextLayoutManager.java | 302 ++++++++++----------- 1 file changed, 147 insertions(+), 155 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 9af0ba90d..f87605b27 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -88,7 +88,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.isSpace = isSpace; this.breakOppAfter = breakOppAfter; } - + public String toString() { return "[ lscnt=" + letterSpaceCount + ", wscnt=" + wordSpaceCount @@ -190,15 +190,29 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } private KnuthPenalty makeInfinitePenalty() { - return new KnuthPenalty(0, KnuthElement.INFINITE, false, getAuxiliaryPosition(), true); + return new KnuthPenalty( + 0, + KnuthElement.INFINITE, + false, + getAuxiliaryPosition(), + true); } private KnuthPenalty makeZeroPenalty() { - return new KnuthPenalty(0, 0, false, getAuxiliaryPosition(), true); + return new KnuthPenalty( + 0, + 0, + false, + getAuxiliaryPosition(), + true); } private KnuthInlineBox makeZeroWidthBox() { - return new KnuthInlineBox(0, null, notifyPos(getAuxiliaryPosition()), true); + return new KnuthInlineBox( + 0, + null, + notifyPos(getAuxiliaryPosition()), + true); } /** {@inheritDoc} */ @@ -519,7 +533,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { thisStart = nextStart; boolean inWord = false; boolean inWhitespace = false; - char ch = 0; + char ch = 0; while (nextStart < textArray.length) { ch = textArray[nextStart]; boolean breakOpportunity = false; @@ -564,12 +578,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { char previous = textArray[prevAi.breakIndex - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } + } if (kern != 0) { //log.info("Kerning between " + previous + " and " + c + ": " + kern); addToLetterAdjust(i, kern); wordIPD.add(kern); - } + } } } if (kerning && breakOpportunity && !isSpace(ch) && lastIndex > 0 && textArray[lastIndex] == CharUtilities.SOFT_HYPHEN) { @@ -596,8 +610,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { tempStart = nextStart; //add the elements - sequence.addAll(createElementsForAWordFragment(alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD)); + addElementsForAWordFragment(sequence, alignment, ai, + vecAreaInfo.size() - 1, letterSpaceIPD); ai = null; thisStart = nextStart; } @@ -613,8 +627,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { prevAi = ai; // create the elements - sequence.addAll - (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); + addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); ai = null; thisStart = nextStart; @@ -623,16 +636,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (ai != null) { vecAreaInfo.add(ai); prevAi = ai; - ai.breakOppAfter = ch == CharUtilities.SPACE || breakOpportunity; - sequence.addAll - (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); + ai.breakOppAfter = (ch == CharUtilities.SPACE) || breakOpportunity; + addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); ai = null; } if (breakAction == LineBreakStatus.EXPLICIT_BREAK) { if (lineEndBAP != 0) { - sequence.add - (new KnuthGlue(lineEndBAP, 0, 0, - getAuxiliaryPosition(), true)); + sequence.add( + new KnuthGlue(lineEndBAP, 0, 0, + getAuxiliaryPosition(), true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -690,12 +702,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } else if (prevAi != null && !prevAi.isSpace) { char previous = textArray[prevAi.breakIndex - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } + } if (kern != 0) { //log.info("Kerning between " + previous + " and " + c + ": " + kern); addToLetterAdjust(i, kern); wordIPD.add(kern); - } + } } } int iLetterSpaces = wordLength - 1; @@ -709,8 +721,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { tempStart = nextStart; // create the elements - sequence.addAll(createElementsForAWordFragment(alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD)); + addElementsForAWordFragment(sequence, alignment, ai, + vecAreaInfo.size() - 1, letterSpaceIPD); ai = null; } else if (inWhitespace) { ai = new AreaInfo(thisStart, (short) (nextStart), @@ -720,14 +732,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { vecAreaInfo.add(ai); // create the elements - sequence.addAll - (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); + addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); ai = null; } else if (ai != null) { vecAreaInfo.add(ai); ai.breakOppAfter = ch == CharUtilities.ZERO_WIDTH_SPACE; - sequence.addAll - (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); + addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); ai = null; } else if (ch == NEWLINE) { if (lineEndBAP != 0) { @@ -945,12 +955,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { AreaInfo ai = (AreaInfo) vecAreaInfo.get(returnedIndex); if (ai.wordSpaceCount == 0) { // ai refers either to a word or a word fragment - returnList.addAll - (createElementsForAWordFragment(alignment, ai, returnedIndex, letterSpaceIPD)); + addElementsForAWordFragment(returnList, alignment, ai, returnedIndex, letterSpaceIPD); } else { // ai refers to a space - returnList.addAll - (createElementsForASpace(alignment, ai, returnedIndex)); + addElementsForASpace(returnList, alignment, ai, returnedIndex); } returnedIndex++; } // end of while @@ -969,9 +977,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - private LinkedList createElementsForASpace(int alignment, - AreaInfo ai, int leafValue) { - LinkedList spaceElements = new LinkedList(); + private void addElementsForASpace(List baseList, + int alignment, + AreaInfo ai, + int leafValue) { LeafPosition mainPosition = new LeafPosition(this, leafValue); if (!ai.breakOppAfter) { @@ -979,14 +988,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (alignment == EN_JUSTIFY) { // the space can stretch and shrink, and must be preserved // when starting a line - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); } else { // the space does not need to stretch or shrink, and must be // preserved when starting a line - spaceElements.add(new KnuthInlineBox(ai.areaIPD.opt, null, + baseList.add(new KnuthInlineBox(ai.areaIPD.opt, null, mainPosition, true)); } } else { @@ -999,17 +1008,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line and at the // beginning of the next one, otherwise they don't add any stretch - spaceElements.add(new KnuthGlue(lineEndBAP, + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue( + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); break; @@ -1020,49 +1029,49 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line, otherwise // they don't add any stretch - spaceElements.add(new KnuthGlue(lineEndBAP, + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue( + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 0, 0, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 0, 0, mainPosition, false)); break; case EN_JUSTIFY: // justified text: // the stretch and shrink depends on the space width - spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue( + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); break; default: // last line justified, the other lines unjustified: // use only the space stretch - spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue( + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); } } else { @@ -1073,17 +1082,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line and at the // beginning of the next one, otherwise they don't add any stretch - spaceElements.add(new KnuthGlue(lineEndBAP, + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue(ai.areaIPD.opt + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue(ai.areaIPD.opt - (lineStartBAP + lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(lineStartBAP, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); break; @@ -1095,24 +1104,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // add a constant amount of stretch at the end of a line, otherwise // they don't add any stretch if (lineStartBAP != 0 || lineEndBAP != 0) { - spaceElements.add(new KnuthGlue(lineEndBAP, + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue(ai.areaIPD.opt + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue(ai.areaIPD.opt - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, getAuxiliaryPosition(), false)); } else { - spaceElements.add(new KnuthGlue(0, + baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue(ai.areaIPD.opt, -3 + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); } @@ -1122,20 +1131,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // justified text: // the stretch and shrink depends on the space width if (lineStartBAP != 0 || lineEndBAP != 0) { - spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue( + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue( ai.areaIPD.opt - (lineStartBAP + lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, getAuxiliaryPosition(), false)); } else { - spaceElements.add(new KnuthGlue(ai.areaIPD.opt, + baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); @@ -1146,32 +1155,33 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // last line justified, the other lines unjustified: // use only the space stretch if (lineStartBAP != 0 || lineEndBAP != 0) { - spaceElements.add(new KnuthGlue(lineEndBAP, 0, 0, + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, getAuxiliaryPosition(), false)); - spaceElements.add(makeZeroPenalty()); - spaceElements.add(new KnuthGlue( + baseList.add(makeZeroPenalty()); + baseList.add(new KnuthGlue( ai.areaIPD.opt - (lineStartBAP + lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, 0, mainPosition, false)); - spaceElements.add(makeZeroWidthBox()); - spaceElements.add(makeInfinitePenalty()); - spaceElements.add(new KnuthGlue(lineStartBAP, 0, 0, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, getAuxiliaryPosition(), false)); } else { - spaceElements.add(new KnuthGlue(ai.areaIPD.opt, + baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, 0, mainPosition, false)); } } } - } - - return spaceElements; + } } - private LinkedList createElementsForAWordFragment(int alignment, - AreaInfo ai, int leafValue, MinOptMax letterSpaceWidth) { - LinkedList wordElements = new LinkedList(); + private void addElementsForAWordFragment(List baseList, + int alignment, + AreaInfo ai, + int leafValue, + MinOptMax letterSpaceWidth) { + LeafPosition mainPosition = new LeafPosition(this, leafValue); // if the last character of the word fragment is '-' or '/', @@ -1181,8 +1191,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (letterSpaceWidth.min == letterSpaceWidth.max) { // constant letter spacing - wordElements.add - (new KnuthInlineBox( + baseList.add(new KnuthInlineBox( suppressibleLetterSpace ? ai.areaIPD.opt - letterSpaceWidth.opt : ai.areaIPD.opt, @@ -1192,18 +1201,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // adjustable letter spacing int unsuppressibleLetterSpaces = suppressibleLetterSpace ? ai.letterSpaceCount - 1 : ai.letterSpaceCount; - wordElements.add + baseList.add (new KnuthInlineBox(ai.areaIPD.opt - ai.letterSpaceCount * letterSpaceWidth.opt, alignmentContext, notifyPos(mainPosition), false)); - wordElements.add(makeInfinitePenalty()); - wordElements.add + baseList.add(makeInfinitePenalty()); + baseList.add (new KnuthGlue(unsuppressibleLetterSpaces * letterSpaceWidth.opt, unsuppressibleLetterSpaces * (letterSpaceWidth.max - letterSpaceWidth.opt), unsuppressibleLetterSpaces * (letterSpaceWidth.opt - letterSpaceWidth.min), getAuxiliaryPosition(), true)); - wordElements.add(makeZeroWidthBox()); + baseList.add(makeZeroWidthBox()); } // extra-elements if the word fragment is the end of a syllable, @@ -1219,44 +1228,42 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // the word fragment ends at the end of a syllable: // if a break occurs the content width increases, // otherwise nothing happens - wordElements.addAll(createElementsForAHyphen(alignment, hyphIPD, widthIfNoBreakOccurs, ai.breakOppAfter && ai.isHyphenated)); + addElementsForAHyphen(baseList, alignment, hyphIPD, widthIfNoBreakOccurs, ai.breakOppAfter && ai.isHyphenated); } else if (suppressibleLetterSpace) { // the word fragment ends with a character that acts as a hyphen // if a break occurs the width does not increase, // otherwise there is one more letter space - wordElements.addAll(createElementsForAHyphen(alignment, 0, letterSpaceWidth, true)); + addElementsForAHyphen(baseList, alignment, 0, letterSpaceWidth, true); } - return wordElements; } // static final int SOFT_HYPHEN_PENALTY = KnuthPenalty.FLAGGED_PENALTY / 10; static final int SOFT_HYPHEN_PENALTY = 1; - private LinkedList createElementsForAHyphen(int alignment, - int widthIfBreakOccurs, MinOptMax widthIfNoBreakOccurs, boolean unflagged) { + + private void addElementsForAHyphen(List baseList, + int alignment, + int widthIfBreakOccurs, + MinOptMax widthIfNoBreakOccurs, + boolean unflagged) { if (widthIfNoBreakOccurs == null) { widthIfNoBreakOccurs = ZERO_MINOPTMAX; } - LinkedList hyphenElements = new LinkedList(); - + switch (alignment) { case EN_CENTER : // centered text: - hyphenElements.add(makeInfinitePenalty()); - hyphenElements.add - (new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), true)); - hyphenElements.add - (new KnuthPenalty(hyphIPD, + baseList.add(new KnuthPenalty(hyphIPD, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, getAuxiliaryPosition(), false)); - hyphenElements.add - (new KnuthGlue(-(lineEndBAP + lineStartBAP), + baseList.add(new KnuthGlue(-(lineEndBAP + lineStartBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - hyphenElements.add(makeZeroWidthBox()); - hyphenElements.add(makeInfinitePenalty()); - hyphenElements.add - (new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), true)); break; @@ -1264,34 +1271,27 @@ public class TextLayoutManager extends LeafNodeLayoutManager { case EN_END : // left- or right-aligned text: if (lineStartBAP != 0 || lineEndBAP != 0) { - hyphenElements.add(makeInfinitePenalty()); - hyphenElements.add - (new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, + baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, getAuxiliaryPosition(), false)); - hyphenElements.add - (new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - hyphenElements.add(makeZeroWidthBox()); - hyphenElements.add(makeInfinitePenalty()); - hyphenElements.add - (new KnuthGlue(lineStartBAP, 0, 0, + baseList.add(makeZeroWidthBox()); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, getAuxiliaryPosition(), false)); } else { - hyphenElements.add(makeInfinitePenalty()); - hyphenElements.add - (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, + baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, getAuxiliaryPosition(), false)); - hyphenElements.add - (new KnuthGlue(widthIfNoBreakOccurs.opt, + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, getAuxiliaryPosition(), false)); } @@ -1301,44 +1301,37 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // justified text, or last line justified: // just a flagged penalty if (lineStartBAP != 0 || lineEndBAP != 0) { - hyphenElements.add(makeInfinitePenalty()); - hyphenElements.add - (new KnuthGlue(lineEndBAP, 0, 0, + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, getAuxiliaryPosition(), false)); - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, + baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, getAuxiliaryPosition(), false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 || widthIfNoBreakOccurs.max != 0) { - hyphenElements.add - (new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, getAuxiliaryPosition(), false)); } else { - hyphenElements.add - (new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, + baseList.add(new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, getAuxiliaryPosition(), false)); } - hyphenElements.add(new KnuthInlineBox(0, null, notifyPos(getAuxiliaryPosition()), true)); - hyphenElements.add(makeInfinitePenalty()); - hyphenElements.add - (new KnuthGlue(lineStartBAP, 0, 0, + baseList.add(new KnuthInlineBox(0, null, notifyPos(getAuxiliaryPosition()), true)); + baseList.add(makeInfinitePenalty()); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, getAuxiliaryPosition(), false)); } else { - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, + baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, getAuxiliaryPosition(), false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 || widthIfNoBreakOccurs.max != 0) { - hyphenElements.add - (new KnuthGlue(widthIfNoBreakOccurs.opt, + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, getAuxiliaryPosition(), false)); @@ -1346,7 +1339,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - return hyphenElements; } } \ No newline at end of file -- cgit v1.2.3 From 8ef418853362f511f72c6cd5c2397aa36aae3ce2 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 4 May 2008 13:04:28 +0000 Subject: Further refinements: -> use cached auxiliary position where possible (analogous to BlockStackingLM) -> consolidate makeXXXPenalty() helpers git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653204 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/inline/TextLayoutManager.java | 187 ++++++++++----------- 1 file changed, 89 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index f87605b27..02f809f73 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -168,6 +168,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private boolean keepTogether; + private final Position auxiliaryPosition; + /** * Create a Text layout manager. * @@ -183,35 +185,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { letterAdjustArray = new MinOptMax[textArray.length + 1]; vecAreaInfo = new java.util.ArrayList(); - } - private LeafPosition getAuxiliaryPosition() { - return new LeafPosition(this, -1); + auxiliaryPosition = new LeafPosition(this, -1); } - private KnuthPenalty makeInfinitePenalty() { + private KnuthPenalty makeZeroWidthPenalty(int penaltyValue) { return new KnuthPenalty( 0, - KnuthElement.INFINITE, - false, - getAuxiliaryPosition(), - true); - } - - private KnuthPenalty makeZeroPenalty() { - return new KnuthPenalty( - 0, - 0, + penaltyValue, false, - getAuxiliaryPosition(), + auxiliaryPosition, true); } - private KnuthInlineBox makeZeroWidthBox() { + private KnuthBox makeAuxiliaryZeroWidthBox() { return new KnuthInlineBox( 0, null, - notifyPos(getAuxiliaryPosition()), + notifyPos(new LeafPosition(this, -1)), true); } @@ -644,7 +635,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (lineEndBAP != 0) { sequence.add( new KnuthGlue(lineEndBAP, 0, 0, - getAuxiliaryPosition(), true)); + auxiliaryPosition, true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -743,7 +734,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (lineEndBAP != 0) { sequence.add (new KnuthGlue(lineEndBAP, 0, 0, - getAuxiliaryPosition(), true)); + auxiliaryPosition, true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -781,11 +772,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // append new elements to oldList oldListIterator = oldList.listIterator(oldList.size()); oldListIterator.add(new KnuthPenalty(0, KnuthPenalty.FLAGGED_PENALTY, true, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); oldListIterator.add(new KnuthGlue(letterSpaceIPD.opt, letterSpaceIPD.max - letterSpaceIPD.opt, letterSpaceIPD.opt - letterSpaceIPD.min, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } else if (letterSpaceIPD.min == letterSpaceIPD.max) { // constant letter space: replace the box oldListIterator.set(new KnuthInlineBox(ai.areaIPD.opt, alignmentContext, pos, false)); @@ -796,7 +787,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { oldListIterator.set(new KnuthGlue(ai.letterSpaceCount * letterSpaceIPD.opt, ai.letterSpaceCount * (letterSpaceIPD.max - letterSpaceIPD.opt), ai.letterSpaceCount * (letterSpaceIPD.opt - letterSpaceIPD.min), - getAuxiliaryPosition(), true)); + auxiliaryPosition, true)); } } return oldList; @@ -988,8 +979,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (alignment == EN_JUSTIFY) { // the space can stretch and shrink, and must be preserved // when starting a line - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); } else { @@ -1010,14 +1001,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // beginning of the next one, otherwise they don't add any stretch baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); @@ -1031,14 +1022,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // they don't add any stretch baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 0, 0, mainPosition, false)); break; @@ -1047,14 +1038,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // justified text: // the stretch and shrink depends on the space width baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); break; @@ -1063,14 +1054,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // last line justified, the other lines unjustified: // use only the space stretch baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - (lineStartBAP + lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); } @@ -1084,17 +1075,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // beginning of the next one, otherwise they don't add any stretch baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue(ai.areaIPD.opt - (lineStartBAP + lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); break; case EN_START: // fall through @@ -1106,21 +1097,21 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (lineStartBAP != 0 || lineEndBAP != 0) { baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue(ai.areaIPD.opt - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } else { baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); @@ -1132,17 +1123,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // the stretch and shrink depends on the space width if (lineStartBAP != 0 || lineEndBAP != 0) { baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( ai.areaIPD.opt - (lineStartBAP + lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } else { baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, @@ -1156,16 +1147,16 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // use only the space stretch if (lineStartBAP != 0 || lineEndBAP != 0) { baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroPenalty()); + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( ai.areaIPD.opt - (lineStartBAP + lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, 0, mainPosition, false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } else { baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, 0, @@ -1206,13 +1197,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { - ai.letterSpaceCount * letterSpaceWidth.opt, alignmentContext, notifyPos(mainPosition), false)); - baseList.add(makeInfinitePenalty()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add (new KnuthGlue(unsuppressibleLetterSpaces * letterSpaceWidth.opt, unsuppressibleLetterSpaces * (letterSpaceWidth.max - letterSpaceWidth.opt), unsuppressibleLetterSpaces * (letterSpaceWidth.opt - letterSpaceWidth.min), - getAuxiliaryPosition(), true)); - baseList.add(makeZeroWidthBox()); + auxiliaryPosition, true)); + baseList.add(makeAuxiliaryZeroWidthBox()); } // extra-elements if the word fragment is the end of a syllable, @@ -1252,48 +1243,48 @@ public class TextLayoutManager extends LeafNodeLayoutManager { switch (alignment) { case EN_CENTER : // centered text: - baseList.add(makeInfinitePenalty()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), true)); + auxiliaryPosition, true)); baseList.add(new KnuthPenalty(hyphIPD, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); baseList.add(new KnuthGlue(-(lineEndBAP + lineStartBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), true)); + auxiliaryPosition, true)); break; case EN_START : // fall through case EN_END : // left- or right-aligned text: if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(makeInfinitePenalty()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); - baseList.add(makeZeroWidthBox()); - baseList.add(makeInfinitePenalty()); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } else { - baseList.add(makeInfinitePenalty()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } break; @@ -1301,12 +1292,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // justified text, or last line justified: // just a flagged penalty if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(makeInfinitePenalty()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 @@ -1314,19 +1305,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } else { baseList.add(new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } - baseList.add(new KnuthInlineBox(0, null, notifyPos(getAuxiliaryPosition()), true)); - baseList.add(makeInfinitePenalty()); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } else { baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 @@ -1334,11 +1325,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - getAuxiliaryPosition(), false)); + auxiliaryPosition, false)); } } } } -} \ No newline at end of file +} -- cgit v1.2.3 From 8f66c4de03295ce2885763fe6536c351b2b3d2a0 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 5 May 2008 06:50:54 +0000 Subject: Bugzilla #43650: PCL Renderer: Improved page format selection so it doesn't interfere with duplex printing. Submitted by: Thomas Margreiter Note: I've only been able to verify that the change doesn't have any negative effects on simplex printers. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653311 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/pcl/PCLRenderer.java | 54 +++++++++++++--------- status.xml | 12 +++-- 2 files changed, 40 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index b89fba9c1..921856b07 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -156,6 +156,11 @@ public class PCLRenderer extends PrintRenderer { */ private boolean disabledPJL = false; + /** contains the pageWith of the last printed page */ + private long pageWidth = 0; + /** contains the pageHeight of the last printed page */ + private long pageHeight = 0; + /** * Create the PCL renderer */ @@ -416,29 +421,34 @@ public class PCLRenderer extends PrintRenderer { } private void selectPageFormat(long pagewidth, long pageheight) throws IOException { - this.currentPageDefinition = PCLPageDefinition.getPageDefinition( - pagewidth, pageheight, 1000); - - if (this.currentPageDefinition == null) { - this.currentPageDefinition = PCLPageDefinition.getDefaultPageDefinition(); - PCLEventProducer eventProducer = PCLEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.paperTypeUnavailable(this, pagewidth, pageheight, - this.currentPageDefinition.getName()); - } - if (log.isDebugEnabled()) { - log.debug("page size: " + currentPageDefinition.getPhysicalPageSize()); - log.debug("logical page: " + currentPageDefinition.getLogicalPageRect()); - } - if (this.currentPageDefinition.isLandscapeFormat()) { - gen.writeCommand("&l1O"); //Orientation - } else { - gen.writeCommand("&l0O"); //Orientation + //Only set the page format if it changes (otherwise duplex printing won't work) + if ((pagewidth != this.pageWidth) || (pageheight != this.pageHeight)) { + this.pageWidth = pagewidth; + this.pageHeight = pageheight; + + this.currentPageDefinition = PCLPageDefinition.getPageDefinition( + pagewidth, pageheight, 1000); + + if (this.currentPageDefinition == null) { + this.currentPageDefinition = PCLPageDefinition.getDefaultPageDefinition(); + log.warn("Paper type could not be determined. Falling back to: " + + this.currentPageDefinition.getName()); + } + if (log.isDebugEnabled()) { + log.debug("page size: " + currentPageDefinition.getPhysicalPageSize()); + log.debug("logical page: " + currentPageDefinition.getLogicalPageRect()); + } + + if (this.currentPageDefinition.isLandscapeFormat()) { + gen.writeCommand("&l1O"); //Landscape Orientation + } else { + gen.writeCommand("&l0O"); //Portrait Orientation + } + gen.selectPageSize(this.currentPageDefinition.getSelector()); + + gen.clearHorizontalMargins(); + gen.setTopMargin(0); } - gen.selectPageSize(this.currentPageDefinition.getSelector()); - - gen.clearHorizontalMargins(); - gen.setTopMargin(0); } /** Saves the current graphics state on the stack. */ diff --git a/status.xml b/status.xml index fa3ee3c44..cfde0ca21 100644 --- a/status.xml +++ b/status.xml @@ -57,11 +57,15 @@ Added SVG support for AFP (GOCA). - + + PCL Renderer: Improved page format selection so it doesn't interfere with + duplex printing. + + Fixed a regression introduced by the fix for - Bugzilla 44286. + Bugzilla 44286. - + Activated min-height/max-height and min-width/max-width properties. @@ -69,7 +73,7 @@ If the source had an associated InputStream, an UnsupportedOperationException was triggered. - + Add partial support for the "show-destination" property on fo:basic-link (PDF output only; see limitations on the compliance page) -- cgit v1.2.3 From e5158b410b3d257e492610b10594e670e6e1d834 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 5 May 2008 19:27:10 +0000 Subject: Correction of indentation git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653564 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/inline/TextLayoutManager.java | 114 ++++++++++----------- 1 file changed, 54 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 02f809f73..be8a13d50 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -127,7 +127,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** Used to reduce instantiation of MinOptMax with zero length. Do not modify! */ private static final MinOptMax ZERO_MINOPTMAX = new MinOptMax(0); - + private FOText foText; private char[] textArray; /** @@ -153,7 +153,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** 1/2 of word-spacing value */ private SpaceVal halfWS; /** 1/2 of letter-spacing value */ - private SpaceVal halfLS; + private SpaceVal halfLS; private boolean hasChanged = false; private int returnedIndex = 0; @@ -165,10 +165,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private int lineStartBAP = 0; private int lineEndBAP = 0; - + private boolean keepTogether; - private final Position auxiliaryPosition; + private final Position auxiliaryPosition = new LeafPosition(this, -1); /** * Create a Text layout manager. @@ -178,15 +178,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { public TextLayoutManager(FOText node) { super(); foText = node; - + textArray = new char[node.endIndex - node.startIndex]; System.arraycopy(node.ca, node.startIndex, textArray, 0, node.endIndex - node.startIndex); letterAdjustArray = new MinOptMax[textArray.length + 1]; vecAreaInfo = new java.util.ArrayList(); - - auxiliaryPosition = new LeafPosition(this, -1); } private KnuthPenalty makeZeroWidthPenalty(int penaltyValue) { @@ -211,16 +209,16 @@ public class TextLayoutManager extends LeafNodeLayoutManager { FontInfo fi = foText.getFOEventHandler().getFontInfo(); FontTriplet[] fontkeys = foText.getCommonFont().getFontState(fi); font = fi.getFontInstance(fontkeys[0], foText.getCommonFont().fontSize.getValue(this)); - + // With CID fonts, space isn't neccesary currentFontState.width(32) spaceCharIPD = font.getCharWidth(' '); // Use hyphenationChar property hyphIPD = foText.getCommonHyphenation().getHyphIPD(font); - + SpaceVal ls = SpaceVal.makeLetterSpacing(foText.getLetterSpacing()); halfLS = new SpaceVal(MinOptMax.multiply(ls.getSpace(), 0.5), ls.isConditional(), ls.isForcing(), ls.getPrecedence()); - + ws = SpaceVal.makeWordSpacing(foText.getWordSpacing(), ls, font); // Make half-space: on either side of a word-space) halfWS = new SpaceVal(MinOptMax.multiply(ws.getSpace(), 0.5), @@ -239,7 +237,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // in the SpaceVal.makeWordSpacing() method letterSpaceIPD = ls.getSpace(); wordSpaceIPD = MinOptMax.add(new MinOptMax(spaceCharIPD), ws.getSpace()); - + keepTogether = foText.getKeepTogether().getWithinLine().getEnum() == Constants.EN_ALWAYS; } @@ -294,9 +292,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { realWidth.add(MinOptMax.multiply(letterSpaceIPD, -1)); letterSpaceCount--; } - + for (int i = ai.startIndex; i < ai.breakIndex; i++) { - MinOptMax ladj = letterAdjustArray[i + 1]; + MinOptMax ladj = letterAdjustArray[i + 1]; if (ladj != null && ladj.isElastic()) { letterSpaceCount++; } @@ -323,7 +321,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { difference = (int) ((double) (realWidth.opt - realWidth.min) * ipdAdjust); } - + // set letter space adjustment if (ipdAdjust > 0.0) { letterSpaceDim @@ -337,7 +335,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { totalAdjust += (letterSpaceDim - letterSpaceIPD.opt) * letterSpaceCount; // set word space adjustment - // + // if (wordSpaceCount > 0) { wordSpaceDim += (difference - totalAdjust) / wordSpaceCount; } else { @@ -366,7 +364,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // the last character of a word and to space characters: in order // to avoid this, we must subtract the letter space width twice; // the renderer will compute the space width as: - // space width = + // space width = // = "normal" space width + letterSpaceAdjust + wordSpaceAdjust // = spaceCharIPD + letterSpaceAdjust + // + (wordSpaceDim - spaceCharIPD - 2 * letterSpaceAdjust) @@ -391,7 +389,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * @param context the layout context * @param spaceDiff unused * @param firstIndex the index of the first AreaInfo used for the TextArea - * @param lastIndex the index of the last AreaInfo used for the TextArea + * @param lastIndex the index of the last AreaInfo used for the TextArea * @param isLastArea is this TextArea the last in a line? * @return the new text area */ @@ -446,7 +444,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // here ends a new word // add a word to the TextArea if (isLastArea - && i == lastIndex + && i == lastIndex && areaInfo.isHyphenated) { len++; } @@ -471,7 +469,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } // String wordChars = new String(textArray, wordStartIndex, len); if (isLastArea - && i == lastIndex + && i == lastIndex && areaInfo.isHyphenated) { // add the hyphenation character wordChars.append(foText.getCommonHyphenation().getHyphChar(font)); @@ -483,12 +481,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } TraitSetter.addFontTraits(textArea, font); textArea.addTrait(Trait.COLOR, foText.getColor()); - + TraitSetter.addTextDecoration(textArea, foText.getTextDecoration()); - + return textArea; } - + private void addToLetterAdjust(int index, int width) { if (letterAdjustArray[index] == null) { letterAdjustArray[index] = new MinOptMax(width); @@ -507,7 +505,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { || CharUtilities.isNonBreakableSpace(ch) || CharUtilities.isFixedWidthSpace(ch); } - + /** {@inheritDoc} */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { lineStartBAP = context.getLineStartBorderAndPaddingWidth(); @@ -569,12 +567,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { char previous = textArray[prevAi.breakIndex - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } + } if (kern != 0) { //log.info("Kerning between " + previous + " and " + c + ": " + kern); addToLetterAdjust(i, kern); wordIPD.add(kern); - } + } } } if (kerning && breakOpportunity && !isSpace(ch) && lastIndex > 0 && textArray[lastIndex] == CharUtilities.SOFT_HYPHEN) { @@ -613,7 +611,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { ai = new AreaInfo(thisStart, nextStart, (short) (nextStart - thisStart), (short) 0, MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), - false, true, breakOpportunity); + false, true, breakOpportunity); vecAreaInfo.add(ai); prevAi = ai; @@ -642,9 +640,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { returnList.add(sequence); } } - - if ((ch == CharUtilities.SPACE - && foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) + + if ((ch == CharUtilities.SPACE + && foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) || ch == CharUtilities.NBSPACE) { // preserved space or non-breaking space: // create the AreaInfo object @@ -657,7 +655,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); ai = new AreaInfo(nextStart, (short) (nextStart + 1), (short) 0, (short) 0, - ipd, false, true, breakOpportunity); + ipd, false, true, breakOpportunity); thisStart = (short) (nextStart + 1); } else if (ch == NEWLINE) { // linefeed; this can happen when linefeed-treatment="preserve" @@ -667,7 +665,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { inWhitespace = ch == CharUtilities.SPACE && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; nextStart++; } // end of while - + // Process any last elements if (inWord) { int lastIndex = nextStart; @@ -693,12 +691,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } else if (prevAi != null && !prevAi.isSpace) { char previous = textArray[prevAi.breakIndex - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } + } if (kern != 0) { //log.info("Kerning between " + previous + " and " + c + ": " + kern); addToLetterAdjust(i, kern); wordIPD.add(kern); - } + } } } int iLetterSpaces = wordLength - 1; @@ -719,7 +717,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { ai = new AreaInfo(thisStart, (short) (nextStart), (short) (nextStart - thisStart), (short) 0, MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), - false, true, true); + false, true, true); vecAreaInfo.add(ai); // create the elements @@ -896,20 +894,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } startIndex = stopIndex; } - if (!hasChanged && !nothingChanged) { - hasChanged = true; - } + hasChanged = !nothingChanged; } /** {@inheritDoc} */ public boolean applyChanges(List oldList) { setFinished(false); - if (changeList != null) { + if (changeList != null && !changeList.isEmpty()) { int areaInfosAdded = 0; int areaInfosRemoved = 0; - int oldIndex = -1; - PendingChange currChange = null; + int oldIndex = -1, changeIndex; + PendingChange currChange; ListIterator changeListIterator = changeList.listIterator(); while (changeListIterator.hasNext()) { currChange = (PendingChange) changeListIterator.next(); @@ -917,14 +913,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { areaInfosRemoved++; areaInfosAdded++; oldIndex = currChange.index; - vecAreaInfo.remove(currChange.index + areaInfosAdded - areaInfosRemoved); - vecAreaInfo.add(currChange.index + areaInfosAdded - areaInfosRemoved, - currChange.ai); + changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; + vecAreaInfo.remove(changeIndex); } else { areaInfosAdded++; - vecAreaInfo.add(currChange.index + areaInfosAdded - areaInfosRemoved, - currChange.ai); + changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; } + vecAreaInfo.add(changeIndex, currChange.ai); } changeList.clear(); } @@ -963,8 +958,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { int leafValue = ((LeafPosition) pos).getLeafPos(); if (leafValue != -1) { AreaInfo ai = (AreaInfo) vecAreaInfo.get(leafValue); - sbChars.append(new String(textArray, ai.startIndex, - ai.breakIndex - ai.startIndex)); + sbChars.append(textArray, ai.startIndex, ai.breakIndex - ai.startIndex); } } @@ -996,7 +990,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { switch (alignment) { case EN_CENTER: // centered text: - // if the second element is chosen as a line break these elements + // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line and at the // beginning of the next one, otherwise they don't add any stretch baseList.add(new KnuthGlue(lineEndBAP, @@ -1017,7 +1011,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { case EN_START: // fall through case EN_END: // left- or right-aligned text: - // if the second element is chosen as a line break these elements + // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line, otherwise // they don't add any stretch baseList.add(new KnuthGlue(lineEndBAP, @@ -1064,13 +1058,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); - } + } } else { // a (possible block) of breaking spaces switch (alignment) { case EN_CENTER: // centered text: - // if the second element is chosen as a line break these elements + // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line and at the // beginning of the next one, otherwise they don't add any stretch baseList.add(new KnuthGlue(lineEndBAP, @@ -1091,7 +1085,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { case EN_START: // fall through case EN_END: // left- or right-aligned text: - // if the second element is chosen as a line break these elements + // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line, otherwise // they don't add any stretch if (lineStartBAP != 0 || lineEndBAP != 0) { @@ -1164,7 +1158,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } } - } + } } private void addElementsForAWordFragment(List baseList, @@ -1190,7 +1184,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { notifyPos(mainPosition), false)); } else { // adjustable letter spacing - int unsuppressibleLetterSpaces + int unsuppressibleLetterSpaces = suppressibleLetterSpace ? ai.letterSpaceCount - 1 : ai.letterSpaceCount; baseList.add (new KnuthInlineBox(ai.areaIPD.opt @@ -1205,7 +1199,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { auxiliaryPosition, true)); baseList.add(makeAuxiliaryZeroWidthBox()); } - + // extra-elements if the word fragment is the end of a syllable, // or it ends with a character that can be used as a line break if (ai.isHyphenated) { @@ -1215,7 +1209,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { widthIfNoBreakOccurs = letterAdjustArray[ai.breakIndex]; } //if (ai.breakIndex) - + // the word fragment ends at the end of a syllable: // if a break occurs the content width increases, // otherwise nothing happens @@ -1257,7 +1251,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, auxiliaryPosition, true)); break; - + case EN_START : // fall through case EN_END : // left- or right-aligned text: @@ -1287,7 +1281,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { auxiliaryPosition, false)); } break; - + default: // justified text, or last line justified: // just a flagged penalty @@ -1329,7 +1323,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } } - - } + } + } -- cgit v1.2.3 From cff8a3713fc7e069ab5bf46585131071d50fb979 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 6 May 2008 16:14:09 +0000 Subject: * Added font substitution configuration reader, model, business logic, junit test and docs. * Added java 1.5 generics comments to many methods. * Performed some preparatory cleanup and refactoring which includes (but is not limited to..) - Creating a FontManager delegating class that is called upon when renderers are setting up fonts - A new FontCollection interface and concrete implementing classes to supercede the static FontSetup mechanism. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653826 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/fonts.xml | 77 +++-- src/java/org/apache/fop/apps/FOURIResolver.java | 28 ++ src/java/org/apache/fop/apps/FOUserAgent.java | 2 +- src/java/org/apache/fop/apps/FopFactory.java | 106 +++---- .../apache/fop/apps/FopFactoryConfigurator.java | 26 +- .../org/apache/fop/fonts/CustomFontCollection.java | 82 +++++ src/java/org/apache/fop/fonts/EmbedFontInfo.java | 33 +- src/java/org/apache/fop/fonts/Font.java | 11 +- src/java/org/apache/fop/fonts/FontCache.java | 70 ++-- src/java/org/apache/fop/fonts/FontCollection.java | 38 +++ src/java/org/apache/fop/fonts/FontDescriptor.java | 2 +- src/java/org/apache/fop/fonts/FontInfo.java | 194 ++++++----- src/java/org/apache/fop/fonts/FontManager.java | 221 +++++++++++++ .../apache/fop/fonts/FontManagerConfigurator.java | 89 ++++++ src/java/org/apache/fop/fonts/FontSetup.java | 225 +++++++------ src/java/org/apache/fop/fonts/FontTriplet.java | 13 +- src/java/org/apache/fop/fonts/FontUtil.java | 36 ++- .../fop/fonts/autodetect/FontFileFinder.java | 2 +- .../fop/fonts/autodetect/FontInfoFinder.java | 4 +- .../fop/fonts/base14/Base14FontCollection.java | 149 +++++++++ .../fop/fonts/substitute/AttributeValue.java | 65 ++++ .../apache/fop/fonts/substitute/FontQualifier.java | 305 ++++++++++++++++++ .../fop/fonts/substitute/FontSubstitution.java | 61 ++++ .../fop/fonts/substitute/FontSubstitutions.java | 66 ++++ .../substitute/FontSubstitutionsConfigurator.java | 83 +++++ .../fop/fonts/substitute/FontWeightRange.java | 115 +++++++ .../fop/layoutmgr/AbstractLayoutManager.java | 4 +- .../fop/render/AbstractRendererConfigurator.java | 6 +- src/java/org/apache/fop/render/PrintRenderer.java | 38 ++- .../fop/render/PrintRendererConfigurator.java | 160 ++++++---- .../org/apache/fop/render/afp/AFPRenderer.java | 4 +- .../fop/render/java2d/Base14FontCollection.java | 181 +++++++++++ .../render/java2d/ConfiguredFontCollection.java | 111 +++++++ .../org/apache/fop/render/java2d/FontSetup.java | 353 --------------------- .../fop/render/java2d/InstalledFontCollection.java | 138 ++++++++ .../apache/fop/render/java2d/Java2DRenderer.java | 9 +- .../org/apache/fop/render/pcl/PCLRenderer.java | 8 +- .../apache/fop/render/ps/AbstractPSTranscoder.java | 2 +- .../apache/fop/render/ps/NativeTextHandler.java | 2 +- .../org/apache/fop/svg/PDFDocumentGraphics2D.java | 2 +- .../fop/svg/PDFDocumentGraphics2DConfigurator.java | 12 +- src/java/org/apache/fop/svg/PDFGraphics2D.java | 2 +- status.xml | 4 + test/config/test_fonts_substitution.xconf | 33 ++ .../apache/fop/config/BaseUserConfigTestCase.java | 2 +- .../fop/config/FontsSubstitutionTestCase.java | 63 ++++ .../org/apache/fop/config/UserConfigTestSuite.java | 1 + .../fop/layoutengine/LayoutEngineTester.java | 4 +- .../org/apache/fop/render/pdf/BasePDFTestCase.java | 2 +- .../fop/render/pdf/PDFAConformanceTestCase.java | 8 +- 50 files changed, 2425 insertions(+), 827 deletions(-) create mode 100644 src/java/org/apache/fop/fonts/CustomFontCollection.java create mode 100644 src/java/org/apache/fop/fonts/FontCollection.java create mode 100644 src/java/org/apache/fop/fonts/FontManager.java create mode 100644 src/java/org/apache/fop/fonts/FontManagerConfigurator.java create mode 100644 src/java/org/apache/fop/fonts/base14/Base14FontCollection.java create mode 100644 src/java/org/apache/fop/fonts/substitute/AttributeValue.java create mode 100644 src/java/org/apache/fop/fonts/substitute/FontQualifier.java create mode 100644 src/java/org/apache/fop/fonts/substitute/FontSubstitution.java create mode 100644 src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java create mode 100644 src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java create mode 100644 src/java/org/apache/fop/fonts/substitute/FontWeightRange.java create mode 100644 src/java/org/apache/fop/render/java2d/Base14FontCollection.java create mode 100644 src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java delete mode 100644 src/java/org/apache/fop/render/java2d/FontSetup.java create mode 100644 src/java/org/apache/fop/render/java2d/InstalledFontCollection.java create mode 100644 test/config/test_fonts_substitution.xconf create mode 100644 test/java/org/apache/fop/config/FontsSubstitutionTestCase.java (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml index 070ca8203..eb466ec73 100644 --- a/src/documentation/content/xdocs/trunk/fonts.xml +++ b/src/documentation/content/xdocs/trunk/fonts.xml @@ -201,17 +201,20 @@ support fonts. These fonts will then automatically be registered.

    - - C:\MyFonts1 + + + + + C:\MyFonts1 - - C:\MyFonts2 + + C:\MyFonts2 - - -]]> + + + + +]]> Review the documentation for FOP Configuration for instructions on making the FOP configuration available to FOP when it runs. @@ -318,23 +321,25 @@ Register Fonts with FOP

    You must tell FOP how to find and use the font metrics files by registering them in the FOP Configuration. Add entries for your custom fonts, regardless of font type, to the configuration file in a manner similar to the following:

    - - - - + + + + + + + - - C:\MyFonts1 + + C:\MyFonts1 - - C:\MyFonts2 + + C:\MyFonts2 - - -]]> + + + + +]]>
    • URLs are used to access the font metric and font files. @@ -359,7 +364,7 @@
    - Auto-Detect and auto-embedd feature + Auto-Detect and auto-embed feature

    When the "auto-detect" flag is set in the configuration, FOP will automatically search for fonts in the default paths for your operating system.

    FOP will also auto-detect fonts which are available in the classpath, if they are described as "application/x-font" in the MANIFEST.MF file. For example, if your .jar file contains font/myfont.ttf:

    Manifest-Version: 1.0 @@ -385,6 +390,30 @@

    When embedding TrueType fonts (ttf) or TrueType Collections (ttc), a subset of the original font, containing only the glyphs used, is embedded in the output document.

    +
    + Substitution +

    When a <substitutions/> section is defined in the configuration, FOP will re-map any font-family references found in your FO input to a given substitution font.

    +
      +
    • If a <substitution/> is declared, it is mandatory that both a <from/> and <to/> child element is declared with a font-family attribute.
    • +
    • Both font-weight and font-style are optional attributes, if they are provided then a value of 'normal' is assumed.
    • +
    +

    For example you could make all FO font-family references to 'Arial' with weights between 700 and 900 reference the normal 'Arial Black' font.

    + + + + + + + + + + + + + +]]> +
    goes to F1 + fontInfo.addMetrics("F1", metric); + metric = new SystemFontMetricsMapper("SansSerif", italic, graphics2d); + // --> goes to F2 + fontInfo.addMetrics("F2", metric); + metric = new SystemFontMetricsMapper("SansSerif", bold, graphics2d); + // --> goes to F3 + fontInfo.addMetrics("F3", metric); + metric = new SystemFontMetricsMapper("SansSerif", bolditalic, graphics2d); + // --> goes to F4 + fontInfo.addMetrics("F4", metric); + + + metric = new SystemFontMetricsMapper("Serif", normal, graphics2d); + // --> goes to F5 + fontInfo.addMetrics("F5", metric); + metric = new SystemFontMetricsMapper("Serif", italic, graphics2d); + // --> goes to F6 + fontInfo.addMetrics("F6", metric); + metric = new SystemFontMetricsMapper("Serif", bold, graphics2d); + // --> goes to F7 + fontInfo.addMetrics("F7", metric); + metric = new SystemFontMetricsMapper("Serif", bolditalic, graphics2d); + // --> goes to F8 + fontInfo.addMetrics("F8", metric); + + metric = new SystemFontMetricsMapper("MonoSpaced", normal, graphics2d); + // --> goes to F9 + fontInfo.addMetrics("F9", metric); + metric = new SystemFontMetricsMapper("MonoSpaced", italic, graphics2d); + // --> goes to F10 + fontInfo.addMetrics("F10", metric); + metric = new SystemFontMetricsMapper("MonoSpaced", bold, graphics2d); + // --> goes to F11 + fontInfo.addMetrics("F11", metric); + metric = new SystemFontMetricsMapper("MonoSpaced", bolditalic, graphics2d); + // --> goes to F12 + fontInfo.addMetrics("F12", metric); + + metric = new SystemFontMetricsMapper("Serif", normal, graphics2d); + //"Symbol" doesn't seem to work here, but "Serif" does the job just fine. *shrug* + // --> goes to F13 and F14 + fontInfo.addMetrics("F13", metric); + fontInfo.addMetrics("F14", metric); + + // Custom type 1 fonts step 1/2 + // fontInfo.addMetrics("F15", new OMEP()); + // fontInfo.addMetrics("F16", new GaramondLightCondensed()); + // fontInfo.addMetrics("F17", new BauerBodoniBoldItalic()); + + /* any is treated as serif */ + fontInfo.addFontProperties("F5", "any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "any", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "any", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F7", "any", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "any", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "any", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + + fontInfo.addFontProperties("F1", "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F2", "sans-serif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F2", "sans-serif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F3", "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F4", "sans-serif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F4", "sans-serif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F5", "serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "serif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "serif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F7", "serif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "serif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "serif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F9", "monospace", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F10", "monospace", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F10", "monospace", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F11", "monospace", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F12", "monospace", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F12", "monospace", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + + fontInfo.addFontProperties("F1", "Helvetica", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F2", "Helvetica", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F2", "Helvetica", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F3", "Helvetica", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F4", "Helvetica", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F4", "Helvetica", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F5", "Times", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "Times", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "Times", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F7", "Times", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "Times", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "Times", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F9", "Courier", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F10", "Courier", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F10", "Courier", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F11", "Courier", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F12", "Courier", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F12", "Courier", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F13", "Symbol", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F14", "ZapfDingbats", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + + // Custom type 1 fonts step 2/2 + // fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL); + // fontInfo.addFontProperties("F16", "Garamond-LightCondensed", "normal", FontInfo.NORMAL); + // fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD); + + /* for compatibility with PassiveTex */ + fontInfo.addFontProperties("F5", "Times-Roman", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "Times-Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "Times-Roman", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F7", "Times-Roman", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "Times-Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "Times-Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F5", "Times Roman", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "Times Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F6", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + fontInfo.addFontProperties("F7", "Times Roman", Font.STYLE_NORMAL, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", + "normal", Font.WEIGHT_NORMAL); + + return 15; + } +} diff --git a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java new file mode 100644 index 000000000..771d3f2d7 --- /dev/null +++ b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java @@ -0,0 +1,111 @@ +/* + * 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.render.java2d; + +import java.util.List; + +import javax.xml.transform.Source; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.fonts.CustomFont; +import org.apache.fop.fonts.EmbedFontInfo; +import org.apache.fop.fonts.FontCollection; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontLoader; +import org.apache.fop.fonts.FontManager; +import org.apache.fop.fonts.FontResolver; +import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.LazyFont; +import org.apache.fop.render.PrintRenderer; + +/** + * A java2d configured font collection + */ +public class ConfiguredFontCollection implements FontCollection { + + private static Log log = LogFactory.getLog(ConfiguredFontCollection.class); + + private PrintRenderer renderer = null; + + /** + * Main constructor + * + * @param renderer a print renderer + */ + public ConfiguredFontCollection(PrintRenderer renderer) { + this.renderer = renderer; + } + + /** + * {@inheritDoc} + */ + public int setup(int start, FontInfo fontInfo) { + List/**/ fontList = renderer.getFontList(); + FontResolver resolver = renderer.getFontResolver(); + int num = start; + if (fontList == null || fontList.size() < 1) { + log.debug("No user configured fonts found."); + return num; + } + if (resolver == null) { + // Ensure that we have minimal font resolution capabilities + resolver = FontManager.createMinimalFontResolver(); + } + String internalName = null; + + for (int i = 0; i < fontList.size(); i++) { + + EmbedFontInfo configFontInfo = (EmbedFontInfo) fontList.get(i); + String fontFile = configFontInfo.getEmbedFile(); + internalName = "F" + num; + num++; + try { + FontMetricsMapper font = null; + String metricsUrl = configFontInfo.getMetricsFile(); + // If the user specified an XML-based metrics file, we'll use it + // Otherwise, calculate metrics directly from the font file. + if (metricsUrl != null) { + LazyFont fontMetrics = new LazyFont(configFontInfo, resolver); + Source fontSource = resolver.resolve(configFontInfo.getEmbedFile()); + font = new CustomFontMetricsMapper(fontMetrics, fontSource); + } else { + CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, resolver); + font = new CustomFontMetricsMapper(fontMetrics); + } + + fontInfo.addMetrics(internalName, font); + + List triplets = configFontInfo.getFontTriplets(); + for (int c = 0; c < triplets.size(); c++) { + FontTriplet triplet = (FontTriplet) triplets.get(c); + + if (log.isDebugEnabled()) { + log.debug("Registering: " + triplet + " under " + internalName); + } + fontInfo.addFontProperties(internalName, triplet); + } + } catch (Exception e) { + log.warn("Unable to load custom font from file '" + fontFile + "'", e); + } + } + return num; + } +} diff --git a/src/java/org/apache/fop/render/java2d/FontSetup.java b/src/java/org/apache/fop/render/java2d/FontSetup.java deleted file mode 100644 index ade457d95..000000000 --- a/src/java/org/apache/fop/render/java2d/FontSetup.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.java2d; - -// FOP -import java.awt.Graphics2D; -import java.awt.GraphicsEnvironment; -import java.util.List; -import java.util.Set; - -import javax.xml.transform.Source; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.fop.fonts.CustomFont; -import org.apache.fop.fonts.EmbedFontInfo; -import org.apache.fop.fonts.Font; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontLoader; -import org.apache.fop.fonts.FontResolver; -import org.apache.fop.fonts.FontTriplet; -import org.apache.fop.fonts.FontUtil; -import org.apache.fop.fonts.LazyFont; - -/** - * Sets up the Java2D/AWT fonts. It is similar to - * org.apache.fop.render.fonts.FontSetup. - * Assigns the font (with metrics) to internal names like "F1" and - * assigns family-style-weight triplets to the fonts. - */ -public class FontSetup { - - /** logging instance */ - protected static Log log = LogFactory.getLog(FontSetup.class); - - private static final int LAST_PREDEFINED_FONT_NUMBER = 14; - - private static final Set HARDCODED_FONT_NAMES; - - static { - HARDCODED_FONT_NAMES = new java.util.HashSet(); - HARDCODED_FONT_NAMES.add("any"); - HARDCODED_FONT_NAMES.add("sans-serif"); - HARDCODED_FONT_NAMES.add("serif"); - HARDCODED_FONT_NAMES.add("monospace"); - - HARDCODED_FONT_NAMES.add("Helvetica"); - HARDCODED_FONT_NAMES.add("Times"); - HARDCODED_FONT_NAMES.add("Courier"); - HARDCODED_FONT_NAMES.add("Symbol"); - HARDCODED_FONT_NAMES.add("ZapfDingbats"); - HARDCODED_FONT_NAMES.add("Times Roman"); - HARDCODED_FONT_NAMES.add("Times-Roman"); - HARDCODED_FONT_NAMES.add("Computer-Modern-Typewriter"); - } - - /** - * Sets up the font info object. - * - * Adds metrics for basic fonts and useful family-style-weight - * triplets for lookup. - * - * @param fontInfo the font info object to set up - * @param configuredFontList of fop config fonts - * @param resolver for resolving the font file URI - * @param graphics needed for access to font metrics - */ - public static void setup(FontInfo fontInfo, List configuredFontList, - FontResolver resolver, Graphics2D graphics) { - FontMetricsMapper metric; - int normal, bold, bolditalic, italic; - - /* - * available java fonts are: - * Serif - bold, normal, italic, bold-italic - * SansSerif - bold, normal, italic, bold-italic - * MonoSpaced - bold, normal, italic, bold-italic - */ - normal = java.awt.Font.PLAIN; - bold = java.awt.Font.BOLD; - italic = java.awt.Font.ITALIC; - bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC; - - metric = new SystemFontMetricsMapper("SansSerif", normal, graphics); - // --> goes to F1 - fontInfo.addMetrics("F1", metric); - metric = new SystemFontMetricsMapper("SansSerif", italic, graphics); - // --> goes to F2 - fontInfo.addMetrics("F2", metric); - metric = new SystemFontMetricsMapper("SansSerif", bold, graphics); - // --> goes to F3 - fontInfo.addMetrics("F3", metric); - metric = new SystemFontMetricsMapper("SansSerif", bolditalic, graphics); - // --> goes to F4 - fontInfo.addMetrics("F4", metric); - - - metric = new SystemFontMetricsMapper("Serif", normal, graphics); - // --> goes to F5 - fontInfo.addMetrics("F5", metric); - metric = new SystemFontMetricsMapper("Serif", italic, graphics); - // --> goes to F6 - fontInfo.addMetrics("F6", metric); - metric = new SystemFontMetricsMapper("Serif", bold, graphics); - // --> goes to F7 - fontInfo.addMetrics("F7", metric); - metric = new SystemFontMetricsMapper("Serif", bolditalic, graphics); - // --> goes to F8 - fontInfo.addMetrics("F8", metric); - - metric = new SystemFontMetricsMapper("MonoSpaced", normal, graphics); - // --> goes to F9 - fontInfo.addMetrics("F9", metric); - metric = new SystemFontMetricsMapper("MonoSpaced", italic, graphics); - // --> goes to F10 - fontInfo.addMetrics("F10", metric); - metric = new SystemFontMetricsMapper("MonoSpaced", bold, graphics); - // --> goes to F11 - fontInfo.addMetrics("F11", metric); - metric = new SystemFontMetricsMapper("MonoSpaced", bolditalic, graphics); - // --> goes to F12 - fontInfo.addMetrics("F12", metric); - - metric = new SystemFontMetricsMapper("Serif", normal, graphics); - //"Symbol" doesn't seem to work here, but "Serif" does the job just fine. *shrug* - // --> goes to F13 and F14 - fontInfo.addMetrics("F13", metric); - fontInfo.addMetrics("F14", metric); - - // Custom type 1 fonts step 1/2 - // fontInfo.addMetrics("F15", new OMEP()); - // fontInfo.addMetrics("F16", new GaramondLightCondensed()); - // fontInfo.addMetrics("F17", new BauerBodoniBoldItalic()); - - /* any is treated as serif */ - fontInfo.addFontProperties("F5", "any", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "any", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "any", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F7", "any", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "any", "italic", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "any", "oblique", Font.WEIGHT_BOLD); - - fontInfo.addFontProperties("F1", "sans-serif", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F2", "sans-serif", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F2", "sans-serif", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F3", "sans-serif", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F4", "sans-serif", "oblique", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F4", "sans-serif", "italic", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F5", "serif", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "serif", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "serif", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F7", "serif", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "serif", "oblique", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "serif", "italic", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F9", "monospace", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F10", "monospace", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F10", "monospace", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F11", "monospace", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F12", "monospace", "oblique", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F12", "monospace", "italic", Font.WEIGHT_BOLD); - - fontInfo.addFontProperties("F1", "Helvetica", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F2", "Helvetica", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F2", "Helvetica", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F3", "Helvetica", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F4", "Helvetica", "oblique", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F4", "Helvetica", "italic", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F5", "Times", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "Times", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "Times", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F7", "Times", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "Times", "oblique", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "Times", "italic", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F9", "Courier", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F10", "Courier", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F10", "Courier", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F11", "Courier", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F12", "Courier", "oblique", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F12", "Courier", "italic", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F13", "Symbol", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F14", "ZapfDingbats", "normal", Font.WEIGHT_NORMAL); - - // Custom type 1 fonts step 2/2 - // fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL); - // fontInfo.addFontProperties("F16", "Garamond-LightCondensed", "normal", FontInfo.NORMAL); - // fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD); - - /* for compatibility with PassiveTex */ - fontInfo.addFontProperties("F5", "Times-Roman", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "Times-Roman", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "Times-Roman", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F7", "Times-Roman", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "Times-Roman", "oblique", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "Times-Roman", "italic", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F5", "Times Roman", "normal", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "Times Roman", "oblique", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F6", "Times Roman", "italic", Font.WEIGHT_NORMAL); - fontInfo.addFontProperties("F7", "Times Roman", "normal", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "Times Roman", "oblique", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F8", "Times Roman", "italic", Font.WEIGHT_BOLD); - fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", - "normal", Font.WEIGHT_NORMAL); - - int lastNum = configureInstalledAWTFonts(fontInfo, graphics, LAST_PREDEFINED_FONT_NUMBER + 1); - addConfiguredFonts(fontInfo, configuredFontList, resolver, lastNum++); - } - - private static int configureInstalledAWTFonts(FontInfo fontInfo, Graphics2D graphics, - int startNumber) { - int num = startNumber; - GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - - java.awt.Font[] fonts = env.getAllFonts(); - for (int i = 0; i < fonts.length; i++) { - java.awt.Font f = fonts[i]; - if (HARDCODED_FONT_NAMES.contains(f.getName())) { - continue; //skip - } - - if (log.isTraceEnabled()) { - log.trace("AWT Font: " + f.getFontName() - + ", family: " + f.getFamily() - + ", PS: " + f.getPSName() - + ", Name: " + f.getName() - + ", Angle: " + f.getItalicAngle() - + ", Style: " + f.getStyle()); - } - - String searchName = FontUtil.stripWhiteSpace(f.getName()).toLowerCase(); - String guessedStyle = FontUtil.guessStyle(searchName); - int guessedWeight = FontUtil.guessWeight(searchName); - - num++; - String fontKey = "F" + num; - int style = convertToAWTFontStyle(guessedStyle, guessedWeight); - addFontMetricsMapper(fontInfo, f.getName(), fontKey, graphics, style); - - //Register appropriate font triplets matching the font. Two different strategies: - //Example: "Arial Bold", normal, normal - addFontTriplet(fontInfo, f.getName(), - Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, fontKey); - if (!f.getName().equals(f.getFamily())) { - //Example: "Arial", bold, normal - addFontTriplet(fontInfo, f.getFamily(), - guessedStyle, guessedWeight, fontKey); - } - } - return num; - - } - - /** - * Add fonts from configuration file starting with internal name F. - * - * @param fontInfo the font info object to set up - * @param fontList a list of EmbedFontInfo objects - * @param num starting index for internal font numbering - * @param resolver the font resolver - */ - private static void addConfiguredFonts(FontInfo fontInfo, List fontList, FontResolver resolver, int num) { - - if (fontList == null || fontList.size() < 1) { - log.debug("No user configured fonts found."); - return; - } - if (resolver == null) { - // Ensure that we have minimal font resolution capabilities - resolver = org.apache.fop.fonts.FontSetup - .createMinimalFontResolver(); - } - String internalName = null; - - for (int i = 0; i < fontList.size(); i++) { - - EmbedFontInfo configFontInfo = (EmbedFontInfo) fontList.get(i); - String fontFile = configFontInfo.getEmbedFile(); - internalName = "F" + num; - num++; - try { - FontMetricsMapper font = null; - String metricsUrl = configFontInfo.getMetricsFile(); - // If the user specified an XML-based metrics file, we'll use it - // Otherwise, calculate metrics directly from the font file. - if (metricsUrl != null) { - LazyFont fontMetrics = new LazyFont(configFontInfo, resolver); - Source fontSource = resolver.resolve(configFontInfo.getEmbedFile()); - font = new CustomFontMetricsMapper(fontMetrics, fontSource); - } else { - CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, resolver); - font = new CustomFontMetricsMapper(fontMetrics); - } - - fontInfo.addMetrics(internalName, font); - - List triplets = configFontInfo.getFontTriplets(); - for (int c = 0; c < triplets.size(); c++) { - FontTriplet triplet = (FontTriplet) triplets.get(c); - - if (log.isDebugEnabled()) { - log.debug("Registering: " + triplet + " under " + internalName); - } - fontInfo.addFontProperties(internalName, triplet); - } - } catch (Exception e) { - log.warn("Unable to load custom font from file '" + fontFile + "'", e); - } - } - } - - - private static void addFontTriplet(FontInfo fontInfo, String fontName, String fontStyle, - int fontWeight, String fontKey) { - FontTriplet triplet = FontInfo.createFontKey(fontName, fontStyle, fontWeight); - fontInfo.addFontProperties(fontKey, triplet); - } - - private static void addFontMetricsMapper(FontInfo fontInfo, String family, String fontKey, - Graphics2D graphics, int style) { - FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, graphics); - fontInfo.addMetrics(fontKey, metric); - } - - private static int convertToAWTFontStyle(String fontStyle, int fontWeight) { - int style = java.awt.Font.PLAIN; - if (fontWeight >= Font.WEIGHT_BOLD) { - style |= java.awt.Font.BOLD; - } - if (!"normal".equals(fontStyle)) { - style |= java.awt.Font.ITALIC; - } - return style; - } - -} - diff --git a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java new file mode 100644 index 000000000..4cdd30c41 --- /dev/null +++ b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java @@ -0,0 +1,138 @@ +/* + * 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.render.java2d; + +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontCollection; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.FontUtil; + +/** + * A custom AWT font collection + */ +public class InstalledFontCollection implements FontCollection { + + private static Log log = LogFactory.getLog(InstalledFontCollection.class); + + private static final Set HARDCODED_FONT_NAMES; + + static { + HARDCODED_FONT_NAMES = new java.util.HashSet(); + HARDCODED_FONT_NAMES.add("any"); + HARDCODED_FONT_NAMES.add("sans-serif"); + HARDCODED_FONT_NAMES.add("serif"); + HARDCODED_FONT_NAMES.add("monospace"); + + HARDCODED_FONT_NAMES.add("Helvetica"); + HARDCODED_FONT_NAMES.add("Times"); + HARDCODED_FONT_NAMES.add("Courier"); + HARDCODED_FONT_NAMES.add("Symbol"); + HARDCODED_FONT_NAMES.add("ZapfDingbats"); + HARDCODED_FONT_NAMES.add("Times Roman"); + HARDCODED_FONT_NAMES.add("Times-Roman"); + HARDCODED_FONT_NAMES.add("Computer-Modern-Typewriter"); + } + + private Graphics2D graphics2D = null; + + /** + * Main constructor + * + * @param graphics2D a graphics 2D + */ + public InstalledFontCollection(Graphics2D graphics2D) { + this.graphics2D = graphics2D; + } + + /** + * {@inheritDoc} + */ + public int setup(int start, FontInfo fontInfo) { + int num = start; + GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + + java.awt.Font[] fonts = env.getAllFonts(); + for (int i = 0; i < fonts.length; i++) { + java.awt.Font f = fonts[i]; + if (HARDCODED_FONT_NAMES.contains(f.getName())) { + continue; //skip + } + + if (log.isTraceEnabled()) { + log.trace("AWT Font: " + f.getFontName() + + ", family: " + f.getFamily() + + ", PS: " + f.getPSName() + + ", Name: " + f.getName() + + ", Angle: " + f.getItalicAngle() + + ", Style: " + f.getStyle()); + } + + String searchName = FontUtil.stripWhiteSpace(f.getName()).toLowerCase(); + String guessedStyle = FontUtil.guessStyle(searchName); + int guessedWeight = FontUtil.guessWeight(searchName); + + num++; + String fontKey = "F" + num; + int style = convertToAWTFontStyle(guessedStyle, guessedWeight); + addFontMetricsMapper(fontInfo, f.getName(), fontKey, graphics2D, style); + + //Register appropriate font triplets matching the font. Two different strategies: + //Example: "Arial Bold", normal, normal + addFontTriplet(fontInfo, f.getName(), + Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, fontKey); + if (!f.getName().equals(f.getFamily())) { + //Example: "Arial", bold, normal + addFontTriplet(fontInfo, f.getFamily(), + guessedStyle, guessedWeight, fontKey); + } + } + return num; + } + + private static void addFontTriplet(FontInfo fontInfo, String fontName, String fontStyle, + int fontWeight, String fontKey) { + FontTriplet triplet = FontInfo.createFontKey(fontName, fontStyle, fontWeight); + fontInfo.addFontProperties(fontKey, triplet); + } + + private static void addFontMetricsMapper(FontInfo fontInfo, String family, String fontKey, + Graphics2D graphics, int style) { + FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, graphics); + fontInfo.addMetrics(fontKey, metric); + } + + private static int convertToAWTFontStyle(String fontStyle, int fontWeight) { + int style = java.awt.Font.PLAIN; + if (fontWeight >= Font.WEIGHT_BOLD) { + style |= java.awt.Font.BOLD; + } + if (!"normal".equals(fontStyle)) { + style |= java.awt.Font.ITALIC; + } + return style; + } +} diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index db8ed6250..eea165525 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -168,14 +168,15 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem public void setupFontInfo(FontInfo inFontInfo) { //Don't call super.setupFontInfo() here! Java2D needs a special font setup // create a temp Image to test font metrics on - fontInfo = inFontInfo; + this.fontInfo = inFontInfo; BufferedImage fontImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); - Graphics2D g = fontImage.createGraphics(); + Graphics2D graphics2D = fontImage.createGraphics(); //The next line is important to get accurate font metrics! - g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - FontSetup.setup(fontInfo, fontList, fontResolver, g); + + userAgent.getFactory().getFontManager().setupRenderer(this, graphics2D); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 921856b07..5ffef15ba 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -89,7 +89,6 @@ import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; import org.apache.fop.render.RendererEventProducer; import org.apache.fop.render.java2d.FontMetricsMapper; -import org.apache.fop.render.java2d.FontSetup; import org.apache.fop.render.java2d.Java2DRenderer; import org.apache.fop.render.pcl.extensions.PCLElementMapping; import org.apache.fop.traits.BorderProps; @@ -202,11 +201,12 @@ public class PCLRenderer extends PrintRenderer { fontInfo = inFontInfo; BufferedImage fontImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); - Graphics2D g = fontImage.createGraphics(); + Graphics2D graphics2D = fontImage.createGraphics(); //The next line is important to get accurate font metrics! - g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - FontSetup.setup(fontInfo, fontList, fontResolver, g); + + userAgent.getFactory().getFontManager().setupRenderer(this, graphics2D); } /** diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java index 75ed0de52..ea4cc50bb 100644 --- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java +++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java @@ -98,7 +98,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { if (!isTextStroked()) { FontInfo fontInfo = new FontInfo(); //TODO Do custom font configuration here somewhere/somehow - FontSetup.setup(fontInfo, null, null); + FontSetup.setup(fontInfo); graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); } diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java index 5b840484d..174fe8077 100644 --- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java +++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java @@ -71,7 +71,7 @@ public class NativeTextHandler implements PSTextHandler { private void setupFontInfo() { //Sets up a FontInfo with default fonts fontInfo = new FontInfo(); - FontSetup.setup(fontInfo, null, null); + FontSetup.setup(fontInfo); } /** diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java index 420e46cb8..513ba4587 100644 --- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java @@ -156,7 +156,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { if (fontInfo == null) { //Default minimal fonts FontInfo fontInfo = new FontInfo(); - FontSetup.setup(fontInfo, null, null); + FontSetup.setup(fontInfo); setFontInfo(fontInfo); } } diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java index f57e8cc58..02e9d6da4 100644 --- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java +++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java @@ -26,6 +26,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.fop.apps.FOPException; import org.apache.fop.fonts.FontCache; import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontSetup; import org.apache.fop.pdf.PDFDocument; @@ -53,17 +54,20 @@ public class PDFDocumentGraphics2DConfigurator { //Fonts try { - FontResolver fontResolver = FontSetup.createMinimalFontResolver(); + FontResolver fontResolver = FontManager.createMinimalFontResolver(); //TODO The following could be optimized by retaining the FontCache somewhere FontCache fontCache = FontCache.load(); if (fontCache == null) { fontCache = new FontCache(); } - List fontList = PrintRendererConfigurator.buildFontListFromConfiguration( - cfg, null, fontResolver, false, fontCache); + //TODO Provide fontBaseURL to this method call + final String fontBaseURL = null; + List/**/ embedFontInfoList + = PrintRendererConfigurator.buildFontListFromConfiguration( + cfg, fontBaseURL, fontResolver, false, fontCache); fontCache.save(); FontInfo fontInfo = new FontInfo(); - FontSetup.setup(fontInfo, fontList, fontResolver); + FontSetup.setup(fontInfo, embedFontInfoList, fontResolver); graphics.setFontInfo(fontInfo); } catch (FOPException e) { throw new ConfigurationException("Error while setting up fonts", e); diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 05c30ef50..5a147f3be 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -959,7 +959,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { preparePainting(); FontInfo specialFontInfo = new FontInfo(); - FontSetup.setup(specialFontInfo, null, null); + FontSetup.setup(specialFontInfo); PDFResources res = pdfDoc.getFactory().makeResources(); PDFResourceContext context = new PDFResourceContext(res); diff --git a/status.xml b/status.xml index cfde0ca21..90992bb56 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,10 @@ Added SVG support for AFP (GOCA). + + Add support for font substitution. + + PCL Renderer: Improved page format selection so it doesn't interfere with duplex printing. diff --git a/test/config/test_fonts_substitution.xconf b/test/config/test_fonts_substitution.xconf new file mode 100644 index 000000000..b5638a035 --- /dev/null +++ b/test/config/test_fonts_substitution.xconf @@ -0,0 +1,33 @@ + + + + true + + + false + + + ./ + + + ./ + + + + + + + + + + + + + + + + + + + + diff --git a/test/java/org/apache/fop/config/BaseUserConfigTestCase.java b/test/java/org/apache/fop/config/BaseUserConfigTestCase.java index 2de7ad673..d216d583a 100644 --- a/test/java/org/apache/fop/config/BaseUserConfigTestCase.java +++ b/test/java/org/apache/fop/config/BaseUserConfigTestCase.java @@ -66,7 +66,7 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase { final File baseDir = getBaseDir(); final String fontFOFilePath = getFontFOFilePath(); File foFile = new File(baseDir, fontFOFilePath); - final boolean dumpOutput = false; + final boolean dumpOutput = true; FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); convertFO(foFile, foUserAgent, dumpOutput); } diff --git a/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java b/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java new file mode 100644 index 000000000..5202e837a --- /dev/null +++ b/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java @@ -0,0 +1,63 @@ +/* + * 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.config; + +import java.io.File; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontManager; +import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.render.PrintRenderer; + +public class FontsSubstitutionTestCase extends BaseConstructiveUserConfigTestCase { + + public FontsSubstitutionTestCase(String name) { + super(name); + } + + /** + * {@inheritDoc} + */ + protected byte[] convertFO(File foFile, FOUserAgent ua, boolean dumpPdfFile) throws Exception { + PrintRenderer renderer = (PrintRenderer)ua.getRendererFactory().createRenderer(ua, MimeConstants.MIME_PDF); + FontInfo fontInfo = new FontInfo(); + renderer.setupFontInfo(fontInfo); + FontManager fontManager = ua.getFactory().getFontManager(); + fontManager.setupRenderer(renderer); + FontTriplet triplet = new FontTriplet("Times", "italic", Font.WEIGHT_NORMAL); + String internalFontKey = fontInfo.getInternalFontKey(triplet); + // Times italic should now be mapped to the 15th font (custom font) + // not the original base 14 (F6) + if (!"F15".equals(internalFontKey)) { + throw new Exception("font substitution failed :" + triplet); + } + return null; + } + + /** + * {@inheritDoc} + */ + public String getUserConfigFilename() { + return "test_fonts_substitution.xconf"; + } +} diff --git a/test/java/org/apache/fop/config/UserConfigTestSuite.java b/test/java/org/apache/fop/config/UserConfigTestSuite.java index 439a2c031..c12180625 100644 --- a/test/java/org/apache/fop/config/UserConfigTestSuite.java +++ b/test/java/org/apache/fop/config/UserConfigTestSuite.java @@ -44,6 +44,7 @@ public class UserConfigTestSuite { suite.addTest(new TestSuite(FontEmbedUrlMalformedTestCase.class)); suite.addTest(new TestSuite(FontsDirectoryRecursiveTestCase.class)); suite.addTest(new TestSuite(FontsAutoDetectTestCase.class)); + suite.addTest(new TestSuite(FontsSubstitutionTestCase.class)); //$JUnit-END$ return suite; } diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java index bcd5f1db4..b37abdf0d 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java @@ -95,8 +95,8 @@ public class LayoutEngineTester { */ public LayoutEngineTester(File areaTreeBackupDir) { this.areaTreeBackupDir = areaTreeBackupDir; - fopFactory.setBase14KerningEnabled(false); - fopFactoryWithBase14Kerning.setBase14KerningEnabled(true); + fopFactory.getFontManager().setBase14KerningEnabled(false); + fopFactoryWithBase14Kerning.getFontManager().setBase14KerningEnabled(true); } private Templates getTestcase2FOStylesheet() throws TransformerConfigurationException { diff --git a/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java b/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java index 7c66a0ceb..d4b748a8d 100644 --- a/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java +++ b/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java @@ -101,7 +101,7 @@ public class BasePDFTestCase extends AbstractFOPTestCase { } } - private static Exception extractOriginalException(Exception e) { + protected static Exception extractOriginalException(Exception e) { if (e.getCause() != null) { return extractOriginalException((Exception)e.getCause()); } else if (e instanceof SAXException) { diff --git a/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java b/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java index 881a8abd2..96167ceb0 100644 --- a/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java +++ b/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java @@ -44,9 +44,9 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { * @return an initialized FOUserAgent * */ protected FOUserAgent getUserAgent() { - final FOUserAgent a = fopFactory.newFOUserAgent(); - a.getRendererOptions().put("pdf-a-mode", "PDF/A-1b"); - return a; + final FOUserAgent userAgent = fopFactory.newFOUserAgent(); + userAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-1b"); + return userAgent; } /** @@ -104,5 +104,5 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { //Good! } } - + } -- cgit v1.2.3 From fb3926df45b065e4161d8769c11131fe8af7b4fd Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Wed, 7 May 2008 14:04:17 +0000 Subject: Bugzilla 41500: Fixed a ClassCastException when fo:wrapper was used as a child of an fo:block-container. Bugzilla 42423: Added support for the "id" attribute on fo:wrappers that are children of the fo:flow. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654111 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/EventFormatter.xml | 3 +- src/java/org/apache/fop/fo/flow/Wrapper.java | 56 ++++++++++++---------- .../fop/layoutmgr/BlockStackingLayoutManager.java | 16 +++++-- .../apache/fop/layoutmgr/FlowLayoutManager.java | 4 +- .../fop/layoutmgr/inline/WrapperLayoutManager.java | 19 +++++++- status.xml | 9 +++- test/layoutengine/disabled-testcases.xml | 6 --- 7 files changed, 75 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml index 74e120407..4bff75f85 100644 --- a/src/java/org/apache/fop/events/EventFormatter.xml +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -26,9 +26,10 @@ The element must be a child of fo:simple-page-master. The element must be a child of fo:declarations. The element must be a child of fo:declarations or fo:simple-page-master. + An fo:wrapper is only permitted to have children that would be permitted for its parent. For "{elementName}", only one "{offendingNode}" may be declared.{{locator}} For "{elementName}", "{tooLateNode}" must be declared before "{tooEarlyNode}"!{{locator}} - "{offendingNode}" is not a valid child element of "{elementName}"![ {ruleViolated,lookup}]{{locator}} + "{offendingNode}" is not a valid child of "{elementName}"![ {ruleViolated,lookup}]{{locator}} "{elementName}" is missing child elements.[ Required content model: {contentModel}]{{locator}} Element "{elementName}" is missing required property "{propertyName}"!{{locator}} diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index 4b1cfeeac..dfe837315 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -22,9 +22,10 @@ package org.apache.fop.fo.flow; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOText; import org.apache.fop.fo.FObjMixed; -import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; /** @@ -39,25 +40,15 @@ public class Wrapper extends FObjMixed { // used for FO validation private boolean blockOrInlineItemFound = false; - private boolean inlineChildrenAllowed = false; /** - * Base constructor + * Create a Wrapper instance that is a child of the + * given {@link FONode} * * @param parent {@link FONode} that is the parent of this object */ public Wrapper(FONode parent) { super(parent); - /* Check if the fo:wrapper is a child of a FO that allows mixed content - * (or a descendant in nested fo:wrapper sequence, the first of which - * is a child of a FO that allows mixed content) */ - FONode ancestor = this.parent; - while (ancestor instanceof Wrapper) { - ancestor = ancestor.getParent(); - } - if (ancestor instanceof FObjMixed ) { - inlineChildrenAllowed = true; - } } /** @@ -66,7 +57,6 @@ public class Wrapper extends FObjMixed { *
    Additionally (unimplemented): "An fo:wrapper that is a child of an * fo:multi-properties is only permitted to have children that would * be permitted in place of the fo:multi-properties." - * */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { @@ -77,8 +67,12 @@ public class Wrapper extends FObjMixed { "(#PCDATA|%inline;|%block;)"); } } else if (isBlockOrInlineItem(nsURI, localName)) { - //delegate validation to parent - FONode.validateChildNode(this.parent, loc, nsURI, localName); + try { + //delegate validation to parent + FONode.validateChildNode(this.parent, loc, nsURI, localName); + } catch (ValidationException vex) { + invalidChildError(loc, getName(), FO_URI, localName, "rule.wrapperInvalidChildForParent"); + } blockOrInlineItemFound = true; } else { invalidChildError(loc, nsURI, localName); @@ -87,15 +81,27 @@ public class Wrapper extends FObjMixed { } /** {@inheritDoc} */ - protected void addCharacters( - char[] data, - int start, - int end, - PropertyList pList, - Locator locator) throws FOPException { - /* Only add text if the fo:wrapper's parent allows inline children */ - if (this.inlineChildrenAllowed) { - super.addCharacters(data, start, end, pList, locator); + protected void addChildNode(FONode child) throws FOPException { + super.addChildNode(child); + /* If the child is a text node, and it generates areas + * (i.e. contains either non-white-space or preserved + * white-space), then check whether the nearest non-wrapper + * ancestor allows this. + */ + if (child instanceof FOText + && ((FOText)child).willCreateArea()) { + FONode ancestor = parent; + while (ancestor.getNameId() == Constants.FO_WRAPPER) { + ancestor = ancestor.getParent(); + } + if (!(ancestor instanceof FObjMixed)) { + invalidChildError( + getLocator(), + getLocalName(), + FONode.FO_URI, + "#PCDATA", + "rule.wrapperInvalidChildForParent"); + } } } diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index e9d529ebe..b208e4e9b 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -1527,10 +1527,20 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager protected void wrapPositionElements(List sourceList, List targetList, boolean force) { ListIterator listIter = sourceList.listIterator(); + Object tempElement; while (listIter.hasNext()) { - ListElement tempElement; - tempElement = (ListElement) listIter.next(); - wrapPositionElement(tempElement, targetList, force); + tempElement = listIter.next(); + if (tempElement instanceof ListElement) { + wrapPositionElement( + (ListElement) tempElement, + targetList, + force); + } else if (tempElement instanceof List) { + wrapPositionElements( + (List) tempElement, + targetList, + force); + } } } diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index c54f0ce12..9cd5c622d 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -30,6 +30,7 @@ import org.apache.fop.area.Area; import org.apache.fop.area.BlockParent; import org.apache.fop.fo.pagination.Flow; import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; +import org.apache.fop.layoutmgr.inline.WrapperLayoutManager; /** * LayoutManager for an fo:flow object. @@ -75,7 +76,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager LinkedList returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { - if (curLM instanceof InlineLevelLayoutManager) { + if (!(curLM instanceof WrapperLayoutManager) + && curLM instanceof InlineLevelLayoutManager) { log.error("inline area not allowed under flow - ignoring"); curLM.setFinished(true); continue; diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index 09e22d481..8108bbf40 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -20,7 +20,12 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.InlineParent; +import org.apache.fop.area.Block; +import org.apache.fop.area.LineArea; import org.apache.fop.fo.flow.Wrapper; +import org.apache.fop.layoutmgr.BlockLayoutManager; +import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; @@ -66,7 +71,19 @@ public class WrapperLayoutManager extends LeafNodeLayoutManager { if (fobj.hasId()) { addId(); InlineArea area = getEffectiveArea(); - parentLM.addChildArea(area); + if (parentLM instanceof BlockStackingLayoutManager + && !(parentLM instanceof BlockLayoutManager)) { + Block helperBlock = new Block(); + LineArea helperLine = new LineArea(); + InlineParent helperInline = new InlineParent(); + helperInline.addChildArea(area); + helperLine.addInlineArea(helperInline); + helperLine.updateExtentsFromChildren(); + helperBlock.addLineArea(helperLine); + parentLM.addChildArea(helperBlock); + } else { + parentLM.addChildArea(area); + } } while (posIter.hasNext()) { posIter.next(); diff --git a/status.xml b/status.xml index 90992bb56..a48920e36 100644 --- a/status.xml +++ b/status.xml @@ -57,10 +57,17 @@ Added SVG support for AFP (GOCA). + + Added support for the "id" attribute on fo:wrappers when used + as a child of the fo:flow. + + + Fixed a ClassCastException when using an fo:wrapper as a child + of an fo:block-container. + Add support for font substitution. - PCL Renderer: Improved page format selection so it doesn't interfere with duplex printing. diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index 12d7ed1aa..c17457a3d 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -233,12 +233,6 @@ is probably not expressing the indended outcome according to the spec. The test case should be revisited. - - fo:wrapper around block-level content (with id) - wrapper_block_id.xml - "id" attributes on fo:wrapper around block-level content don't get - added to the area tree. - Soft hyphen with normal hyphenation enabled block_shy_linebreaking_hyph.xml -- cgit v1.2.3 From 92e9727bae29acaa5d7567ebef7ca3fd9fd41d2d Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Wed, 7 May 2008 17:41:07 +0000 Subject: Added comment git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654190 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/Wrapper.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index dfe837315..5ed594ecc 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -67,8 +67,13 @@ public class Wrapper extends FObjMixed { "(#PCDATA|%inline;|%block;)"); } } else if (isBlockOrInlineItem(nsURI, localName)) { + /* delegate validation to parent, but keep the error reporting + * tidy. If we would simply call validateChildNode() on the + * parent, the user would get a wrong impression, as only the + * locator (if any) will contain a reference to the offending + * fo:wrapper. + */ try { - //delegate validation to parent FONode.validateChildNode(this.parent, loc, nsURI, localName); } catch (ValidationException vex) { invalidChildError(loc, getName(), FO_URI, localName, "rule.wrapperInvalidChildForParent"); -- cgit v1.2.3 From ed1db93f52dc1fb48c34a938103f999df5c8f16f Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Wed, 7 May 2008 22:45:46 +0000 Subject: Corrected errors in ColumnNumberPropertyMaker.java; temporarily disabled two testcases for a non-standard feature git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654314 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/table/TableFObj.java | 48 ++++++++++++++++------ test/fotree/disabled-testcases.xml | 10 +++++ 2 files changed, 46 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 9b60de740..731b2f77f 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -27,9 +27,7 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; -import org.apache.fop.fo.properties.CommonBorderPaddingBackground; -import org.apache.fop.fo.properties.NumberProperty; -import org.apache.fop.fo.properties.Property; +import org.apache.fop.fo.properties.*; import org.apache.fop.layoutmgr.table.CollapsingBorderModel; /** @@ -51,7 +49,7 @@ public abstract class TableFObj extends FObj { /** * Main constructor - * + * * @param parent the parent node */ public TableFObj(FONode parent) { @@ -76,7 +74,7 @@ public abstract class TableFObj extends FObj { } /** - * + * * @param side the side for which to return the border precedence * @return the "border-precedence" value for the given side */ @@ -98,9 +96,9 @@ public abstract class TableFObj extends FObj { /** * Convenience method to returns a reference * to the base Table instance - * + * * @return the base table instance - * + * */ public Table getTable() { // Will be overridden in Table; for any other Table-node, recursive call to @@ -142,7 +140,7 @@ public abstract class TableFObj extends FObj { * Check the value of the column-number property. * Return the parent's column index (initial value) in case * of a negative or zero value - * + * * @see org.apache.fop.fo.properties.PropertyMaker#make(PropertyList, String, FObj) */ public Property make(PropertyList propertyList, String value, FObj fo) @@ -155,20 +153,46 @@ public abstract class TableFObj extends FObj { int columnIndex = p.getNumeric().getValue(); int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED) .getNumeric().getValue(); - int i = -1; - while (++i < colSpan) { - if (columnIndexManager.isColumnNumberUsed(columnIndex + i)) { + + int i = columnIndex - 1; + int lastIndex = (columnIndex + colSpan) - 1; + while (++i < lastIndex) { + if (columnIndexManager.isColumnNumberUsed(i)) { /* if column-number is already in use by another * cell/column => error! */ TableEventProducer eventProducer = TableEventProducer.Provider.get( fo.getUserAgent().getEventBroadcaster()); - eventProducer.cellOverlap(this, fo.getName(), columnIndex + 1, fo.getLocator()); + eventProducer.cellOverlap(this, propertyList.getFObj().getName(), + i, fo.getLocator()); } } return p; } + + /** + * If the value is not positive, return a property with value of the next + * free column number + * + * {@inheritDoc} + */ + public Property convertProperty(Property p, + PropertyList propertyList, FObj fo) + throws PropertyException { + if (p instanceof EnumProperty) { + return EnumNumber.getInstance(p); + } + Number val = p.getNumber(); + if (val != null) { + int i = val.intValue(); + if (i <= 0) { + i = 1; + } + return NumberProperty.getInstance(i); + } + return convertPropertyDatatype(p, propertyList, fo); + } } /** {@inheritDoc} */ diff --git a/test/fotree/disabled-testcases.xml b/test/fotree/disabled-testcases.xml index 196eafcc4..0d0a76f6b 100644 --- a/test/fotree/disabled-testcases.xml +++ b/test/fotree/disabled-testcases.xml @@ -28,4 +28,14 @@ The code currently evaluates this function according to the column in which the marker appears in the source document, rather than the column it is retrieved in. + + column-number_negative-or-zero + column-number_negative-or-zero.fo + + + + column-number_non-integer + column-number_non-integer.fo + + -- cgit v1.2.3 From 860e8234581a041579834fae8da11248a12dedc4 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 7 May 2008 23:27:45 +0000 Subject: Looks like the serialVersionUID got bumped but the log statement wasn't being completely honest about what it was doing. FontCache now attempts to delete its cache file so subsequent runs should repopulate it. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654322 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontCache.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index c5b6ab9c7..213f5cdee 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -151,6 +151,11 @@ public final class FontCache implements Serializable { //We don't really care about the exception since it's just a cache file log.warn("I/O exception while reading font cache (" + ioe.getMessage() + "). Discarding font cache file."); + try { + cacheFile.delete(); + } catch(SecurityException ex) { + log.warn("Failed to delete font cache file: " + cacheFile.getAbsolutePath()); + } } } return null; -- cgit v1.2.3 From 644183c1cfd7e6d3501a010a63b9172c70a1dffc Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 7 May 2008 23:29:04 +0000 Subject: Whoops.. small checkstyle nit :) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654323 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index 213f5cdee..3cddb8234 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -153,7 +153,7 @@ public final class FontCache implements Serializable { + "). Discarding font cache file."); try { cacheFile.delete(); - } catch(SecurityException ex) { + } catch (SecurityException ex) { log.warn("Failed to delete font cache file: " + cacheFile.getAbsolutePath()); } } -- cgit v1.2.3 From faa85b230ffb2e7819d5ad8a4ae03c70a11af550 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 8 May 2008 00:18:14 +0000 Subject: Removed inadvertently added override [Avoid late night commits...] git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654338 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/table/TableFObj.java | 23 ---------------------- 1 file changed, 23 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 731b2f77f..8fd56a085 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -170,29 +170,6 @@ public abstract class TableFObj extends FObj { return p; } - - /** - * If the value is not positive, return a property with value of the next - * free column number - * - * {@inheritDoc} - */ - public Property convertProperty(Property p, - PropertyList propertyList, FObj fo) - throws PropertyException { - if (p instanceof EnumProperty) { - return EnumNumber.getInstance(p); - } - Number val = p.getNumber(); - if (val != null) { - int i = val.intValue(); - if (i <= 0) { - i = 1; - } - return NumberProperty.getInstance(i); - } - return convertPropertyDatatype(p, propertyList, fo); - } } /** {@inheritDoc} */ -- cgit v1.2.3 From 6a1cd530ec0c384ccfcce1636707e7213b60a535 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 8 May 2008 00:33:21 +0000 Subject: Removed tabs. Checkstyle now configured. Late nights.. and a new machine build.. :S git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654347 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontCache.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index 3cddb8234..ba9529c02 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -152,9 +152,9 @@ public final class FontCache implements Serializable { log.warn("I/O exception while reading font cache (" + ioe.getMessage() + "). Discarding font cache file."); try { - cacheFile.delete(); + cacheFile.delete(); } catch (SecurityException ex) { - log.warn("Failed to delete font cache file: " + cacheFile.getAbsolutePath()); + log.warn("Failed to delete font cache file: " + cacheFile.getAbsolutePath()); } } } -- cgit v1.2.3 From 0c1a6a21c219d237e43e6ded1d6bf1adb58e79c3 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 8 May 2008 07:32:02 +0000 Subject: Checkstyle fix. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654437 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/TableFObj.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 8fd56a085..ca1afa622 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -27,7 +27,9 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; -import org.apache.fop.fo.properties.*; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.NumberProperty; +import org.apache.fop.fo.properties.Property; import org.apache.fop.layoutmgr.table.CollapsingBorderModel; /** -- cgit v1.2.3 From c68f717f73d501c415aa0630db12a17ea720d145 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 8 May 2008 09:55:55 +0000 Subject: Added support for font referencing for auto-detected fonts. Referenced TrueType fonts can now use glyphs outside the WinAnsi charset (Same approach as for extended glyph support with Type 1 fonts). Removed FopFactory reference from FontManager to make the class more useful outside this context (ex. transcoders). Updated fonts documentation with information that TTCs are now supported through auto-detection. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654461 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/fonts.xml | 70 ++++++++++++----- src/java/org/apache/fop/apps/FopFactory.java | 11 ++- .../apache/fop/apps/FopFactoryConfigurator.java | 6 +- src/java/org/apache/fop/fonts/EmbedFontInfo.java | 33 +++++++- src/java/org/apache/fop/fonts/FontLoader.java | 34 ++++---- src/java/org/apache/fop/fonts/FontManager.java | 52 +++++++------ .../apache/fop/fonts/FontManagerConfigurator.java | 73 ++++++++++++++++- src/java/org/apache/fop/fonts/FontSetup.java | 9 +-- src/java/org/apache/fop/fonts/FontTriplet.java | 15 ++++ src/java/org/apache/fop/fonts/LazyFont.java | 9 ++- .../fop/fonts/autodetect/FontInfoFinder.java | 5 +- .../apache/fop/fonts/truetype/TTFFontLoader.java | 91 +++++++++++++++++----- .../apache/fop/fonts/type1/Type1FontLoader.java | 9 ++- .../fop/render/PrintRendererConfigurator.java | 36 +++++++-- .../render/java2d/ConfiguredFontCollection.java | 3 +- src/java/org/apache/fop/render/ps/PSFontUtils.java | 3 +- .../fop/svg/PDFDocumentGraphics2DConfigurator.java | 21 ++--- status.xml | 4 + 18 files changed, 365 insertions(+), 119 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml index eb466ec73..30b72ffac 100644 --- a/src/documentation/content/xdocs/trunk/fonts.xml +++ b/src/documentation/content/xdocs/trunk/fonts.xml @@ -177,10 +177,8 @@ if you wanted to add a custom font. This unconvenient step has been removed and in addition to that, FOP supports auto-registration of fonts, i.e. FOP can find fonts installed in your operating system or can scan user-specified directories for fonts. - Font registration via XML font metrics file is still supported and is still necessary - if you want to use a TrueType Collection (*.ttc). Direct support for TrueType - collections may be added later. Furthermore, the XML font metrics files are still - required if you don't want to embed, but only reference a font. + Font registration via XML font metrics file is still supported and may still be necessary + for some very special cases as fallback variant while we stabilize font auto-detection.

    Basic information about fonts can be found at: @@ -375,20 +373,56 @@

    Embedding - The PostScript renderer does not yet support TrueType fonts, but can embed Type 1 fonts. - The font is simply embedded into the PDF file, it is not converted. -

    Font embedding is enabled in the userconfig.xml file and controlled by the embed-url attribute. - If you don't specify the embed-url attribute the font will not be embedded, but will only be referenced.

    - - Omitting the embed-url attribute for CID-encoded TrueType fonts will currently produce invalid - PDF files! If you create the XML font metric file using the "-enc ansi" option, you can omit - the embed-url attribute for TrueType fonts but you're restricted to the WinAnsi character set. - -

    When FOP embeds a font, it adds a prefix to the fontname to ensure that the name will not match the fontname of an installed font. - This is helpful with older versions of Acrobat Reader that preferred installed fonts over embedded fonts.

    -

    When embedding PostScript fonts, the entire font is always embedded.

    -

    When embedding TrueType fonts (ttf) or TrueType Collections (ttc), a subset of the - original font, containing only the glyphs used, is embedded in the output document.

    +

    + By default, all fonts are embedded if an output format supports font embedding. In some + cases, however, it is preferred that some fonts are only referenced. When working + with referenced fonts it is important to be in control of the target environment where + the produced document is consumed, i.e. the necessary fonts have to be installed there. +

    +

    + There are two different ways how you can specify that a font should be referenced: +

    +
      +
    1. + When using the old-style "font" element to configure a single font, font referencing + is controlled by the embed-url attribute. If you don't specify the embed-url attribute + the font will not be embedded, but will only be referenced. +
    2. +
    3. + For automatically configured fonts there's a different mechanism to specify which + fonts should be referenced rather than embedded. This is done in the "referenced-fonts" + element in the configuration. Here's an example: +
    4. +
    + + + + + + + +]]> +

    + At the moment, you can only match fonts against their font-family. It is possible to use + regular expressions as is shown in the second example above ("DejaVu.*"). The syntax for + the regular expressions used here are the one used by the + java.util.regex package. + So, in the above snippet "Helvetica" and all variants of the "DejaVu" font family are + referenced. If you want to reference all fonts, just specify font-family=".*". +

    +

    + Various notes related to embedded fonts: +

    +
      +
    • The PostScript renderer does not yet support TrueType fonts, but can embed Type 1 fonts.
    • +
    • The font is simply embedded into the PDF file, it is not converted.
    • +
    • When FOP embeds a font, it adds a prefix to the fontname to ensure that the name will not match the fontname of an installed font. + This is helpful with older versions of Acrobat Reader that preferred installed fonts over embedded fonts.
    • +
    • When embedding PostScript fonts, the entire font is always embedded.
    • +
    • When embedding TrueType fonts (ttf) or TrueType Collections (ttc), a subset of the + original font, containing only the glyphs used, is embedded in the output document.
    • +
    Substitution diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index bd54ffb2f..c196e1204 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -692,12 +692,19 @@ public class FopFactory implements ImageContext { } /** - * Returns the font manager + * Returns the font manager. * @return the font manager */ public FontManager getFontManager() { if (fontManager == null) { - this.fontManager = new FontManager(this); + this.fontManager = new FontManager() { + + /** {@inheritDoc} */ + public void setFontBaseURL(String fontBase) throws MalformedURLException { + super.setFontBaseURL(getFOURIResolver().checkBaseURL(fontBase)); + } + + }; } return this.fontManager; } diff --git a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java index 89388ae77..cc3ce2d0b 100644 --- a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java +++ b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java @@ -23,15 +23,17 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; +import org.xml.sax.SAXException; + import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontManagerConfigurator; import org.apache.fop.util.LogUtil; -import org.xml.sax.SAXException; /** * FopFactory configurator @@ -174,7 +176,7 @@ public class FopFactoryConfigurator { // configure font manager FontManager fontManager = factory.getFontManager(); FontManagerConfigurator fontManagerConfigurator = new FontManagerConfigurator(cfg); - fontManagerConfigurator.configure(fontManager); + fontManagerConfigurator.configure(fontManager, strict); } /** diff --git a/src/java/org/apache/fop/fonts/EmbedFontInfo.java b/src/java/org/apache/fop/fonts/EmbedFontInfo.java index dc40da780..0d0bcafdb 100644 --- a/src/java/org/apache/fop/fonts/EmbedFontInfo.java +++ b/src/java/org/apache/fop/fonts/EmbedFontInfo.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts; +import java.io.IOException; import java.io.Serializable; import java.util.List; @@ -45,6 +46,8 @@ public class EmbedFontInfo implements Serializable { /** the list of associated font triplets */ private List/**/ fontTriplets = null; + private transient boolean embedded = true; + /** * Main constructor * @param metricsFile Path to the xml file containing font metrics @@ -120,11 +123,37 @@ public class EmbedFontInfo implements Serializable { } /** - * {@inheritDoc} + * Indicates whether the font is only referenced rather than embedded. + * @return true if the font is embedded, false if it is referenced. + */ + public boolean isEmbedded() { + if (metricsFile != null && embedFile == null) { + return false; + } else { + return this.embedded; + } + } + + /** + * Defines whether the font is embedded or not. + * @param value true to embed the font, false to reference it */ + public void setEmbedded(boolean value) { + this.embedded = value; + } + + private void readObject(java.io.ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + this.embedded = true; + } + + /** {@inheritDoc} */ public String toString() { return "metrics-url=" + metricsFile + ",embed-url=" + embedFile + ", kerning=" + kerning + ", " + "font-triplet=" + fontTriplets - + (getSubFontName() != null ? ", sub-font=" + getSubFontName() : ""); + + (getSubFontName() != null ? ", sub-font=" + getSubFontName() : "") + + (isEmbedded() ? "" : ", NOT embedded"); } + } diff --git a/src/java/org/apache/fop/fonts/FontLoader.java b/src/java/org/apache/fop/fonts/FontLoader.java index 69c55ceae..2699ca6d5 100644 --- a/src/java/org/apache/fop/fonts/FontLoader.java +++ b/src/java/org/apache/fop/fonts/FontLoader.java @@ -39,9 +39,7 @@ import org.apache.fop.fonts.type1.Type1FontLoader; */ public abstract class FontLoader { - /** - * logging instance - */ + /** logging instance */ protected static Log log = LogFactory.getLog(FontLoader.class); /** URI representing the font file */ @@ -53,14 +51,18 @@ public abstract class FontLoader { /** true if the font has been loaded */ protected boolean loaded = false; + /** true if the font will be embedded, false if it will be referenced only. */ + protected boolean embedded = true; /** * Default constructor. * @param fontFileURI the URI to the PFB file of a Type 1 font + * @param embedded indicates whether the font is embedded or referenced * @param resolver the font resolver used to resolve URIs */ - public FontLoader(String fontFileURI, FontResolver resolver) { + public FontLoader(String fontFileURI, boolean embedded, FontResolver resolver) { this.fontFileURI = fontFileURI; + this.embedded = embedded; this.resolver = resolver; } @@ -72,46 +74,48 @@ public abstract class FontLoader { * Loads a custom font from a File. In the case of Type 1 fonts, the PFB file must be specified. * @param fontFile the File representation of the font * @param subFontName the sub-fontname of a font (for TrueType Collections, null otherwise) + * @param embedded indicates whether the font is embedded or referenced * @param resolver the font resolver to use when resolving URIs * @return the newly loaded font * @throws IOException In case of an I/O error */ - public static CustomFont loadFont(File fontFile, String subFontName, FontResolver resolver) - throws IOException { - return loadFont(fontFile.getAbsolutePath(), subFontName, resolver); + public static CustomFont loadFont(File fontFile, String subFontName, + boolean embedded, FontResolver resolver) throws IOException { + return loadFont(fontFile.getAbsolutePath(), subFontName, embedded, resolver); } /** * Loads a custom font from an URL. In the case of Type 1 fonts, the PFB file must be specified. * @param fontUrl the URL representation of the font * @param subFontName the sub-fontname of a font (for TrueType Collections, null otherwise) + * @param embedded indicates whether the font is embedded or referenced * @param resolver the font resolver to use when resolving URIs * @return the newly loaded font * @throws IOException In case of an I/O error */ - public static CustomFont loadFont(URL fontUrl, String subFontName, FontResolver resolver) - throws IOException { - return loadFont(fontUrl.toExternalForm(), subFontName, resolver); + public static CustomFont loadFont(URL fontUrl, String subFontName, + boolean embedded, FontResolver resolver) throws IOException { + return loadFont(fontUrl.toExternalForm(), subFontName, embedded, resolver); } - /** * Loads a custom font from a URI. In the case of Type 1 fonts, the PFB file must be specified. * @param fontFileURI the URI to the font * @param subFontName the sub-fontname of a font (for TrueType Collections, null otherwise) + * @param embedded indicates whether the font is embedded or referenced * @param resolver the font resolver to use when resolving URIs * @return the newly loaded font * @throws IOException In case of an I/O error */ - public static CustomFont loadFont(String fontFileURI, String subFontName, FontResolver resolver) - throws IOException { + public static CustomFont loadFont(String fontFileURI, String subFontName, + boolean embedded, FontResolver resolver) throws IOException { fontFileURI = fontFileURI.trim(); boolean type1 = isType1(fontFileURI); FontLoader loader; if (type1) { - loader = new Type1FontLoader(fontFileURI, resolver); + loader = new Type1FontLoader(fontFileURI, embedded, resolver); } else { - loader = new TTFFontLoader(fontFileURI, subFontName, resolver); + loader = new TTFFontLoader(fontFileURI, subFontName, embedded, resolver); } return loader.getFont(); } diff --git a/src/java/org/apache/fop/fonts/FontManager.java b/src/java/org/apache/fop/fonts/FontManager.java index 8ff85afb4..d25d2d390 100644 --- a/src/java/org/apache/fop/fonts/FontManager.java +++ b/src/java/org/apache/fop/fonts/FontManager.java @@ -25,7 +25,7 @@ import java.net.MalformedURLException; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; -import org.apache.fop.apps.FopFactory; +import org.apache.fop.fonts.FontTriplet.Matcher; import org.apache.fop.fonts.substitute.FontSubstitutions; import org.apache.fop.render.PrintRenderer; @@ -34,7 +34,8 @@ import org.apache.fop.render.PrintRenderer; // and start using POJO config/properties type classes /** - * The manager of fonts + * The manager of fonts. The class holds a reference to the font cache and information about + * font substitution, referenced fonts and similar. */ public class FontManager { /** Use cache (record previously detected font triplet info) */ @@ -49,42 +50,31 @@ public class FontManager { /** Font substitutions */ private FontSubstitutions fontSubstitutions = null; - private FopFactory fopFactory = null; - /** Allows enabling kerning on the base 14 fonts, default is false */ private boolean enableBase14Kerning = false; + /** FontTriplet matcher for fonts that shall be referenced rather than embedded. */ + private FontTriplet.Matcher referencedFontsMatcher; + /** * Main constructor - * - * @param fopFactory the fo URI resolver */ - public FontManager(FopFactory fopFactory) { - this(fopFactory, DEFAULT_USE_CACHE); - } - - /** - * Constructor - * - * @param fopFactory the fo URI resolver - * @param useCache true if the FontCache should be used - */ - public FontManager(FopFactory fopFactory, boolean useCache) { - this.fopFactory = fopFactory; - setUseCache(useCache); + public FontManager() { + setUseCache(DEFAULT_USE_CACHE); } /** * Sets the font base URL. * @param fontBase font base URL - * @throws MalformedURLException if there's a problem with a file URL + * @throws MalformedURLException if there's a problem with a URL */ public void setFontBaseURL(String fontBase) throws MalformedURLException { - this.fontBase = fopFactory.getFOURIResolver().checkBaseURL(fontBase); + this.fontBase = fontBase; } /** - * @return the font base URL + * Returns the font base URL. + * @return the font base URL (or null if none was set) */ public String getFontBaseURL() { return this.fontBase; @@ -218,4 +208,22 @@ public class FontManager { } }; } + + /** + * Sets the {@link FontTriplet.Matcher} that can be used to identify the fonts that shall + * be referenced rather than embedded. + * @param matcher the font triplet matcher + */ + public void setReferencedFontsMatcher(FontTriplet.Matcher matcher) { + this.referencedFontsMatcher = matcher; + } + + /** + * Gets the {@link FontTriplet.Matcher} that can be used to identify the fonts that shall + * be referenced rather than embedded. + * @return the font triplet matcher (or null if none is set) + */ + public Matcher getReferencedFontsMatcher() { + return this.referencedFontsMatcher; + } } diff --git a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java index edee46a0f..d44470e6b 100644 --- a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java +++ b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java @@ -20,11 +20,14 @@ package org.apache.fop.fonts; import java.net.MalformedURLException; +import java.util.List; +import java.util.regex.Pattern; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; import org.apache.fop.fonts.substitute.FontSubstitutions; import org.apache.fop.fonts.substitute.FontSubstitutionsConfigurator; @@ -51,9 +54,11 @@ public class FontManagerConfigurator { /** * Initializes font settings from the user configuration * @param fontManager a font manager - * @throws FOPException fop exception + * @param strict true if strict checking of the configuration is enabled + * @throws FOPException if an exception occurs while processing the configuration */ - public void configure(FontManager fontManager) throws FOPException { + public void configure(FontManager fontManager, boolean strict) throws FOPException { + // caching (fonts) if (cfg.getChild("use-cache", false) != null) { try { @@ -84,6 +89,68 @@ public class FontManagerConfigurator { fontSubstitutionsConfigurator.configure(substitutions); fontManager.setFontSubstitutions(substitutions); } + + // referenced fonts (fonts which are not to be embedded) + Configuration referencedFontsCfg = fontsCfg.getChild("referenced-fonts", false); + if (referencedFontsCfg != null) { + createReferencedFontsMatcher(referencedFontsCfg, strict, fontManager); + } + } - } + } + + private static void createReferencedFontsMatcher(Configuration referencedFontsCfg, + boolean strict, FontManager fontManager) throws FOPException { + List matcherList = new java.util.ArrayList(); + Configuration[] matches = referencedFontsCfg.getChildren("match"); + for (int i = 0; i < matches.length; i++) { + try { + matcherList.add(new FontFamilyRegExFontTripletMatcher( + matches[i].getAttribute("font-family"))); + } catch (ConfigurationException ce) { + LogUtil.handleException(log, ce, strict); + continue; + } + } + FontTriplet.Matcher orMatcher = new OrFontTripletMatcher( + (FontTriplet.Matcher[])matcherList.toArray( + new FontTriplet.Matcher[matcherList.size()])); + fontManager.setReferencedFontsMatcher(orMatcher); + } + + private static class OrFontTripletMatcher implements FontTriplet.Matcher { + + private FontTriplet.Matcher[] matchers; + + public OrFontTripletMatcher(FontTriplet.Matcher[] matchers) { + this.matchers = matchers; + } + + /** {@inheritDoc} */ + public boolean matches(FontTriplet triplet) { + for (int i = 0, c = matchers.length; i < c; i++) { + if (matchers[i].matches(triplet)) { + return true; + } + } + return false; + } + + } + + private static class FontFamilyRegExFontTripletMatcher implements FontTriplet.Matcher { + + private Pattern regex; + + public FontFamilyRegExFontTripletMatcher(String regex) { + this.regex = Pattern.compile(regex); + } + + /** {@inheritDoc} */ + public boolean matches(FontTriplet triplet) { + return regex.matcher(triplet.getName()).matches(); + } + + } + } diff --git a/src/java/org/apache/fop/fonts/FontSetup.java b/src/java/org/apache/fop/fonts/FontSetup.java index ab893d385..9aa8440db 100644 --- a/src/java/org/apache/fop/fonts/FontSetup.java +++ b/src/java/org/apache/fop/fonts/FontSetup.java @@ -27,6 +27,7 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fonts.base14.Courier; import org.apache.fop.fonts.base14.CourierBold; import org.apache.fop.fonts.base14.CourierBoldOblique; @@ -205,20 +206,12 @@ public class FontSetup { } String internalName = null; - //FontReader reader = null; for (int i = 0; i < embedFontInfoList.size(); i++) { EmbedFontInfo embedFontInfo = (EmbedFontInfo)embedFontInfoList.get(i); - //String metricsFile = configFontInfo.getMetricsFile(); internalName = "F" + num; num++; - /* - reader = new FontReader(metricsFile); - reader.useKerning(configFontInfo.getKerning()); - reader.setFontEmbedPath(configFontInfo.getEmbedFile()); - fontInfo.addMetrics(internalName, reader.getFont()); - */ LazyFont font = new LazyFont(embedFontInfo, resolver); fontInfo.addMetrics(internalName, font); diff --git a/src/java/org/apache/fop/fonts/FontTriplet.java b/src/java/org/apache/fop/fonts/FontTriplet.java index 9091219f5..a989cf0f7 100644 --- a/src/java/org/apache/fop/fonts/FontTriplet.java +++ b/src/java/org/apache/fop/fonts/FontTriplet.java @@ -128,5 +128,20 @@ public class FontTriplet implements Comparable, Serializable { public String toString() { return getKey(); } + + + /** + * Matcher interface for {@link FontTriplet}. + */ + public interface Matcher { + + /** + * Indicates whether the given {@link FontTriplet} matches a particular criterium. + * @param triplet the font triplet + * @return true if the font triplet is a match + */ + boolean matches(FontTriplet triplet); + } + } diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index 5490e13f1..b4f7773a3 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -44,6 +44,7 @@ public class LazyFont extends Typeface implements FontDescriptor { private String metricsFileName = null; private String fontEmbedPath = null; private boolean useKerning = false; + private boolean embedded = true; private String subFontName = null; private boolean isMetricsLoaded = false; @@ -63,6 +64,7 @@ public class LazyFont extends Typeface implements FontDescriptor { this.fontEmbedPath = fontInfo.getEmbedFile(); this.useKerning = fontInfo.getKerning(); this.subFontName = fontInfo.getSubFontName(); + this.embedded = fontInfo.isEmbedded(); this.resolver = resolver; } @@ -118,14 +120,17 @@ public class LazyFont extends Typeface implements FontDescriptor { new URL(metricsFileName).openStream())); } reader.setKerningEnabled(useKerning); - reader.setFontEmbedPath(fontEmbedPath); + if (this.embedded) { + reader.setFontEmbedPath(fontEmbedPath); + } reader.setResolver(resolver); realFont = reader.getFont(); } else { if (fontEmbedPath == null) { throw new RuntimeException("Cannot load font. No font URIs available."); } - realFont = FontLoader.loadFont(fontEmbedPath, this.subFontName, resolver); + realFont = FontLoader.loadFont(fontEmbedPath, this.subFontName, + this.embedded, resolver); } if (realFont instanceof FontDescriptor) { realFontDescriptor = (FontDescriptor) realFont; diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index b2ee4a274..987b7e918 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -223,7 +223,8 @@ public class FontInfoFinder { log.debug("Loading " + fontName); } try { - TTFFontLoader ttfLoader = new TTFFontLoader(fontFileURI, fontName, resolver); + TTFFontLoader ttfLoader = new TTFFontLoader( + fontFileURI, fontName, true, resolver); customFont = ttfLoader.getFont(); if (this.eventListener != null) { customFont.setEventListener(this.eventListener); @@ -247,7 +248,7 @@ public class FontInfoFinder { } else { // The normal case try { - customFont = FontLoader.loadFont(fontUrl, null, resolver); + customFont = FontLoader.loadFont(fontUrl, null, true, resolver); if (this.eventListener != null) { customFont.setEventListener(this.eventListener); } diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index 9cd59b5b3..325c46971 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -27,11 +27,16 @@ import java.util.Map; import org.apache.commons.io.IOUtils; +import org.apache.xmlgraphics.fonts.Glyphs; + import org.apache.fop.fonts.BFEntry; import org.apache.fop.fonts.CIDFontType; import org.apache.fop.fonts.FontLoader; import org.apache.fop.fonts.FontResolver; +import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.MultiByteFont; +import org.apache.fop.fonts.NamedCharacter; +import org.apache.fop.fonts.SingleByteFont; /** * Loads a TrueType font into memory directly from the original font file. @@ -39,6 +44,7 @@ import org.apache.fop.fonts.MultiByteFont; public class TTFFontLoader extends FontLoader { private MultiByteFont multiFont; + private SingleByteFont singleFont; private String subFontName; /** @@ -47,7 +53,7 @@ public class TTFFontLoader extends FontLoader { * @param resolver the FontResolver for font URI resolution */ public TTFFontLoader(String fontFileURI, FontResolver resolver) { - this(fontFileURI, null, resolver); + this(fontFileURI, null, true, resolver); } /** @@ -55,10 +61,12 @@ public class TTFFontLoader extends FontLoader { * @param fontFileURI the URI representing the font file * @param subFontName the sub-fontname of a font in a TrueType Collection (or null for normal * TrueType fonts) + * @param embedded indicates whether the font is embedded or referenced * @param resolver the FontResolver for font URI resolution */ - public TTFFontLoader(String fontFileURI, String subFontName, FontResolver resolver) { - super(fontFileURI, resolver); + public TTFFontLoader(String fontFileURI, String subFontName, + boolean embedded, FontResolver resolver) { + super(fontFileURI, embedded, resolver); this.subFontName = subFontName; } @@ -95,43 +103,86 @@ public class TTFFontLoader extends FontLoader { throw new UnsupportedOperationException( "OpenType fonts with CFF data are not supported, yet"); } - multiFont = new MultiByteFont(); - multiFont.setResolver(this.resolver); - returnFont = multiFont; + + boolean isCid = this.embedded; + + if (isCid) { + multiFont = new MultiByteFont(); + returnFont = multiFont; + multiFont.setTTCName(ttcFontName); + } else { + singleFont = new SingleByteFont(); + returnFont = singleFont; + } + returnFont.setResolver(resolver); returnFont.setFontName(ttf.getPostScriptName()); returnFont.setFullName(ttf.getFullName()); returnFont.setFamilyNames(ttf.getFamilyNames()); returnFont.setFontSubFamilyName(ttf.getSubFamilyName()); - multiFont.setTTCName(ttcFontName); returnFont.setCapHeight(ttf.getCapHeight()); returnFont.setXHeight(ttf.getXHeight()); returnFont.setAscender(ttf.getLowerCaseAscent()); returnFont.setDescender(ttf.getLowerCaseDescent()); returnFont.setFontBBox(ttf.getFontBBox()); - //returnFont.setFirstChar(ttf.getFirstChar();) returnFont.setFlags(ttf.getFlags()); returnFont.setStemV(Integer.parseInt(ttf.getStemV())); //not used for TTF returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle())); returnFont.setMissingWidth(0); returnFont.setWeight(ttf.getWeightClass()); - - multiFont.setCIDType(CIDFontType.CIDTYPE2); + + if (isCid) { + multiFont.setCIDType(CIDFontType.CIDTYPE2); + int[] wx = ttf.getWidths(); + multiFont.setWidthArray(wx); + List entries = ttf.getCMaps(); + BFEntry[] bfentries = new BFEntry[entries.size()]; + int pos = 0; + Iterator iter = ttf.getCMaps().listIterator(); + while (iter.hasNext()) { + TTFCmapEntry ce = (TTFCmapEntry)iter.next(); + bfentries[pos] = new BFEntry(ce.getUnicodeStart(), ce.getUnicodeEnd(), + ce.getGlyphStartIndex()); + pos++; + } + multiFont.setBFEntries(bfentries); + } else { + singleFont.setFontType(FontType.TRUETYPE); + singleFont.setEncoding(ttf.getCharSetName()); + returnFont.setFirstChar(ttf.getFirstChar()); + returnFont.setLastChar(ttf.getLastChar()); + copyWidthsSingleByte(ttf); + } + + copyKerning(ttf, isCid); + if (this.embedded && ttf.isEmbeddable()) { + multiFont.setEmbedFileName(this.fontFileURI); + } + } + + private void copyWidthsSingleByte(TTFFile ttf) { int[] wx = ttf.getWidths(); - multiFont.setWidthArray(wx); - List entries = ttf.getCMaps(); - BFEntry[] bfentries = new BFEntry[entries.size()]; - int pos = 0; + for (int i = singleFont.getFirstChar(); i <= singleFont.getLastChar(); i++) { + singleFont.setWidth(i, ttf.getCharWidth(i)); + } Iterator iter = ttf.getCMaps().listIterator(); while (iter.hasNext()) { TTFCmapEntry ce = (TTFCmapEntry)iter.next(); - bfentries[pos] = new BFEntry(ce.getUnicodeStart(), ce.getUnicodeEnd(), - ce.getGlyphStartIndex()); - pos++; + if (ce.getUnicodeStart() < 0xFFFE) { + for (char u = (char)ce.getUnicodeStart(); u <= ce.getUnicodeEnd(); u++) { + int codePoint = singleFont.getEncoding().mapChar(u); + if (codePoint <= 0) { + String unicode = Character.toString(u); + String charName = Glyphs.stringToGlyph(unicode); + if (charName.length() > 0) { + NamedCharacter nc = new NamedCharacter(charName, unicode); + int glyphIndex = ce.getGlyphStartIndex() + u - ce.getUnicodeStart(); + singleFont.addUnencodedCharacter(nc, wx[glyphIndex]); + } + } + } + } } - multiFont.setBFEntries(bfentries); - copyKerning(ttf, true); - multiFont.setEmbedFileName(this.fontFileURI); } /** diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 3187379d5..ffb572109 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -44,12 +44,13 @@ public class Type1FontLoader extends FontLoader { /** * Constructs a new Type 1 font loader. * @param fontFileURI the URI to the PFB file of a Type 1 font + * @param embedded indicates whether the font is embedded or referenced * @param resolver the font resolver used to resolve URIs * @throws IOException In case of an I/O error */ - public Type1FontLoader(String fontFileURI, FontResolver resolver) + public Type1FontLoader(String fontFileURI, boolean embedded, FontResolver resolver) throws IOException { - super(fontFileURI, resolver); + super(fontFileURI, embedded, resolver); } private String getPFMURI(String pfbURI) { @@ -119,7 +120,9 @@ public class Type1FontLoader extends FontLoader { singleFont = new SingleByteFont(); singleFont.setFontType(FontType.TYPE1); singleFont.setResolver(this.resolver); - singleFont.setEmbedFileName(this.fontFileURI); + if (this.embedded) { + singleFont.setEmbedFileName(this.fontFileURI); + } returnFont = singleFont; handleEncoding(afm, pfm); diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index 6273b7050..50d06932d 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -95,8 +95,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator FontCache fontCache = fontManager.getFontCache(); List/**/ embedFontInfoList = buildFontListFromConfiguration(cfg, - userAgent.getFontBaseURL(), fontResolver, strict, - fontCache); + fontResolver, strict, fontManager); if (fontCache != null && fontCache.hasChanged()) { fontCache.save(); @@ -108,16 +107,17 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator * Builds a list of EmbedFontInfo objects for use with the setup() method. * * @param cfg Configuration object - * @param fontBaseURL the base URL to resolve relative font URLs with * @param fontResolver the FontResolver to use * @param strict true if an Exception should be thrown if an error is found. - * @param fontCache the font cache (or null if it is disabled) + * @param fontManager the font manager * @return a List of EmbedFontInfo objects. * @throws FOPException If an error occurs while processing the configuration */ public static List/**/ buildFontListFromConfiguration(Configuration cfg, - String fontBaseURL, FontResolver fontResolver, - boolean strict, FontCache fontCache) throws FOPException { + FontResolver fontResolver, + boolean strict, FontManager fontManager) throws FOPException { + FontCache fontCache = fontManager.getFontCache(); + String fontBaseURL = fontManager.getFontBaseURL(); List/**/ fontInfoList = new java.util.ArrayList/**/(); @@ -213,7 +213,10 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator fontInfoList.add(embedFontInfo); } } - + + // Update referenced fonts (fonts which are not to be embedded) + updateReferencedFonts(fontInfoList, fontManager.getReferencedFontsMatcher()); + if (log.isDebugEnabled()) { log.debug("Finished font configuration in " + (System.currentTimeMillis() - start) + "ms"); @@ -222,6 +225,25 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator return fontInfoList; } + private static void updateReferencedFonts(List fontInfoList, FontTriplet.Matcher matcher) { + if (matcher == null) { + return; //No referenced fonts + } + Iterator iter = fontInfoList.iterator(); + while (iter.hasNext()) { + EmbedFontInfo fontInfo = (EmbedFontInfo)iter.next(); + Iterator triplets = fontInfo.getFontTriplets().iterator(); + while (triplets.hasNext()) { + FontTriplet triplet = (FontTriplet)triplets.next(); + if (matcher.matches(triplet)) { + fontInfo.setEmbedded(false); + break; + } + } + } + } + + /** * Iterates over font file list adding font info to list * @param fontFileList font file list diff --git a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java index 771d3f2d7..4981905fa 100644 --- a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java +++ b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java @@ -25,6 +25,7 @@ import javax.xml.transform.Source; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.EmbedFontInfo; import org.apache.fop.fonts.FontCollection; @@ -87,7 +88,7 @@ public class ConfiguredFontCollection implements FontCollection { Source fontSource = resolver.resolve(configFontInfo.getEmbedFile()); font = new CustomFontMetricsMapper(fontMetrics, fontSource); } else { - CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, resolver); + CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, true, resolver); font = new CustomFontMetricsMapper(fontMetrics); } diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java index 1566ef799..63b12c5c8 100644 --- a/src/java/org/apache/fop/render/ps/PSFontUtils.java +++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java @@ -191,8 +191,7 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { } private static boolean isEmbeddable(CustomFont font) { - return font.isEmbeddable() - && (font.getEmbedFileName() != null || font.getEmbedResourceName() != null); + return font.isEmbeddable(); } private static InputStream getInputStreamOnFont(PSGenerator gen, CustomFont font) diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java index 02e9d6da4..789a7c247 100644 --- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java +++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java @@ -23,8 +23,8 @@ import java.util.List; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; + import org.apache.fop.apps.FOPException; -import org.apache.fop.fonts.FontCache; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontResolver; @@ -55,17 +55,18 @@ public class PDFDocumentGraphics2DConfigurator { //Fonts try { FontResolver fontResolver = FontManager.createMinimalFontResolver(); - //TODO The following could be optimized by retaining the FontCache somewhere - FontCache fontCache = FontCache.load(); - if (fontCache == null) { - fontCache = new FontCache(); - } - //TODO Provide fontBaseURL to this method call - final String fontBaseURL = null; + //TODO The following could be optimized by retaining the FontManager somewhere + FontManager fontManager = new FontManager(); + + //TODO Make use of fontBaseURL, font substitution and referencing configuration + //Requires a change to the expected configuration layout + List/**/ embedFontInfoList = PrintRendererConfigurator.buildFontListFromConfiguration( - cfg, fontBaseURL, fontResolver, false, fontCache); - fontCache.save(); + cfg, fontResolver, false, fontManager); + if (fontManager.useCache()) { + fontManager.getFontCache().save(); + } FontInfo fontInfo = new FontInfo(); FontSetup.setup(fontInfo, embedFontInfoList, fontResolver); graphics.setFontInfo(fontInfo); diff --git a/status.xml b/status.xml index c25e0b93a..e1432b856 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,10 @@ Added SVG support for AFP (GOCA). + + For auto-detected fonts it is now possible to specify that a font needs to be referenced + rather than embedded (for the output formats that support this distinction). + Added support for the "id" attribute on fo:wrappers when used as a child of the fo:flow. -- cgit v1.2.3 From 4e22f88702287c9a3714c2e3cdea5f10f745926a Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 8 May 2008 13:56:14 +0000 Subject: Tweak: -> add 'runtimeType' member and toString() to PropertyCache to facilitate debugging -> modify the initial assignment in the related Property types accordingly git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654528 13f79535-47bb-0310-9956-ffa450edef68 --- .../fo/properties/BackgroundPositionShorthand.java | 8 ++- .../fop/fo/properties/CharacterProperty.java | 2 +- .../apache/fop/fo/properties/ColorProperty.java | 15 ++--- .../org/apache/fop/fo/properties/CommonFont.java | 4 +- .../fop/fo/properties/CommonHyphenation.java | 2 +- .../org/apache/fop/fo/properties/EnumNumber.java | 2 +- .../org/apache/fop/fo/properties/EnumProperty.java | 2 +- .../org/apache/fop/fo/properties/FixedLength.java | 2 +- .../fop/fo/properties/FontFamilyProperty.java | 2 +- .../org/apache/fop/fo/properties/KeepProperty.java | 2 +- .../apache/fop/fo/properties/NumberProperty.java | 2 +- .../apache/fop/fo/properties/PropertyCache.java | 67 ++++++++++++---------- .../apache/fop/fo/properties/StringProperty.java | 39 +++++++------ 13 files changed, 78 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java b/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java index de74d4be6..6307ad1c5 100644 --- a/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java +++ b/src/java/org/apache/fop/fo/properties/BackgroundPositionShorthand.java @@ -41,7 +41,11 @@ public class BackgroundPositionShorthand extends ListProperty { */ public static class Maker extends ListProperty.Maker { - /** {@inheritDoc} */ + /** + * Construct an instance of a Maker for the given property. + * + * @param propId The Constant ID of the property to be made. + */ public Maker(int propId) { super(propId); } @@ -72,7 +76,7 @@ public class BackgroundPositionShorthand extends ListProperty { * Returns a {@link org.apache.fop.datatypes.PercentBase} whose * getDimension() returns 1. */ - public PercentBase getPercentBase() { + public PercentBase getPercentBase(PropertyList pl) { return new PercentBase() { /** {@inheritDoc} */ public int getBaseLength(PercentBaseContext context) throws PropertyException { diff --git a/src/java/org/apache/fop/fo/properties/CharacterProperty.java b/src/java/org/apache/fop/fo/properties/CharacterProperty.java index 1496f5f86..f42591fe8 100644 --- a/src/java/org/apache/fop/fo/properties/CharacterProperty.java +++ b/src/java/org/apache/fop/fo/properties/CharacterProperty.java @@ -48,7 +48,7 @@ public final class CharacterProperty extends Property { } /** cache containing all canonical CharacterProperty instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(CharacterProperty.class); private final char character; diff --git a/src/java/org/apache/fop/fo/properties/ColorProperty.java b/src/java/org/apache/fop/fo/properties/ColorProperty.java index de648420b..a2a3d2150 100644 --- a/src/java/org/apache/fop/fo/properties/ColorProperty.java +++ b/src/java/org/apache/fop/fo/properties/ColorProperty.java @@ -33,7 +33,7 @@ import org.apache.fop.util.ColorUtil; public final class ColorProperty extends Property { /** cache holding canonical ColorProperty instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(ColorProperty.class); /** * The color represented by this property. @@ -92,6 +92,8 @@ public final class ColorProperty extends Property { * * @param foUserAgent FOP user agent * @param value RGB value as String to be parsed + * @return the canonical ColorProperty instance corresponding + * to the given value * @throws PropertyException if the value can't be parsed * @see ColorUtil#parseColorString(FOUserAgent, String) */ @@ -99,18 +101,9 @@ public final class ColorProperty extends Property { ColorProperty instance = new ColorProperty( ColorUtil.parseColorString( foUserAgent, value)); - return (ColorProperty) cache.fetch(instance); + return (ColorProperty)cache.fetch(instance); } - /** - * Returns an instance of a color property given a color - * @param color the color value - * @return the color property - */ - public static ColorProperty getInstance(Color color) { - return (ColorProperty) cache.fetch(new ColorProperty(color)); - } - /** * Create a new ColorProperty with a given color. * diff --git a/src/java/org/apache/fop/fo/properties/CommonFont.java b/src/java/org/apache/fop/fo/properties/CommonFont.java index a2d01ffa3..1e3f8d43d 100755 --- a/src/java/org/apache/fop/fo/properties/CommonFont.java +++ b/src/java/org/apache/fop/fo/properties/CommonFont.java @@ -37,7 +37,7 @@ public final class CommonFont { /** cache holding canonical CommonFont instances (only those with * absolute font-size and font-size-adjust) */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(CommonFont.class); /** * Class holding canonical instances of bundles of the @@ -47,7 +47,7 @@ public final class CommonFont { protected static final class CachedCommonFont { /** cache holding all canonical instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(CachedCommonFont.class); private int hash = 0; diff --git a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java index dfafa3b16..a294b2bbd 100644 --- a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java +++ b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java @@ -38,7 +38,7 @@ public final class CommonHyphenation { /** Logger */ protected static Log log = LogFactory.getLog(CommonHyphenation.class); - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(CommonHyphenation.class); private int hash = 0; diff --git a/src/java/org/apache/fop/fo/properties/EnumNumber.java b/src/java/org/apache/fop/fo/properties/EnumNumber.java index 2cfc67f27..5e60b4e35 100755 --- a/src/java/org/apache/fop/fo/properties/EnumNumber.java +++ b/src/java/org/apache/fop/fo/properties/EnumNumber.java @@ -29,7 +29,7 @@ import org.apache.fop.fo.expr.PropertyException; public final class EnumNumber extends Property implements Numeric { /** cache holding all canonical EnumNumber instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(EnumNumber.class); private final EnumProperty enumProperty; diff --git a/src/java/org/apache/fop/fo/properties/EnumProperty.java b/src/java/org/apache/fop/fo/properties/EnumProperty.java index 328ed85a9..d3043c5c3 100644 --- a/src/java/org/apache/fop/fo/properties/EnumProperty.java +++ b/src/java/org/apache/fop/fo/properties/EnumProperty.java @@ -29,7 +29,7 @@ import org.apache.fop.fo.expr.PropertyException; public final class EnumProperty extends Property { /** cache holding all canonical EnumProperty instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(EnumProperty.class); /** * Inner class for creating EnumProperty instances diff --git a/src/java/org/apache/fop/fo/properties/FixedLength.java b/src/java/org/apache/fop/fo/properties/FixedLength.java index 6debdd145..5636a4225 100644 --- a/src/java/org/apache/fop/fo/properties/FixedLength.java +++ b/src/java/org/apache/fop/fo/properties/FixedLength.java @@ -45,7 +45,7 @@ public final class FixedLength extends LengthProperty { public static final String MPT = "mpt"; /** cache holding all canonical FixedLength instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(FixedLength.class); /** canonical zero-length instance */ public static final FixedLength ZERO_FIXED_LENGTH = new FixedLength(0, FixedLength.MPT, 1.0f); diff --git a/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java b/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java index 610882aa4..7404dbe9b 100644 --- a/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java +++ b/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java @@ -31,7 +31,7 @@ import org.apache.fop.fo.expr.PropertyException; public final class FontFamilyProperty extends ListProperty { /** cache holding all canonical FontFamilyProperty instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(FontFamilyProperty.class); private int hash = 0; diff --git a/src/java/org/apache/fop/fo/properties/KeepProperty.java b/src/java/org/apache/fop/fo/properties/KeepProperty.java index 2701c3f59..67961b6e5 100644 --- a/src/java/org/apache/fop/fo/properties/KeepProperty.java +++ b/src/java/org/apache/fop/fo/properties/KeepProperty.java @@ -30,7 +30,7 @@ import org.apache.fop.fo.expr.PropertyException; public final class KeepProperty extends Property implements CompoundDatatype { /** class holding all canonical KeepProperty instances*/ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(KeepProperty.class); private boolean isCachedValue = false; private Property withinLine; diff --git a/src/java/org/apache/fop/fo/properties/NumberProperty.java b/src/java/org/apache/fop/fo/properties/NumberProperty.java index 58400d76e..0ba5300ae 100644 --- a/src/java/org/apache/fop/fo/properties/NumberProperty.java +++ b/src/java/org/apache/fop/fo/properties/NumberProperty.java @@ -103,7 +103,7 @@ public final class NumberProperty extends Property implements Numeric { } /** cache holding all canonical NumberProperty instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(NumberProperty.class); private final Number number; diff --git a/src/java/org/apache/fop/fo/properties/PropertyCache.java b/src/java/org/apache/fop/fo/properties/PropertyCache.java index 26ec2e611..2c51bc081 100644 --- a/src/java/org/apache/fop/fo/properties/PropertyCache.java +++ b/src/java/org/apache/fop/fo/properties/PropertyCache.java @@ -42,7 +42,9 @@ public final class PropertyCache { /** the table of hash-buckets */ private CacheEntry[] table = new CacheEntry[8]; - boolean[] votesForRehash = new boolean[SEGMENT_MASK + 1]; + private Class runtimeType; + + final boolean[] votesForRehash = new boolean[SEGMENT_MASK + 1]; /* same hash function as used by java.util.HashMap */ private static int hash(Object x) { @@ -80,10 +82,10 @@ public final class PropertyCache { /* Wrapper objects to synchronize on */ private final class CacheSegment { private int count = 0; - private ReferenceQueue staleEntries = new ReferenceQueue(); + private volatile ReferenceQueue staleEntries = new ReferenceQueue(); } - private final void cleanSegment(int segmentIndex) { + private void cleanSegment(int segmentIndex) { CacheEntry entry; CacheSegment segment = segments[segmentIndex]; int bucketIndex; @@ -113,29 +115,26 @@ public final class PropertyCache { } synchronized (votesForRehash) { if (oldCount > segment.count) { - if (votesForRehash[segmentIndex]) { - votesForRehash[segmentIndex] = false; - } + votesForRehash[segmentIndex] = false; return; - } else { - /* cleanup had no effect */ - if (!votesForRehash[segmentIndex]) { - /* first time for this segment */ - votesForRehash[segmentIndex] = true; - int voteCount = 0; - for (int i = SEGMENT_MASK + 1; --i >= 0; ) { - if (votesForRehash[i]) { - voteCount++; - } + } + /* cleanup had no effect */ + if (!votesForRehash[segmentIndex]) { + /* first time for this segment */ + votesForRehash[segmentIndex] = true; + int voteCount = 0; + for (int i = SEGMENT_MASK + 1; --i >= 0; ) { + if (votesForRehash[i]) { + voteCount++; } - if (voteCount > SEGMENT_MASK / 4) { - rehash(SEGMENT_MASK); - /* reset votes */ - for (int i = SEGMENT_MASK + 1; --i >= 0;) { - votesForRehash[i] = false; - } - + } + if (voteCount > SEGMENT_MASK / 4) { + rehash(SEGMENT_MASK); + /* reset votes */ + for (int i = SEGMENT_MASK + 1; --i >= 0;) { + votesForRehash[i] = false; } + } } } @@ -148,7 +147,7 @@ public final class PropertyCache { * cleanup will be performed to try and remove obsolete * entries. */ - private final void put(Object o) { + private void put(Object o) { int hash = hash(o); CacheSegment segment = segments[hash & SEGMENT_MASK]; @@ -180,7 +179,7 @@ public final class PropertyCache { /* Gets a cached instance. Returns null if not found */ - private final Object get(Object o) { + private Object get(Object o) { int hash = hash(o); int index = hash & (table.length - 1); @@ -219,7 +218,7 @@ public final class PropertyCache { * extends the cache and redistributes the entries. * */ - private final void rehash(int index) { + private void rehash(int index) { CacheSegment seg = segments[index]; synchronized (seg) { @@ -258,12 +257,15 @@ public final class PropertyCache { } /** - * Default constructor. + * Default constructor. + * + * @param c Runtime type of the objects that will be stored in the cache */ - public PropertyCache() { + public PropertyCache(Class c) { for (int i = SEGMENT_MASK + 1; --i >= 0;) { segments[i] = new CacheSegment(); } + this.runtimeType = c; } /** @@ -275,7 +277,7 @@ public final class PropertyCache { * @param obj the Object to check for * @return the cached instance */ - private final Object fetch(Object obj) { + private Object fetch(Object obj) { if (obj == null) { return null; } @@ -339,4 +341,11 @@ public final class PropertyCache { return (CommonFont) fetch((Object) cf); } + + /** {@inheritDoc} */ + public String toString() { + return super.toString() + "[runtimeType=" + this.runtimeType + "]"; + } + + } diff --git a/src/java/org/apache/fop/fo/properties/StringProperty.java b/src/java/org/apache/fop/fo/properties/StringProperty.java index f84a76c83..194170fec 100644 --- a/src/java/org/apache/fop/fo/properties/StringProperty.java +++ b/src/java/org/apache/fop/fo/properties/StringProperty.java @@ -72,13 +72,16 @@ public final class StringProperty extends Property { value = str; } } - return new StringProperty(value); + return StringProperty.getInstance(value); } - } // end String.Maker + } /** cache containing all canonical StringProperty instances */ - private static final PropertyCache cache = new PropertyCache(); + private static final PropertyCache cache = new PropertyCache(StringProperty.class); + + /** canonical instance for empty strings */ + public static final StringProperty EMPTY_STRING_PROPERTY = new StringProperty(""); private final String str; @@ -97,40 +100,38 @@ public final class StringProperty extends Property { * @return the canonical instance */ public static StringProperty getInstance(String str) { - return (StringProperty)cache.fetch( - new StringProperty(str)); + if ("".equals(str) || str == null) { + return EMPTY_STRING_PROPERTY; + } else { + return (StringProperty)cache.fetch( + new StringProperty(str)); + } } - /** - * @return the Object equivalent of this property - */ + /** @return the Object equivalent of this property */ public Object getObject() { return this.str; } - /** - * @return the String equivalent of this property - */ + /** @return the String equivalent of this property */ public String getString() { return this.str; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public boolean equals(Object obj) { + if (this == obj) { + return true; + } if (obj instanceof StringProperty) { StringProperty sp = (StringProperty)obj; return (sp.str == this.str || sp.str.equals(this.str)); - } else { - return false; } + return false; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int hashCode() { return str.hashCode(); } -- cgit v1.2.3 From f54710eda526c851973299ebdf30ef5a67c65b63 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 8 May 2008 19:29:55 +0000 Subject: In collapsed borders, the 'nonLeadingTrailing' case actually corresponds to the usual, 'normal' case, when no break occurs in the table. Renamed fields and parameters accordingly for readability and simplicity git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654600 13f79535-47bb-0310-9956-ffa450edef68 --- .../fo/flow/table/CollapsingBorderResolver.java | 69 ++++++++++--------- .../fop/fo/flow/table/ConditionalBorder.java | 79 +++++++++++----------- .../org/apache/fop/fo/flow/table/GridUnit.java | 34 +++++----- .../table/CollapsedConditionalBorderTestCase.java | 16 ++--- 4 files changed, 97 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index 23f797a3e..86bf40f2f 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -79,18 +79,18 @@ class CollapsingBorderResolver implements BorderResolver { * * @param row the first row of the table (in the header, or in the body if the * table has no header) + * @param withNormal * @param withLeadingTrailing - * @param withNonLeadingTrailing * @param withRest */ - void resolveBordersFirstRowInTable(List/**/ row, boolean withLeadingTrailing, - boolean withNonLeadingTrailing, boolean withRest) { + void resolveBordersFirstRowInTable(List/**/ row, boolean withNormal, + boolean withLeadingTrailing, boolean withRest) { assert firstInTable; for (int i = 0; i < row.size(); i++) { TableColumn column = table.getColumn(i); ((GridUnit) row.get(i)).integrateBorderSegment( - CommonBorderPaddingBackground.BEFORE, column, withLeadingTrailing, - withNonLeadingTrailing, withRest); + CommonBorderPaddingBackground.BEFORE, column, withNormal, + withLeadingTrailing, withRest); } firstInTable = false; } @@ -113,11 +113,11 @@ class CollapsingBorderResolver implements BorderResolver { } /** Integrates the border-after of the part. */ - void resolveBordersLastRowInPart(List/**/ row, boolean withLeadingTrailing, - boolean withNonLeadingTrailing, boolean withRest) { + void resolveBordersLastRowInPart(List/**/ row, boolean withNormal, + boolean withLeadingTrailing, boolean withRest) { for (int i = 0; i < row.size(); i++) { ((GridUnit) row.get(i)).integrateBorderSegment(CommonBorderPaddingBackground.AFTER, - tablePart, withLeadingTrailing, withNonLeadingTrailing, withRest); + tablePart, withNormal, withLeadingTrailing, withRest); } } @@ -126,16 +126,16 @@ class CollapsingBorderResolver implements BorderResolver { * * @param row the last row of the footer, or of the last body if the table has no * footer + * @param withNormal * @param withLeadingTrailing - * @param withNonLeadingTrailing * @param withRest */ - void resolveBordersLastRowInTable(List/**/ row, boolean withLeadingTrailing, - boolean withNonLeadingTrailing, boolean withRest) { + void resolveBordersLastRowInTable(List/**/ row, boolean withNormal, + boolean withLeadingTrailing, boolean withRest) { for (int i = 0; i < row.size(); i++) { TableColumn column = table.getColumn(i); ((GridUnit) row.get(i)).integrateBorderSegment(CommonBorderPaddingBackground.AFTER, - column, withLeadingTrailing, withNonLeadingTrailing, withRest); + column, withNormal, withLeadingTrailing, withRest); } } @@ -151,7 +151,7 @@ class CollapsingBorderResolver implements BorderResolver { GridUnit gu = (GridUnit) row.get(i); ConditionalBorder border = (ConditionalBorder) leadingBorders.get(i); gu.integrateCompetingBorder(CommonBorderPaddingBackground.BEFORE, border, - true, false, true); + false, true, true); } } @@ -167,7 +167,7 @@ class CollapsingBorderResolver implements BorderResolver { GridUnit gu = (GridUnit) row.get(i); ConditionalBorder border = (ConditionalBorder) trailingBorders.get(i); gu.integrateCompetingBorder(CommonBorderPaddingBackground.AFTER, border, - true, false, true); + false, true, true); } } @@ -250,16 +250,15 @@ class CollapsingBorderResolver implements BorderResolver { * The two only sensible values for border-before on the header's first row are: * - at the beginning of the table (normal case) * - if the header is repeated after each page break - * To represent those values we (ab)use the nonLeadingTrailing and the rest - * fields of ConditionalBorder. But strictly speaking this is not their - * purposes. + * To represent those values we (ab)use the normal and the rest fields of + * ConditionalBorder. But strictly speaking this is not their purposes. */ for (Iterator guIter = row.iterator(); guIter.hasNext();) { ConditionalBorder borderBefore = ((GridUnit) guIter.next()).borderBefore; - borderBefore.leadingTrailing = borderBefore.nonLeadingTrailing; - borderBefore.rest = borderBefore.nonLeadingTrailing; + borderBefore.leadingTrailing = borderBefore.normal; + borderBefore.rest = borderBefore.normal; } - resolveBordersFirstRowInTable(row, false, true, true); + resolveBordersFirstRowInTable(row, true, false, true); } previousRow = row; } @@ -272,14 +271,14 @@ class CollapsingBorderResolver implements BorderResolver { * The border-after of a header is always the same. Leading and rest don't * apply to cells in the header since they are never broken. To ease * resolution we override the (normally unused) leadingTrailing and rest - * fields of ConditionalBorder with the only sensible nonLeadingTrailing - * field. That way grid units from the body will always resolve against the - * same, normal header border. + * fields of ConditionalBorder with the only sensible normal field. That way + * grid units from the body will always resolve against the same, normal + * header border. */ for (Iterator guIter = previousRow.iterator(); guIter.hasNext();) { ConditionalBorder borderAfter = ((GridUnit) guIter.next()).borderAfter; - borderAfter.leadingTrailing = borderAfter.nonLeadingTrailing; - borderAfter.rest = borderAfter.nonLeadingTrailing; + borderAfter.leadingTrailing = borderAfter.normal; + borderAfter.rest = borderAfter.normal; leadingBorders.add(borderAfter); } /* TODO Temporary hack for resolved borders in header */ @@ -311,8 +310,8 @@ class CollapsingBorderResolver implements BorderResolver { // See same method in ResolverInHeader for an explanation of the hack for (Iterator guIter = footerFirstRow.iterator(); guIter.hasNext();) { ConditionalBorder borderBefore = ((GridUnit) guIter.next()).borderBefore; - borderBefore.leadingTrailing = borderBefore.nonLeadingTrailing; - borderBefore.rest = borderBefore.nonLeadingTrailing; + borderBefore.leadingTrailing = borderBefore.normal; + borderBefore.rest = borderBefore.normal; trailingBorders.add(borderBefore); } } @@ -324,10 +323,10 @@ class CollapsingBorderResolver implements BorderResolver { // See endRow method in ResolverInHeader for an explanation of the hack for (Iterator guIter = footerLastRow.iterator(); guIter.hasNext();) { ConditionalBorder borderAfter = ((GridUnit) guIter.next()).borderAfter; - borderAfter.leadingTrailing = borderAfter.nonLeadingTrailing; - borderAfter.rest = borderAfter.nonLeadingTrailing; + borderAfter.leadingTrailing = borderAfter.normal; + borderAfter.rest = borderAfter.normal; } - resolveBordersLastRowInTable(footerLastRow, false, true, true); + resolveBordersLastRowInTable(footerLastRow, true, false, true); } } @@ -351,7 +350,7 @@ class CollapsingBorderResolver implements BorderResolver { firstInBody = false; for (Iterator iter = row.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); - gu.borderBefore.leadingTrailing = gu.borderBefore.nonLeadingTrailing; + gu.borderBefore.leadingTrailing = gu.borderBefore.normal; } } } @@ -361,11 +360,11 @@ class CollapsingBorderResolver implements BorderResolver { resolverInFooter.endTable(); } else { // Trailing and rest borders already resolved with integrateTrailingBorders - resolveBordersLastRowInTable(previousRow, false, true, false); + resolveBordersLastRowInTable(previousRow, true, false, false); } for (Iterator iter = previousRow.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); - gu.borderAfter.leadingTrailing = gu.borderAfter.nonLeadingTrailing; + gu.borderAfter.leadingTrailing = gu.borderAfter.normal; } } } @@ -428,13 +427,13 @@ class CollapsingBorderResolver implements BorderResolver { if (headerLastRow != null) { for (Iterator iter = headerLastRow.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); - gu.borderAfter.leadingTrailing = gu.borderAfter.nonLeadingTrailing; + gu.borderAfter.leadingTrailing = gu.borderAfter.normal; } } if (footerLastRow != null) { for (Iterator iter = footerLastRow.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); - gu.borderAfter.leadingTrailing = gu.borderAfter.nonLeadingTrailing; + gu.borderAfter.leadingTrailing = gu.borderAfter.normal; } } /* End of temporary hack */ diff --git a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java index 4313b82a6..389681f1d 100644 --- a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java +++ b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java @@ -26,7 +26,7 @@ import org.apache.fop.layoutmgr.table.CollapsingBorderModel; * in the collapsing model. These three values are (for border-before, similar for * border-after): *
      - *
    • non-leading: common case, when a cell follows the cell before on a same page;
    • + *
    • normal: common case, when a cell follows the cell before on a same page;
    • *
    • leading: when the table is broken and the cell appears at the top of a page, in * which case its border must be resolved with the header (or the top of the table) * instead of with the previous cell;
    • @@ -42,23 +42,23 @@ public class ConditionalBorder { public static final int REST = 2; + /** Normal case, no break. */ + BorderSpecification normal; + /** Special case: the cell is at the top or the bottom of the page. */ BorderSpecification leadingTrailing; - /** Normal case, no break. */ - BorderSpecification nonLeadingTrailing; - /** Special case: break inside the cell. */ BorderSpecification rest; /** The model used to resolve borders. */ private CollapsingBorderModel collapsingBorderModel; - private ConditionalBorder(BorderSpecification leadingTrailing, - BorderSpecification nonLeadingTrailing, BorderSpecification rest, + private ConditionalBorder(BorderSpecification normal, + BorderSpecification leadingTrailing, BorderSpecification rest, CollapsingBorderModel collapsingBorderModel) { + this.normal = normal; this.leadingTrailing = leadingTrailing; - this.nonLeadingTrailing = nonLeadingTrailing; this.rest = rest; this.collapsingBorderModel = collapsingBorderModel; } @@ -71,8 +71,8 @@ public class ConditionalBorder { */ ConditionalBorder(BorderSpecification borderSpecification, CollapsingBorderModel collapsingBorderModel) { - leadingTrailing = borderSpecification; - nonLeadingTrailing = leadingTrailing; + normal = borderSpecification; + leadingTrailing = normal; if (borderSpecification.getBorderInfo().getWidth().isDiscard()) { rest = BorderSpecification.getDefaultBorder(); } else { @@ -85,26 +85,26 @@ public class ConditionalBorder { * Resolves and updates the relevant parts of this border as well as the given one. * * @param competitor + * @param withNormal * @param withLeadingTrailing - * @param withNonLeadingTrailing * @param withRest */ - void resolve(ConditionalBorder competitor, boolean withLeadingTrailing, - boolean withNonLeadingTrailing, boolean withRest) { - if (withLeadingTrailing) { + void resolve(ConditionalBorder competitor, boolean withNormal, + boolean withLeadingTrailing, boolean withRest) { + if (withNormal) { BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( - leadingTrailing, competitor.leadingTrailing); + normal, competitor.normal); if (resolvedBorder != null) { - leadingTrailing = resolvedBorder; - competitor.leadingTrailing = resolvedBorder; + normal = resolvedBorder; + competitor.normal = resolvedBorder; } } - if (withNonLeadingTrailing) { + if (withLeadingTrailing) { BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( - nonLeadingTrailing, competitor.nonLeadingTrailing); + leadingTrailing, competitor.leadingTrailing); if (resolvedBorder != null) { - nonLeadingTrailing = resolvedBorder; - competitor.nonLeadingTrailing = resolvedBorder; + leadingTrailing = resolvedBorder; + competitor.leadingTrailing = resolvedBorder; } } if (withRest) { @@ -124,24 +124,24 @@ public class ConditionalBorder { * keeping the components to their old values. * * @param competitor + * @param withNormal * @param withLeadingTrailing - * @param withNonLeadingTrailing * @param withRest */ - void integrateCompetingSegment(ConditionalBorder competitor, boolean withLeadingTrailing, - boolean withNonLeadingTrailing, boolean withRest) { - if (withLeadingTrailing) { + void integrateCompetingSegment(ConditionalBorder competitor, boolean withNormal, + boolean withLeadingTrailing, boolean withRest) { + if (withNormal) { BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( - leadingTrailing, competitor.leadingTrailing); + normal, competitor.normal); if (resolvedBorder != null) { - leadingTrailing = resolvedBorder; + normal = resolvedBorder; } } - if (withNonLeadingTrailing) { + if (withLeadingTrailing) { BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( - nonLeadingTrailing, competitor.nonLeadingTrailing); + leadingTrailing, competitor.leadingTrailing); if (resolvedBorder != null) { - nonLeadingTrailing = resolvedBorder; + leadingTrailing = resolvedBorder; } } if (withRest) { @@ -158,22 +158,21 @@ public class ConditionalBorder { * CollapsingBorderModel is not expected to return null. * * @param segment + * @param withNormal * @param withLeadingTrailing - * @param withNonLeadingTrailing * @param withRest */ - void integrateSegment(ConditionalBorder segment, boolean withLeadingTrailing, - boolean withNonLeadingTrailing, boolean withRest) { + void integrateSegment(ConditionalBorder segment, boolean withNormal, + boolean withLeadingTrailing, boolean withRest) { + if (withNormal) { + normal = collapsingBorderModel.determineWinner(normal, segment.normal); + assert normal != null; + } if (withLeadingTrailing) { leadingTrailing = collapsingBorderModel.determineWinner(leadingTrailing, segment.leadingTrailing); assert leadingTrailing != null; } - if (withNonLeadingTrailing) { - nonLeadingTrailing = collapsingBorderModel.determineWinner(nonLeadingTrailing, - segment.nonLeadingTrailing); - assert nonLeadingTrailing != null; - } if (withRest) { rest = collapsingBorderModel.determineWinner(rest, segment.rest); assert rest != null; @@ -186,14 +185,12 @@ public class ConditionalBorder { * @return a copy of this border */ ConditionalBorder copy() { - return new ConditionalBorder(leadingTrailing, nonLeadingTrailing, rest, - collapsingBorderModel); + return new ConditionalBorder(normal, leadingTrailing, rest, collapsingBorderModel); } /** {@inheritDoc} */ public String toString() { - return "{non-leading: " + nonLeadingTrailing + ", leading: " + leadingTrailing + ", rest: " - + rest + "}"; + return "{normal: " + normal + ", leading: " + leadingTrailing + ", rest: " + rest + "}"; } /** diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java index 578fcb883..ec84dd200 100644 --- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java @@ -133,11 +133,11 @@ public class GridUnit { protected void setBordersFromCell() { borderBefore = cell.borderBefore.copy(); if (rowSpanIndex > 0) { - borderBefore.nonLeadingTrailing = BorderSpecification.getDefaultBorder(); + borderBefore.normal = BorderSpecification.getDefaultBorder(); } borderAfter = cell.borderAfter.copy(); if (!isLastGridUnitRowSpan()) { - borderAfter.nonLeadingTrailing = BorderSpecification.getDefaultBorder(); + borderAfter.normal = BorderSpecification.getDefaultBorder(); } if (colSpanIndex == 0) { borderStart = cell.borderStart; @@ -235,7 +235,7 @@ public class GridUnit { public BorderInfo getBorderBefore(int which) { switch (which) { case ConditionalBorder.NORMAL: - return borderBefore.nonLeadingTrailing.getBorderInfo(); + return borderBefore.normal.getBorderInfo(); case ConditionalBorder.LEADING_TRAILING: return borderBefore.leadingTrailing.getBorderInfo(); case ConditionalBorder.REST: @@ -257,7 +257,7 @@ public class GridUnit { public BorderInfo getBorderAfter(int which) { switch (which) { case ConditionalBorder.NORMAL: - return borderAfter.nonLeadingTrailing.getBorderInfo(); + return borderAfter.normal.getBorderInfo(); case ConditionalBorder.LEADING_TRAILING: return borderAfter.leadingTrailing.getBorderInfo(); case ConditionalBorder.REST: @@ -299,10 +299,10 @@ public class GridUnit { void resolveBorder(GridUnit other, int side) { switch (side) { case CommonBorderPaddingBackground.BEFORE: - borderBefore.resolve(other.borderAfter, false, true, false); + borderBefore.resolve(other.borderAfter, true, false, false); break; case CommonBorderPaddingBackground.AFTER: - borderAfter.resolve(other.borderBefore, false, true, false); + borderAfter.resolve(other.borderBefore, true, false, false); break; case CommonBorderPaddingBackground.START: BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner( @@ -333,16 +333,16 @@ public class GridUnit { * @param parent a table element whose corresponding border coincides on the given * side */ - void integrateBorderSegment(int side, TableFObj parent, boolean withLeadingTrailing, - boolean withNonLeadingTrailing, boolean withRest) { + void integrateBorderSegment(int side, TableFObj parent, boolean withNormal, + boolean withLeadingTrailing, boolean withRest) { switch (side) { case CommonBorderPaddingBackground.BEFORE: - borderBefore.integrateSegment(parent.borderBefore, withLeadingTrailing, - withNonLeadingTrailing, withRest); + borderBefore.integrateSegment(parent.borderBefore, withNormal, + withLeadingTrailing, withRest); break; case CommonBorderPaddingBackground.AFTER: - borderAfter.integrateSegment(parent.borderAfter, withLeadingTrailing, - withNonLeadingTrailing, withRest); + borderAfter.integrateSegment(parent.borderAfter, withNormal, + withLeadingTrailing, withRest); break; default: assert false; } @@ -375,15 +375,15 @@ public class GridUnit { } void integrateCompetingBorder(int side, ConditionalBorder competitor, - boolean withLeadingTrailing, boolean withNonLeadingTrailing, boolean withRest) { + boolean withNormal, boolean withLeadingTrailing, boolean withRest) { switch (side) { case CommonBorderPaddingBackground.BEFORE: - borderBefore.integrateCompetingSegment(competitor, withLeadingTrailing, - withNonLeadingTrailing, withRest); + borderBefore.integrateCompetingSegment(competitor, withNormal, + withLeadingTrailing, withRest); break; case CommonBorderPaddingBackground.AFTER: - borderAfter.integrateCompetingSegment(competitor, withLeadingTrailing, - withNonLeadingTrailing, withRest); + borderAfter.integrateCompetingSegment(competitor, withNormal, + withLeadingTrailing, withRest); break; default: assert false; } diff --git a/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java b/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java index e42ee2935..3abc2f73b 100644 --- a/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java +++ b/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java @@ -141,12 +141,12 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase { GridUnit gu = getGridUnit(body); String errorMsge = baseErrorMsge + "border-before"; - checkBorder(errorMsge, gu.borderBefore.nonLeadingTrailing, 8000, Color.black); + checkBorder(errorMsge, gu.borderBefore.normal, 8000, Color.black); checkBorder(errorMsge, gu.borderBefore.leadingTrailing, 8000, Color.black); checkBorder(errorMsge, gu.borderBefore.rest, resolvedBorders[tableNum][0]); errorMsge = baseErrorMsge + "border-after"; - checkBorder(errorMsge, gu.borderAfter.nonLeadingTrailing, 8000, Color.black); + checkBorder(errorMsge, gu.borderAfter.normal, 8000, Color.black); checkBorder(errorMsge, gu.borderAfter.leadingTrailing, 8000, Color.black); checkBorder(errorMsge, gu.borderAfter.rest, resolvedBorders[tableNum][1]); @@ -165,14 +165,14 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase { TableBody header = table.getTableHeader(); GridUnit gu = getGridUnit(header); - checkBorder(errorMsge, gu.borderBefore.nonLeadingTrailing, + checkBorder(errorMsge, gu.borderBefore.normal, resolvedBordersHF[tableNum][borderNum++]); checkBorder(errorMsge, gu.borderBefore.rest, resolvedBordersHF[tableNum][borderNum++]); TableBody footer = table.getTableFooter(); gu = getGridUnit(footer); - checkBorder(errorMsge, gu.borderAfter.nonLeadingTrailing, + checkBorder(errorMsge, gu.borderAfter.normal, resolvedBordersHF[tableNum][borderNum++]); checkBorder(errorMsge, gu.borderAfter.rest, resolvedBordersHF[tableNum][borderNum++]); @@ -180,13 +180,13 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase { FONodeIterator bodyIter = table.getChildNodes(); TableBody body = (TableBody) bodyIter.nextNode(); gu = getGridUnit(body); - checkBorder(errorMsge, gu.borderBefore.nonLeadingTrailing, + checkBorder(errorMsge, gu.borderBefore.normal, resolvedBordersHF[tableNum][borderNum++]); checkBorder(errorMsge, gu.borderBefore.leadingTrailing, resolvedBordersHF[tableNum][borderNum++]); checkBorder(errorMsge, gu.borderBefore.rest, resolvedBordersHF[tableNum][borderNum++]); - checkBorder(errorMsge, gu.borderAfter.nonLeadingTrailing, + checkBorder(errorMsge, gu.borderAfter.normal, resolvedBordersHF[tableNum][borderNum++]); checkBorder(errorMsge, gu.borderAfter.leadingTrailing, resolvedBordersHF[tableNum][borderNum++]); @@ -195,13 +195,13 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTestCase { body = (TableBody) bodyIter.nextNode(); gu = getGridUnit(body); - checkBorder(errorMsge, gu.borderBefore.nonLeadingTrailing, + checkBorder(errorMsge, gu.borderBefore.normal, resolvedBordersHF[tableNum][borderNum++]); checkBorder(errorMsge, gu.borderBefore.leadingTrailing, resolvedBordersHF[tableNum][borderNum++]); checkBorder(errorMsge, gu.borderBefore.rest, resolvedBordersHF[tableNum][borderNum++]); - checkBorder(errorMsge, gu.borderAfter.nonLeadingTrailing, + checkBorder(errorMsge, gu.borderAfter.normal, resolvedBordersHF[tableNum][borderNum++]); checkBorder(errorMsge, gu.borderAfter.leadingTrailing, resolvedBordersHF[tableNum][borderNum++]); -- cgit v1.2.3 From 8e7dceedd34226cfe8d6fc922186d5d4c3c6c1e3 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 8 May 2008 23:46:45 +0000 Subject: Quick-fix to avoid creating unnecessarily large ArrayLists when adding inline ids to the page git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654654 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/IDTracker.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/area/IDTracker.java b/src/java/org/apache/fop/area/IDTracker.java index d073bdb94..e8b53b20c 100644 --- a/src/java/org/apache/fop/area/IDTracker.java +++ b/src/java/org/apache/fop/area/IDTracker.java @@ -78,7 +78,11 @@ public class IDTracker { tryIDResolution(id, pv, pvList); } } else { - pvList.add(pv); + /* TODO: The check is a quick-fix to avoid a waste + * when adding inline-ids to the page */ + if (!pvList.contains(pv)) { + pvList.add(pv); + } } } @@ -140,7 +144,7 @@ public class IDTracker { * * @param id ID to resolve * @param pv page viewport whose ID refs to resolve - * @param List of PageViewports + * @param pvList of PageViewports */ private void tryIDResolution(String id, PageViewport pv, List pvList) { Set todo = (Set) unresolvedIDRefs.get(id); -- cgit v1.2.3 From 5a0f93d17cc2d4cddca9f9aa0ccde76f52bb08e0 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 9 May 2008 12:30:40 +0000 Subject: Checkstyle and minor typo fixes Set svn:keywords and svn:eol-style properties on new files git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654783 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/apps/FOURIResolver.java | 8 +- src/java/org/apache/fop/apps/FOUserAgent.java | 76 +++--- src/java/org/apache/fop/apps/FopFactory.java | 134 +++++------ .../apache/fop/apps/FopFactoryConfigurator.java | 46 ++-- .../org/apache/fop/fonts/CustomFontCollection.java | 13 +- src/java/org/apache/fop/fonts/EmbedFontInfo.java | 34 +-- src/java/org/apache/fop/fonts/Font.java | 16 +- src/java/org/apache/fop/fonts/FontCache.java | 64 ++--- src/java/org/apache/fop/fonts/FontCollection.java | 2 +- src/java/org/apache/fop/fonts/FontDescriptor.java | 34 +-- src/java/org/apache/fop/fonts/FontInfo.java | 68 +++--- src/java/org/apache/fop/fonts/FontManager.java | 20 +- .../apache/fop/fonts/FontManagerConfigurator.java | 28 +-- src/java/org/apache/fop/fonts/FontSetup.java | 8 +- src/java/org/apache/fop/fonts/FontTriplet.java | 22 +- src/java/org/apache/fop/fonts/FontUtil.java | 22 +- .../fop/fonts/autodetect/FontFileFinder.java | 26 +-- .../fop/fonts/autodetect/FontInfoFinder.java | 34 +-- .../fop/fonts/base14/Base14FontCollection.java | 8 +- .../fop/fonts/substitute/AttributeValue.java | 16 +- .../apache/fop/fonts/substitute/FontQualifier.java | 52 ++--- .../fop/fonts/substitute/FontSubstitution.java | 8 +- .../fop/fonts/substitute/FontSubstitutions.java | 10 +- .../substitute/FontSubstitutionsConfigurator.java | 8 +- .../fop/fonts/substitute/FontWeightRange.java | 13 +- .../fop/layoutmgr/AbstractLayoutManager.java | 36 +-- .../fop/render/AbstractRendererConfigurator.java | 12 +- src/java/org/apache/fop/render/PrintRenderer.java | 18 +- .../fop/render/PrintRendererConfigurator.java | 54 ++--- .../org/apache/fop/render/afp/AFPRenderer.java | 30 +-- .../fop/render/java2d/Base14FontCollection.java | 8 +- .../render/java2d/ConfiguredFontCollection.java | 4 +- .../fop/render/java2d/InstalledFontCollection.java | 4 +- .../apache/fop/render/java2d/Java2DRenderer.java | 102 ++++---- .../org/apache/fop/render/pcl/PCLRenderer.java | 260 ++++++++++----------- .../apache/fop/render/ps/AbstractPSTranscoder.java | 22 +- .../apache/fop/render/ps/NativeTextHandler.java | 32 +-- .../org/apache/fop/svg/PDFDocumentGraphics2D.java | 32 +-- .../fop/svg/PDFDocumentGraphics2DConfigurator.java | 12 +- src/java/org/apache/fop/svg/PDFGraphics2D.java | 54 ++--- .../apache/fop/config/BaseUserConfigTestCase.java | 20 +- .../fop/config/FontsSubstitutionTestCase.java | 2 +- .../fop/layoutengine/LayoutEngineTester.java | 52 ++--- .../org/apache/fop/render/pdf/BasePDFTestCase.java | 6 +- .../fop/render/pdf/PDFAConformanceTestCase.java | 12 +- 45 files changed, 771 insertions(+), 771 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/apps/FOURIResolver.java b/src/java/org/apache/fop/apps/FOURIResolver.java index bc0ca25b5..76b0bedd5 100644 --- a/src/java/org/apache/fop/apps/FOURIResolver.java +++ b/src/java/org/apache/fop/apps/FOURIResolver.java @@ -52,7 +52,7 @@ public class FOURIResolver implements javax.xml.transform.URIResolver { /** URIResolver for RFC 2397 data URLs */ private URIResolver dataURIResolver = new DataURIResolver(); - + /** A user settable URI Resolver */ private URIResolver uriResolver = null; @@ -77,7 +77,7 @@ public class FOURIResolver implements javax.xml.transform.URIResolver { } File dir = new File(base); try { - base = (dir.isDirectory() ? dir.toURL() : new URL(base)).toExternalForm(); + base = (dir.isDirectory() ? dir.toURL() : new URL(base)).toExternalForm(); } catch (MalformedURLException mfue) { if (throwExceptions) { throw mfue; @@ -147,11 +147,11 @@ public class FOURIResolver implements javax.xml.transform.URIResolver { */ public Source resolve(String href, String base) throws TransformerException { Source source = null; - + // data URLs can be quite long so evaluate early and don't try to build a File // (can lead to problems) source = dataURIResolver.resolve(href, base); - + // Custom uri resolution if (source == null && uriResolver != null) { source = uriResolver.resolve(href, base); diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index f4c68933e..c7a904f29 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -76,7 +76,7 @@ public class FOUserAgent { private static Log log = LogFactory.getLog("FOP"); private FopFactory factory; - + /** * The base URL for all URL resolutions, especially for * external-graphics. @@ -88,7 +88,7 @@ public class FOUserAgent { /** A user settable URI Resolver */ private URIResolver uriResolver = null; - + private float targetResolution = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION; private Map rendererOptions = new java.util.HashMap(); private File outputFile = null; @@ -96,7 +96,7 @@ public class FOUserAgent { private FOEventHandler foEventHandlerOverride = null; private boolean locatorEnabled = true; // true by default (for error messages). private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster(); - + /** Producer: Metadata element for the system/software that produces * the document. (Some renderers can store this in the document.) */ @@ -107,18 +107,18 @@ public class FOUserAgent { */ protected String creator = null; - /** Creation Date: Override of the date the document was created. + /** Creation Date: Override of the date the document was created. * (Some renderers can store this in the document.) */ protected Date creationDate = null; - + /** Author of the content of the document. */ protected String author = null; /** Title of the document. */ protected String title = null; /** Set of keywords applicable to this document. */ protected String keywords = null; - + private ImageSessionContext imageSessionContext = new AbstractImageSessionContext() { public ImageContext getParentContext() { @@ -132,11 +132,11 @@ public class FOUserAgent { public Source resolveURI(String uri) { return FOUserAgent.this.resolveURI(uri); } - + }; - + /** - * Main constructor. This constructor should not be called directly. Please use the + * Main constructor. This constructor should not be called directly. Please use the * methods from FopFactory to construct FOUserAgent instances! * @param factory the factory that provides environment-level information * @see org.apache.fop.apps.FopFactory @@ -150,17 +150,17 @@ public class FOUserAgent { setFontBaseURL(factory.getFontManager().getFontBaseURL()); setTargetResolution(factory.getTargetResolution()); } - + /** @return the associated FopFactory instance */ public FopFactory getFactory() { return this.factory; } - + // ---------------------------------------------- rendering-run dependent stuff - + /** - * Sets an explicit renderer to use which overrides the one defined by the - * render type setting. + * Sets an explicit renderer to use which overrides the one defined by the + * render type setting. * @param renderer the Renderer instance to use */ public void setRendererOverride(Renderer renderer) { @@ -177,7 +177,7 @@ public class FOUserAgent { /** * Sets an explicit FOEventHandler instance which overrides the one - * defined by the render type setting. + * defined by the render type setting. * @param handler the FOEventHandler instance */ public void setFOEventHandlerOverride(FOEventHandler handler) { @@ -193,7 +193,7 @@ public class FOUserAgent { } /** - * Sets the producer of the document. + * Sets the producer of the document. * @param producer source of document */ public void setProducer(String producer) { @@ -209,7 +209,7 @@ public class FOUserAgent { } /** - * Sets the creator of the document. + * Sets the creator of the document. * @param creator of document */ public void setCreator(String creator) { @@ -225,7 +225,7 @@ public class FOUserAgent { } /** - * Sets the creation date of the document. + * Sets the creation date of the document. * @param creationDate date of document */ public void setCreationDate(Date creationDate) { @@ -241,7 +241,7 @@ public class FOUserAgent { } /** - * Sets the author of the document. + * Sets the author of the document. * @param author of document */ public void setAuthor(String author) { @@ -258,7 +258,7 @@ public class FOUserAgent { /** * Sets the title of the document. This will override any title coming from - * an fo:title element. + * an fo:title element. * @param title of document */ public void setTitle(String title) { @@ -274,7 +274,7 @@ public class FOUserAgent { } /** - * Sets the keywords for the document. + * Sets the keywords for the document. * @param keywords for the document */ public void setKeywords(String keywords) { @@ -296,7 +296,7 @@ public class FOUserAgent { public Map getRendererOptions() { return rendererOptions; } - + /** * Sets the base URL. * @param baseUrl base URL @@ -343,7 +343,7 @@ public class FOUserAgent { * to the default resolver. * @param uri URI to access * @return A {@link javax.xml.transform.Source} object, or null if the URI - * cannot be resolved. + * cannot be resolved. * @see org.apache.fop.apps.FOURIResolver */ public Source resolveURI(String uri) { @@ -357,7 +357,7 @@ public class FOUserAgent { * @param href URI to access * @param base the base URI to resolve against * @return A {@link javax.xml.transform.Source} object, or null if the URI - * cannot be resolved. + * cannot be resolved. * @see org.apache.fop.apps.FOURIResolver */ public Source resolveURI(String href, String base) { @@ -402,9 +402,9 @@ public class FOUserAgent { * @see #getTargetResolution() */ public float getTargetPixelUnitToMillimeter() { - return 25.4f / this.targetResolution; + return 25.4f / this.targetResolution; } - + /** @return the resolution for resolution-dependant output */ public float getTargetResolution() { return this.targetResolution; @@ -419,7 +419,7 @@ public class FOUserAgent { public void setTargetResolution(float dpi) { this.targetResolution = dpi; if (log.isDebugEnabled()) { - log.debug("target-resolution set to: " + targetResolution + log.debug("target-resolution set to: " + targetResolution + "dpi (px2mm=" + getTargetPixelUnitToMillimeter() + ")"); } } @@ -433,7 +433,7 @@ public class FOUserAgent { public void setTargetResolution(int dpi) { setTargetResolution((float)dpi); } - + /** * Returns the image session context for the image package. * @return the ImageSessionContext instance for this rendering run @@ -441,7 +441,7 @@ public class FOUserAgent { public ImageSessionContext getImageSessionContext() { return this.imageSessionContext; } - + // ---------------------------------------------- environment-level stuff // (convenience access to FopFactory methods) @@ -457,9 +457,9 @@ public class FOUserAgent { * @see #getSourceResolution() */ public float getSourcePixelUnitToMillimeter() { - return getFactory().getSourcePixelUnitToMillimeter(); + return getFactory().getSourcePixelUnitToMillimeter(); } - + /** @return the resolution for resolution-dependant input */ public float getSourceResolution() { return getFactory().getSourceResolution(); @@ -475,7 +475,7 @@ public class FOUserAgent { public String getPageHeight() { return getFactory().getPageHeight(); } - + /** * Gets the default page-width to use as fallback, * in case page-width="auto" @@ -486,7 +486,7 @@ public class FOUserAgent { public String getPageWidth() { return getFactory().getPageWidth(); } - + /** * Returns whether FOP is strictly validating input XSL * @return true of strict validation turned on, false otherwise @@ -497,7 +497,7 @@ public class FOUserAgent { } /** - * @return true if the indent inheritance should be broken when crossing reference area + * @return true if the indent inheritance should be broken when crossing reference area * boundaries (for more info, see the javadoc for the relative member variable) * @see FopFactory#isBreakIndentInheritanceOnReferenceAreaBoundary() */ @@ -518,7 +518,7 @@ public class FOUserAgent { public XMLHandlerRegistry getXMLHandlerRegistry() { return getFactory().getXMLHandlerRegistry(); } - + /** * Controls the use of SAXLocators to provide location information in error * messages. @@ -550,7 +550,7 @@ public class FOUserAgent { private class FOPEventBroadcaster extends DefaultEventBroadcaster { private EventListener rootListener; - + public FOPEventBroadcaster() { //Install a temporary event listener that catches the first event to //do some initialization. @@ -569,13 +569,13 @@ public class FOUserAgent { } }; } - + /** {@inheritDoc} */ public void broadcastEvent(Event event) { rootListener.processEvent(event); } } - + } diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index c196e1204..ae4d25949 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -59,37 +59,37 @@ import org.apache.fop.util.ContentHandlerFactoryRegistry; * found and managed in the FOUserAgent. */ public class FopFactory implements ImageContext { - + /** logger instance */ private static Log log = LogFactory.getLog(FopFactory.class); - + /** Factory for Renderers and FOEventHandlers */ private RendererFactory rendererFactory; - + /** Registry for XML handlers */ private XMLHandlerRegistry xmlHandlers; - + /** The registry for ElementMapping instances */ private ElementMappingRegistry elementMappingRegistry; - /** The registry for ContentHandlerFactory instance */ - private ContentHandlerFactoryRegistry contentHandlerFactoryRegistry + /** The registry for ContentHandlerFactory instance */ + private ContentHandlerFactoryRegistry contentHandlerFactoryRegistry = new ContentHandlerFactoryRegistry(); - + /** The resolver for user-supplied hyphenation patterns */ private HyphenationTreeResolver hyphResolver = null; private ColorSpaceCache colorSpaceCache = null; - + /** Image manager for loading and caching image objects */ private ImageManager imageManager; /** Font manager for font substitution, autodetection and caching **/ private FontManager fontManager; - + /** Configuration layer used to configure fop */ private FopFactoryConfigurator config = null; - + /** * The base URL for all URL resolutions, especially for * external-graphics. @@ -101,10 +101,10 @@ public class FopFactory implements ImageContext { /** * FOP has the ability, for some FO's, to continue processing even if the - * input XSL violates that FO's content model. This is the default + * input XSL violates that FO's content model. This is the default * behavior for FOP. However, this flag, if set, provides the user the * ability for FOP to halt on all content model violations if desired. - */ + */ private boolean strictFOValidation = FopFactoryConfigurator.DEFAULT_STRICT_FO_VALIDATION; /** @@ -113,7 +113,7 @@ public class FopFactory implements ImageContext { */ private boolean strictUserConfigValidation = FopFactoryConfigurator.DEFAULT_STRICT_USERCONFIG_VALIDATION; - + /** Source resolution in dpi */ private float sourceResolution = FopFactoryConfigurator.DEFAULT_SOURCE_RESOLUTION; @@ -122,7 +122,7 @@ public class FopFactory implements ImageContext { /** Page height */ private String pageHeight = FopFactoryConfigurator.DEFAULT_PAGE_HEIGHT; - + /** Page width */ private String pageWidth = FopFactoryConfigurator.DEFAULT_PAGE_WIDTH; @@ -136,7 +136,7 @@ public class FopFactory implements ImageContext { private Set ignoredNamespaces; private FOURIResolver foURIResolver; - + /** * Main constructor. */ @@ -150,7 +150,7 @@ public class FopFactory implements ImageContext { this.xmlHandlers = new XMLHandlerRegistry(); this.ignoredNamespaces = new java.util.HashSet(); } - + /** * Returns a new FopFactory instance. * @return the requested FopFactory instance. @@ -158,13 +158,13 @@ public class FopFactory implements ImageContext { public static FopFactory newInstance() { return new FopFactory(); } - + /** * Returns a new FOUserAgent instance. Use the FOUserAgent to configure special values that * are particular to a rendering run. Don't reuse instances over multiple rendering runs but * instead create a new one each time and reuse the FopFactory. * @return the newly created FOUserAgent instance initialized with default values - * @throws FOPException + * @throws FOPException */ public FOUserAgent newFOUserAgent() { FOUserAgent userAgent = new FOUserAgent(this); @@ -172,12 +172,12 @@ public class FopFactory implements ImageContext { } /** - * Returns a new {@link Fop} instance. FOP will be configured with a default user agent + * Returns a new {@link Fop} instance. FOP will be configured with a default user agent * instance. *

      * MIME types are used to select the output format (ex. "application/pdf" for PDF). You can * use the constants defined in {@link MimeConstants}. - * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). + * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). * @return the new Fop instance * @throws FOPException when the constructor fails */ @@ -186,29 +186,29 @@ public class FopFactory implements ImageContext { } /** - * Returns a new {@link Fop} instance. Use this factory method if you want to configure this + * Returns a new {@link Fop} instance. Use this factory method if you want to configure this * very rendering run, i.e. if you want to set some metadata like the title and author of the - * document you want to render. In that case, create a new {@link FOUserAgent} + * document you want to render. In that case, create a new {@link FOUserAgent} * instance using {@link #newFOUserAgent()}. *

      * MIME types are used to select the output format (ex. "application/pdf" for PDF). You can * use the constants defined in {@link MimeConstants}. * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). - * @param userAgent the user agent that will be used to control the rendering run + * @param userAgent the user agent that will be used to control the rendering run * @return the new Fop instance * @throws FOPException when the constructor fails */ public Fop newFop(String outputFormat, FOUserAgent userAgent) throws FOPException { return newFop(outputFormat, userAgent, null); } - + /** - * Returns a new {@link Fop} instance. FOP will be configured with a default user agent + * Returns a new {@link Fop} instance. FOP will be configured with a default user agent * instance. Use this factory method if your output type requires an output stream. *

      * MIME types are used to select the output format (ex. "application/pdf" for PDF). You can * use the constants defined in {@link MimeConstants}. - * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). + * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). * @param stream the output stream * @return the new Fop instance * @throws FOPException when the constructor fails @@ -227,30 +227,30 @@ public class FopFactory implements ImageContext { * MIME types are used to select the output format (ex. "application/pdf" for PDF). You can * use the constants defined in {@link MimeConstants}. * @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). - * @param userAgent the user agent that will be used to control the rendering run + * @param userAgent the user agent that will be used to control the rendering run * @param stream the output stream * @return the new Fop instance * @throws FOPException when the constructor fails */ - public Fop newFop(String outputFormat, FOUserAgent userAgent, OutputStream stream) + public Fop newFop(String outputFormat, FOUserAgent userAgent, OutputStream stream) throws FOPException { if (userAgent == null) { throw new NullPointerException("The userAgent parameter must not be null!"); } return new Fop(outputFormat, userAgent, stream); } - + /** * Returns a new {@link Fop} instance. Use this factory method if you want to supply your - * own {@link org.apache.fop.render.Renderer Renderer} or - * {@link org.apache.fop.fo.FOEventHandler FOEventHandler} + * own {@link org.apache.fop.render.Renderer Renderer} or + * {@link org.apache.fop.fo.FOEventHandler FOEventHandler} * instance instead of the default ones created internally by FOP. - * @param userAgent the user agent that will be used to control the rendering run + * @param userAgent the user agent that will be used to control the rendering run * @return the new Fop instance * @throws FOPException when the constructor fails */ public Fop newFop(FOUserAgent userAgent) throws FOPException { - if (userAgent.getRendererOverride() == null + if (userAgent.getRendererOverride() == null && userAgent.getFOEventHandlerOverride() == null) { throw new IllegalStateException("Either the overriding renderer or the overriding" + " FOEventHandler must be set when this factory method is used!"); @@ -267,7 +267,7 @@ public class FopFactory implements ImageContext { public XMLHandlerRegistry getXMLHandlerRegistry() { return this.xmlHandlers; } - + /** @return the element mapping registry */ public ElementMappingRegistry getElementMappingRegistry() { return this.elementMappingRegistry; @@ -310,7 +310,7 @@ public class FopFactory implements ImageContext { public LayoutManagerMaker getLayoutManagerMakerOverride() { return this.lmMakerOverride; } - + /** * Sets the base URL. * @param base the base URL @@ -327,7 +327,7 @@ public class FopFactory implements ImageContext { public String getBaseURL() { return this.base; } - + /** * Sets the font base URL. * @param fontBase font base URL @@ -367,10 +367,10 @@ public class FopFactory implements ImageContext { } this.hyphenBase = foURIResolver.checkBaseURL(hyphenBase); } - + /** * Sets the URI Resolver. It is used for resolving factory-level URIs like hyphenation - * patterns and as backup for URI resolution performed during a rendering run. + * patterns and as backup for URI resolution performed during a rendering run. * @param uriResolver the new URI resolver */ public void setURIResolver(URIResolver uriResolver) { @@ -397,7 +397,7 @@ public class FopFactory implements ImageContext { public HyphenationTreeResolver getHyphenationTreeResolver() { return this.hyphResolver; } - + /** * Sets the HyphenationTreeResolver to be used for resolving user-supplied hyphenation files. * @param hyphResolver the HyphenationTreeResolver instance @@ -424,7 +424,7 @@ public class FopFactory implements ImageContext { } /** - * @return true if the indent inheritance should be broken when crossing reference area + * @return true if the indent inheritance should be broken when crossing reference area * boundaries (for more info, see the javadoc for the relative member variable) */ public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() { @@ -447,7 +447,7 @@ public class FopFactory implements ImageContext { public void setBreakIndentInheritanceOnReferenceAreaBoundary(boolean value) { this.breakIndentInheritanceOnReferenceAreaBoundary = value; } - + /** * @return true if kerning on base 14 fonts is enabled * @deprecated use getFontManager().isBase14KerningEnabled() instead @@ -455,7 +455,7 @@ public class FopFactory implements ImageContext { public boolean isBase14KerningEnabled() { return getFontManager().isBase14KerningEnabled(); } - + /** * Controls whether kerning is activated on base 14 fonts. * @param value true if kerning should be activated @@ -464,7 +464,7 @@ public class FopFactory implements ImageContext { public void setBase14KerningEnabled(boolean value) { getFontManager().setBase14KerningEnabled(value); } - + /** @return the resolution for resolution-dependant input */ public float getSourceResolution() { return this.sourceResolution; @@ -477,7 +477,7 @@ public class FopFactory implements ImageContext { * @see #getSourceResolution() */ public float getSourcePixelUnitToMillimeter() { - return 25.4f / getSourceResolution(); + return 25.4f / getSourceResolution(); } /** @@ -488,7 +488,7 @@ public class FopFactory implements ImageContext { public void setSourceResolution(float dpi) { this.sourceResolution = dpi; if (log.isDebugEnabled()) { - log.debug("source-resolution set to: " + sourceResolution + log.debug("source-resolution set to: " + sourceResolution + "dpi (px2mm=" + getSourcePixelUnitToMillimeter() + ")"); } } @@ -505,7 +505,7 @@ public class FopFactory implements ImageContext { * @see #getTargetResolution() */ public float getTargetPixelUnitToMillimeter() { - return 25.4f / this.targetResolution; + return 25.4f / this.targetResolution; } /** @@ -525,7 +525,7 @@ public class FopFactory implements ImageContext { public void setSourceResolution(int dpi) { setSourceResolution((float)dpi); } - + /** * Gets the default page-height to use as fallback, * in case page-height="auto" @@ -535,7 +535,7 @@ public class FopFactory implements ImageContext { public String getPageHeight() { return this.pageHeight; } - + /** * Sets the page-height to use as fallback, in case * page-height="auto" @@ -548,7 +548,7 @@ public class FopFactory implements ImageContext { log.debug("Default page-height set to: " + pageHeight); } } - + /** * Gets the default page-width to use as fallback, * in case page-width="auto" @@ -558,7 +558,7 @@ public class FopFactory implements ImageContext { public String getPageWidth() { return this.pageWidth; } - + /** * Sets the page-width to use as fallback, in case * page-width="auto" @@ -571,27 +571,27 @@ public class FopFactory implements ImageContext { log.debug("Default page-width set to: " + pageWidth); } } - + /** * Adds a namespace to the set of ignored namespaces. - * If FOP encounters a namespace which it cannot handle, it issues a warning except if this + * If FOP encounters a namespace which it cannot handle, it issues a warning except if this * namespace is in the ignored set. * @param namespaceURI the namespace URI */ public void ignoreNamespace(String namespaceURI) { this.ignoredNamespaces.add(namespaceURI); } - + /** * Adds a collection of namespaces to the set of ignored namespaces. - * If FOP encounters a namespace which it cannot handle, it issues a warning except if this + * If FOP encounters a namespace which it cannot handle, it issues a warning except if this * namespace is in the ignored set. * @param namespaceURIs the namespace URIs */ public void ignoreNamespaces(Collection namespaceURIs) { this.ignoredNamespaces.addAll(namespaceURIs); } - + /** * Indicates whether a namespace URI is on the ignored list. * @param namespaceURI the namespace URI @@ -600,14 +600,14 @@ public class FopFactory implements ImageContext { public boolean isNamespaceIgnored(String namespaceURI) { return this.ignoredNamespaces.contains(namespaceURI); } - + /** @return the set of namespaces that are ignored by FOP */ public Set getIgnoredNamespace() { return Collections.unmodifiableSet(this.ignoredNamespaces); } //------------------------------------------- Configuration stuff - + /** * Set the user configuration. * @param userConfigFile the configuration file @@ -627,11 +627,11 @@ public class FopFactory implements ImageContext { public void setUserConfig(String uri) throws SAXException, IOException { config.setUserConfig(uri); } - + /** * Set the user configuration. * @param userConfig configuration - * @throws FOPException if a configuration problem occurs + * @throws FOPException if a configuration problem occurs */ public void setUserConfig(Configuration userConfig) throws FOPException { config.setUserConfig(userConfig); @@ -690,7 +690,7 @@ public class FopFactory implements ImageContext { public FontCache getFontCache() { return getFontManager().getFontCache(); } - + /** * Returns the font manager. * @return the font manager @@ -698,17 +698,17 @@ public class FopFactory implements ImageContext { public FontManager getFontManager() { if (fontManager == null) { this.fontManager = new FontManager() { - + /** {@inheritDoc} */ public void setFontBaseURL(String fontBase) throws MalformedURLException { super.setFontBaseURL(getFOURIResolver().checkBaseURL(fontBase)); } - + }; } return this.fontManager; } - + /** * Attempts to resolve the given URI. * Will use the configured resolver and if not successful fall back @@ -716,7 +716,7 @@ public class FopFactory implements ImageContext { * @param href URI to access * @param baseUri the base URI to resolve against * @return A {@link javax.xml.transform.Source} object, or null if the URI - * cannot be resolved. + * cannot be resolved. * @see org.apache.fop.apps.FOURIResolver */ public Source resolveURI(String href, String baseUri) { @@ -728,19 +728,19 @@ public class FopFactory implements ImageContext { } return source; } - + /** * Create (if needed) and return an ICC ColorSpace instance. * * The ICC profile source is taken from the src attribute of the color-profile FO element. * If the ICC ColorSpace is not yet in the cache a new one is created and stored in the cache. * - * The FOP URI resolver is used to try and locate the ICC file. + * The FOP URI resolver is used to try and locate the ICC file. * If that fails null is returned. * * @param baseUri a base URI to resolve relative URIs * @param iccProfileSrc ICC Profile source to return a ColorSpace for - * @return ICC ColorSpace object or null if ColorSpace could not be created + * @return ICC ColorSpace object or null if ColorSpace could not be created */ public ColorSpace getColorSpace(String baseUri, String iccProfileSrc) { return colorSpaceCache.get(baseUri, iccProfileSrc); diff --git a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java index cc3ce2d0b..ffcc1332b 100644 --- a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java +++ b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java @@ -42,25 +42,25 @@ public class FopFactoryConfigurator { /** Defines if FOP should use an alternative rule to determine text indents */ public static final boolean DEFAULT_BREAK_INDENT_INHERITANCE = false; - + /** Defines if FOP should validate the user config strictly */ public static final boolean DEFAULT_STRICT_USERCONFIG_VALIDATION = true; - + /** Defines if FOP should use strict validation for FO and user config */ public static final boolean DEFAULT_STRICT_FO_VALIDATION = true; - + /** Defines the default page-width */ public static final String DEFAULT_PAGE_WIDTH = "8.26in"; - + /** Defines the default page-height */ public static final String DEFAULT_PAGE_HEIGHT = "11in"; - + /** Defines the default source resolution (72dpi) for FOP */ public static final float DEFAULT_SOURCE_RESOLUTION = 72.0f; //dpi - + /** Defines the default target resolution (72dpi) for FOP */ public static final float DEFAULT_TARGET_RESOLUTION = 72.0f; //dpi - + /** logger instance */ private final Log log = LogFactory.getLog(FopFactoryConfigurator.class); @@ -78,7 +78,7 @@ public class FopFactoryConfigurator { super(); this.factory = factory; } - + /** * Initializes user agent settings from the user configuration * file, if present: baseURL, resolution, default page size,... @@ -87,7 +87,7 @@ public class FopFactoryConfigurator { */ public void configure(FopFactory factory) throws FOPException { if (log.isDebugEnabled()) { - log.debug("Initializing FopFactory Configuration"); + log.debug("Initializing FopFactory Configuration"); } // strict configuration @@ -98,9 +98,9 @@ public class FopFactoryConfigurator { } catch (ConfigurationException e) { LogUtil.handleException(log, e, false); } - } + } boolean strict = factory.validateUserConfigStrictly(); - + // strict fo validation if (cfg.getChild("strict-validation", false) != null) { try { @@ -128,14 +128,14 @@ public class FopFactoryConfigurator { LogUtil.handleException(log, mfue, strict); } } - + // renderer options if (cfg.getChild("source-resolution", false) != null) { factory.setSourceResolution( cfg.getChild("source-resolution").getValueAsFloat( FopFactoryConfigurator.DEFAULT_SOURCE_RESOLUTION)); if (log.isDebugEnabled()) { - log.debug("source-resolution set to: " + factory.getSourceResolution() + log.debug("source-resolution set to: " + factory.getSourceResolution() + "dpi (px2mm=" + factory.getSourcePixelUnitToMillimeter() + ")"); } } @@ -144,9 +144,9 @@ public class FopFactoryConfigurator { cfg.getChild("target-resolution").getValueAsFloat( FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION)); if (log.isDebugEnabled()) { - log.debug("target-resolution set to: " + factory.getTargetResolution() + log.debug("target-resolution set to: " + factory.getTargetResolution() + "dpi (px2mm=" + factory.getTargetPixelUnitToMillimeter() - + ")"); + + ")"); } } if (cfg.getChild("break-indent-inheritance", false) != null) { @@ -156,13 +156,13 @@ public class FopFactoryConfigurator { } catch (ConfigurationException e) { LogUtil.handleException(log, e, strict); } - } + } Configuration pageConfig = cfg.getChild("default-page-settings"); if (pageConfig.getAttribute("height", null) != null) { factory.setPageHeight( pageConfig.getAttribute("height", FopFactoryConfigurator.DEFAULT_PAGE_HEIGHT)); if (log.isInfoEnabled()) { - log.info("Default page-height set to: " + factory.getPageHeight()); + log.info("Default page-height set to: " + factory.getPageHeight()); } } if (pageConfig.getAttribute("width", null) != null) { @@ -178,7 +178,7 @@ public class FopFactoryConfigurator { FontManagerConfigurator fontManagerConfigurator = new FontManagerConfigurator(cfg); fontManagerConfigurator.configure(fontManager, strict); } - + /** * Set the user configuration. * @param userConfigFile the configuration file @@ -193,7 +193,7 @@ public class FopFactoryConfigurator { throw new FOPException(e); } } - + /** * Set the user configuration from an URI. * @param uri the URI to the configuration file @@ -208,22 +208,22 @@ public class FopFactoryConfigurator { throw new FOPException(e); } } - + /** * Set the user configuration. * @param cfg avalon configuration - * @throws FOPException if a configuration problem occurs + * @throws FOPException if a configuration problem occurs */ public void setUserConfig(Configuration cfg) throws FOPException { this.cfg = cfg; configure(this.factory); } - + /** * Get the avalon user configuration. * @return the user configuration */ public Configuration getUserConfig() { return this.cfg; - } + } } diff --git a/src/java/org/apache/fop/fonts/CustomFontCollection.java b/src/java/org/apache/fop/fonts/CustomFontCollection.java index 3c0ffbed4..5e5a61189 100644 --- a/src/java/org/apache/fop/fonts/CustomFontCollection.java +++ b/src/java/org/apache/fop/fonts/CustomFontCollection.java @@ -15,7 +15,8 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ + package org.apache.fop.fonts; import java.util.List; @@ -26,7 +27,7 @@ import org.apache.fop.render.PrintRenderer; * Sets up a set of custom (embedded) fonts */ public class CustomFontCollection implements FontCollection { - + private PrintRenderer renderer = null; /** @@ -51,7 +52,7 @@ public class CustomFontCollection implements FontCollection { //Ensure that we have minimal font resolution capabilities resolver = FontManager.createMinimalFontResolver(); } - + String internalName = null; //FontReader reader = null; @@ -67,7 +68,7 @@ public class CustomFontCollection implements FontCollection { reader.setFontEmbedPath(configFontInfo.getEmbedFile()); fontInfo.addMetrics(internalName, reader.getFont()); */ - + LazyFont font = new LazyFont(embedFontInfo, resolver); fontInfo.addMetrics(internalName, font); @@ -78,5 +79,5 @@ public class CustomFontCollection implements FontCollection { } } return num; - } -} \ No newline at end of file + } +} diff --git a/src/java/org/apache/fop/fonts/EmbedFontInfo.java b/src/java/org/apache/fop/fonts/EmbedFontInfo.java index 0d0bcafdb..9496b8459 100644 --- a/src/java/org/apache/fop/fonts/EmbedFontInfo.java +++ b/src/java/org/apache/fop/fonts/EmbedFontInfo.java @@ -16,7 +16,7 @@ */ /* $Id$ */ - + package org.apache.fop.fonts; import java.io.IOException; @@ -27,17 +27,17 @@ import java.util.List; * FontInfo contains meta information on fonts (where is the metrics file etc.) */ public class EmbedFontInfo implements Serializable { - + /** Serialization Version UID */ private static final long serialVersionUID = 8755432068669997367L; - + /** filename of the metrics file */ protected String metricsFile; /** filename of the main font file */ protected String embedFile; /** false, to disable kerning */ protected boolean kerning; - + /** the PostScript name of the font */ protected String postScriptName = null; /** the sub-fontname of the font (used for TrueType Collections, null otherwise) */ @@ -47,7 +47,7 @@ public class EmbedFontInfo implements Serializable { private List/**/ fontTriplets = null; private transient boolean embedded = true; - + /** * Main constructor * @param metricsFile Path to the xml file containing font metrics @@ -64,7 +64,7 @@ public class EmbedFontInfo implements Serializable { this.fontTriplets = fontTriplets; this.subFontName = subFontName; } - + /** * Returns the path to the metrics file * @return the metrics file path @@ -88,16 +88,16 @@ public class EmbedFontInfo implements Serializable { public boolean getKerning() { return kerning; } - + /** - * Returns the sub-font name name of the font. This is primarily used for TrueType Collections - * to select one of the sub-fonts. For all other fonts, this is always null. + * Returns the sub-font name of the font. This is primarily used for TrueType Collections + * to select one of the sub-fonts. For all other fonts, this is always null. * @return the sub-font name (or null) */ public String getSubFontName() { return this.subFontName; } - + /** * Returns the PostScript name of the font. * @return the PostScript name @@ -105,7 +105,7 @@ public class EmbedFontInfo implements Serializable { public String getPostScriptName() { return postScriptName; } - + /** * Sets the PostScript name of the font * @param postScriptName the PostScript name @@ -113,7 +113,7 @@ public class EmbedFontInfo implements Serializable { public void setPostScriptName(String postScriptName) { this.postScriptName = postScriptName; } - + /** * Returns the list of font triplets associated with this font. * @return List of font triplets @@ -121,7 +121,7 @@ public class EmbedFontInfo implements Serializable { public List/**/ getFontTriplets() { return fontTriplets; } - + /** * Indicates whether the font is only referenced rather than embedded. * @return true if the font is embedded, false if it is referenced. @@ -133,7 +133,7 @@ public class EmbedFontInfo implements Serializable { return this.embedded; } } - + /** * Defines whether the font is embedded or not. * @param value true to embed the font, false to reference it @@ -141,19 +141,19 @@ public class EmbedFontInfo implements Serializable { public void setEmbedded(boolean value) { this.embedded = value; } - + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); this.embedded = true; } - + /** {@inheritDoc} */ public String toString() { return "metrics-url=" + metricsFile + ",embed-url=" + embedFile + ", kerning=" + kerning + ", " + "font-triplet=" + fontTriplets + (getSubFontName() != null ? ", sub-font=" + getSubFontName() : "") - + (isEmbedded() ? "" : ", NOT embedded"); + + (isEmbedded() ? "" : ", NOT embedded"); } } diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index 4ce3cbfbd..90aced052 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -32,10 +32,10 @@ public class Font { /** Extra Bold font weight */ public static final int WEIGHT_EXTRA_BOLD = 800; - + /** Bold font weight */ public static final int WEIGHT_BOLD = 700; - + /** Normal font weight */ public static final int WEIGHT_NORMAL = 400; @@ -56,7 +56,7 @@ public class Font { /** Default selection priority */ public static final int PRIORITY_DEFAULT = 0; - + /** Default fallback key */ public static final FontTriplet DEFAULT_FONT = new FontTriplet( "any", STYLE_NORMAL, WEIGHT_NORMAL, PRIORITY_DEFAULT); @@ -96,7 +96,7 @@ public class Font { public FontMetrics getFontMetrics() { return this.metric; } - + /** * Returns the font's ascender. * @return the ascender @@ -128,7 +128,7 @@ public class Font { public String getFontName() { return fontName; } - + /** @return the font triplet that selected this font */ public FontTriplet getFontTriplet() { return this.triplet; @@ -154,7 +154,7 @@ public class Font { public boolean hasKerning() { return metric.hasKerningInfo(); } - + /** * Returns the font's kerning table * @return the kerning table @@ -166,7 +166,7 @@ public class Font { return java.util.Collections.EMPTY_MAP; } } - + /** * Returns the amount of kerning between two characters. * @param ch1 first character @@ -217,7 +217,7 @@ public class Font { return c; } - + /** * Determines whether this font contains a particular character/glyph. * @param c character to check diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index ba9529c02..f2ca741ff 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -43,7 +43,7 @@ import org.apache.fop.util.LogUtil; * Fop cache (currently only used for font info caching) */ public final class FontCache implements Serializable { - + /** * Serialization Version UID. Change this value if you want to make sure the user's cache * file is purged after an update. @@ -59,13 +59,13 @@ public final class FontCache implements Serializable { /** font cache file path */ private static final String DEFAULT_CACHE_FILENAME = "fop-fonts.cache"; - + /** has this cache been changed since it was last read? */ private transient boolean changed = false; - + /** change lock */ private transient Object changeLock = new Object(); - + /** master mapping of font url -> font info. This needs to be * a list, since a TTC file may contain more than 1 font. */ private Map/**/ fontfileMap = null; @@ -96,7 +96,7 @@ public final class FontCache implements Serializable { } return null; } - + /** * Returns the default font cache file. * @param forWriting true if the user directory should be created @@ -113,7 +113,7 @@ public final class FontCache implements Serializable { } return new File(FOP_USER_DIR); } - + /** * Reads the default font cache file and returns its contents. * @return the font cache deserialized from the file (or null if no cache file exists or if @@ -122,7 +122,7 @@ public final class FontCache implements Serializable { public static FontCache load() { return loadFrom(getDefaultCacheFile(false)); } - + /** * Reads a font cache file and returns its contents. * @param cacheFile the cache file @@ -145,11 +145,11 @@ public final class FontCache implements Serializable { } } catch (ClassNotFoundException e) { //We don't really care about the exception since it's just a cache file - log.warn("Could not read font cache. Discarding font cache file. Reason: " + log.warn("Could not read font cache. Discarding font cache file. Reason: " + e.getMessage()); } catch (IOException ioe) { //We don't really care about the exception since it's just a cache file - log.warn("I/O exception while reading font cache (" + ioe.getMessage() + log.warn("I/O exception while reading font cache (" + ioe.getMessage() + "). Discarding font cache file."); try { cacheFile.delete(); @@ -160,7 +160,7 @@ public final class FontCache implements Serializable { } return null; } - + /** * Writes the font cache to disk. * @throws FOPException fop exception @@ -168,10 +168,10 @@ public final class FontCache implements Serializable { public void save() throws FOPException { saveTo(getDefaultCacheFile(true)); } - + /** * Writes the font cache to disk. - * @param cacheFile the file to write to + * @param cacheFile the file to write to * @throws FOPException fop exception */ public void saveTo(File cacheFile) throws FOPException { @@ -219,7 +219,7 @@ public final class FontCache implements Serializable { public boolean hasChanged() { return this.changed; } - + /** * is this font in the cache? * @param embedUrl font info @@ -248,11 +248,11 @@ public final class FontCache implements Serializable { * Tries to identify a File instance from an array of URLs. If there's no file URL in the * array, the method returns null. * @param urls array of possible font urls - * @return file font file + * @return file font file */ public static File getFileFromUrls(String[] urls) { for (int i = 0; i < urls.length; i++) { - String urlStr = urls[i]; + String urlStr = urls[i]; if (urlStr != null) { File fontFile = null; if (urlStr.startsWith("file:")) { @@ -270,7 +270,7 @@ public final class FontCache implements Serializable { return fontFile; } } - } + } return null; } @@ -280,7 +280,7 @@ public final class FontCache implements Serializable { } return fontfileMap; } - + /** * Adds a font info to cache * @param fontInfo font info @@ -313,7 +313,7 @@ public final class FontCache implements Serializable { /** * Returns a font from the cache. * @param embedUrl font info - * @return CachedFontFile object + * @return CachedFontFile object */ public CachedFontFile getFontFile(String embedUrl) { if (containsFont(embedUrl)) { @@ -321,7 +321,7 @@ public final class FontCache implements Serializable { } return null; } - + /** * Returns the EmbedFontInfo instances belonging to a font file. If the font file was * modified since it was cached the entry is removed and null is returned. @@ -338,7 +338,7 @@ public final class FontCache implements Serializable { return null; } } - + /** * removes font from cache * @param embedUrl embed url @@ -354,7 +354,7 @@ public final class FontCache implements Serializable { } } } - + /** * has this font previously failed to load? * @param embedUrl embed url @@ -370,7 +370,7 @@ public final class FontCache implements Serializable { // from failed font map for now getFailedFontMap().remove(embedUrl); changed = true; - } + } } return true; } @@ -397,7 +397,7 @@ public final class FontCache implements Serializable { } return failedFontMap; } - + /** * Clears font cache */ @@ -411,7 +411,7 @@ public final class FontCache implements Serializable { changed = true; } } - + /** * Retrieve the last modified date/time of a URL. * @param url the URL @@ -432,7 +432,7 @@ public final class FontCache implements Serializable { return 0; } } - + private static class CachedFontFile implements Serializable { private static final long serialVersionUID = 4524237324330578883L; @@ -440,18 +440,18 @@ public final class FontCache implements Serializable { private long lastModified = -1; private Map/**/ filefontsMap = null; - + public CachedFontFile(long lastModified) { setLastModified(lastModified); } private Map/**/ getFileFontsMap() { if (filefontsMap == null) { - filefontsMap = new java.util.HashMap/**/(); + filefontsMap = new java.util.HashMap/**/(); } return filefontsMap; } - + void put(EmbedFontInfo efi) { getFileFontsMap().put(efi.getPostScriptName(), efi); } @@ -467,7 +467,7 @@ public final class FontCache implements Serializable { return (EmbedFontInfo[])getFileFontsMap().values().toArray( new EmbedFontInfo[getFileFontsMap().size()]); } - + /** * Gets the modified timestamp for font file (not always available) * @return modified timestamp @@ -478,15 +478,15 @@ public final class FontCache implements Serializable { /** * Gets the modified timestamp for font file - * (used for the purposes of font info caching) + * (used for the purposes of font info caching) * @param lastModified modified font file timestamp */ public void setLastModified(long lastModified) { this.lastModified = lastModified; } - + /** - * @return string representation of this object + * @return string representation of this object * {@inheritDoc} */ public String toString() { diff --git a/src/java/org/apache/fop/fonts/FontCollection.java b/src/java/org/apache/fop/fonts/FontCollection.java index c83f2523a..331d2639f 100644 --- a/src/java/org/apache/fop/fonts/FontCollection.java +++ b/src/java/org/apache/fop/fonts/FontCollection.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts; diff --git a/src/java/org/apache/fop/fonts/FontDescriptor.java b/src/java/org/apache/fop/fonts/FontDescriptor.java index 73cb235e8..841d99de2 100644 --- a/src/java/org/apache/fop/fonts/FontDescriptor.java +++ b/src/java/org/apache/fop/fonts/FontDescriptor.java @@ -16,12 +16,12 @@ */ /* $Id$ */ - + package org.apache.fop.fonts; /** * This interface enhances the font metrics interface with access methods to - * value needed to register fonts in various target formats like PDF or + * value needed to register fonts in various target formats like PDF or * PostScript. */ public interface FontDescriptor extends FontMetrics { @@ -31,55 +31,55 @@ public interface FontDescriptor extends FontMetrics { * @return the ascender */ int getAscender(); - - + + /** * Returns the capital height of the font. * @return the capital height */ int getCapHeight(); - - + + /** * Returns the descender value of the font. (Descent in pdf spec) * @return the descender value */ int getDescender(); - - + + /** * Returns the flags for the font. (See pdf spec) * @return the flags */ int getFlags(); - - + + /** * Returns the font's bounding box. * @return the bounding box */ int[] getFontBBox(); - - + + /** * Returns the italic angle for the font. * @return the italic angle */ int getItalicAngle(); - - + + /** * Returns the vertical stem width for the font. * @return the vertical stem width */ int getStemV(); - + /** * Indicates if this font may be embedded. * @return True, if embedding is possible/permitted */ boolean isEmbeddable(); - - + + } diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index 9ac4c1e6a..4e327c782 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -39,34 +39,34 @@ import org.apache.commons.logging.LogFactory; * implemented. */ public class FontInfo { - + private static final FontTriplet[] TRIPLETS_TYPE = new FontTriplet[1]; - + /** logging instance */ protected static Log log = LogFactory.getLog(FontInfo.class); /** Map containing fonts that have been used */ private Map/**/ usedFonts = null; //(String = font key) - + /** look up a font-triplet to find a font-name */ private Map/**/ triplets = null; //(String = font key) - + /** look up a font-triplet to find its priority * (only used inside addFontProperties()) */ private Map/**/ tripletPriorities = null; //Map /** look up a font-name to get a font (that implements FontMetrics at least) */ private Map/**/ fonts = null; //(String = font key) - + /** - * a collection of missing fonts; used to make sure the user gets + * a collection of missing fonts; used to make sure the user gets * a warning for a missing font only once (not every time the font is used) */ private Set/**/ loggedFontKeys = null; /** Cache for Font instances. */ private Map/**/ fontInstanceCache = null; - + /** Event listener for font events */ private FontEventListener eventListener = null; @@ -79,7 +79,7 @@ public class FontInfo { this.fonts = new java.util.HashMap/**/(); this.usedFonts = new java.util.HashMap/**/(); } - + /** * Sets the font event listener that can be used to receive events about particular events * in this class. @@ -88,9 +88,9 @@ public class FontInfo { public void setEventListener(FontEventListener listener) { this.eventListener = listener; } - + /** - * Checks if the font setup is valid (At least the ultimate fallback font + * Checks if the font setup is valid (At least the ultimate fallback font * must be registered.) * @return True if valid */ @@ -188,7 +188,7 @@ public class FontInfo { * @param family font family * @param style font style * @param weight font weight - * @param substFont true if the font may be substituted with the + * @param substFont true if the font may be substituted with the * default font if not found * @return internal font triplet key */ @@ -196,8 +196,8 @@ public class FontInfo { int weight, boolean substFont) { if (log.isTraceEnabled()) { log.trace("Font lookup: " + family + " " + style + " " + weight); - } - + } + FontTriplet startKey = createFontKey(family, style, weight); FontTriplet fontTriplet = startKey; // first try given parameters @@ -227,7 +227,7 @@ public class FontInfo { return key; } } - + // adjust weight, favouring normal or bold key = findAdjustWeight(family, style, weight); internalFontKey = getInternalFontKey(key); @@ -235,7 +235,7 @@ public class FontInfo { if (!substFont && internalFontKey == null) { return null; } - + // only if the font may be substituted // fallback 1: try the same font-family and weight with default style if (internalFontKey == null && style != Font.STYLE_NORMAL) { @@ -260,14 +260,14 @@ public class FontInfo { } } } - + // fallback 2: try the same font-family with default style and weight /* obsolete: replaced by the loop above if (f == null) { key = createFontKey(family, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); f = getInternalFontKey(key); }*/ - + // fallback 3: try any family with orig style/weight if (internalFontKey == null) { return fuzzyFontLookup("any", style, weight, startKey, false); @@ -285,7 +285,7 @@ public class FontInfo { return null; } } - + /** * Tells this class that the font with the given internal name has been used. * @param internalName the internal font name (F1, F2 etc.) @@ -293,7 +293,7 @@ public class FontInfo { public void useFont(String internalName) { usedFonts.put(internalName, fonts.get(internalName)); } - + private Map/*>*/ getFontInstanceCache() { if (fontInstanceCache == null) { fontInstanceCache = new java.util.HashMap/*>*/(); @@ -302,7 +302,7 @@ public class FontInfo { } /** - * Retrieves a (possibly cached) Font instance based on a FontTriplet and a font size. + * Retrieves a (possibly cached) Font instance based on a FontTriplet and a font size. * @param triplet the font triplet designating the requested font * @param fontSize the font size * @return the requested Font instance @@ -325,7 +325,7 @@ public class FontInfo { } return font; } - + /** * Lookup a font. *
      @@ -342,7 +342,7 @@ public class FontInfo { int weight) { return fontLookup(family, style, weight, true); } - + /** * Looks up a set of fonts. *
      @@ -383,14 +383,14 @@ public class FontInfo { "fontLookup must return an array with at least one " + "FontTriplet on the last call. Lookup: " + sb.toString()); } - + private Set/**/ getLoggedFontKeys() { if (loggedFontKeys == null) { loggedFontKeys = new java.util.HashSet/**/(); } return loggedFontKeys; } - + private void notifyFontReplacement(FontTriplet replacedKey, FontTriplet newKey) { if (!getLoggedFontKeys().contains(replacedKey)) { getLoggedFontKeys().add(replacedKey); @@ -402,7 +402,7 @@ public class FontInfo { } } } - + /** * Find a font with a given family and style by trying * different font weights according to the spec. @@ -476,7 +476,7 @@ public class FontInfo { public String getInternalFontKey(FontTriplet triplet) { return (String)triplets.get(triplet); } - + /** * Creates a key from the given strings. * @param family font family @@ -504,7 +504,7 @@ public class FontInfo { public Map/**/ getFontTriplets() { return this.triplets; } - + /** * This is used by the renderers to retrieve all the * fonts used in the document. @@ -541,7 +541,7 @@ public class FontInfo { } return foundTriplets; } - + /** * Returns the first triplet matching the given font name. * As there may be multiple triplets matching the font name @@ -557,7 +557,7 @@ public class FontInfo { } return null; } - + /** * Returns the font style for a particular font. * There may be multiple font styles matching this font. Only the first @@ -574,7 +574,7 @@ public class FontInfo { return ""; } } - + /** * Returns the font weight for a particular font. * There may be multiple font weights matching this font. Only the first @@ -591,14 +591,14 @@ public class FontInfo { return 0; } } - + /** - * Diagnostic method for logging all registered fonts to System.out. + * Diagnostic method for logging all registered fonts to System.out. */ public void dumpAllTripletsToSystemOut() { System.out.print(toString()); } - + /** * {@inheritDoc} */ @@ -608,7 +608,7 @@ public class FontInfo { while (iter.hasNext()) { FontTriplet triplet = (FontTriplet)iter.next(); String key = getInternalFontKey(triplet); - FontMetrics metrics = getMetricsFor(key); + FontMetrics metrics = getMetricsFor(key); entries.add(triplet.toString() + " -> " + key + " -> " + metrics.getFontName() + "\n"); } StringBuffer stringBuffer = new StringBuffer(); diff --git a/src/java/org/apache/fop/fonts/FontManager.java b/src/java/org/apache/fop/fonts/FontManager.java index d25d2d390..c180fbcc9 100644 --- a/src/java/org/apache/fop/fonts/FontManager.java +++ b/src/java/org/apache/fop/fonts/FontManager.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts; @@ -29,7 +29,7 @@ import org.apache.fop.fonts.FontTriplet.Matcher; import org.apache.fop.fonts.substitute.FontSubstitutions; import org.apache.fop.render.PrintRenderer; -// TODO: Refactor fonts package so major font activities (autodetection etc) +// TODO: Refactor fonts package so major font activities (autodetection etc) // are all centrally managed and delegated from this class, also remove dependency on FopFactory // and start using POJO config/properties type classes @@ -62,7 +62,7 @@ public class FontManager { public FontManager() { setUseCache(DEFAULT_USE_CACHE); } - + /** * Sets the font base URL. * @param fontBase font base URL @@ -90,7 +90,7 @@ public class FontManager { * @param value true if kerning should be activated */ public void setBase14KerningEnabled(boolean value) { - this.enableBase14Kerning = value; + this.enableBase14Kerning = value; } /** @@ -100,7 +100,7 @@ public class FontManager { public void setFontSubstitutions(FontSubstitutions substitutions) { this.fontSubstitutions = substitutions; } - + /** * Returns the font substitution catalog * @return the font substitution catalog @@ -142,7 +142,7 @@ public class FontManager { public FontCache getFontCache() { return this.fontCache; } - + /** * Sets up the fonts on a given PrintRenderer * @param renderer a print renderer @@ -151,7 +151,7 @@ public class FontManager { FontInfo fontInfo = renderer.getFontInfo(); int startNum = 1; - + // Configure base 14 fonts org.apache.fop.fonts.base14.Base14FontCollection base14FontCollection = new org.apache.fop.fonts.base14.Base14FontCollection(this.enableBase14Kerning); @@ -161,7 +161,7 @@ public class FontManager { org.apache.fop.fonts.CustomFontCollection customFontCollection = new org.apache.fop.fonts.CustomFontCollection(renderer); startNum = customFontCollection.setup(startNum, fontInfo); - + // Make any defined substitutions in the font info getFontSubstitutions().adjustFontInfo(fontInfo); } @@ -179,7 +179,7 @@ public class FontManager { // setup base 14 fonts org.apache.fop.render.java2d.Base14FontCollection base14FontCollection = new org.apache.fop.render.java2d.Base14FontCollection(graphics2D); - + // setup any custom font collection startNum = base14FontCollection.setup(startNum, fontInfo); @@ -194,7 +194,7 @@ public class FontManager { startNum = configuredFontCollection.setup(startNum, fontInfo); // Make any defined substitutions in the font info - getFontSubstitutions().adjustFontInfo(fontInfo); + getFontSubstitutions().adjustFontInfo(fontInfo); } /** @return a new FontResolver to be used by the font subsystem */ diff --git a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java index d44470e6b..7f1c267da 100644 --- a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java +++ b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts; @@ -37,12 +37,12 @@ import org.apache.fop.util.LogUtil; * Configurator of the FontManager */ public class FontManagerConfigurator { - + /** logger instance */ private static Log log = LogFactory.getLog(FontManagerConfigurator.class); private Configuration cfg; - + /** * Main constructor * @param cfg the font manager configuration object @@ -58,7 +58,7 @@ public class FontManagerConfigurator { * @throws FOPException if an exception occurs while processing the configuration */ public void configure(FontManager fontManager, boolean strict) throws FOPException { - + // caching (fonts) if (cfg.getChild("use-cache", false) != null) { try { @@ -84,12 +84,12 @@ public class FontManagerConfigurator { Configuration substitutionsCfg = fontsCfg.getChild("substitutions", false); if (substitutionsCfg != null) { FontSubstitutionsConfigurator fontSubstitutionsConfigurator - = new FontSubstitutionsConfigurator(substitutionsCfg); + = new FontSubstitutionsConfigurator(substitutionsCfg); FontSubstitutions substitutions = new FontSubstitutions(); fontSubstitutionsConfigurator.configure(substitutions); fontManager.setFontSubstitutions(substitutions); } - + // referenced fonts (fonts which are not to be embedded) Configuration referencedFontsCfg = fontsCfg.getChild("referenced-fonts", false); if (referencedFontsCfg != null) { @@ -121,11 +121,11 @@ public class FontManagerConfigurator { private static class OrFontTripletMatcher implements FontTriplet.Matcher { private FontTriplet.Matcher[] matchers; - + public OrFontTripletMatcher(FontTriplet.Matcher[] matchers) { this.matchers = matchers; } - + /** {@inheritDoc} */ public boolean matches(FontTriplet triplet) { for (int i = 0, c = matchers.length; i < c; i++) { @@ -135,22 +135,22 @@ public class FontManagerConfigurator { } return false; } - + } - + private static class FontFamilyRegExFontTripletMatcher implements FontTriplet.Matcher { private Pattern regex; - + public FontFamilyRegExFontTripletMatcher(String regex) { this.regex = Pattern.compile(regex); } - + /** {@inheritDoc} */ public boolean matches(FontTriplet triplet) { return regex.matcher(triplet.getName()).matches(); } - + } - + } diff --git a/src/java/org/apache/fop/fonts/FontSetup.java b/src/java/org/apache/fop/fonts/FontSetup.java index 9aa8440db..7629e67c3 100644 --- a/src/java/org/apache/fop/fonts/FontSetup.java +++ b/src/java/org/apache/fop/fonts/FontSetup.java @@ -182,7 +182,7 @@ public class FontSetup { // All base 14 configured now, so any custom embedded fonts start from 15 final int startNum = 15; - + /* Add configured fonts */ addConfiguredFonts(fontInfo, embedFontInfoList, startNum, resolver); } @@ -204,7 +204,7 @@ public class FontSetup { //Ensure that we have minimal font resolution capabilities resolver = createMinimalFontResolver1(); } - + String internalName = null; for (int i = 0; i < embedFontInfoList.size(); i++) { @@ -212,7 +212,7 @@ public class FontSetup { internalName = "F" + num; num++; - + LazyFont font = new LazyFont(embedFontInfo, resolver); fontInfo.addMetrics(internalName, font); @@ -234,5 +234,5 @@ public class FontSetup { return new StreamSource(href); } }; - } + } } diff --git a/src/java/org/apache/fop/fonts/FontTriplet.java b/src/java/org/apache/fop/fonts/FontTriplet.java index a989cf0f7..906698e53 100644 --- a/src/java/org/apache/fop/fonts/FontTriplet.java +++ b/src/java/org/apache/fop/fonts/FontTriplet.java @@ -16,7 +16,7 @@ */ /* $Id$ */ - + package org.apache.fop.fonts; import java.io.Serializable; @@ -25,15 +25,15 @@ import java.io.Serializable; * FontTriplet contains information on name, style and weight of one font */ public class FontTriplet implements Comparable, Serializable { - + /** serial version UID */ private static final long serialVersionUID = 1168991106658033508L; - + private String name; private String style; private int weight; private int priority; // priority of this triplet/font mapping - + //This is only a cache private transient String key; @@ -78,7 +78,7 @@ public class FontTriplet implements Comparable, Serializable { public String getStyle() { return style; } - + /** @return the font weight */ public int getWeight() { return weight; @@ -96,7 +96,7 @@ public class FontTriplet implements Comparable, Serializable { } return this.key; } - + /** {@inheritDoc} */ public int compareTo(Object o) { return getKey().compareTo(((FontTriplet)o).getKey()); @@ -117,7 +117,7 @@ public class FontTriplet implements Comparable, Serializable { if (obj instanceof FontTriplet) { FontTriplet other = (FontTriplet)obj; return (getName().equals(other.getName()) - && getStyle().equals(other.getStyle()) + && getStyle().equals(other.getStyle()) && (getWeight() == other.getWeight())); } } @@ -128,13 +128,13 @@ public class FontTriplet implements Comparable, Serializable { public String toString() { return getKey(); } - - + + /** * Matcher interface for {@link FontTriplet}. */ public interface Matcher { - + /** * Indicates whether the given {@link FontTriplet} matches a particular criterium. * @param triplet the font triplet @@ -142,6 +142,6 @@ public class FontTriplet implements Comparable, Serializable { */ boolean matches(FontTriplet triplet); } - + } diff --git a/src/java/org/apache/fop/fonts/FontUtil.java b/src/java/org/apache/fop/fonts/FontUtil.java index d72e283cf..5df5707f0 100644 --- a/src/java/org/apache/fop/fonts/FontUtil.java +++ b/src/java/org/apache/fop/fonts/FontUtil.java @@ -16,7 +16,7 @@ */ /* $Id$ */ - + package org.apache.fop.fonts; /** @@ -25,7 +25,7 @@ package org.apache.fop.fonts; public class FontUtil { /** - * Parses an CSS2 (SVG and XSL-FO) font weight (normal, bold, 100-900) to + * Parses an CSS2 (SVG and XSL-FO) font weight (normal, bold, 100-900) to * an integer. * See http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font-weight * TODO: Implement "lighter" and "bolder". @@ -47,7 +47,7 @@ public class FontUtil { weight = 700; } else { throw new IllegalArgumentException( - "Illegal value for font weight: '" + "Illegal value for font weight: '" + text + "'. Use one of: 100, 200, 300, " + "400, 500, 600, 700, 800, 900, " @@ -90,7 +90,7 @@ public class FontUtil { /** font constituent names which identify a font as being of "bold" weight */ private static final String[] BOLD_WORDS = {"bold"}; /** font constituent names which identify a font as being of "extra bold" weight */ - private static final String[] EXTRA_BOLD_WORDS = {"extrabold", "extra bold", "black", + private static final String[] EXTRA_BOLD_WORDS = {"extrabold", "extra bold", "black", "heavy", "ultra", "super"}; /** @@ -102,7 +102,7 @@ public class FontUtil { if (fontName != null) { for (int i = 0; i < ITALIC_WORDS.length; i++) { if (fontName.indexOf(ITALIC_WORDS[i]) != -1) { - return Font.STYLE_ITALIC; + return Font.STYLE_ITALIC; } } } @@ -117,18 +117,18 @@ public class FontUtil { public static int guessWeight(String fontName) { // weight int weight = Font.WEIGHT_NORMAL; - + for (int i = 0; i < BOLD_WORDS.length; i++) { if (fontName.indexOf(BOLD_WORDS[i]) != -1) { weight = Font.WEIGHT_BOLD; break; - } + } } for (int i = 0; i < MEDIUM_WORDS.length; i++) { if (fontName.indexOf(MEDIUM_WORDS[i]) != -1) { weight = Font.WEIGHT_NORMAL + 100; //500 break; - } + } } //Search for "semi/demi" before "light", but after "bold" //(normally semi/demi-bold is meant, but it can also be semi/demi-light) @@ -136,19 +136,19 @@ public class FontUtil { if (fontName.indexOf(DEMI_WORDS[i]) != -1) { weight = Font.WEIGHT_BOLD - 100; //600 break; - } + } } for (int i = 0; i < EXTRA_BOLD_WORDS.length; i++) { if (fontName.indexOf(EXTRA_BOLD_WORDS[i]) != -1) { weight = Font.WEIGHT_EXTRA_BOLD; break; - } + } } for (int i = 0; i < LIGHT_WORDS.length; i++) { if (fontName.indexOf(LIGHT_WORDS[i]) != -1) { weight = Font.WEIGHT_LIGHT; break; - } + } } return weight; } diff --git a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java index 11b52f916..c0cc03276 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java @@ -44,22 +44,22 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { /** default depth limit of recursion when searching for font files **/ public static final int DEFAULT_DEPTH_LIMIT = -1; - + /** - * Default constructor + * Default constructor */ public FontFileFinder() { super(getDirectoryFilter(), getFileFilter(), DEFAULT_DEPTH_LIMIT); } /** - * Constructor + * Constructor * @param depthLimit recursion depth limit */ public FontFileFinder(int depthLimit) { super(getDirectoryFilter(), getFileFilter(), depthLimit); } - + /** * Font directory filter. Currently ignores hidden directories. * @return IOFileFilter font directory filter @@ -70,7 +70,7 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter(".")) ); } - + /** * Font file filter. Currently searches for files with .ttf, .ttc, .otf, and .pfb extensions. * @return IOFileFilter font file filter @@ -83,13 +83,13 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { IOCase.INSENSITIVE) ); } - + /** * @param directory directory to handle * @param depth recursion depth * @param results collection * @return whether directory should be handled - * {@inheritDoc} + * {@inheritDoc} */ protected boolean handleDirectory(File directory, int depth, Collection results) { return true; @@ -99,7 +99,7 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { * @param file file to handle * @param depth recursion depth * @param results collection - * {@inheritDoc} + * {@inheritDoc} */ protected void handleFile(File file, int depth, Collection results) { try { @@ -109,7 +109,7 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { log.debug("MalformedURLException" + e.getMessage()); } } - + /** * @param directory the directory being processed * @param depth the current directory level @@ -119,10 +119,10 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { protected void handleDirectoryEnd(File directory, int depth, Collection results) { if (log.isDebugEnabled()) { log.debug(directory + ": found " + results.size() + " font" - + ((results.size() == 1) ? "" : "s")); + + ((results.size() == 1) ? "" : "s")); } - } - + } + /** * Automagically finds a list of font files on local system * @@ -162,5 +162,5 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { List results = new java.util.ArrayList(); super.walk(new File(dir), results); return results; - } + } } diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index 987b7e918..9ab04282d 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -49,12 +49,12 @@ import org.apache.fop.fonts.truetype.TTFFontLoader; * Attempts to determine correct FontInfo */ public class FontInfoFinder { - + /** logging instance */ private Log log = LogFactory.getLog(FontInfoFinder.class); private FontEventListener eventListener; - + /** * Sets the font event listener that can be used to receive events about particular events * in this class. @@ -63,7 +63,7 @@ public class FontInfoFinder { public void setEventListener(FontEventListener listener) { this.eventListener = listener; } - + /** * Attempts to determine FontTriplets from a given CustomFont. * It seems to be fairly accurate but will probably require some tweaking over time @@ -73,9 +73,9 @@ public class FontInfoFinder { */ private void generateTripletsFromFont(CustomFont customFont, Collection triplets) { if (log.isTraceEnabled()) { - log.trace("Font: " + customFont.getFullName() - + ", family: " + customFont.getFamilyNames() - + ", PS: " + customFont.getFontName() + log.trace("Font: " + customFont.getFullName() + + ", family: " + customFont.getFamilyNames() + + ", PS: " + customFont.getFontName() + ", EmbedName: " + customFont.getEmbedFontName()); } @@ -87,7 +87,7 @@ public class FontInfoFinder { String style = guessStyle(customFont, searchName); int weight; //= customFont.getWeight(); - int guessedWeight = FontUtil.guessWeight(searchName); + int guessedWeight = FontUtil.guessWeight(searchName); //We always take the guessed weight for now since it yield much better results. //OpenType's OS/2 usWeightClass value proves to be unreliable. weight = guessedWeight; @@ -114,9 +114,9 @@ public class FontInfoFinder { } } } - + private final Pattern quotePattern = Pattern.compile("'"); - + private String stripQuotes(String name) { return quotePattern.matcher(name).replaceAll(""); } @@ -125,13 +125,13 @@ public class FontInfoFinder { // style String style = Font.STYLE_NORMAL; if (customFont.getItalicAngle() > 0) { - style = Font.STYLE_ITALIC; + style = Font.STYLE_ITALIC; } else { style = FontUtil.guessStyle(fontName); } return style; } - + /** * Attempts to determine FontInfo from a given custom font * @param fontUrl the font URL @@ -151,13 +151,13 @@ public class FontInfoFinder { } EmbedFontInfo fontInfo = new EmbedFontInfo(null, customFont.isKerningEnabled(), fontTripletList, embedUrl, subFontName); - fontInfo.setPostScriptName(customFont.getFontName()); + fontInfo.setPostScriptName(customFont.getFontName()); if (fontCache != null) { fontCache.addFont(fontInfo); } return fontInfo; } - + /** * Attempts to determine EmbedFontInfo from a given font file. * @@ -170,7 +170,7 @@ public class FontInfoFinder { public EmbedFontInfo[] find(URL fontUrl, FontResolver resolver, FontCache fontCache) { String embedUrl = null; embedUrl = fontUrl.toExternalForm(); - + long fileLastModified = -1; if (fontCache != null) { fileLastModified = FontCache.getLastModified(fontUrl); @@ -188,8 +188,8 @@ public class FontInfoFinder { return null; } } - - + + // try to determine triplet information from font file CustomFont customFont = null; if (fontUrl.toExternalForm().endsWith(".ttc")) { @@ -241,7 +241,7 @@ public class FontInfoFinder { EmbedFontInfo fi = getFontInfoFromCustomFont(fontUrl, customFont, fontCache); if (fi != null) { embedFontInfoList.add(fi); - } + } } return (EmbedFontInfo[])embedFontInfoList.toArray( new EmbedFontInfo[embedFontInfoList.size()]); diff --git a/src/java/org/apache/fop/fonts/base14/Base14FontCollection.java b/src/java/org/apache/fop/fonts/base14/Base14FontCollection.java index 68324f13a..7bebccc88 100644 --- a/src/java/org/apache/fop/fonts/base14/Base14FontCollection.java +++ b/src/java/org/apache/fop/fonts/base14/Base14FontCollection.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.base14; @@ -27,7 +27,7 @@ import org.apache.fop.fonts.FontInfo; * Sets up Base 14 fonts */ public class Base14FontCollection implements FontCollection { - + private boolean kerning = false; /** @@ -38,7 +38,7 @@ public class Base14FontCollection implements FontCollection { public Base14FontCollection(boolean kerning) { this.kerning = kerning; } - + /** * {@inheritDoc} */ @@ -143,7 +143,7 @@ public class Base14FontCollection implements FontCollection { fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); - + return 15; } } diff --git a/src/java/org/apache/fop/fonts/substitute/AttributeValue.java b/src/java/org/apache/fop/fonts/substitute/AttributeValue.java index 1c697dc02..44f2ff571 100644 --- a/src/java/org/apache/fop/fonts/substitute/AttributeValue.java +++ b/src/java/org/apache/fop/fonts/substitute/AttributeValue.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.substitute; @@ -25,7 +25,7 @@ import java.util.StringTokenizer; * Encapsulates a font attribute value */ public class AttributeValue extends java.util.ArrayList { - + private static final long serialVersionUID = 748610847500940557L; /** @@ -38,15 +38,15 @@ public class AttributeValue extends java.util.ArrayList { */ public static AttributeValue valueOf(String valuesString) { AttributeValue attribute = new AttributeValue(); - StringTokenizer stringTokenzier = new StringTokenizer(valuesString, ","); - if (stringTokenzier.countTokens() > 1) { - while (stringTokenzier.hasMoreTokens()) { - String token = stringTokenzier.nextToken().trim(); + StringTokenizer stringTokenizer = new StringTokenizer(valuesString, ","); + if (stringTokenizer.countTokens() > 1) { + while (stringTokenizer.hasMoreTokens()) { + String token = stringTokenizer.nextToken().trim(); AttributeValue tokenAttribute = AttributeValue.valueOf(token); attribute.addAll(tokenAttribute); } } else { - String token = stringTokenzier.nextToken().trim(); + String token = stringTokenizer.nextToken().trim(); Object value = null; try { value = Integer.valueOf(token); @@ -60,6 +60,6 @@ public class AttributeValue extends java.util.ArrayList { attribute.add(value); } } - return attribute; + return attribute; } } diff --git a/src/java/org/apache/fop/fonts/substitute/FontQualifier.java b/src/java/org/apache/fop/fonts/substitute/FontQualifier.java index a68bb2ccd..63ec13db1 100644 --- a/src/java/org/apache/fop/fonts/substitute/FontQualifier.java +++ b/src/java/org/apache/fop/fonts/substitute/FontQualifier.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.substitute; @@ -32,7 +32,7 @@ import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.FontUtil; /** - * Encapsulates a font substitution qualifier + * Encapsulates a font substitution qualifier */ public class FontQualifier { @@ -47,15 +47,15 @@ public class FontQualifier { /** font weight attribute value */ private AttributeValue fontWeightAttributeValue = null; - + /** * Default constructor */ public FontQualifier() { } - + /** - * Sets the font family + * Sets the font family * @param fontFamily the font family */ public void setFontFamily(String fontFamily) { @@ -66,20 +66,20 @@ public class FontQualifier { } this.fontFamilyAttributeValue = fontFamilyAttribute; } - + /** - * Sets the font style + * Sets the font style * @param fontStyle the font style */ public void setFontStyle(String fontStyle) { AttributeValue fontStyleAttribute = AttributeValue.valueOf(fontStyle); if (fontStyleAttribute != null) { - this.fontStyleAttributeValue = fontStyleAttribute; + this.fontStyleAttributeValue = fontStyleAttribute; } } /** - * Sets the font weight + * Sets the font weight * @param fontWeight the font weight */ public void setFontWeight(String fontWeight) { @@ -100,7 +100,7 @@ public class FontQualifier { this.fontWeightAttributeValue = fontWeightAttribute; } } - + /** * @return the font family attribute */ @@ -117,7 +117,7 @@ public class FontQualifier { } return this.fontStyleAttributeValue; } - + /** * @return the font weight attribute */ @@ -141,7 +141,7 @@ public class FontQualifier { public boolean hasFontStyle() { return this.fontStyleAttributeValue != null; } - + /** * Returns a list of matching font triplet found in a given font info * @@ -154,7 +154,7 @@ public class FontQualifier { AttributeValue styleValue = getFontStyle(); List/**/ matchingTriplets = new java.util.ArrayList/**/(); - + // try to find matching destination font triplet for (Iterator attrIt = fontFamilyValue.iterator(); attrIt.hasNext();) { String fontFamilyString = (String)attrIt.next(); @@ -165,7 +165,7 @@ public class FontQualifier { tripletIt.hasNext();) { FontTriplet triplet = (FontTriplet)tripletIt.next(); String fontName = triplet.getName(); - + // matched font family name if (fontFamilyString.toLowerCase().equals(fontName.toLowerCase())) { @@ -194,7 +194,7 @@ public class FontQualifier { } } } - + // try and match font style boolean styleMatched = false; String fontStyleString = triplet.getStyle(); @@ -204,17 +204,17 @@ public class FontQualifier { styleMatched = true; } } - + if (weightMatched && styleMatched) { matchingTriplets.add(triplet); } } } - } + } } return matchingTriplets; } - + /** * Returns the highest priority matching font triplet found in a given font info * @param fontInfo the font info @@ -240,25 +240,25 @@ public class FontQualifier { } return bestTriplet; } - + /** * @return a list of font triplets matching this qualifier */ public List/**/ getTriplets() { List/**/ triplets = new java.util.ArrayList/**/(); - + AttributeValue fontFamilyValue = getFontFamily(); for (Iterator fontFamilyIt = fontFamilyValue.iterator(); fontFamilyIt.hasNext();) { String name = (String)fontFamilyIt.next(); - + AttributeValue styleValue = getFontStyle(); for (Iterator styleIt = styleValue.iterator(); styleIt.hasNext();) { String style = (String)styleIt.next(); - + AttributeValue weightValue = getFontWeight(); for (Iterator weightIt = weightValue.iterator(); weightIt.hasNext();) { Object weightObj = weightIt.next(); - + if (weightObj instanceof FontWeightRange) { FontWeightRange fontWeightRange = (FontWeightRange)weightObj; int[] weightRange = fontWeightRange.toArray(); @@ -292,14 +292,14 @@ public class FontQualifier { if (str.length() > 0) { str += ", "; } - str += "font-style=" + fontStyleAttributeValue; + str += "font-style=" + fontStyleAttributeValue; } if (fontWeightAttributeValue != null) { if (str.length() > 0) { str += ", "; } - str += "font-weight=" + fontWeightAttributeValue; + str += "font-weight=" + fontWeightAttributeValue; } return str; } -} \ No newline at end of file +} diff --git a/src/java/org/apache/fop/fonts/substitute/FontSubstitution.java b/src/java/org/apache/fop/fonts/substitute/FontSubstitution.java index 5f71e7b7c..7e9709a51 100644 --- a/src/java/org/apache/fop/fonts/substitute/FontSubstitution.java +++ b/src/java/org/apache/fop/fonts/substitute/FontSubstitution.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.substitute; @@ -23,7 +23,7 @@ package org.apache.fop.fonts.substitute; * Encapsulates a pair of substitution qualifiers */ public class FontSubstitution { - + private FontQualifier fromQualifier; private FontQualifier toQualifier; @@ -51,11 +51,11 @@ public class FontSubstitution { public FontQualifier getToQualifier() { return toQualifier; } - + /** * {@inheritDoc} */ public String toString() { return "from=" + fromQualifier + ", to=" + toQualifier; } -} \ No newline at end of file +} diff --git a/src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java b/src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java index 346b967e2..cc4e74143 100644 --- a/src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java +++ b/src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.substitute; @@ -44,9 +44,9 @@ public class FontSubstitutions extends java.util.ArrayList/**/ { public void adjustFontInfo(FontInfo fontInfo) { for (Iterator/**/ subsIt = super.iterator(); subsIt.hasNext();) { FontSubstitution substitution = (FontSubstitution)subsIt.next(); - + // find the best matching font triplet - FontQualifier toQualifier = substitution.getToQualifier(); + FontQualifier toQualifier = substitution.getToQualifier(); FontTriplet fontTriplet = toQualifier.bestMatch(fontInfo); if (fontTriplet == null) { log.error("Unable to match font substitution for destination qualifier " @@ -54,7 +54,7 @@ public class FontSubstitutions extends java.util.ArrayList/**/ { continue; } String internalFontKey = fontInfo.getInternalFontKey(fontTriplet); - + FontQualifier fromQualifier = substitution.getFromQualifier(); List/**/ tripletList = fromQualifier.getTriplets(); for (Iterator tripletit = tripletList.iterator(); tripletit.hasNext();) { @@ -62,5 +62,5 @@ public class FontSubstitutions extends java.util.ArrayList/**/ { fontInfo.addFontProperties(internalFontKey, triplet); } } - } + } } diff --git a/src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java b/src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java index 53045c601..44950221d 100644 --- a/src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java +++ b/src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.substitute; @@ -37,7 +37,7 @@ public class FontSubstitutionsConfigurator { public FontSubstitutionsConfigurator(Configuration cfg) { this.cfg = cfg; } - + private static FontQualifier getQualfierFromConfiguration(Configuration cfg) throws FOPException { String fontFamily = cfg.getAttribute("font-family", null); @@ -56,7 +56,7 @@ public class FontSubstitutionsConfigurator { } return qualifier; } - + /** * Configures a font substitution catalog * @@ -74,7 +74,7 @@ public class FontSubstitutionsConfigurator { if (fromCfg == null) { throw new FOPException("'substitution' element without child 'to' element"); } - FontQualifier fromQualifier = getQualfierFromConfiguration(fromCfg); + FontQualifier fromQualifier = getQualfierFromConfiguration(fromCfg); FontQualifier toQualifier = getQualfierFromConfiguration(toCfg); FontSubstitution substitution = new FontSubstitution(fromQualifier, toQualifier); substitutions.add(substitution); diff --git a/src/java/org/apache/fop/fonts/substitute/FontWeightRange.java b/src/java/org/apache/fop/fonts/substitute/FontWeightRange.java index 630bc1895..890d6cf7b 100644 --- a/src/java/org/apache/fop/fonts/substitute/FontWeightRange.java +++ b/src/java/org/apache/fop/fonts/substitute/FontWeightRange.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.fonts.substitute; @@ -23,13 +23,12 @@ import java.util.StringTokenizer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.fonts.FontUtil; /** * Encapsulates a range of font weight values */ public class FontWeightRange { - + /** logging instance */ protected static Log log = LogFactory.getLog("org.apache.fop.render.fonts"); @@ -68,7 +67,7 @@ public class FontWeightRange { /** the start range */ private int start; - + /** the end range */ private int end; @@ -81,7 +80,7 @@ public class FontWeightRange { this.start = start; this.end = end; } - + /** * Returns true if the given integer value is within this integer range * @param value the integer value @@ -90,7 +89,7 @@ public class FontWeightRange { public boolean isWithinRange(int value) { return (value >= start && value <= end); } - + /** * {@inheritDoc} */ @@ -111,5 +110,5 @@ public class FontWeightRange { range[i] = start + (i * 100); } return range; - } + } } diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index f83434f47..1a7b6b710 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -38,7 +38,7 @@ import org.apache.fop.fo.flow.RetrieveMarker; /** * The base class for most LayoutManagers. */ -public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager +public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager implements Constants { /** @@ -57,13 +57,13 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** True if this LayoutManager has handled all of its content. */ private boolean bFinished = false; - + /** child LM during getNextKnuthElement phase */ protected LayoutManager curChildLM = null; - + /** child LM iterator during getNextKnuthElement phase */ protected ListIterator childLMiter = null; - + private int lastGeneratedPosition = -1; private int smallestPosNumberChecked = Integer.MAX_VALUE; @@ -154,7 +154,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } /** - * {@inheritDoc} + * {@inheritDoc} */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { @@ -164,7 +164,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } /** - * {@inheritDoc} + * {@inheritDoc} */ public LinkedList getChangedKnuthElements(List oldList, int alignment) { @@ -229,20 +229,20 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager public PageSequenceLayoutManager getPSLM() { return parentLM.getPSLM(); } - + /** * @see PageSequenceLayoutManager#getCurrentPage() * @return the {@link Page} instance corresponding to the current page */ public Page getCurrentPage() { return getPSLM().getCurrentPage(); - } - + } + /** @return the current page viewport */ public PageViewport getCurrentPV() { return getPSLM().getCurrentPage().getPageViewport(); - } - + } + /** * {@inheritDoc} */ @@ -306,7 +306,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager pos.setIndex(lastGeneratedPosition); return pos; } - + /** * Indicates whether the given Position is the first area-generating Position of this LM. * @param pos the Position (must be one with a position index) @@ -326,7 +326,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager return false; } } - + /** * Indicates whether the given Position is the last area-generating Position of this LM. * @param pos the Position (must be one with a position index) @@ -349,7 +349,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager Map atts = fobj.getForeignAttributes(); targetArea.setForeignAttributes(atts); } - + /** * Registers the FO's markers on the current PageViewport * @@ -360,9 +360,9 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager protected void addMarkersToPage(boolean isStarting, boolean isFirst, boolean isLast) { if (this.markers != null) { getCurrentPV().addMarkers( - this.markers, - isStarting, - isFirst, + this.markers, + isStarting, + isFirst, isLast); } } @@ -390,5 +390,5 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager public String toString() { return (super.toString() + (fobj != null ? "[fobj=" + fobj.toString() + "]" : "")); } - + } diff --git a/src/java/org/apache/fop/render/AbstractRendererConfigurator.java b/src/java/org/apache/fop/render/AbstractRendererConfigurator.java index bce5abfbd..982b23f05 100644 --- a/src/java/org/apache/fop/render/AbstractRendererConfigurator.java +++ b/src/java/org/apache/fop/render/AbstractRendererConfigurator.java @@ -36,7 +36,7 @@ public abstract class AbstractRendererConfigurator { /** fop factory configuration */ protected FOUserAgent userAgent = null; - + /** * Default constructor * @param userAgent user agent @@ -45,7 +45,7 @@ public abstract class AbstractRendererConfigurator { super(); this.userAgent = userAgent; } - + /** * Returns the configuration subtree for a specific renderer. * @param renderer the renderer @@ -59,7 +59,7 @@ public abstract class AbstractRendererConfigurator { } return null; } - + return getRendererConfig(mimeType); } @@ -74,11 +74,11 @@ public abstract class AbstractRendererConfigurator { if (log.isDebugEnabled()) { log.debug("userconfig is null"); } - return null; + return null; } - + Configuration userRendererConfig = null; - + Configuration[] cfgs = cfg.getChild("renderers").getChildren("renderer"); for (int i = 0; i < cfgs.length; ++i) { diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index 23f8a1f62..c37012cb4 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -45,7 +45,7 @@ public abstract class PrintRenderer extends AbstractRenderer { /** list of fonts */ protected List/**/ embedFontInfoList = null; - + /** * Adds a font list to current list of fonts * @param fontList a font info list @@ -57,7 +57,7 @@ public abstract class PrintRenderer extends AbstractRenderer { fontList.addAll(fontList); } } - + /** * @param embedFontInfoList list of available fonts */ @@ -91,7 +91,7 @@ public abstract class PrintRenderer extends AbstractRenderer { FontTriplet triplet = (FontTriplet)area.getTrait(Trait.FONT); return fontInfo.getInternalFontKey(triplet); } - + /** * Returns a Font object constructed based on the font traits in an area * @param area the area from which to retrieve the font triplet information @@ -102,7 +102,7 @@ public abstract class PrintRenderer extends AbstractRenderer { int size = ((Integer)area.getTrait(Trait.FONT_SIZE)).intValue(); return fontInfo.getFontInstance(triplet, size); } - + /** * Lightens up a color for groove, ridge, inset and outset border effects. * @param col the color to lighten up @@ -135,7 +135,7 @@ public abstract class PrintRenderer extends AbstractRenderer { * @param foreignAttributes a Map or foreign attributes, may be null * @return the RendererContext */ - protected RendererContext createRendererContext(int x, int y, int width, int height, + protected RendererContext createRendererContext(int x, int y, int width, int height, Map foreignAttributes) { RendererContext context; context = new RendererContext(this, getMimeType()); @@ -149,7 +149,7 @@ public abstract class PrintRenderer extends AbstractRenderer { new Integer(x)); context.setProperty(RendererContextConstants.YPOS, new Integer(y)); - context.setProperty(RendererContextConstants.PAGE_VIEWPORT, + context.setProperty(RendererContextConstants.PAGE_VIEWPORT, getCurrentPageViewport()); if (foreignAttributes != null) { context.setProperty(RendererContextConstants.FOREIGN_ATTRIBUTES, foreignAttributes); @@ -165,12 +165,12 @@ public abstract class PrintRenderer extends AbstractRenderer { * @param foreignAttributes the foreign attributes containing rendering hints, or null */ public void renderDocument(Document doc, String ns, Rectangle2D pos, Map foreignAttributes) { - int x = currentIPPosition + (int) pos.getX(); + int x = currentIPPosition + (int) pos.getX(); int y = currentBPPosition + (int) pos.getY(); int width = (int)pos.getWidth(); int height = (int)pos.getHeight(); RendererContext context = createRendererContext(x, y, width, height, foreignAttributes); - + renderXML(context, doc, ns); } @@ -185,7 +185,7 @@ public abstract class PrintRenderer extends AbstractRenderer { } return this.fontResolver; } - + /** * @return the font info */ diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index 50d06932d..6849f867f 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -55,7 +55,7 @@ import org.apache.fop.util.LogUtil; /** * Base Print renderer configurator (mostly handles font configuration) */ -public class PrintRendererConfigurator extends AbstractRendererConfigurator +public class PrintRendererConfigurator extends AbstractRendererConfigurator implements RendererConfigurator { /** logger instance */ @@ -94,9 +94,9 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator boolean strict = factory.validateUserConfigStrictly(); FontCache fontCache = fontManager.getFontCache(); - List/**/ embedFontInfoList = buildFontListFromConfiguration(cfg, + List/**/ embedFontInfoList = buildFontListFromConfiguration(cfg, fontResolver, strict, fontManager); - + if (fontCache != null && fontCache.hasChanged()) { fontCache.save(); } @@ -113,13 +113,13 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator * @return a List of EmbedFontInfo objects. * @throws FOPException If an error occurs while processing the configuration */ - public static List/**/ buildFontListFromConfiguration(Configuration cfg, - FontResolver fontResolver, + public static List/**/ buildFontListFromConfiguration(Configuration cfg, + FontResolver fontResolver, boolean strict, FontManager fontManager) throws FOPException { FontCache fontCache = fontManager.getFontCache(); String fontBaseURL = fontManager.getFontBaseURL(); List/**/ fontInfoList - = new java.util.ArrayList/**/(); + = new java.util.ArrayList/**/(); Configuration fonts = cfg.getChild("fonts", false); if (fonts != null) { @@ -128,7 +128,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator log.debug("Starting font configuration..."); start = System.currentTimeMillis(); } - + // native o/s search (autodetect) configuration boolean autodetectFonts = (fonts.getChild("auto-detect", false) != null); if (autodetectFonts) { @@ -203,7 +203,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator LogUtil.handleException(log, e, strict); } } - + // font file (singular) configuration Configuration[] font = fonts.getChildren("font"); for (int i = 0; i < font.length; i++) { @@ -216,9 +216,9 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator // Update referenced fonts (fonts which are not to be embedded) updateReferencedFonts(fontInfoList, fontManager.getReferencedFontsMatcher()); - + if (log.isDebugEnabled()) { - log.debug("Finished font configuration in " + log.debug("Finished font configuration in " + (System.currentTimeMillis() - start) + "ms"); } } @@ -243,7 +243,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator } } - + /** * Iterates over font file list adding font info to list * @param fontFileList font file list @@ -258,7 +258,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator // parse font to ascertain font info FontInfoFinder finder = new FontInfoFinder(); //EmbedFontInfo fontInfo = finder.find(fontUrl, resolver, fontCache); - + //List embedFontInfoList = finder.find(fontUrl, resolver, fontCache); EmbedFontInfo[] embedFontInfos = finder.find(fontUrl, resolver, fontCache); @@ -299,14 +299,14 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator LogUtil.handleError(log, "font-triplet without name", strict); return null; } - + String weightStr = tripletCfg.getAttribute("weight"); if (weightStr == null) { LogUtil.handleError(log, "font-triplet without weight", strict); return null; } int weight = FontUtil.parseCSS2FontWeight(FontUtil.stripWhiteSpace(weightStr)); - + String style = tripletCfg.getAttribute("style"); if (style == null) { LogUtil.handleError(log, "font-triplet without style", strict); @@ -320,7 +320,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator } return null; } - + /** * Returns a font info from a font node Configuration definition * @@ -337,7 +337,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator String metricsUrl = fontCfg.getAttribute("metrics-url", null); String embedUrl = fontCfg.getAttribute("embed-url", null); String subFont = fontCfg.getAttribute("sub-font", null); - + if (metricsUrl == null && embedUrl == null) { LogUtil.handleError(log, "Font configuration without metric-url or embed-url attribute", @@ -366,13 +366,13 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator } } } - + Configuration[] tripletCfg = fontCfg.getChildren("font-triplet"); - + // no font triplet info if (tripletCfg.length == 0) { LogUtil.handleError(log, "font without font-triplet", strict); - + File fontFile = FontCache.getFileFromUrls(new String[] {embedUrl, metricsUrl}); URL fontUrl; try { @@ -384,28 +384,28 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator } if (fontFile != null) { FontInfoFinder finder = new FontInfoFinder(); - EmbedFontInfo[] infos = finder.find(fontUrl, fontResolver, fontCache); + EmbedFontInfo[] infos = finder.find(fontUrl, fontResolver, fontCache); return infos[0]; //When subFont is set, only one font is returned } else { return null; } } - + List/**/ tripletList = new java.util.ArrayList/**/(); for (int j = 0; j < tripletCfg.length; j++) { FontTriplet fontTriplet = getFontTripletFromConfiguration(tripletCfg[j], strict); tripletList.add(fontTriplet); } - + boolean useKerning = fontCfg.getAttributeAsBoolean("kerning", true); EmbedFontInfo embedFontInfo - = new EmbedFontInfo(metricsUrl, useKerning, tripletList, embedUrl, subFont); + = new EmbedFontInfo(metricsUrl, useKerning, tripletList, embedUrl, subFont); if (fontCache != null) { if (!fontCache.containsFont(embedFontInfo)) { - fontCache.addFont(embedFontInfo); + fontCache.addFont(embedFontInfo); } } - + if (log.isDebugEnabled()) { String embedFile = embedFontInfo.getEmbedFile(); log.debug("Adding font " + (embedFile != null ? embedFile + ", " : "") @@ -417,8 +417,8 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator + triplet.getStyle() + ", " + triplet.getWeight()); } - } + } return embedFontInfo; } - + } diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index bdbf207d4..045ba9835 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -497,7 +497,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { AffineTransform positionTransform = new AffineTransform(); positionTransform.translate(bv.getXOffset(), bv.getYOffset()); - + //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); @@ -506,7 +506,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { //saveGraphicsState(); //Viewport position //concatenateTransformationMatrix(mptToPt(positionTransform)); - + //Background and borders float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; @@ -537,7 +537,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { //concatenateTransformationMatrix(mptToPt(contentTransform)); contentRect = new Rectangle2D.Double(0, 0, 1000 * width, 1000 * height); pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentTransform))); - + currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); @@ -595,7 +595,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { //Not used here since AFPRenderer defines its own renderBlockViewport() method. throw new UnsupportedOperationException("NYI"); } - + /** * {@inheritDoc} */ @@ -919,7 +919,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {ImageFlavor.RAW_CCITTFAX, ImageFlavor.GRAPHICS2D, - ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE, ImageFlavor.XML_DOM}; @@ -947,12 +947,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { try { ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); - + //Only now fully load/prepare the image Map hints = ImageUtil.getDefaultHints(sessionContext); org.apache.xmlgraphics.image.loader.Image img = manager.getImage( info, FLAVORS, hints, sessionContext); - + //...and process the image if (img instanceof ImageGraphics2D) { ImageGraphics2D imageG2D = (ImageGraphics2D)img; @@ -966,7 +966,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } else if (img instanceof ImageRendered) { ImageRendered imgRend = (ImageRendered)img; RenderedImage ri = imgRend.getRenderedImage(); - + drawBufferedImage(ri, getResolution(), posInt.x + currentIPPosition, posInt.y + currentBPPosition, @@ -1029,7 +1029,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { getUserAgent().getEventBroadcaster()); eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); } - + /* ImageFactory fact = userAgent.getFactory().getImageFactory(); FopImage fopimage = fact.getImage(url, userAgent); @@ -1102,7 +1102,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (!fopimage.load(FopImage.BITMAP)) { return; } - convertToGrayScaleImage(io, fopimage.getBitmaps(), + convertToGrayScaleImage(io, fopimage.getBitmaps(), fopimage.getWidth(), fopimage.getHeight()); } } else { @@ -1413,9 +1413,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ // UNUSED // public void setOptions(Map options) { -// +// // this.afpOptions = options; -// +// // } /** * Determines the orientation from the string representation, this method @@ -1482,7 +1482,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Sets the rotation to be used for landsacpe pages, valid values are 0, 90, * 180, 270 (default). - * + * * @param rotation * The rotation in degrees. */ @@ -1649,7 +1649,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { io.setImageIDESize((byte) bitsPerPixel); io.setImageData(bw); } - + private final class ViewPortPos { private int x = 0; @@ -1805,7 +1805,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } this.resolution = resolution; } - + /** * Returns the output/device resolution. * @return the resolution in dpi diff --git a/src/java/org/apache/fop/render/java2d/Base14FontCollection.java b/src/java/org/apache/fop/render/java2d/Base14FontCollection.java index f97a68191..ca4a4bce3 100644 --- a/src/java/org/apache/fop/render/java2d/Base14FontCollection.java +++ b/src/java/org/apache/fop/render/java2d/Base14FontCollection.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.java2d; @@ -31,7 +31,7 @@ import org.apache.fop.fonts.FontInfo; public class Base14FontCollection implements FontCollection { private Graphics2D graphics2d = null; - + /** * Main constructor * @param graphics2d a graphics 2D @@ -39,7 +39,7 @@ public class Base14FontCollection implements FontCollection { public Base14FontCollection(Graphics2D graphics2d) { this.graphics2d = graphics2d; } - + /** * {@inheritDoc} */ @@ -175,7 +175,7 @@ public class Base14FontCollection implements FontCollection { fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD); fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", "normal", Font.WEIGHT_NORMAL); - + return 15; } } diff --git a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java index 4981905fa..843ab8413 100644 --- a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java +++ b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.java2d; @@ -54,7 +54,7 @@ public class ConfiguredFontCollection implements FontCollection { public ConfiguredFontCollection(PrintRenderer renderer) { this.renderer = renderer; } - + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java index 4cdd30c41..4eac922e8 100644 --- a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java +++ b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.java2d; @@ -67,7 +67,7 @@ public class InstalledFontCollection implements FontCollection { public InstalledFontCollection(Graphics2D graphics2D) { this.graphics2D = graphics2D; } - + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index eea165525..e39ae5831 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -129,17 +129,17 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** false: paints a non-transparent white background, true: for a transparent background */ protected boolean transparentPageBackground = false; - + /** The current state, holds a Graphics2D and its context */ protected Java2DGraphicsState state; - + private Stack stateStack = new Stack(); /** true if the renderer has finished rendering all the pages */ private boolean renderingDone; private GeneralPath currentPath = null; - + /** Default constructor */ public Java2DRenderer() { } @@ -150,7 +150,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem public void setUserAgent(FOUserAgent foUserAgent) { super.setUserAgent(foUserAgent); userAgent.setRendererOverride(this); // for document regeneration - + String s = (String)userAgent.getRendererOptions().get(JAVA2D_TRANSPARENT_PAGE_BACKGROUND); if (s != null) { this.transparentPageBackground = "true".equalsIgnoreCase(s); @@ -173,9 +173,9 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = fontImage.createGraphics(); //The next line is important to get accurate font metrics! - graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - + userAgent.getFactory().getFontManager().setupRenderer(this, graphics2D); } @@ -218,7 +218,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem public boolean isRenderingDone() { return this.renderingDone; } - + /** * @return The 0-based current page number */ @@ -279,7 +279,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem assert pageViewport.getPageIndex() >= 0; pageViewportList.add(pageViewport); } - + /** * Generates a desired page from the renderer's page viewport list. * @@ -300,18 +300,18 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem + " (pageWidth " + pageWidth + ", pageHeight " + pageHeight + ")"); - double scaleX = scaleFactor - * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) + double scaleX = scaleFactor + * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) / userAgent.getTargetPixelUnitToMillimeter(); double scaleY = scaleFactor * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) / userAgent.getTargetPixelUnitToMillimeter(); int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5); int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5); - - + + BufferedImage currentPageImage = getBufferedImage(bitmapWidth, bitmapHeight); - + Graphics2D graphics = currentPageImage.createGraphics(); graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); @@ -374,7 +374,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem return new BufferedImage( bitmapWidth, bitmapHeight, BufferedImage.TYPE_INT_ARGB); } - + /** * Returns a page viewport. * @param pageIndex the page index (zero-based) @@ -414,21 +414,21 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem state.dispose(); state = (Java2DGraphicsState)stateStack.pop(); } - + /** {@inheritDoc} */ protected void concatenateTransformationMatrix(AffineTransform at) { state.transform(at); } - + /** {@inheritDoc} */ protected void startVParea(CTM ctm, Rectangle2D clippingRect) { saveGraphicsState(); if (clippingRect != null) { - clipRect((float)clippingRect.getX() / 1000f, - (float)clippingRect.getY() / 1000f, - (float)clippingRect.getWidth() / 1000f, + clipRect((float)clippingRect.getX() / 1000f, + (float)clippingRect.getY() / 1000f, + (float)clippingRect.getWidth() / 1000f, (float)clippingRect.getHeight() / 1000f); } @@ -465,7 +465,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem */ protected void restoreStateStackAfterBreakOut(List breakOutList) { log.debug("Block.FIXED --> restoring context after break-out"); - + Iterator i = breakOutList.iterator(); while (i.hasNext()) { Java2DGraphicsState s = (Java2DGraphicsState)i.next(); @@ -475,7 +475,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } /** - * {@inheritDoc} + * {@inheritDoc} */ protected void updateColor(Color col, boolean fill) { state.updateColor(col); @@ -500,7 +500,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } /** - * {@inheritDoc} + * {@inheritDoc} */ protected void lineTo(float x, float y) { if (currentPath == null) { @@ -510,7 +510,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } /** - * {@inheritDoc} + * {@inheritDoc} */ protected void moveTo(float x, float y) { if (currentPath == null) { @@ -520,26 +520,26 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } /** - * {@inheritDoc} + * {@inheritDoc} */ protected void clipRect(float x, float y, float width, float height) { state.updateClip(new Rectangle2D.Float(x, y, width, height)); } /** - * {@inheritDoc} + * {@inheritDoc} */ protected void fillRect(float x, float y, float width, float height) { state.getGraph().fill(new Rectangle2D.Float(x, y, width, height)); } - + /** - * {@inheritDoc} + * {@inheritDoc} */ - protected void drawBorderLine(float x1, float y1, float x2, float y2, + protected void drawBorderLine(float x1, float y1, float x2, float y2, boolean horz, boolean startOrBefore, int style, Color col) { Graphics2D g2d = state.getGraph(); - drawBorderLine(new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1), + drawBorderLine(new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1), horz, startOrBefore, style, col, g2d); } @@ -547,13 +547,13 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem * Draw a border segment of an XSL-FO style border. * @param lineRect the line defined by its bounding rectangle * @param horz true for horizontal border segments, false for vertical border segments - * @param startOrBefore true for border segments on the start or before edge, + * @param startOrBefore true for border segments on the start or before edge, * false for end or after. * @param style the border style (one of Constants.EN_DASHED etc.) * @param col the color for the border segment * @param g2d the Graphics2D instance to paint to */ - public static void drawBorderLine(Rectangle2D.Float lineRect, + public static void drawBorderLine(Rectangle2D.Float lineRect, boolean horz, boolean startOrBefore, int style, Color col, Graphics2D g2d) { float x1 = lineRect.x; float y1 = lineRect.y; @@ -566,7 +566,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem return; } switch (style) { - case Constants.EN_DASHED: + case Constants.EN_DASHED: g2d.setColor(col); if (horz) { float unit = Math.abs(2 * h); @@ -576,7 +576,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } unit = w / rep; float ym = y1 + (h / 2); - BasicStroke s = new BasicStroke(h, BasicStroke.CAP_BUTT, + BasicStroke s = new BasicStroke(h, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] {unit}, 0); g2d.setStroke(s); g2d.draw(new Line2D.Float(x1, ym, x2, ym)); @@ -588,7 +588,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } unit = h / rep; float xm = x1 + (w / 2); - BasicStroke s = new BasicStroke(w, BasicStroke.CAP_BUTT, + BasicStroke s = new BasicStroke(w, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] {unit}, 0); g2d.setStroke(s); g2d.draw(new Line2D.Float(xm, y1, xm, y2)); @@ -604,7 +604,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } unit = w / rep; float ym = y1 + (h / 2); - BasicStroke s = new BasicStroke(h, BasicStroke.CAP_ROUND, + BasicStroke s = new BasicStroke(h, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER, 10.0f, new float[] {0, unit}, 0); g2d.setStroke(s); g2d.draw(new Line2D.Float(x1, ym, x2, ym)); @@ -616,7 +616,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } unit = h / rep; float xm = x1 + (w / 2); - BasicStroke s = new BasicStroke(w, BasicStroke.CAP_ROUND, + BasicStroke s = new BasicStroke(w, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER, 10.0f, new float[] {0, unit}, 0); g2d.setStroke(s); g2d.draw(new Line2D.Float(xm, y1, xm, y2)); @@ -722,7 +722,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem state.transform(at); renderText(text, state.getGraph(), font); restoreGraphicsState(); - + currentIPPosition = saveIP + text.getAllocIPD(); //super.renderText(text); @@ -755,8 +755,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem int[] letterAdjust = word.getLetterAdjustArray(); GlyphVector gv = g2d.getFont().createGlyphVector(g2d.getFontRenderContext(), s); double additionalWidth = 0.0; - if (letterAdjust == null - && text.getTextLetterSpaceAdjust() == 0 + if (letterAdjust == null + && text.getTextLetterSpaceAdjust() == 0 && text.getTextWordSpaceAdjust() == 0) { //nop } else { @@ -776,8 +776,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem SpaceArea space = (SpaceArea)child; String s = space.getSpace(); char sp = s.charAt(0); - int tws = (space.isAdjustable() - ? text.getTextWordSpaceAdjust() + int tws = (space.isAdjustable() + ? text.getTextWordSpaceAdjust() + 2 * text.getTextLetterSpaceAdjust() : 0); @@ -787,8 +787,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } } } - - private static int[] getGlyphOffsets(String s, Font font, TextArea text, + + private static int[] getGlyphOffsets(String s, Font font, TextArea text, int[] letterAdjust) { int textLen = s.length(); int[] offsets = new int[textLen]; @@ -804,11 +804,11 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } int cw = font.getWidth(mapped); int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0); - int tls = (i < textLen - 1 ? text.getTextLetterSpaceAdjust() : 0); + int tls = (i < textLen - 1 ? text.getTextLetterSpaceAdjust() : 0); offsets[i] = cw + ladj + tls + wordSpace; } return offsets; - } + } /** * Render leader area. This renders a leader area which is an area with a @@ -824,7 +824,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; float starty = ((currentBPPosition + area.getOffset()) / 1000f); - float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + area.getIPD()) / 1000f; Color col = (Color) area.getTrait(Trait.COLOR); @@ -839,7 +839,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem case EN_SOLID: case EN_DASHED: case EN_DOUBLE: - drawBorderLine(startx, starty, endx, starty + ruleThickness, + drawBorderLine(startx, starty, endx, starty + ruleThickness, true, true, style, col); break; case EN_DOTTED: @@ -905,7 +905,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem int x = currentIPPosition + (int)Math.round(pos.getX()); int y = currentBPPosition + (int)Math.round(pos.getY()); uri = URISpecification.getURL(uri); - + ImageManager manager = getUserAgent().getFactory().getImageManager(); ImageInfo info = null; try { @@ -913,8 +913,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem info = manager.getImageInfo(uri, sessionContext); final ImageFlavor[] flavors = new ImageFlavor[] {ImageFlavor.GRAPHICS2D, - ImageFlavor.BUFFERED_IMAGE, - ImageFlavor.RENDERED_IMAGE, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE, ImageFlavor.XML_DOM}; Map hints = ImageUtil.getDefaultHints(sessionContext); org.apache.xmlgraphics.image.loader.Image img = manager.getImage( @@ -958,7 +958,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } /** {@inheritDoc} */ - protected RendererContext createRendererContext(int x, int y, int width, int height, + protected RendererContext createRendererContext(int x, int y, int width, int height, Map foreignAttributes) { RendererContext context = super.createRendererContext( x, y, width, height, foreignAttributes); diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 5ffef15ba..007ce4828 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -16,7 +16,7 @@ */ /* $Id$ */ - + package org.apache.fop.render.pcl; //Java @@ -111,14 +111,14 @@ public class PCLRenderer extends PrintRenderer { /** The MIME type for PCL */ public static final String MIME_TYPE = MimeConstants.MIME_PCL_ALT; - private static final QName CONV_MODE + private static final QName CONV_MODE = new QName(ExtensionElementMapping.URI, null, "conversion-mode"); - private static final QName SRC_TRANSPARENCY + private static final QName SRC_TRANSPARENCY = new QName(ExtensionElementMapping.URI, null, "source-transparency"); - + /** The OutputStream to write the PCL stream to */ protected OutputStream out; - + /** The PCL generator */ protected PCLGenerator gen; private boolean ioTrouble = false; @@ -130,13 +130,13 @@ public class PCLRenderer extends PrintRenderer { private int currentPrintDirection = 0; private GeneralPath currentPath = null; private java.awt.Color currentFillColor = null; - + /** * Controls whether appearance is more important than speed. False can cause some FO feature - * to be ignored (like the advanced borders). + * to be ignored (like the advanced borders). */ private boolean qualityBeforeSpeed = false; - + /** * Controls whether all text should be painted as text. This is a fallback setting in case * the mixture of native and bitmapped text does not provide the necessary quality. @@ -149,17 +149,17 @@ public class PCLRenderer extends PrintRenderer { * this to true will increase memory consumption. */ private boolean useColorCanvas = false; - + /** - * Controls whether the generation of PJL commands gets disabled. + * Controls whether the generation of PJL commands gets disabled. */ private boolean disabledPJL = false; - + /** contains the pageWith of the last printed page */ private long pageWidth = 0; /** contains the pageHeight of the last printed page */ private long pageHeight = 0; - + /** * Create the PCL renderer */ @@ -182,7 +182,7 @@ public class PCLRenderer extends PrintRenderer { public void setPJLDisabled(boolean disable) { this.disabledPJL = disable; } - + /** * Indicates whether PJL generation is disabled. * @return true if PJL generation is disabled. @@ -190,7 +190,7 @@ public class PCLRenderer extends PrintRenderer { public boolean isPJLDisabled() { return this.disabledPJL; } - + /** * {@inheritDoc} */ @@ -203,9 +203,9 @@ public class PCLRenderer extends PrintRenderer { BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = fontImage.createGraphics(); //The next line is important to get accurate font metrics! - graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - + userAgent.getFactory().getFontManager().setupRenderer(this, graphics2D); } @@ -231,7 +231,7 @@ public class PCLRenderer extends PrintRenderer { public GraphicContext getGraphicContext() { return this.graphicContext; } - + /** @return the target resolution */ protected int getResolution() { int resolution = (int)Math.round(userAgent.getTargetResolution()); @@ -241,7 +241,7 @@ public class PCLRenderer extends PrintRenderer { return 600; } } - + /** * Sets the current font (NOTE: Hard-coded font mappings ATM!) * @param name the font name (internal F* names for now) @@ -317,25 +317,25 @@ public class PCLRenderer extends PrintRenderer { case 9: // F9 = Courier gen.writeCommand("(0N"); - gen.writeCommand("(s0p" + gen.formatDouble2(120.01f / (size / 1000.00f)) + gen.writeCommand("(s0p" + gen.formatDouble2(120.01f / (size / 1000.00f)) + "h0s0b4099T"); break; case 10: // F10 = Courier Oblique gen.writeCommand("(0N"); - gen.writeCommand("(s0p" + gen.formatDouble2(120.01f / (size / 1000.00f)) + gen.writeCommand("(s0p" + gen.formatDouble2(120.01f / (size / 1000.00f)) + "h1s0b4099T"); break; case 11: // F11 = Courier Bold gen.writeCommand("(0N"); - gen.writeCommand("(s0p" + gen.formatDouble2(120.01f / (size / 1000.00f)) + gen.writeCommand("(s0p" + gen.formatDouble2(120.01f / (size / 1000.00f)) + "h0s3b4099T"); break; case 12: // F12 = Courier Bold Oblique gen.writeCommand("(0N"); - gen.writeCommand("(s0p" + gen.formatDouble2(120.01f / (size / 1000.00f)) + gen.writeCommand("(s0p" + gen.formatDouble2(120.01f / (size / 1000.00f)) + "h1s3b4099T"); break; case 13: // F13 = Symbol @@ -400,52 +400,52 @@ public class PCLRenderer extends PrintRenderer { */ public void renderPage(PageViewport page) throws IOException, FOPException { saveGraphicsState(); - + //Paper source String paperSource = page.getForeignAttributeValue( new QName(PCLElementMapping.NAMESPACE, null, "paper-source")); if (paperSource != null) { gen.selectPaperSource(Integer.parseInt(paperSource)); } - + //Page size final long pagewidth = Math.round(page.getViewArea().getWidth()); final long pageheight = Math.round(page.getViewArea().getHeight()); selectPageFormat(pagewidth, pageheight); - + super.renderPage(page); - + //Eject page gen.formFeed(); restoreGraphicsState(); } private void selectPageFormat(long pagewidth, long pageheight) throws IOException { - //Only set the page format if it changes (otherwise duplex printing won't work) + //Only set the page format if it changes (otherwise duplex printing won't work) if ((pagewidth != this.pageWidth) || (pageheight != this.pageHeight)) { this.pageWidth = pagewidth; this.pageHeight = pageheight; - + this.currentPageDefinition = PCLPageDefinition.getPageDefinition( pagewidth, pageheight, 1000); - + if (this.currentPageDefinition == null) { this.currentPageDefinition = PCLPageDefinition.getDefaultPageDefinition(); - log.warn("Paper type could not be determined. Falling back to: " + log.warn("Paper type could not be determined. Falling back to: " + this.currentPageDefinition.getName()); } if (log.isDebugEnabled()) { log.debug("page size: " + currentPageDefinition.getPhysicalPageSize()); log.debug("logical page: " + currentPageDefinition.getLogicalPageRect()); } - + if (this.currentPageDefinition.isLandscapeFormat()) { gen.writeCommand("&l1O"); //Landscape Orientation } else { gen.writeCommand("&l0O"); //Portrait Orientation } gen.selectPageSize(this.currentPageDefinition.getSelector()); - + gen.clearHorizontalMargins(); gen.setTopMargin(0); } @@ -461,7 +461,7 @@ public class PCLRenderer extends PrintRenderer { protected void restoreGraphicsState() { graphicContext = (GraphicContext)graphicContextStack.pop(); } - + /** * Clip an area. write a clipping operation given coordinates in the current * transform. Coordinates are in points. @@ -478,7 +478,7 @@ public class PCLRenderer extends PrintRenderer { private Point2D transformedPoint(float x, float y) { return transformedPoint(Math.round(x), Math.round(y)); } - + private Point2D transformedPoint(int x, int y) { AffineTransform at = graphicContext.getTransform(); if (log.isTraceEnabled()) { @@ -488,7 +488,7 @@ public class PCLRenderer extends PrintRenderer { Point2D.Float transPoint = new Point2D.Float(); at.transform(orgPoint, transPoint); //At this point we have the absolute position in FOP's coordinate system - + //Now get PCL coordinates taking the current print direction and the logical page //into account. Dimension pageSize = currentPageDefinition.getPhysicalPageSize(); @@ -527,18 +527,18 @@ public class PCLRenderer extends PrintRenderer { } return transPoint; } - + private void changePrintDirection() { AffineTransform at = graphicContext.getTransform(); int newDir; try { - if (at.getScaleX() == 0 && at.getScaleY() == 0 + if (at.getScaleX() == 0 && at.getScaleY() == 0 && at.getShearX() == 1 && at.getShearY() == -1) { newDir = 90; - } else if (at.getScaleX() == -1 && at.getScaleY() == -1 + } else if (at.getScaleX() == -1 && at.getScaleY() == -1 && at.getShearX() == 0 && at.getShearY() == 0) { newDir = 180; - } else if (at.getScaleX() == 0 && at.getScaleY() == 0 + } else if (at.getScaleX() == 0 && at.getScaleY() == 0 && at.getShearX() == -1 && at.getShearY() == 1) { newDir = 270; } else { @@ -588,7 +588,7 @@ public class PCLRenderer extends PrintRenderer { protected void handleBlockTraits(Block block) { int borderPaddingStart = block.getBorderAndPaddingWidthStart(); int borderPaddingBefore = block.getBorderAndPaddingWidthBefore(); - + float startx = currentIPPosition / 1000f; float starty = currentBPPosition / 1000f; float width = block.getIPD() / 1000f; @@ -628,7 +628,7 @@ public class PCLRenderer extends PrintRenderer { */ protected void renderText(final TextArea text) { renderInlineAreaBackAndBorders(text); - + String fontname = getInternalFontNameForArea(text); final int fontsize = text.getTraitAsInteger(Trait.FONT_SIZE); @@ -640,9 +640,9 @@ public class PCLRenderer extends PrintRenderer { try { final Color col = (Color)text.getTrait(Trait.COLOR); - boolean pclFont = allTextAsBitmaps + boolean pclFont = allTextAsBitmaps ? false - : setFont(fontname, fontsize, text.getText()); + : setFont(fontname, fontsize, text.getText()); if (pclFont) { //this.currentFill = col; if (col != null) { @@ -650,7 +650,7 @@ public class PCLRenderer extends PrintRenderer { gen.setTransparencyMode(true, false); gen.selectGrayscale(col); } - + saveGraphicsState(); graphicContext.translate(rx, bl); setCursorPos(0, 0); @@ -667,25 +667,25 @@ public class PCLRenderer extends PrintRenderer { //Use Java2D to paint different fonts via bitmap final Font font = getFontFromArea(text); final int baseline = text.getBaselineOffset(); - + //for cursive fonts, so the text isn't clipped int extraWidth = font.getFontSize() / 3; final FontMetricsMapper mapper = (FontMetricsMapper)fontInfo.getMetricsFor( font.getFontName()); int maxAscent = mapper.getMaxAscent(font.getFontSize()) / 1000; final int additionalBPD = maxAscent - baseline; - + Graphics2DAdapter g2a = getGraphics2DAdapter(); final Rectangle paintRect = new Rectangle( rx, currentBPPosition + text.getOffset() - additionalBPD, text.getIPD() + extraWidth, text.getBPD() + additionalBPD); - RendererContext rc = createRendererContext(paintRect.x, paintRect.y, + RendererContext rc = createRendererContext(paintRect.x, paintRect.y, paintRect.width, paintRect.height, null); Map atts = new java.util.HashMap(); atts.put(CONV_MODE, "bitmap"); atts.put(SRC_TRANSPARENCY, "true"); rc.setProperty(RendererContextConstants.FOREIGN_ATTRIBUTES, atts); - + Graphics2DImagePainter painter = new Graphics2DImagePainter() { public void paint(Graphics2D g2d, Rectangle2D area) { @@ -696,17 +696,17 @@ public class PCLRenderer extends PrintRenderer { Java2DRenderer.renderText(text, g2d, font); renderTextDecoration(g2d, mapper, fontsize, text, 0, 0); } - + public Dimension getImageSize() { return paintRect.getSize(); } - + }; - g2a.paintImage(painter, rc, + g2a.paintImage(painter, rc, paintRect.x, paintRect.y, paintRect.width, paintRect.height); currentIPPosition = saveIP + text.getAllocIPD(); } - + } catch (IOException ioe) { handleIOTrouble(ioe); } @@ -721,11 +721,11 @@ public class PCLRenderer extends PrintRenderer { * @param baseline position of the baseline * @param startx start IPD */ - private static void renderTextDecoration(Graphics2D g2d, - FontMetrics fm, int fontsize, InlineArea inline, + private static void renderTextDecoration(Graphics2D g2d, + FontMetrics fm, int fontsize, InlineArea inline, int baseline, int startx) { - boolean hasTextDeco = inline.hasUnderline() - || inline.hasOverline() + boolean hasTextDeco = inline.hasUnderline() + || inline.hasOverline() || inline.hasLineThrough(); if (hasTextDeco) { float descender = fm.getDescender(fontsize) / 1000f; @@ -737,7 +737,7 @@ public class PCLRenderer extends PrintRenderer { g2d.setColor(ct); float y = baseline - descender / 2f; g2d.setStroke(new BasicStroke(lineWidth)); - g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f, + g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f, endx, y / 1000f)); } if (inline.hasOverline()) { @@ -745,7 +745,7 @@ public class PCLRenderer extends PrintRenderer { g2d.setColor(ct); float y = (float)(baseline - (1.1 * capHeight)); g2d.setStroke(new BasicStroke(lineWidth)); - g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f, + g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f, endx, y / 1000f)); } if (inline.hasLineThrough()) { @@ -753,12 +753,12 @@ public class PCLRenderer extends PrintRenderer { g2d.setColor(ct); float y = (float)(baseline - (0.45 * capHeight)); g2d.setStroke(new BasicStroke(lineWidth)); - g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f, + g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f, endx, y / 1000f)); } } } - + /** * Sets the current cursor position. The coordinates are transformed to the absolute position * on the logical PCL page and then passed on to the PCLGenerator. @@ -784,7 +784,7 @@ public class PCLRenderer extends PrintRenderer { } /** - * Closes the current subpath by appending a straight line segment from + * Closes the current subpath by appending a straight line segment from * the current point to the starting point of the subpath. */ protected void closePath() { @@ -792,8 +792,8 @@ public class PCLRenderer extends PrintRenderer { } /** - * Appends a straight line segment from the current point to (x, y). The - * new current point is (x, y). + * Appends a straight line segment from the current point to (x, y). The + * new current point is (x, y). * @param x x coordinate * @param y y coordinate */ @@ -805,7 +805,7 @@ public class PCLRenderer extends PrintRenderer { } /** - * Moves the current point to (x, y), omitting any connecting line segment. + * Moves the current point to (x, y), omitting any connecting line segment. * @param x x coordinate * @param y y coordinate */ @@ -815,7 +815,7 @@ public class PCLRenderer extends PrintRenderer { } currentPath.moveTo(x, y); } - + /** * Fill a rectangular area. * @param x the x coordinate (in pt) @@ -826,13 +826,13 @@ public class PCLRenderer extends PrintRenderer { protected void fillRect(float x, float y, float width, float height) { try { setCursorPos(x * 1000, y * 1000); - gen.fillRect((int)(width * 1000), (int)(height * 1000), + gen.fillRect((int)(width * 1000), (int)(height * 1000), this.currentFillColor); } catch (IOException ioe) { handleIOTrouble(ioe); } } - + /** * Sets the new current fill color. * @param color the color @@ -866,9 +866,9 @@ public class PCLRenderer extends PrintRenderer { String s = space.getSpace(); char sp = s.charAt(0); Font font = getFontFromArea(textArea); - - int tws = (space.isAdjustable() - ? textArea.getTextWordSpaceAdjust() + + int tws = (space.isAdjustable() + ? textArea.getTextWordSpaceAdjust() + 2 * textArea.getTextLetterSpaceAdjust() : 0); @@ -893,10 +893,10 @@ public class PCLRenderer extends PrintRenderer { float y = (currentBPPosition + viewport.getOffset()) / 1000f; float width = viewport.getIPD() / 1000f; float height = viewport.getBPD() / 1000f; - // TODO: Calculate the border rect correctly. + // TODO: Calculate the border rect correctly. float borderPaddingStart = viewport.getBorderAndPaddingWidthStart() / 1000f; float borderPaddingBefore = viewport.getBorderAndPaddingWidthBefore() / 1000f; - float bpwidth = borderPaddingStart + float bpwidth = borderPaddingStart + (viewport.getBorderAndPaddingWidthEnd() / 1000f); float bpheight = borderPaddingBefore + (viewport.getBorderAndPaddingWidthAfter() / 1000f); @@ -931,7 +931,7 @@ public class PCLRenderer extends PrintRenderer { //This is the content-rect float width = (float)bv.getIPD() / 1000f; float height = (float)bv.getBPD() / 1000f; - + if (bv.getPositioning() == Block.ABSOLUTE || bv.getPositioning() == Block.FIXED) { @@ -943,17 +943,17 @@ public class PCLRenderer extends PrintRenderer { if (bv.getPositioning() == Block.FIXED) { breakOutList = breakOutOfStateStack(); } - + AffineTransform positionTransform = new AffineTransform(); positionTransform.translate(bv.getXOffset(), bv.getYOffset()); - + //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); saveGraphicsState(); //Viewport position concatenateTransformationMatrix(mptToPt(positionTransform)); - + //Background and borders float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; @@ -963,7 +963,7 @@ public class PCLRenderer extends PrintRenderer { AffineTransform contentRectTransform = new AffineTransform(); contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); concatenateTransformationMatrix(mptToPt(contentRectTransform)); - + //Clipping if (bv.getClip()) { clipRect(0f, 0f, width, height); @@ -973,7 +973,7 @@ public class PCLRenderer extends PrintRenderer { //Set up coordinate system for content rectangle AffineTransform contentTransform = ctm.toAffineTransform(); concatenateTransformationMatrix(mptToPt(contentTransform)); - + currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); @@ -984,7 +984,7 @@ public class PCLRenderer extends PrintRenderer { if (breakOutList != null) { restoreStateStackAfterBreakOut(breakOutList); } - + currentIPPosition = saveIP; currentBPPosition = saveBP; } else { @@ -999,16 +999,16 @@ public class PCLRenderer extends PrintRenderer { CTM tempctm = new CTM(containingIPPosition, currentBPPosition); ctm = tempctm.multiply(ctm); - + //Now adjust for border/padding currentBPPosition += borderPaddingBefore; Rectangle2D clippingRect = null; if (bv.getClip()) { - clippingRect = new Rectangle(currentIPPosition, currentBPPosition, + clippingRect = new Rectangle(currentIPPosition, currentBPPosition, bv.getIPD(), bv.getBPD()); } - + startVParea(ctm, clippingRect); currentIPPosition = 0; currentBPPosition = 0; @@ -1017,7 +1017,7 @@ public class PCLRenderer extends PrintRenderer { currentIPPosition = saveIP; currentBPPosition = saveBP; - + currentBPPosition += (int)(bv.getAllocBPD()); } //currentFontName = saveFontName; @@ -1034,7 +1034,7 @@ public class PCLRenderer extends PrintRenderer { changePrintDirection(); } } - + private List breakOutOfStateStack() { log.debug("Block.FIXED --> break out"); List breakOutList = new java.util.ArrayList(); @@ -1054,7 +1054,7 @@ public class PCLRenderer extends PrintRenderer { } /** {@inheritDoc} */ - protected RendererContext createRendererContext(int x, int y, int width, int height, + protected RendererContext createRendererContext(int x, int y, int width, int height, Map foreignAttributes) { RendererContext context = super.createRendererContext( x, y, width, height, foreignAttributes); @@ -1070,7 +1070,7 @@ public class PCLRenderer extends PrintRenderer { private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {ImageFlavor.GRAPHICS2D, - ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE, ImageFlavor.XML_DOM}; /** @@ -1089,18 +1089,18 @@ public class PCLRenderer extends PrintRenderer { Point origin = new Point(currentIPPosition, currentBPPosition); int x = origin.x + posInt.x; int y = origin.y + posInt.y; - + ImageManager manager = getUserAgent().getFactory().getImageManager(); ImageInfo info = null; try { ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); - + //Only now fully load/prepare the image Map hints = ImageUtil.getDefaultHints(sessionContext); org.apache.xmlgraphics.image.loader.Image img = manager.getImage( info, FLAVORS, hints, sessionContext); - + //...and process the image if (img instanceof ImageGraphics2D) { ImageGraphics2D imageG2D = (ImageGraphics2D)img; @@ -1113,8 +1113,8 @@ public class PCLRenderer extends PrintRenderer { ImageRendered imgRend = (ImageRendered)img; RenderedImage ri = imgRend.getRenderedImage(); setCursorPos(x, y); - gen.paintBitmap(ri, - new Dimension(posInt.width, posInt.height), + gen.paintBitmap(ri, + new Dimension(posInt.width, posInt.height), false); } else if (img instanceof ImageXMLDOM) { ImageXMLDOM imgXML = (ImageXMLDOM)img; @@ -1160,18 +1160,18 @@ public class PCLRenderer extends PrintRenderer { float height = area.getBPD() / 1000f; float borderPaddingStart = area.getBorderAndPaddingWidthStart() / 1000f; float borderPaddingBefore = area.getBorderAndPaddingWidthBefore() / 1000f; - float bpwidth = borderPaddingStart + float bpwidth = borderPaddingStart + (area.getBorderAndPaddingWidthEnd() / 1000f); float bpheight = borderPaddingBefore + (area.getBorderAndPaddingWidthAfter() / 1000f); - + if (height != 0.0f || bpheight != 0.0f && bpwidth != 0.0f) { drawBackAndBorders(area, x, y - borderPaddingBefore , width + bpwidth , height + bpheight); } } - + /** * Draw the background and borders. This draws the background and border * traits for an area given the position. @@ -1188,18 +1188,18 @@ public class PCLRenderer extends PrintRenderer { BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER); BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START); BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END); - + // draw background Trait.Background back; back = (Trait.Background) area.getTrait(Trait.BACKGROUND); if (back != null) { - + // Calculate padding rectangle float sx = startx; float sy = starty; float paddRectWidth = width; float paddRectHeight = height; - + if (bpsStart != null) { sx += bpsStart.width / 1000f; paddRectWidth -= bpsStart.width / 1000f; @@ -1214,15 +1214,15 @@ public class PCLRenderer extends PrintRenderer { if (bpsAfter != null) { paddRectHeight -= bpsAfter.width / 1000f; } - + if (back.getColor() != null) { updateFillColor(back.getColor()); fillRect(sx, sy, paddRectWidth, paddRectHeight); } - + // background image if (back.getImageInfo() != null) { - ImageSize imageSize = back.getImageInfo().getSize(); + ImageSize imageSize = back.getImageInfo().getSize(); saveGraphicsState(); clipRect(sx, sy, paddRectWidth, paddRectHeight); int horzCount = (int) ((paddRectWidth * 1000 / imageSize.getWidthMpt()) + 1.0f); @@ -1250,7 +1250,7 @@ public class PCLRenderer extends PrintRenderer { Rectangle2D pos; // Image positions are relative to the currentIP/BP pos = new Rectangle2D.Float( - sx - currentIPPosition + sx - currentIPPosition + (x * imageSize.getWidthMpt()), sy - currentBPPosition + (y * imageSize.getHeightMpt()), @@ -1262,7 +1262,7 @@ public class PCLRenderer extends PrintRenderer { restoreGraphicsState(); } } - + Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height); drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd); } @@ -1275,8 +1275,8 @@ public class PCLRenderer extends PrintRenderer { * @param bpsStart the border specification on the start side * @param bpsEnd the border specification on the end side */ - protected void drawBorders(Rectangle2D.Float borderRect, - final BorderProps bpsBefore, final BorderProps bpsAfter, + protected void drawBorders(Rectangle2D.Float borderRect, + final BorderProps bpsBefore, final BorderProps bpsAfter, final BorderProps bpsStart, final BorderProps bpsEnd) { if (bpsBefore == null && bpsAfter == null && bpsStart == null && bpsEnd == null) { return; //no borders to paint @@ -1287,7 +1287,7 @@ public class PCLRenderer extends PrintRenderer { drawFastBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd); } } - + /** * Draws borders. Borders are drawn as shaded rectangles with no clipping. * @param borderRect the border rectangle @@ -1296,8 +1296,8 @@ public class PCLRenderer extends PrintRenderer { * @param bpsStart the border specification on the start side * @param bpsEnd the border specification on the end side */ - protected void drawFastBorders(Rectangle2D.Float borderRect, - final BorderProps bpsBefore, final BorderProps bpsAfter, + protected void drawFastBorders(Rectangle2D.Float borderRect, + final BorderProps bpsBefore, final BorderProps bpsAfter, final BorderProps bpsStart, final BorderProps bpsEnd) { float startx = borderRect.x; float starty = borderRect.y; @@ -1311,7 +1311,7 @@ public class PCLRenderer extends PrintRenderer { if (bpsAfter != null) { float borderWidth = bpsAfter.width / 1000f; updateFillColor(bpsAfter.color); - fillRect(startx, (starty + height - borderWidth), + fillRect(startx, (starty + height - borderWidth), width, borderWidth); } if (bpsStart != null) { @@ -1325,7 +1325,7 @@ public class PCLRenderer extends PrintRenderer { fillRect((startx + width - borderWidth), starty, borderWidth, height); } } - + /** * Draws borders. Borders are drawn in-memory and painted as a bitmap. * @param borderRect the border rectangle @@ -1334,8 +1334,8 @@ public class PCLRenderer extends PrintRenderer { * @param bpsStart the border specification on the start side * @param bpsEnd the border specification on the end side */ - protected void drawQualityBorders(Rectangle2D.Float borderRect, - final BorderProps bpsBefore, final BorderProps bpsAfter, + protected void drawQualityBorders(Rectangle2D.Float borderRect, + final BorderProps bpsBefore, final BorderProps bpsAfter, final BorderProps bpsStart, final BorderProps bpsEnd) { Graphics2DAdapter g2a = getGraphics2DAdapter(); final Rectangle.Float effBorderRect = new Rectangle2D.Float( @@ -1345,7 +1345,7 @@ public class PCLRenderer extends PrintRenderer { borderRect.height); final Rectangle paintRect = new Rectangle( (int)Math.round(borderRect.x * 1000f), - (int)Math.round(borderRect.y * 1000f), + (int)Math.round(borderRect.y * 1000f), (int)Math.floor(borderRect.width * 1000f) + 1, (int)Math.floor(borderRect.height * 1000f) + 1); //Add one pixel wide safety margin around the paint area @@ -1356,14 +1356,14 @@ public class PCLRenderer extends PrintRenderer { paintRect.y += yoffset; paintRect.width += 2 * pixelWidth; paintRect.height += 2 * pixelWidth; - - RendererContext rc = createRendererContext(paintRect.x, paintRect.y, + + RendererContext rc = createRendererContext(paintRect.x, paintRect.y, paintRect.width, paintRect.height, null); Map atts = new java.util.HashMap(); atts.put(CONV_MODE, "bitmap"); atts.put(SRC_TRANSPARENCY, "true"); rc.setProperty(RendererContextConstants.FOREIGN_ATTRIBUTES, atts); - + Graphics2DImagePainter painter = new Graphics2DImagePainter() { public void paint(Graphics2D g2d, Rectangle2D area) { @@ -1374,7 +1374,7 @@ public class PCLRenderer extends PrintRenderer { float width = effBorderRect.width; float height = effBorderRect.height; boolean[] b = new boolean[] { - (bpsBefore != null), (bpsEnd != null), + (bpsBefore != null), (bpsEnd != null), (bpsAfter != null), (bpsStart != null)}; if (!b[0] && !b[1] && !b[2] && !b[3]) { return; @@ -1385,9 +1385,9 @@ public class PCLRenderer extends PrintRenderer { (b[2] ? bpsAfter.width / 1000f : 0.0f), (b[3] ? bpsStart.width / 1000f : 0.0f)}; float[] clipw = new float[] { - BorderProps.getClippedWidth(bpsBefore) / 1000f, - BorderProps.getClippedWidth(bpsEnd) / 1000f, - BorderProps.getClippedWidth(bpsAfter) / 1000f, + BorderProps.getClippedWidth(bpsBefore) / 1000f, + BorderProps.getClippedWidth(bpsEnd) / 1000f, + BorderProps.getClippedWidth(bpsAfter) / 1000f, BorderProps.getClippedWidth(bpsStart) / 1000f}; starty += clipw[0]; height -= clipw[0]; @@ -1395,7 +1395,7 @@ public class PCLRenderer extends PrintRenderer { startx += clipw[3]; width -= clipw[3]; width -= clipw[1]; - + boolean[] slant = new boolean[] { (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])}; if (bpsBefore != null) { @@ -1433,7 +1433,7 @@ public class PCLRenderer extends PrintRenderer { currentPath = null; Rectangle2D.Float lineRect = new Rectangle2D.Float( sx1a, outery, ex1a - sx1a, innery - outery); - Java2DRenderer.drawBorderLine(lineRect, true, true, + Java2DRenderer.drawBorderLine(lineRect, true, true, bpsBefore.style, bpsBefore.color, g); //restoreGraphicsState(); } @@ -1447,7 +1447,7 @@ public class PCLRenderer extends PrintRenderer { float outerx = startx + width + clipw[1]; float clipx = outerx - clipw[1]; float innerx = outerx - bw[1]; - + //saveGraphicsState(); Graphics2D g = (Graphics2D)g2d.create(); moveTo(clipx, sy1); @@ -1472,7 +1472,7 @@ public class PCLRenderer extends PrintRenderer { currentPath = null; Rectangle2D.Float lineRect = new Rectangle2D.Float( innerx, sy1a, outerx - innerx, ey1a - sy1a); - Java2DRenderer.drawBorderLine(lineRect, false, false, + Java2DRenderer.drawBorderLine(lineRect, false, false, bpsEnd.style, bpsEnd.color, g); //restoreGraphicsState(); } @@ -1511,7 +1511,7 @@ public class PCLRenderer extends PrintRenderer { currentPath = null; Rectangle2D.Float lineRect = new Rectangle2D.Float( sx1a, innery, ex1a - sx1a, outery - innery); - Java2DRenderer.drawBorderLine(lineRect, true, false, + Java2DRenderer.drawBorderLine(lineRect, true, false, bpsAfter.style, bpsAfter.color, g); //restoreGraphicsState(); } @@ -1550,7 +1550,7 @@ public class PCLRenderer extends PrintRenderer { currentPath = null; Rectangle2D.Float lineRect = new Rectangle2D.Float( outerx, sy1a, innerx - outerx, ey1a - sy1a); - Java2DRenderer.drawBorderLine(lineRect, false, false, + Java2DRenderer.drawBorderLine(lineRect, false, false, bpsStart.style, bpsStart.color, g); //restoreGraphicsState(); } @@ -1559,10 +1559,10 @@ public class PCLRenderer extends PrintRenderer { public Dimension getImageSize() { return paintRect.getSize(); } - + }; try { - g2a.paintImage(painter, rc, + g2a.paintImage(painter, rc, paintRect.x - xoffset, paintRect.y, paintRect.width, paintRect.height); } catch (IOException ioe) { handleIOTrouble(ioe); @@ -1577,7 +1577,7 @@ public class PCLRenderer extends PrintRenderer { public void setAllTextAsBitmaps(boolean allTextAsBitmaps) { this.allTextAsBitmaps = allTextAsBitmaps; } - - - + + + } diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java index ea4cc50bb..aa0fc88b9 100644 --- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java +++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java @@ -16,7 +16,7 @@ */ /* $Id$ */ - + package org.apache.fop.render.ps; @@ -91,28 +91,28 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { * @exception TranscoderException if an error occured while transcoding */ protected void transcode(Document document, String uri, - TranscoderOutput output) + TranscoderOutput output) throws TranscoderException { graphics = createDocumentGraphics2D(); if (!isTextStroked()) { - FontInfo fontInfo = new FontInfo(); - //TODO Do custom font configuration here somewhere/somehow - FontSetup.setup(fontInfo); + FontInfo fontInfo = new FontInfo(); + //TODO Do custom font configuration here somewhere/somehow + FontSetup.setup(fontInfo); graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); } super.transcode(document, uri, output); getLogger().trace("document size: " + width + " x " + height); - + // prepare the image to be painted - UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, + UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, document.getDocumentElement()); - float widthInPt = UnitProcessor.userSpaceToSVG(width, SVGLength.SVG_LENGTHTYPE_PT, + float widthInPt = UnitProcessor.userSpaceToSVG(width, SVGLength.SVG_LENGTHTYPE_PT, UnitProcessor.HORIZONTAL_LENGTH, uctx); int w = (int)(widthInPt + 0.5); - float heightInPt = UnitProcessor.userSpaceToSVG(height, SVGLength.SVG_LENGTHTYPE_PT, + float heightInPt = UnitProcessor.userSpaceToSVG(height, SVGLength.SVG_LENGTHTYPE_PT, UnitProcessor.HORIZONTAL_LENGTH, uctx); int h = (int)(heightInPt + 0.5); getLogger().trace("document size: " + w + "pt x " + h + "pt"); @@ -140,7 +140,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { throw new TranscoderException(ex); } } - + /** {@inheritDoc} */ protected BridgeContext createBridgeContext() { @@ -148,7 +148,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { if (!isTextStroked()) { TextHandler handler = graphics.getCustomTextHandler(); if (handler instanceof NativeTextHandler) { - NativeTextHandler nativeTextHandler = (NativeTextHandler)handler; + NativeTextHandler nativeTextHandler = (NativeTextHandler)handler; PSTextPainter textPainter = new PSTextPainter(nativeTextHandler); ctx.setTextPainter(textPainter); ctx.putBridge(new PSTextElementBridge(textPainter)); diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java index 174fe8077..9f62097e9 100644 --- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java +++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java @@ -38,16 +38,16 @@ import org.apache.xmlgraphics.ps.PSGenerator; public class NativeTextHandler implements PSTextHandler { private PSGraphics2D g2d; - + /** FontInfo containing all available fonts */ protected FontInfo fontInfo; /** Currently valid Font */ protected Font font; - + /** Overriding FontState */ protected Font overrideFont = null; - + /** the current (internal) font name */ protected String currentFontName; @@ -67,13 +67,13 @@ public class NativeTextHandler implements PSTextHandler { setupFontInfo(); } } - + private void setupFontInfo() { //Sets up a FontInfo with default fonts fontInfo = new FontInfo(); FontSetup.setup(fontInfo); } - + /** * Return the font information associated with this object * @return the FontInfo object @@ -85,7 +85,7 @@ public class NativeTextHandler implements PSTextHandler { private PSGenerator getPSGenerator() { return this.g2d.getPSGenerator(); } - + /** {@inheritDoc} */ public void writeSetup() throws IOException { if (fontInfo != null) { @@ -99,9 +99,9 @@ public class NativeTextHandler implements PSTextHandler { } /** - * Draw a string to the PostScript document. The text is painted using + * Draw a string to the PostScript document. The text is painted using * text operations. - * {@inheritDoc} + * {@inheritDoc} */ public void drawString(String s, float x, float y) throws IOException { g2d.preparePainting(); @@ -112,7 +112,7 @@ public class NativeTextHandler implements PSTextHandler { this.font = this.overrideFont; this.overrideFont = null; } - + //Color and Font state g2d.establishColor(g2d.getColor()); establishCurrentFont(); @@ -130,14 +130,14 @@ public class NativeTextHandler implements PSTextHandler { gen.writeln(gen.formatDouble(x) + " " + gen.formatDouble(y) + " moveto "); gen.writeln("1 -1 scale"); - + StringBuffer sb = new StringBuffer("("); escapeText(s, sb); sb.append(") t "); gen.writeln(sb.toString()); - - gen.restoreGraphicsState(); + + gen.restoreGraphicsState(); } private void escapeText(final String text, StringBuffer target) { @@ -157,7 +157,7 @@ public class NativeTextHandler implements PSTextHandler { int fontSize = 1000 * f.getSize(); String style = f.isItalic() ? "italic" : "normal"; int weight = f.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL; - + FontTriplet triplet = fontInfo.findAdjustWeight(fontFamily, style, weight); if (triplet == null) { triplet = fontInfo.findAdjustWeight("sans-serif", style, weight); @@ -166,10 +166,10 @@ public class NativeTextHandler implements PSTextHandler { } private void establishCurrentFont() throws IOException { - if ((currentFontName != this.font.getFontName()) + if ((currentFontName != this.font.getFontName()) || (currentFontSize != this.font.getFontSize())) { PSGenerator gen = getPSGenerator(); - gen.writeln(this.font.getFontName() + " " + gen.writeln(this.font.getFontName() + " " + gen.formatDouble(font.getFontSize() / 1000f) + " F"); currentFontName = this.font.getFontName(); currentFontSize = this.font.getFontSize(); @@ -183,6 +183,6 @@ public class NativeTextHandler implements PSTextHandler { public void setOverrideFont(Font override) { this.overrideFont = override; } - + } diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java index 513ba4587..5bdfe8c8d 100644 --- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java @@ -56,7 +56,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { private int width; private int height; - + //for SVG scaling private float svgWidth; private float svgHeight; @@ -65,7 +65,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { public static final int NORMAL_PDF_RESOLUTION = 72; /** Default device resolution (300dpi is a resonable quality for most purposes) */ public static final int DEFAULT_NATIVE_DPI = 300; - + /** * The device resolution may be different from the normal target resolution. See * http://issues.apache.org/bugzilla/show_bug.cgi?id=37305 @@ -96,7 +96,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { public PDFDocumentGraphics2D(boolean textAsShapes) { super(textAsShapes); - this.pdfDoc = new PDFDocument("Apache FOP Version " + Version.getVersion() + this.pdfDoc = new PDFDocument("Apache FOP Version " + Version.getVersion() + ": PDFDocumentGraphics2D"); this.pdfContext = new PDFContext(); } @@ -150,7 +150,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { } /** - * Setup a default FontInfo instance if none has been setup before. + * Setup a default FontInfo instance if none has been setup before. */ public void setupDefaultFontInfo() { if (fontInfo == null) { @@ -160,7 +160,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { setFontInfo(fontInfo); } } - + /** * Set the device resolution for rendering. Will take effect at the * start of the next page. @@ -184,7 +184,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { public void setFontInfo(FontInfo fontInfo) { this.fontInfo = fontInfo; } - + /** * Get the font info for this pdf document. * @return the font information @@ -208,7 +208,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { public PDFContext getPDFContext() { return this.pdfContext; } - + /** * Set the dimensions of the svg document that will be drawn. * This is useful if the dimensions of the svg document are different @@ -248,9 +248,9 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { public void nextPage() { closePage(); } - + /** - * Closes the current page and adds it to the PDF file. + * Closes the current page and adds it to the PDF file. */ protected void closePage() { if (!pdfContext.isPagePending()) { @@ -270,7 +270,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { this.pdfDoc.addObject(pdfContext.getCurrentPage()); pdfContext.clearCurrentPage(); } - + /** {@inheritDoc} */ protected void preparePainting() { if (pdfContext.isPagePending()) { @@ -300,7 +300,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { if (this.initialTransform == null) { //Save initial transformation matrix this.initialTransform = getTransform(); - this.initialClip = getClip(); + this.initialClip = getClip(); } else { //Reset transformation matrix setTransform(this.initialTransform); @@ -313,7 +313,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { if (currentStream == null) { currentStream = new StringWriter(); } - + PDFResources pdfResources = this.pdfDoc.getResources(); PDFPage page = this.pdfDoc.getFactory().makePage(pdfResources, width, height); @@ -321,7 +321,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { pdfContext.setCurrentPage(page); pageRef = page.referencePDF(); - AffineTransform at = new AffineTransform(1.0, 0.0, 0.0, -1.0, + AffineTransform at = new AffineTransform(1.0, 0.0, 0.0, -1.0, 0.0, (double)height); currentStream.write("1 0 0 -1 0 " + height + " cm\n"); if (svgWidth != 0) { @@ -336,7 +336,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { at.scale(s, s); currentStream.write("" + PDFNumber.doubleOut(s) + " 0 0 " + PDFNumber.doubleOut(s) + " 0 0 cm\n"); - + scale(1 / s, 1 / s); } // Remember the transform we installed. @@ -344,8 +344,8 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { pdfContext.increasePageCount(); } - - + + /** * The rendering process has finished. * This should be called after the rendering has completed as there is diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java index 789a7c247..cda1478bb 100644 --- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java +++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java @@ -44,23 +44,23 @@ public class PDFDocumentGraphics2DConfigurator { * @param cfg the configuration * @throws ConfigurationException if an error occurs while configuring the object */ - public void configure(PDFDocumentGraphics2D graphics, Configuration cfg) + public void configure(PDFDocumentGraphics2D graphics, Configuration cfg) throws ConfigurationException { PDFDocument pdfDoc = graphics.getPDFDocument(); - + //Filter map pdfDoc.setFilterMap( PDFRendererConfigurator.buildFilterMapFromConfiguration(cfg)); - + //Fonts try { FontResolver fontResolver = FontManager.createMinimalFontResolver(); //TODO The following could be optimized by retaining the FontManager somewhere FontManager fontManager = new FontManager(); - + //TODO Make use of fontBaseURL, font substitution and referencing configuration //Requires a change to the expected configuration layout - + List/**/ embedFontInfoList = PrintRendererConfigurator.buildFontListFromConfiguration( cfg, fontResolver, false, fontManager); @@ -74,5 +74,5 @@ public class PDFDocumentGraphics2DConfigurator { throw new ConfigurationException("Error while setting up fonts", e); } } - + } diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 5a147f3be..4d1ee6a6d 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -106,13 +106,13 @@ import org.apache.fop.util.ColorExt; public class PDFGraphics2D extends AbstractGraphics2D { private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform(); - - /** The number of decimal places. */ + + /** The number of decimal places. */ private static final int DEC = 8; /** Convenience constant for full opacity */ static final int OPAQUE = 255; - + /** * the PDF Document being created */ @@ -308,7 +308,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { public String getPageReference() { return this.pageRef; } - + /** * Set the Graphics context. * @param c the graphics context to use @@ -319,10 +319,10 @@ public class PDFGraphics2D extends AbstractGraphics2D { } private void setPrivateHints() { - setRenderingHint(RenderingHintsKeyExt.KEY_AVOID_TILE_PAINTING, + setRenderingHint(RenderingHintsKeyExt.KEY_AVOID_TILE_PAINTING, RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_ON); } - + /** * Set the override font state for drawing text. * This is used by the PDF text painter so that it can temporarily @@ -362,7 +362,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { concatMatrix(matrix); } } - + /** * This is mainly used for shading patterns which use the document-global coordinate system * instead of the local one. @@ -372,7 +372,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { AffineTransform at = new AffineTransform(graphicsState.getTransform()); return at; } - + /** * This is a pdf specific method used to add a link to the * pdf document. @@ -417,7 +417,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { * @param width the width to draw the image * @param height the height to draw the image */ - void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y, + void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y, float width, float height) { preparePainting(); String key = image.getInfo().getOriginalURI(); @@ -425,10 +425,10 @@ public class PDFGraphics2D extends AbstractGraphics2D { // Need to include hash code as when invoked from FO you // may have several 'independent' PDFGraphics2D so the // count is not enough. - key = "__AddNative_" + hashCode() + "_" + nativeCount; + key = "__AddNative_" + hashCode() + "_" + nativeCount; nativeCount++; } - + PDFImage pdfImage; if (image instanceof ImageRawJPEG) { pdfImage = new ImageRawJPEGAdapter((ImageRawJPEG)image, key); @@ -438,7 +438,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { throw new IllegalArgumentException( "Unsupported Image subclass: " + image.getClass().getName()); } - + PDFXObject xObject = this.pdfDoc.addImage(resourceContext, pdfImage); if (outputStream != null) { try { @@ -649,7 +649,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { graphicsState.pop(); } } - + /* // in theory we could set the clip using these methods // it doesn't seem to improve the file sizes much @@ -784,8 +784,8 @@ public class PDFGraphics2D extends AbstractGraphics2D { (float) gpaint.getPoint1().getX(), (float) gpaint.getPoint1().getY(), (float) gpaint.getPoint2().getX(), - (float) gpaint.getPoint2().getY(), - new float[] {0, 1}, + (float) gpaint.getPoint2().getY(), + new float[] {0, 1}, new Color[] {gpaint.getColor1(), gpaint.getColor2()}, gpaint.isCyclic() ? LinearGradientPaint.REPEAT : LinearGradientPaint.NO_CYCLE); } @@ -927,7 +927,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { return false; // PDF can't do alpha } - someColors.add(new PDFColor(cc.getRed(), cc.getGreen(), + someColors.add(new PDFColor(cc.getRed(), cc.getGreen(), cc.getBlue())); } @@ -947,7 +947,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { currentStream.write(myPat.getColorSpaceOut(fill)); return true; - } + } if (paint instanceof PatternPaint) { PatternPaint pp = (PatternPaint)paint; return createPattern(pp, fill); @@ -990,14 +990,14 @@ public class PDFGraphics2D extends AbstractGraphics2D { // double patMaxX = rect.getX() + rect.getWidth(); // double patMaxY = rect.getY() + rect.getHeight(); // double stepX = rect.getWidth(); - // double stepY = rect.getHeight(); - // + // double stepY = rect.getHeight(); + // // int startX = (int)((rect.getX() - gnMaxX)/stepX); // int startY = (int)((rect.getY() - gnMaxY)/stepY); - // + // // int endX = (int)((patMaxX - gnMinX)/stepX); // int endY = (int)((patMaxY - gnMinY)/stepY); - // + // // pattGraphic.translate(startX*stepX, startY*stepY); // for (int yIdx=startY; yIdx<=endY; yIdx++) { // for (int xIdx=startX; xIdx<=endX; xIdx++) { @@ -1027,14 +1027,14 @@ public class PDFGraphics2D extends AbstractGraphics2D { } /** @todo see if pdfDoc and res can be linked here, - (currently res <> PDFDocument's resources) so addFonts() + (currently res <> PDFDocument's resources) so addFonts() can be moved to PDFDocument class */ res.addFonts(pdfDoc, specialFontInfo); PDFPattern myPat = pdfDoc.getFactory().makePattern( resourceContext, 1, res, 1, 1, bbox, rect.getWidth(), rect.getHeight(), - theMatrix, null, + theMatrix, null, pattGraphic.getBuffer()); currentStream.write(myPat.getColorSpaceOut(fill)); @@ -1094,7 +1094,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { (rgbCS, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, false, DataBuffer.TYPE_BYTE); - PaintContext pctx = paint.createContext(rgbCM, devBounds, usrBounds, + PaintContext pctx = paint.createContext(rgbCM, devBounds, usrBounds, at, getRenderingHints()); PDFXObject imageInfo = pdfDoc.getXObject ("TempImage:" + pctx.toString()); @@ -1112,7 +1112,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { final int[] line = new int[devW]; final byte[] mask; int x, y, val, rgbIdx = 0; - + if (pcm.hasAlpha()) { mask = new byte[devW * devH]; int maskIdx = 0; @@ -1611,7 +1611,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { return; } } - + AffineTransform trans = getTransform(); double[] tranvals = new double[6]; trans.getMatrix(tranvals); @@ -1709,7 +1709,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { iter.next(); } } - + /** * Do the PDF drawing command. * This does the PDF drawing command according to fill diff --git a/test/java/org/apache/fop/config/BaseUserConfigTestCase.java b/test/java/org/apache/fop/config/BaseUserConfigTestCase.java index d216d583a..ff14e5f0b 100644 --- a/test/java/org/apache/fop/config/BaseUserConfigTestCase.java +++ b/test/java/org/apache/fop/config/BaseUserConfigTestCase.java @@ -33,7 +33,7 @@ import org.apache.fop.render.pdf.BasePDFTestCase; import org.xml.sax.SAXException; /** - * Basic runtime test for FOP's font configuration. It is used to verify that + * Basic runtime test for FOP's font configuration. It is used to verify that * nothing obvious is broken after compiling. */ public abstract class BaseUserConfigTestCase extends BasePDFTestCase { @@ -59,7 +59,7 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase { } protected void initConfig() throws Exception { - fopFactory.setUserConfig(getUserConfig()); + fopFactory.setUserConfig(getUserConfig()); } protected void convertFO() throws Exception { @@ -70,7 +70,7 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase { FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); convertFO(foFile, foUserAgent, dumpOutput); } - + /** * get test FOP config File * @return fo test filepath @@ -82,9 +82,9 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase { /** * get test FOP Configuration * @return fo test filepath - * @throws IOException - * @throws SAXException - * @throws ConfigurationException + * @throws IOException + * @throws SAXException + * @throws ConfigurationException */ protected Configuration getUserConfig(String configString) throws ConfigurationException, SAXException, IOException { return cfgBuilder.build(new ByteArrayInputStream(configString.getBytes())); @@ -114,11 +114,11 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase { /** * get test FOP Configuration * @return fo test filepath - * @throws IOException - * @throws SAXException - * @throws ConfigurationException + * @throws IOException + * @throws SAXException + * @throws ConfigurationException */ protected Configuration getUserConfig() throws ConfigurationException, SAXException, IOException { return cfgBuilder.buildFromFile(getUserConfigFile()); - } + } } diff --git a/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java b/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java index 5202e837a..f915a2060 100644 --- a/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java +++ b/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.config; diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java index b37abdf0d..013a622a4 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java @@ -68,26 +68,26 @@ import org.apache.fop.util.ConsoleEventListenerForTests; public class LayoutEngineTester { private static final Map CHECK_CLASSES = new java.util.HashMap(); - + // configure fopFactory as desired private FopFactory fopFactory = FopFactory.newInstance(); private FopFactory fopFactoryWithBase14Kerning = FopFactory.newInstance(); - - private SAXTransformerFactory tfactory + + private SAXTransformerFactory tfactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); private Templates testcase2fo; private Templates testcase2checks; - + private File areaTreeBackupDir; - + static { CHECK_CLASSES.put("true", TrueCheck.class); CHECK_CLASSES.put("eval", EvalCheck.class); CHECK_CLASSES.put("element-list", ElementListCheck.class); CHECK_CLASSES.put("result", ResultCheck.class); } - + /** * Constructs a new instance. * @param areaTreeBackupDir Optional directory that receives the generated @@ -98,7 +98,7 @@ public class LayoutEngineTester { fopFactory.getFontManager().setBase14KerningEnabled(false); fopFactoryWithBase14Kerning.getFontManager().setBase14KerningEnabled(true); } - + private Templates getTestcase2FOStylesheet() throws TransformerConfigurationException { if (testcase2fo == null) { //Load and cache stylesheet @@ -107,7 +107,7 @@ public class LayoutEngineTester { } return testcase2fo; } - + private Templates getTestcase2ChecksStylesheet() throws TransformerConfigurationException { if (testcase2checks == null) { //Load and cache stylesheet @@ -116,7 +116,7 @@ public class LayoutEngineTester { } return testcase2checks; } - + /** * Runs a single layout engine test case. * @param testFile Test case to run @@ -125,14 +125,14 @@ public class LayoutEngineTester { * @throws SAXException In case of a problem during SAX processing * @throws ParserConfigurationException In case of a problem with the XML parser setup */ - public void runTest(File testFile) + public void runTest(File testFile) throws TransformerException, SAXException, IOException, ParserConfigurationException { - + DOMResult domres = new DOMResult(); ElementListCollector elCollector = new ElementListCollector(); ElementListObserver.addObserver(elCollector); - + Fop fop; try { @@ -141,47 +141,47 @@ public class LayoutEngineTester { dbf.setValidating(false); DocumentBuilder builder = dbf.newDocumentBuilder(); Document testDoc = builder.parse(testFile); - + XObject xo = XPathAPI.eval(testDoc, "/testcase/cfg/base14kerning"); String s = xo.str(); boolean base14kerning = ("true".equalsIgnoreCase(s)); FopFactory effFactory = (base14kerning ? fopFactoryWithBase14Kerning : fopFactory); - + //Setup Transformer to convert the testcase XML to XSL-FO Transformer transformer = getTestcase2FOStylesheet().newTransformer(); Source src = new DOMSource(testDoc); - + //Setup Transformer to convert the area tree to a DOM TransformerHandler athandler = tfactory.newTransformerHandler(); athandler.setResult(domres); - + //Setup FOP for area tree rendering FOUserAgent ua = effFactory.newFOUserAgent(); ua.setBaseURL(testFile.getParentFile().toURL().toString()); ua.getEventBroadcaster().addEventListener( new ConsoleEventListenerForTests(testFile.getName())); - + XMLRenderer atrenderer = new XMLRenderer(); atrenderer.setUserAgent(ua); atrenderer.setContentHandler(athandler); ua.setRendererOverride(atrenderer); fop = effFactory.newFop(ua); - + SAXResult fores = new SAXResult(fop.getDefaultHandler()); transformer.transform(src, fores); } finally { ElementListObserver.removeObserver(elCollector); } - + Document doc = (Document)domres.getNode(); if (this.areaTreeBackupDir != null) { saveAreaTreeXML(doc, new File(this.areaTreeBackupDir, testFile.getName() + ".at.xml")); } - FormattingResults results = fop.getResults(); + FormattingResults results = fop.getResults(); LayoutResult result = new LayoutResult(doc, elCollector, results); checkAll(testFile, result); } - + /** * Factory method to create checks from DOM elements. * @param el DOM element to create the check from @@ -196,14 +196,14 @@ public class LayoutEngineTester { LayoutEngineCheck instance = (LayoutEngineCheck)c.newInstance(new Object[] {el}); return instance; } catch (Exception e) { - throw new RuntimeException("Error while instantiating check '" + throw new RuntimeException("Error while instantiating check '" + name + "': " + e.getMessage()); } } else { throw new IllegalArgumentException("No check class found: " + name); } } - + /** * Perform all checks on the area tree. * @param testFile Test case XML file @@ -215,7 +215,7 @@ public class LayoutEngineTester { Source src = new StreamSource(testFile); DOMResult res = new DOMResult(); transformer.transform(src, res); - + List checks = new java.util.ArrayList(); Document doc = (Document)res.getNode(); NodeList nodes = doc.getDocumentElement().getChildNodes(); @@ -225,7 +225,7 @@ public class LayoutEngineTester { checks.add(createCheck((Element)node)); } } - + if (checks.size() == 0) { throw new RuntimeException("No checks are available!"); } @@ -235,7 +235,7 @@ public class LayoutEngineTester { check.check(result); } } - + /** * Save the area tree XML for later inspection. * @param doc area tree as a DOM document diff --git a/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java b/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java index 7c66a0ceb..29a77a932 100644 --- a/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java +++ b/test/java/org/apache/fop/render/pdf/BasePDFTestCase.java @@ -112,10 +112,10 @@ public class BasePDFTestCase extends AbstractFOPTestCase { } return e; } - + /** - * get FOP config File - * @return user config file to be used for testing + * get FOP config File + * @return user config file to be used for testing */ protected File getUserConfigFile() { return new File("test/test.xconf"); diff --git a/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java b/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java index 96167ceb0..2fc62c6d1 100644 --- a/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java +++ b/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java @@ -31,7 +31,7 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { private File foBaseDir = new File("test/xml/pdf-a"); private boolean dumpPDF = Boolean.getBoolean("PDFAConformanceTestCase.dumpPDF"); - + /** * Main constructor * @param name the name of the test case @@ -40,7 +40,7 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { super(name); } - /** create an FOUserAgent for our tests + /** create an FOUserAgent for our tests * @return an initialized FOUserAgent * */ protected FOUserAgent getUserAgent() { @@ -48,7 +48,7 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { userAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-1b"); return userAgent; } - + /** * Test exception when PDF/A-1 is enabled and everything is as it should. * @throws Exception if the test fails @@ -57,7 +57,7 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { File foFile = new File(foBaseDir, "minimal-pdf-a.fo"); convertFO(foFile, getUserAgent(), dumpPDF); } - + /** * Test exception when PDF/A-1 is enabled together with encryption. * @throws Exception if the test fails @@ -73,7 +73,7 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { //Good! } } - + /** * Test exception when PDF/A-1 is enabled and a font is used which is not embedded. * @throws Exception if the test fails @@ -87,7 +87,7 @@ public class PDFAConformanceTestCase extends BasePDFTestCase { //Good! } } - + /** * Test exception when PDF/A-1 is enabled and images. * @throws Exception if the test fails -- cgit v1.2.3 From 7095bf0694db872628b4d039b7e5566407a769be Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 9 May 2008 15:14:37 +0000 Subject: Unwanted list self concatenation :). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654849 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/PrintRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index c37012cb4..35630d628 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -54,7 +54,7 @@ public abstract class PrintRenderer extends AbstractRenderer { if (embedFontInfoList == null) { setFontList(fontList); } else { - fontList.addAll(fontList); + embedFontInfoList.addAll(fontList); } } -- cgit v1.2.3 From 6f9ca1ab175781c0e6dafc0d65de4c715f7f94ff Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 9 May 2008 16:13:47 +0000 Subject: Moved the instantiation of the FontManager to the constructor along with all the other aggregated objects. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654869 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/apps/FopFactory.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index ae4d25949..2d4029da8 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -144,6 +144,14 @@ public class FopFactory implements ImageContext { this.config = new FopFactoryConfigurator(this); this.elementMappingRegistry = new ElementMappingRegistry(this); this.foURIResolver = new FOURIResolver(validateUserConfigStrictly()); + this.fontManager = new FontManager() { + + /** {@inheritDoc} */ + public void setFontBaseURL(String fontBase) throws MalformedURLException { + super.setFontBaseURL(getFOURIResolver().checkBaseURL(fontBase)); + } + + }; this.colorSpaceCache = new ColorSpaceCache(foURIResolver); this.imageManager = new ImageManager(this); this.rendererFactory = new RendererFactory(); @@ -696,16 +704,6 @@ public class FopFactory implements ImageContext { * @return the font manager */ public FontManager getFontManager() { - if (fontManager == null) { - this.fontManager = new FontManager() { - - /** {@inheritDoc} */ - public void setFontBaseURL(String fontBase) throws MalformedURLException { - super.setFontBaseURL(getFOURIResolver().checkBaseURL(fontBase)); - } - - }; - } return this.fontManager; } -- cgit v1.2.3 From ba10485d4aa530fc27ba294a455a7be67559e9be Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Fri, 9 May 2008 21:40:14 +0000 Subject: Bugzilla 44794: Added support for page-number-citation and page-number-citation-last of fo:inline. Corrected behavior for page-number-citation-last of fo:block - forward references properly resolved. (+ support for page-number-citation-last on list-related FOs) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@654946 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/AbstractLayoutManager.java | 22 +++- .../apache/fop/layoutmgr/BlockLayoutManager.java | 4 +- .../fop/layoutmgr/inline/InlineLayoutManager.java | 1 + .../fop/layoutmgr/list/ListBlockLayoutManager.java | 2 +- .../list/ListItemContentLayoutManager.java | 2 +- .../fop/layoutmgr/list/ListItemLayoutManager.java | 2 +- status.xml | 5 + test/layoutengine/disabled-testcases.xml | 5 - .../page-number-citation_bugzilla44794.xml | 70 ++++++++++++ .../page-number-citation_list.xml | 126 +++++++++++++++++++++ 10 files changed, 226 insertions(+), 13 deletions(-) create mode 100644 test/layoutengine/standard-testcases/page-number-citation_bugzilla44794.xml create mode 100644 test/layoutengine/standard-testcases/page-number-citation_list.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 1a7b6b710..ef32bbc75 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -56,7 +56,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager private Map markers = null; /** True if this LayoutManager has handled all of its content. */ - private boolean bFinished = false; + private boolean isFinished = false; /** child LM during getNextKnuthElement phase */ protected LayoutManager curChildLM = null; @@ -136,7 +136,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager * ie. the last one returned represents the end of the content. */ public boolean isFinished() { - return bFinished; + return isFinished; } /** @@ -144,7 +144,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager * @param fin the flag value to be set */ public void setFinished(boolean fin) { - bFinished = fin; + isFinished = fin; } /** @@ -302,6 +302,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager if (pos.getIndex() >= 0) { throw new IllegalStateException("Position already got its index"); } + lastGeneratedPosition++; pos.setIndex(lastGeneratedPosition); return pos; @@ -386,6 +387,21 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } } + /** + * Checks to see if the incoming {@link Position} + * is the last one for this LM, and if so, calls + * {@link #notifyEndOfLayout()} + * + * @param pos the {@link Position} to check + */ + protected void checkEndOfLayout(Position pos) { + if (pos != null + && pos.getLM() == this + && this.isLast(pos)) { + notifyEndOfLayout(); + } + } + /** {@inheritDoc} */ public String toString() { return (super.toString() + (fobj != null ? "[fobj=" + fobj.toString() + "]" : "")); diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index d129be666..c5c7d9445 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -392,8 +392,8 @@ public class BlockLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - // Notify end of block layout manager to the PSLM - notifyEndOfLayout(); + //Notify end of block layout manager to the PSLM + checkEndOfLayout(lastPos); } /** diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index b59f0466a..7c2e4748a 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -518,6 +518,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { context.setFlags(LayoutContext.LAST_AREA, isLast); areaCreated = true; + checkEndOfLayout(lastPos); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index 7be146d0d..dfffbdd04 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -219,7 +219,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - notifyEndOfLayout(); + checkEndOfLayout(lastPos); } /** diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index edee772d6..549244267 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -172,7 +172,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { curBlockArea = null; - notifyEndOfLayout(); + checkEndOfLayout(lastPos); } /** diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index d0e8665e7..6a3a38db1 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -557,7 +557,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - notifyEndOfLayout(); + checkEndOfLayout(lastPos); } /** diff --git a/status.xml b/status.xml index e1432b856..3bfcaf827 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,11 @@ Added SVG support for AFP (GOCA). + + Added support for page-number-citation and page-number-citation-last + of fo:inline. Corrected behavior for page-number-citation-last + of fo:block: forward references now properly resolved. + For auto-detected fonts it is now possible to specify that a font needs to be referenced rather than embedded (for the output formats that support this distinction). diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index c17457a3d..476db249e 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -188,11 +188,6 @@ Background-images on page-number-citations are not placed correctly. - - page-number-citation-last: FOs spanning multiple pages are not properly handled. - page-number-citation-last_basic.xml - Resolution of forward references does not wait until an FO is fully finished when an FO spans multiple pages. - IDs are not working on all FO elements page-number-citation_complex_1.xml diff --git a/test/layoutengine/standard-testcases/page-number-citation_bugzilla44794.xml b/test/layoutengine/standard-testcases/page-number-citation_bugzilla44794.xml new file mode 100644 index 000000000..7875c7321 --- /dev/null +++ b/test/layoutengine/standard-testcases/page-number-citation_bugzilla44794.xml @@ -0,0 +1,70 @@ + + + + + +

      + This test checks page-number-citation and page-number-citation-last on block and inline +

      + + + + + + + + + + + + + block: to . + + + inline: to . + + + + textXXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXXtext + + + + + + + inline: to + + + block: to + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/page-number-citation_list.xml b/test/layoutengine/standard-testcases/page-number-citation_list.xml new file mode 100644 index 000000000..70205ee04 --- /dev/null +++ b/test/layoutengine/standard-testcases/page-number-citation_list.xml @@ -0,0 +1,126 @@ + + + + + +

      + This test checks page-number-citations of list-block, list-item, + list-item-label and list-item-body. +

      +
      + + + + + + + + + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + here is text in the list item body + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + + + + + + + + + + + + + + + + + + + + + +
      -- cgit v1.2.3 From 4a70395ffb83b059c54d34ffa4982d0426d385d0 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 10 May 2008 13:44:09 +0000 Subject: Tweaks: -> remove split in CommonFont: font-size is resolved early, so no need anymore for CachedCommonFont -> allow disabling the PropertyCache via a system property (just in case...) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655085 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/properties/CommonFont.java | 276 +++++++-------------- .../apache/fop/fo/properties/PropertyCache.java | 30 ++- 2 files changed, 107 insertions(+), 199 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/CommonFont.java b/src/java/org/apache/fop/fo/properties/CommonFont.java index 1e3f8d43d..ca543a050 100755 --- a/src/java/org/apache/fop/fo/properties/CommonFont.java +++ b/src/java/org/apache/fop/fo/properties/CommonFont.java @@ -39,177 +39,60 @@ public final class CommonFont { * absolute font-size and font-size-adjust) */ private static final PropertyCache cache = new PropertyCache(CommonFont.class); - /** - * Class holding canonical instances of bundles of the - * cacheable (non-relative) CommonFont properties - * - */ - protected static final class CachedCommonFont { - - /** cache holding all canonical instances */ - private static final PropertyCache cache = new PropertyCache(CachedCommonFont.class); - - private int hash = 0; - - /** - * The "font-family" property. - */ - private final FontFamilyProperty fontFamily; - - /** - * The "font-selection-strategy" property. - */ - private final EnumProperty fontSelectionStrategy; + /** hashcode of this instance */ + private int hash = 0; - /** - * The "font-stretch" property. - */ - private final EnumProperty fontStretch; + /** The "font-family" property. */ + private final FontFamilyProperty fontFamily; - /** - * The "font-style" property. - */ - private final EnumProperty fontStyle; + /** The "font-selection-strategy" property. */ + private final EnumProperty fontSelectionStrategy; - /** - * The "font-variant" property. - */ - private final EnumProperty fontVariant; + /** The "font-stretch" property. */ + private final EnumProperty fontStretch; - /** - * The "font-weight" property. - */ - private final EnumProperty fontWeight; - - /** - * Constructor - * - * @param fontFamily the font-family property - * @param fontSelectionStrategy the font-selection-strategy property - * @param fontStretch the font-stretch property - * @param fontStyle the font-style property - * @param fontVariant the font-variant property - * @param fontWeight the font-weight property - */ - private CachedCommonFont(FontFamilyProperty fontFamily, - EnumProperty fontSelectionStrategy, - EnumProperty fontStretch, - EnumProperty fontStyle, - EnumProperty fontVariant, - EnumProperty fontWeight) { - this.fontFamily = fontFamily; - this.fontSelectionStrategy = fontSelectionStrategy; - this.fontStretch = fontStretch; - this.fontStyle = fontStyle; - this.fontVariant = fontVariant; - this.fontWeight = fontWeight; - } - - /** - * Returns the canonical instance corresponding to the given - * properties - * - * @param fontFamily the font-family property - * @param fontSelectionStrategy the font-selection-strategy property - * @param fontStretch the font-stretch property - * @param fontStyle the font-style property - * @param fontVariant the font-variant property - * @param fontWeight the font-weight property - * @return the canonical instance - */ - private static final CachedCommonFont getInstance(FontFamilyProperty fontFamily, - EnumProperty fontSelectionStrategy, - EnumProperty fontStretch, - EnumProperty fontStyle, - EnumProperty fontVariant, - EnumProperty fontWeight) { - return cache.fetch(new CachedCommonFont( - fontFamily, - fontSelectionStrategy, - fontStretch, - fontStyle, - fontVariant, - fontWeight)); - } - - /** @return the first font-family name in the list */ - private String getFirstFontFamily() { - return ((Property) fontFamily.list.get(0)).getString(); - } - - /** @return an array with the font-family names */ - private String[] getFontFamily() { - List lst = fontFamily.getList(); - String[] fontFamily = new String[lst.size()]; - for (int i = 0, c = lst.size(); i < c; i++) { - fontFamily[i] = ((Property)lst.get(i)).getString(); - } - return fontFamily; - } - - /** {@inheritDoc} */ - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o instanceof CachedCommonFont) { - CachedCommonFont ccf = (CachedCommonFont) o; - return (ccf.fontFamily == this.fontFamily) - && (ccf.fontSelectionStrategy == this.fontSelectionStrategy) - && (ccf.fontStretch == this.fontStretch) - && (ccf.fontStyle == this.fontStyle) - && (ccf.fontVariant == this.fontVariant) - && (ccf.fontWeight == this.fontWeight); - } - return false; - } - - /** {@inheritDoc} */ - public int hashCode() { - if (this.hash == 0) { - int hash = 17; - hash = 37 * hash + (fontFamily == null ? 0 : fontFamily.hashCode()); - hash = 37 * hash + (fontSelectionStrategy == null ? 0 : fontSelectionStrategy.hashCode()); - hash = 37 * hash + (fontStretch == null ? 0 : fontStretch.hashCode()); - hash = 37 * hash + (fontStyle == null ? 0 : fontStyle.hashCode()); - hash = 37 * hash + (fontVariant == null ? 0 : fontVariant.hashCode()); - hash = 37 * hash + (fontStretch == null ? 0 : fontStretch.hashCode()); - this.hash = hash; - } - return this.hash; - } - - } + /** The "font-style" property. */ + private final EnumProperty fontStyle; - /** - * The cached CommonFont properties (access these through the getters) - * The remaining properties, font-size and font-size-adjust, - * will only be cached values if they are absolute. - */ - private final CachedCommonFont cachedCommonFont; + /** The "font-variant" property. */ + private final EnumProperty fontVariant; + + /** The "font-weight" property. */ + private final EnumProperty fontWeight; - /** - * The "font-size" property. - */ + /** The "font-size" property. */ public final Length fontSize; - /** - * The "font-size-adjust" property. - */ + /** The "font-size-adjust" property. */ public final Numeric fontSizeAdjust; + /** * Construct a CommonFont instance * - * @param ccf the cached CommonFont properties + * @param fontFamily the font-family property + * @param fontSelectionStrategy the font-selection-strategy property + * @param fontStretch the font-stretch property + * @param fontStyle the font-style property + * @param fontVariant the font-variant property + * @param fontWeight the font-weight property * @param fontSize the font-size (possibly non-cached) * @param fontSizeAdjust the font-size-adjust (possibly non-cached) */ - private CommonFont(CachedCommonFont ccf, + private CommonFont(FontFamilyProperty fontFamily, + EnumProperty fontSelectionStrategy, + EnumProperty fontStretch, + EnumProperty fontStyle, + EnumProperty fontVariant, + EnumProperty fontWeight, Length fontSize, Numeric fontSizeAdjust) { - this.cachedCommonFont = ccf; + this.fontFamily = fontFamily; + this.fontSelectionStrategy = fontSelectionStrategy; + this.fontStretch = fontStretch; + this.fontStyle = fontStyle; + this.fontVariant = fontVariant; + this.fontWeight = fontWeight; this.fontSize = fontSize; this.fontSizeAdjust = fontSizeAdjust; } @@ -232,53 +115,59 @@ public final class CommonFont { EnumProperty fontStyle = (EnumProperty) pList.get(Constants.PR_FONT_STYLE); EnumProperty fontVariant = (EnumProperty) pList.get(Constants.PR_FONT_VARIANT); EnumProperty fontWeight = (EnumProperty) pList.get(Constants.PR_FONT_WEIGHT); - CachedCommonFont cachedCommonFont = CachedCommonFont.getInstance( - fontFamily, - fontSelectionStrategy, - fontStretch, - fontStyle, - fontVariant, - fontWeight); - Numeric fontSizeAdjust = pList.get(Constants.PR_FONT_SIZE_ADJUST).getNumeric(); Length fontSize = pList.get(Constants.PR_FONT_SIZE).getLength(); - CommonFont cf = new CommonFont(cachedCommonFont, fontSize, fontSizeAdjust); - if (fontSize.isAbsolute() && fontSizeAdjust.isAbsolute()) { - return cache.fetch(cf); - } else { - return cf; - } + CommonFont commonFont = new CommonFont(fontFamily, + fontSelectionStrategy, + fontStretch, + fontStyle, + fontVariant, + fontWeight, + fontSize, + fontSizeAdjust); + + return cache.fetch(commonFont); } + /** @return an array with the font-family names */ + private String[] getFontFamily() { + List lst = fontFamily.getList(); + String[] fontFamily = new String[lst.size()]; + for (int i = 0, c = lst.size(); i < c; i++) { + fontFamily[i] = ((Property)lst.get(i)).getString(); + } + return fontFamily; + } + /** @return the first font-family name in the list */ public String getFirstFontFamily() { - return cachedCommonFont.getFirstFontFamily(); + return ((Property) fontFamily.list.get(0)).getString(); } /** @return the "font-selection-strategy" property */ public int getFontSelectionStrategy() { - return cachedCommonFont.fontSelectionStrategy.getEnum(); + return fontSelectionStrategy.getEnum(); } /** @return the "font-stretch" property */ public int getFontStretch() { - return cachedCommonFont.fontStretch.getEnum(); + return fontStretch.getEnum(); } /** @return the "font-style" property */ public int getFontStyle() { - return cachedCommonFont.fontStyle.getEnum(); + return fontStyle.getEnum(); } /** @return the "font-variant" property */ public int getFontVariant() { - return cachedCommonFont.fontVariant.getEnum(); + return fontVariant.getEnum(); } /** @return the "font-weight" property */ public int getFontWeight() { - return cachedCommonFont.fontWeight.getEnum(); + return fontWeight.getEnum(); } /** @@ -290,7 +179,7 @@ public final class CommonFont { */ public FontTriplet[] getFontState(FontInfo fontInfo) { int font_weight; - switch (cachedCommonFont.fontWeight.getEnum()) { + switch (fontWeight.getEnum()) { case Constants.EN_100: font_weight = 100; break; case Constants.EN_200: font_weight = 200; break; case Constants.EN_300: font_weight = 300; break; @@ -304,7 +193,7 @@ public final class CommonFont { } String style; - switch (cachedCommonFont.fontStyle.getEnum()) { + switch (fontStyle.getEnum()) { case Constants.EN_ITALIC: style = "italic"; break; @@ -321,32 +210,53 @@ public final class CommonFont { // various kinds of keywords too //int fontVariant = propertyList.get("font-variant").getEnum(); FontTriplet[] triplets = fontInfo.fontLookup( - cachedCommonFont.getFontFamily(), + getFontFamily(), style, font_weight); return triplets; } /** {@inheritDoc} */ public boolean equals(Object o) { + + if (o == null) { + return false; + } + if (this == o) { return true; } if (o instanceof CommonFont) { CommonFont cf = (CommonFont) o; - return (cf.cachedCommonFont == this.cachedCommonFont - && cf.fontSize == this.fontSize - && cf.fontSizeAdjust == this.fontSizeAdjust); + return (cf.fontFamily == this.fontFamily) + && (cf.fontSelectionStrategy == this.fontSelectionStrategy) + && (cf.fontStretch == this.fontStretch) + && (cf.fontStyle == this.fontStyle) + && (cf.fontVariant == this.fontVariant) + && (cf.fontWeight == this.fontWeight) + && (cf.fontSize == this.fontSize) + && (cf.fontSizeAdjust == this.fontSizeAdjust); } return false; + } /** {@inheritDoc} */ public int hashCode() { - int hash = 17; - hash = 37 * hash + cachedCommonFont.hashCode(); - hash = 37 * hash + fontSize.hashCode(); - hash = 37 * hash + fontSizeAdjust.hashCode(); + + if (this.hash == -1) { + int hash = 17; + hash = 37 * hash + (fontSize == null ? 0 : fontSize.hashCode()); + hash = 37 * hash + (fontSizeAdjust == null ? 0 : fontSizeAdjust.hashCode()); + hash = 37 * hash + (fontFamily == null ? 0 : fontFamily.hashCode()); + hash = 37 * hash + (fontSelectionStrategy == null ? 0 : fontSelectionStrategy.hashCode()); + hash = 37 * hash + (fontStretch == null ? 0 : fontStretch.hashCode()); + hash = 37 * hash + (fontStyle == null ? 0 : fontStyle.hashCode()); + hash = 37 * hash + (fontVariant == null ? 0 : fontVariant.hashCode()); + hash = 37 * hash + (fontStretch == null ? 0 : fontStretch.hashCode()); + this.hash = hash; + } return hash; + } } diff --git a/src/java/org/apache/fop/fo/properties/PropertyCache.java b/src/java/org/apache/fop/fo/properties/PropertyCache.java index 2c51bc081..6fe36e0b8 100644 --- a/src/java/org/apache/fop/fo/properties/PropertyCache.java +++ b/src/java/org/apache/fop/fo/properties/PropertyCache.java @@ -36,6 +36,12 @@ public final class PropertyCache { /** bitmask to apply to the hash to get to the * corresponding cache segment */ private static final int SEGMENT_MASK = 0x1F; + /** + * Indicates whether the cache should be used at all + * Can be controlled by the system property: + * org.apache.fop.fo.properties.use-cache + */ + private final boolean useCache; /** the segments array (length = 32) */ private CacheSegment[] segments = new CacheSegment[SEGMENT_MASK + 1]; @@ -262,6 +268,7 @@ public final class PropertyCache { * @param c Runtime type of the objects that will be stored in the cache */ public PropertyCache(Class c) { + this.useCache = Boolean.getBoolean("org.apache.fop.fo.properties.use-cache"); for (int i = SEGMENT_MASK + 1; --i >= 0;) { segments[i] = new CacheSegment(); } @@ -278,6 +285,10 @@ public final class PropertyCache { * @return the cached instance */ private Object fetch(Object obj) { + if (!this.useCache) { + return obj; + } + if (obj == null) { return null; } @@ -291,7 +302,7 @@ public final class PropertyCache { } /** - * Checks if the given Property is present in the cache - + * Checks if the given {@link Property} is present in the cache - * if so, returns a reference to the cached instance. * Otherwise the given object is added to the cache and returned. * @@ -304,7 +315,7 @@ public final class PropertyCache { } /** - * Checks if the given CommonHyphenation is present in the cache - + * Checks if the given {@link CommonHyphenation} is present in the cache - * if so, returns a reference to the cached instance. * Otherwise the given object is added to the cache and returned. * @@ -317,20 +328,7 @@ public final class PropertyCache { } /** - * Checks if the given CachedCommonFont is present in the cache - - * if so, returns a reference to the cached instance. - * Otherwise the given object is added to the cache and returned. - * - * @param ccf the CachedCommonFont instance to check for - * @return the cached instance - */ - public final CommonFont.CachedCommonFont fetch(CommonFont.CachedCommonFont ccf) { - - return (CommonFont.CachedCommonFont) fetch((Object) ccf); - } - - /** - * Checks if the given CommonFont is present in the cache - + * Checks if the given {@link CommonFont} is present in the cache - * if so, returns a reference to the cached instance. * Otherwise the given object is added to the cache and returned. * -- cgit v1.2.3 From dbc0c79b06fc75164dde3bb4bb26991b82fb676e Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 10 May 2008 14:23:56 +0000 Subject: Correction: set default to true... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655093 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/properties/PropertyCache.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/PropertyCache.java b/src/java/org/apache/fop/fo/properties/PropertyCache.java index 6fe36e0b8..b5f4f90ba 100644 --- a/src/java/org/apache/fop/fo/properties/PropertyCache.java +++ b/src/java/org/apache/fop/fo/properties/PropertyCache.java @@ -268,9 +268,13 @@ public final class PropertyCache { * @param c Runtime type of the objects that will be stored in the cache */ public PropertyCache(Class c) { - this.useCache = Boolean.getBoolean("org.apache.fop.fo.properties.use-cache"); - for (int i = SEGMENT_MASK + 1; --i >= 0;) { - segments[i] = new CacheSegment(); + this.useCache = Boolean.valueOf(System.getProperty( + "org.apache.fop.fo.properties.use-cache", "true") + ).booleanValue(); + if (useCache) { + for (int i = SEGMENT_MASK + 1; --i >= 0;) { + segments[i] = new CacheSegment(); + } } this.runtimeType = c; } -- cgit v1.2.3 From 9526915ada1d579194a4b38a596d43f75921311c Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sun, 11 May 2008 07:30:55 +0000 Subject: made sure warning for missing glyphs is emitted in all cases git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655275 13f79535-47bb-0310-9956-ffa450edef68 --- src/codegen/fonts/font-file.xsl | 4 +- src/java/org/apache/fop/fonts/Font.java | 2 +- src/java/org/apache/fop/fonts/MultiByteFont.java | 12 ++--- src/java/org/apache/fop/fonts/SingleByteFont.java | 31 +------------ src/java/org/apache/fop/fonts/Typeface.java | 54 +++++++++++++++++++++-- 5 files changed, 63 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/codegen/fonts/font-file.xsl b/src/codegen/fonts/font-file.xsl index 21a6507b8..85b968808 100644 --- a/src/codegen/fonts/font-file.xsl +++ b/src/codegen/fonts/font-file.xsl @@ -42,6 +42,7 @@ import java.util.Set; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.Base14Font; import org.apache.fop.fonts.CodePointMapping; +import org.apache.fop.fonts.Typeface;; public class extends Base14Font { private final static String fontName = ""; @@ -169,7 +170,8 @@ public class extends Base14Font { if (d != 0) { return d; } else { - return '#'; + this.warnMissingGlyph(c); + return Typeface.NOT_FOUND; } } diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index 90aced052..3a0d82046 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -212,7 +212,7 @@ public class Font { c = d; } else { log.warn("Glyph " + (int) c + " not available in font " + fontName); - c = '#'; + c = Typeface.NOT_FOUND; } return c; diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index 5849379bd..2f3031646 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -30,7 +30,7 @@ public class MultiByteFont extends CIDFont { private static int uniqueCounter = -1; private static final DecimalFormat COUNTER_FORMAT = new DecimalFormat("00000"); - + private String ttcName = null; private String encoding = "Identity-H"; @@ -158,7 +158,7 @@ public class MultiByteFont extends CIDFont { */ private int findGlyphIndex(char c) { int idx = (int)c; - int retIdx = 0; //.notdef + int retIdx = SingleByteEncoding.NOT_FOUND_CODE_POINT; for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) { if (bfentries[i].getUnicodeStart() <= idx @@ -176,17 +176,19 @@ public class MultiByteFont extends CIDFont { public char mapChar(char c) { notifyMapOperation(); int glyphIndex = findGlyphIndex(c); - + if (glyphIndex == SingleByteEncoding.NOT_FOUND_CODE_POINT) { + warnMissingGlyph(c); + glyphIndex = findGlyphIndex(Typeface.NOT_FOUND); + } if (isEmbeddable()) { glyphIndex = subset.mapSubsetChar(glyphIndex, c); } - return (char)glyphIndex; } /** {@inheritDoc} */ public boolean hasChar(char c) { - return (findGlyphIndex(c) > 0); + return (findGlyphIndex(c) != SingleByteEncoding.NOT_FOUND_CODE_POINT); } /** diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index feb1b440c..f1b7b1b48 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -21,21 +21,15 @@ package org.apache.fop.fonts; import java.util.List; import java.util.Map; -import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.xmlgraphics.fonts.Glyphs; - /** * Generic SingleByte font */ public class SingleByteFont extends CustomFont { - /** Code point that is used if no code point for a specific character has been found. */ - public static final char NOT_FOUND = '#'; - /** logger */ private static Log log = LogFactory.getLog(SingleByteFont.class); @@ -43,8 +37,6 @@ public class SingleByteFont extends CustomFont { private int[] width = null; - private Set warnedChars; - private Map unencodedCharacters; //Map private List additionalEncodings; @@ -115,27 +107,8 @@ public class SingleByteFont extends CustomFont { if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) { return d; } - - //Give up, character is not available - Character ch = new Character(c); - if (warnedChars == null) { - warnedChars = new java.util.HashSet(); - } - if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { - warnedChars.add(ch); - if (this.eventListener != null) { - this.eventListener.glyphNotAvailable(this, c, getFontName()); - } else { - if (warnedChars.size() == 8) { - log.warn("Many requested glyphs are not available in font " + getFontName()); - } else { - log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) - + ", " + Glyphs.charToGlyphName(c) - + ") not available in font " + getFontName()); - } - } - } - return NOT_FOUND; + this.warnMissingGlyph(c); + return Typeface.NOT_FOUND; } private char mapUnencodedChar(char ch) { diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java index b6c78a3b0..4a434745c 100644 --- a/src/java/org/apache/fop/fonts/Typeface.java +++ b/src/java/org/apache/fop/fonts/Typeface.java @@ -19,20 +19,38 @@ package org.apache.fop.fonts; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.fonts.Glyphs; + /** * Base class for font classes */ public abstract class Typeface implements FontMetrics { /** - * Used to identify whether a font has been used (a character map operation is used as - * the trigger). This could just as well be a boolean but is a long out of statistical interest. + * Code point that is used if no code point for a specific character has + * been found. + */ + public static final char NOT_FOUND = '#'; + + /** logger */ + private static Log log = LogFactory.getLog(Typeface.class); + + /** + * Used to identify whether a font has been used (a character map operation + * is used as the trigger). This could just as well be a boolean but is a + * long out of statistical interest. */ private long charMapOps = 0; /** An optional event listener that receives events such as missing glyphs etc. */ protected FontEventListener eventListener; - + + private Set warnedChars; + /** * Get the encoding of the font. * @return the encoding @@ -92,5 +110,33 @@ public abstract class Typeface implements FontMetrics { this.eventListener = listener; } + /** + * Provide proper warning if a glyph is not available. + * + * @param c + * the character which is missing. + */ + protected void warnMissingGlyph(char c) { + // Give up, character is not available + Character ch = new Character(c); + if (warnedChars == null) { + warnedChars = new java.util.HashSet(); + } + if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { + warnedChars.add(ch); + if (this.eventListener != null) { + this.eventListener.glyphNotAvailable(this, c, getFontName()); + } else { + if (warnedChars.size() == 8) { + log.warn("Many requested glyphs are not available in font " + + getFontName()); + } else { + log.warn("Glyph " + (int) c + " (0x" + + Integer.toHexString(c) + ", " + + Glyphs.charToGlyphName(c) + + ") not available in font " + getFontName()); + } + } + } + } } - -- cgit v1.2.3 From b79ac835070e53519be4167a224b59fcbc03722e Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sun, 11 May 2008 09:01:31 +0000 Subject: Support character-by-character font-selection strategy on fo:character element git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655281 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- .../layoutmgr/inline/CharacterLayoutManager.java | 34 ++++++++++++++++++---- status.xml | 3 ++ 3 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 643fc7b73..8fed90a35 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -963,7 +963,7 @@ public final class FOPropertyMapping implements Constants { // font-family m = new FontFamilyProperty.Maker(PR_FONT_FAMILY); m.setInherited(true); - m.setDefault("sans-serif"); + m.setDefault("sans-serif,Symbol,ZapfDingbats"); m.addShorthand(s_generics[PR_FONT]); addPropertyMaker("font-family", m); diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index b53e442d4..b292d97bf 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -61,11 +61,8 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public void initialize() { - Character fobj = (Character)this.fobj; - - FontInfo fi = fobj.getFOEventHandler().getFontInfo(); - FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); - font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this)); + Character fobj = (Character)this.fobj; + font = this.selectFontForCharacter(fobj); SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing()); letterSpaceIPD = ls.getSpace(); hyphIPD = fobj.getCommonHyphenation().getHyphIPD(font); @@ -75,6 +72,33 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { chArea.setBaselineOffset(font.getAscender()); setCurrentArea(chArea); } + + /** + * Selects a font which is able to display the given character. + *

      + * Please note: this implements the font-selection-strategy + * character-by-character. + *

      + * TODO: The same function could apply to other elements as well. + * + * @param fobj + * a Character object containing the character and its + * attributed. + * @return a Font object. + */ + private Font selectFontForCharacter(Character fobj) { + FontInfo fi = fobj.getFOEventHandler().getFontInfo(); + FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); + for (int i = 0; i < fontkeys.length; i++) { + font = fi.getFontInstance(fontkeys[i], + fobj.getCommonFont().fontSize.getValue(this)); + if (font.hasChar(fobj.getCharacter())) { + return font; + } + } + return fi.getFontInstance(fontkeys[0], + fobj.getCommonFont().fontSize.getValue(this)); + } private org.apache.fop.area.inline.TextArea getCharacterInlineArea(Character node) { org.apache.fop.area.inline.TextArea text diff --git a/status.xml b/status.xml index 3bfcaf827..2f0df7c31 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,9 @@ Added SVG support for AFP (GOCA). + + Support character-by-character font-selection strategy on fo:character element. + Added support for page-number-citation and page-number-citation-last of fo:inline. Corrected behavior for page-number-citation-last -- cgit v1.2.3 From 7085b0c9a97cca2eb7fa1fa4d7a1aa83e9de918c Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 11 May 2008 12:22:22 +0000 Subject: Make the LM clean up on end-of-layout, if possible. Added clearChildNodes() method to FObj to release the reference to the FO's children. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655309 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FObj.java | 9 ++++- .../fop/layoutmgr/AbstractLayoutManager.java | 39 ++++++++++++++++------ 2 files changed, 37 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index 79b04c4d7..0bbec4d47 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -515,6 +515,13 @@ public abstract class FObj extends FONode implements Constants { return -1; } + /** + * Clears the list of child nodes. + */ + public void clearChildNodes() { + this.firstChild = null; + } + /** @return the "id" property. */ public String getId() { return id; @@ -598,7 +605,7 @@ public abstract class FObj extends FONode implements Constants { return (super.toString() + "[@id=" + this.id + "]"); } - + /** Basic {@link FONodeIterator} implementation */ public class FObjIterator implements FONodeIterator { private static final int F_NONE_ALLOWED = 0; diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index ef32bbc75..3f2143bae 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -147,15 +147,11 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager isFinished = fin; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void addAreas(PositionIterator posIter, LayoutContext context) { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { log.warn("null implementation of getNextKnuthElements() called!"); @@ -163,9 +159,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager return null; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public LinkedList getChangedKnuthElements(List oldList, int alignment) { log.warn("null implementation of getChangeKnuthElement() called!"); @@ -390,7 +384,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** * Checks to see if the incoming {@link Position} * is the last one for this LM, and if so, calls - * {@link #notifyEndOfLayout()} + * {@link #notifyEndOfLayout()} and cleans up. * * @param pos the {@link Position} to check */ @@ -398,7 +392,32 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager if (pos != null && pos.getLM() == this && this.isLast(pos)) { + notifyEndOfLayout(); + + /* References to the child LMs are no longer needed + */ + childLMs = null; + curChildLM = null; + childLMiter = null; + + /* markers that qualify have been transferred to the page + */ + markers = null; + + /* References to the FO's children can be released if the + * LM is a descendant of the FlowLM. For static-content + * the FO may still be needed on following pages. + */ + LayoutManager lm = this.parentLM; + while (!(lm instanceof FlowLayoutManager + || lm instanceof PageSequenceLayoutManager)) { + lm = lm.getParent(); + } + if (lm instanceof FlowLayoutManager) { + fobj.clearChildNodes(); + fobjIter = null; + } } } -- cgit v1.2.3 From 4f78b6a919a39cdfa5635d38dc23355b99818e02 Mon Sep 17 00:00:00 2001 From: Simon Pepping Date: Sun, 11 May 2008 18:05:51 +0000 Subject: The spec requires rounding, not truncating git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655349 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/properties/NumberProperty.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/NumberProperty.java b/src/java/org/apache/fop/fo/properties/NumberProperty.java index 0ba5300ae..aa4791889 100644 --- a/src/java/org/apache/fop/fo/properties/NumberProperty.java +++ b/src/java/org/apache/fop/fo/properties/NumberProperty.java @@ -91,7 +91,7 @@ public final class NumberProperty extends Property implements Numeric { } Number val = p.getNumber(); if (val != null) { - int i = val.intValue(); + int i = Math.round(val.floatValue()); if (i <= 0) { i = 1; } -- cgit v1.2.3 From 792c78edcbb37ed4e3ae213dfd18fa6be56bbb1d Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 11 May 2008 21:03:41 +0000 Subject: Avoid creation of unnecessary dummy areas. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655370 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index 8108bbf40..a5bbdb33c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -74,12 +74,7 @@ public class WrapperLayoutManager extends LeafNodeLayoutManager { if (parentLM instanceof BlockStackingLayoutManager && !(parentLM instanceof BlockLayoutManager)) { Block helperBlock = new Block(); - LineArea helperLine = new LineArea(); - InlineParent helperInline = new InlineParent(); - helperInline.addChildArea(area); - helperLine.addInlineArea(helperInline); - helperLine.updateExtentsFromChildren(); - helperBlock.addLineArea(helperLine); + TraitSetter.setProducerID(helperBlock, fobj.getId()); parentLM.addChildArea(helperBlock); } else { parentLM.addChildArea(area); -- cgit v1.2.3 From 6d07774192bb641251bd72b7ea68f012f20e2d88 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 12 May 2008 12:30:42 +0000 Subject: Replaced hack in TableStepper to get the steps' penalty values with a more proper implementation. Allows in the same time to avoid skimming, at each step, through the active cells' LinkedLists of elements, which may have a negative impact on performance git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655489 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/ActiveCell.java | 16 ++++++++++++++-- .../org/apache/fop/layoutmgr/table/TableStepper.java | 11 ++--------- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 70e2b2330..feb4b67ac 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -99,6 +99,8 @@ class ActiveCell { private int totalLength; /** Length of the penalty ending this step, if any. */ private int penaltyLength; + /** Value of the penalty ending this step, 0 if the step does not end on a penalty. */ + private int penaltyValue; /** * One of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, @@ -127,6 +129,7 @@ class ActiveCell { this.contentLength = other.contentLength; this.totalLength = other.totalLength; this.penaltyLength = other.penaltyLength; + this.penaltyValue = other.penaltyValue; this.condBeforeContentLength = other.condBeforeContentLength; this.breakClass = other.breakClass; } @@ -287,6 +290,7 @@ class ActiveCell { private void gotoNextLegalBreak() { afterNextStep.penaltyLength = 0; + afterNextStep.penaltyValue = 0; afterNextStep.condBeforeContentLength = 0; afterNextStep.breakClass = Constants.EN_AUTO; boolean breakFound = false; @@ -299,8 +303,9 @@ class ActiveCell { if (el.getP() < KnuthElement.INFINITE) { // First legal break point breakFound = true; - afterNextStep.penaltyLength = el.getW(); KnuthPenalty p = (KnuthPenalty) el; + afterNextStep.penaltyLength = p.getW(); + afterNextStep.penaltyValue = p.getP(); if (p.isForcedBreak()) { afterNextStep.breakClass = p.getBreakClass(); } @@ -542,7 +547,14 @@ class ActiveCell { return keepWithNextStrength; } - + int getPenaltyValue() { + if (includedInLastStep()) { + return nextStep.penaltyValue; + } else { + return previousStep.penaltyValue; + } + } + /** {@inheritDoc} */ public String toString() { return "Cell " + (pgu.getRowIndex() + 1) + "." + (pgu.getColIndex() + 1); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 2d3c990f8..f514844ac 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -200,20 +200,11 @@ public class TableStepper { } //Put all involved grid units into a list - int stepPenalty = 0; 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); - - //Record highest penalty value of part - if (part.end >= 0) { - KnuthElement endEl = (KnuthElement)part.pgu.getElements().get(part.end); - if (endEl instanceof KnuthPenalty) { - stepPenalty = Math.max(stepPenalty, endEl.getP()); - } - } } //Create elements for step @@ -242,9 +233,11 @@ public class TableStepper { } int strength = BlockLevelLayoutManager.KEEP_AUTO; + int stepPenalty = 0; for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); strength = Math.max(strength, activeCell.getKeepWithNextStrength()); + stepPenalty = Math.max(stepPenalty, activeCell.getPenaltyValue()); } if (!rowFinished) { strength = Math.max(strength, rowGroup[activeRowIndex].getKeepTogetherStrength()); -- cgit v1.2.3 From d9d54fe7e42c72f6af8b4558a75eb6bf770b11a6 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 12 May 2008 13:42:49 +0000 Subject: Extended caching to CondLengthProperty CommonBorderPaddingBackground.BorderInfo and CommonBorderPaddingBackground. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655500 13f79535-47bb-0310-9956-ffa450edef68 --- .../properties/CommonBorderPaddingBackground.java | 339 ++++++++++++++++----- .../fop/fo/properties/CondLengthProperty.java | 47 ++- .../apache/fop/fo/properties/PropertyCache.java | 26 ++ 3 files changed, 339 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index 96c1e80e2..1c54d63db 100755 --- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java +++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java @@ -38,35 +38,44 @@ import org.apache.fop.fo.expr.PropertyException; * See Sec. 7.7 of the XSL-FO Standard. */ public class CommonBorderPaddingBackground { + + /** + * cache holding all canonical instances + * (w/ absolute background-position-* and padding-*) + */ + private static final PropertyCache cache = new PropertyCache(CommonBorderPaddingBackground.class); + + private int hash = -1; + /** * The "background-attachment" property. */ - public int backgroundAttachment; + public final int backgroundAttachment; /** * The "background-color" property. */ - public Color backgroundColor; + public final Color backgroundColor; /** * The "background-image" property. */ - public String backgroundImage; + public final String backgroundImage; /** * The "background-repeat" property. */ - public int backgroundRepeat; + public final int backgroundRepeat; /** * The "background-position-horizontal" property. */ - public Length backgroundPositionHorizontal; + public final Length backgroundPositionHorizontal; /** * The "background-position-vertical" property. */ - public Length backgroundPositionVertical; + public final Length backgroundPositionVertical; private ImageInfo backgroundImageInfo; @@ -81,29 +90,68 @@ public class CommonBorderPaddingBackground { /** the "end" edge */ public static final int END = 3; + /** + * + */ public static class BorderInfo { + + /** cache holding all canonical instances */ + private static final PropertyCache cache = new PropertyCache(BorderInfo.class); + private int mStyle; // Enum for border style private Color mColor; // Border color private CondLengthProperty mWidth; + + private int hash = -1; - BorderInfo(int style, CondLengthProperty width, Color color) { + /** + * Hidden constructor + */ + private BorderInfo(int style, CondLengthProperty width, Color color) { mStyle = style; mWidth = width; mColor = color; } + /** + * Returns a BorderInfo instance corresponding to the given values + * + * @param style the border-style + * @param width the border-width + * @param color the border-color + * @return a cached BorderInfo instance + */ + public static BorderInfo getInstance(int style, CondLengthProperty width, Color color) { + return cache.fetch(new BorderInfo(style, width, color)); + } + + /** + * @return the border-style + */ public int getStyle() { return this.mStyle; } + /** + * @return the border-color + */ public Color getColor() { return this.mColor; } + /** + * @return the border-width + */ public CondLengthProperty getWidth() { return this.mWidth; } + /** + * Convenience method returning the border-width, + * taking into account values of "none" and "hidden" + * + * @return the retained border-width + */ public int getRetainedWidth() { if ((mStyle == Constants.EN_NONE) || (mStyle == Constants.EN_HIDDEN)) { @@ -125,14 +173,43 @@ public class CommonBorderPaddingBackground { sb.append("}"); return sb.toString(); } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof BorderInfo) { + BorderInfo bi = (BorderInfo)obj; + return (this.mColor == bi.mColor + && this.mStyle == bi.mStyle + && this.mWidth == bi.mWidth); + } + + return false; + } + + /** {@inheritDoc} */ + public int hashCode() { + if (this.hash == -1) { + int hash = 17; + hash = 37 * hash + (mColor == null ? 0 : mColor.hashCode()); + hash = 37 * hash + mStyle; + hash = 37 * hash + (mWidth == null ? 0 : mWidth.hashCode()); + this.hash = hash; + } + return this.hash; + } } /** - * A border info with style none. Used as a singleton, in the collapsing-border model, + * A border info with style "none". Used as a singleton, in the collapsing-border model, * for elements which don't specify any border on some of their sides. */ - private static BorderInfo defaultBorderInfo; - + private static final BorderInfo defaultBorderInfo + = BorderInfo.getInstance(Constants.EN_NONE, new ConditionalNullLength(), null); + /** * A conditional length of value 0. Returned by the * {@link CommonBorderPaddingBackground#getBorderInfo(int)} method when the @@ -191,43 +268,39 @@ public class CommonBorderPaddingBackground { * * @return a BorderInfo instance with style set to {@link Constants#EN_NONE} */ - public static synchronized BorderInfo getDefaultBorderInfo() { - if (defaultBorderInfo == null) { - /* It is enough to set color to null, as it should never be consulted */ - defaultBorderInfo = new BorderInfo(Constants.EN_NONE, - new ConditionalNullLength(), null); - } + public static BorderInfo getDefaultBorderInfo() { return defaultBorderInfo; } private BorderInfo[] borderInfo = new BorderInfo[4]; private CondLengthProperty[] padding = new CondLengthProperty[4]; - /** - * Construct a CommonBorderPaddingBackground object. - */ - public CommonBorderPaddingBackground() { - } - /** * Construct a CommonBorderPaddingBackground object. * * @param pList The PropertyList to get properties from. * @throws PropertyException if there's an error while binding the properties */ - public CommonBorderPaddingBackground(PropertyList pList) throws PropertyException { + private CommonBorderPaddingBackground(PropertyList pList) throws PropertyException { backgroundAttachment = pList.get(Constants.PR_BACKGROUND_ATTACHMENT).getEnum(); - backgroundColor = pList.get(Constants.PR_BACKGROUND_COLOR).getColor( + + Color bc = pList.get(Constants.PR_BACKGROUND_COLOR).getColor( pList.getFObj().getUserAgent()); - if (backgroundColor.getAlpha() == 0) { + if (bc.getAlpha() == 0) { backgroundColor = null; + } else { + backgroundColor = bc; } - backgroundImage = pList.get(Constants.PR_BACKGROUND_IMAGE).getString(); - if (backgroundImage == null || "none".equals(backgroundImage)) { - backgroundImage = null; + String img = pList.get(Constants.PR_BACKGROUND_IMAGE).getString(); + if (img == null || "none".equals(img)) { + backgroundImage = ""; + backgroundRepeat = -1; + backgroundPositionHorizontal = null; + backgroundPositionVertical = null; } else { + backgroundImage = img; backgroundRepeat = pList.get(Constants.PR_BACKGROUND_REPEAT).getEnum(); backgroundPositionHorizontal = pList.get( Constants.PR_BACKGROUND_POSITION_HORIZONTAL).getLength(); @@ -272,18 +345,48 @@ public class CommonBorderPaddingBackground { } + /** + * Obtain a CommonBorderPaddingBackground instance based on the + * related property valus in the given {@link PropertyList} + * + * @param pList the {@link PropertyList} to use + * @return a CommonBorderPaddingBackground instance (cached if possible) + * @throws PropertyException in case of an error + */ + public static CommonBorderPaddingBackground getInstance(PropertyList pList) + throws PropertyException { + + CommonBorderPaddingBackground newInstance + = new CommonBorderPaddingBackground(pList); + + /* if padding-* and background-position-* resolve to absolute lengths + * the whole instance can be cached */ + if ((newInstance.padding[BEFORE] == null || newInstance.padding[BEFORE].getLength().isAbsolute()) + && (newInstance.padding[AFTER] == null || newInstance.padding[AFTER].getLength().isAbsolute()) + && (newInstance.padding[START] == null || newInstance.padding[START].getLength().isAbsolute()) + && (newInstance.padding[END] == null || newInstance.padding[END].getLength().isAbsolute()) + && (newInstance.backgroundPositionHorizontal == null || newInstance.backgroundPositionHorizontal.isAbsolute()) + && (newInstance.backgroundPositionVertical == null || newInstance.backgroundPositionVertical.isAbsolute())) { + return cache.fetch(newInstance); + } + + return newInstance; + } + private void initBorderInfo(PropertyList pList, int side, int colorProp, int styleProp, int widthProp, int paddingProp) throws PropertyException { + padding[side] = pList.get(paddingProp).getCondLength(); // If style = none, force width to 0, don't get Color (spec 7.7.20) int style = pList.get(styleProp).getEnum(); if (style != Constants.EN_NONE) { FOUserAgent ua = pList.getFObj().getUserAgent(); - setBorderInfo(new BorderInfo(style, + setBorderInfo(BorderInfo.getInstance(style, pList.get(widthProp).getCondLength(), pList.get(colorProp).getColor(ua)), side); } + } /** @@ -291,7 +394,7 @@ public class CommonBorderPaddingBackground { * @param info the border information * @param side the side to apply the info to */ - public void setBorderInfo(BorderInfo info, int side) { + private void setBorderInfo(BorderInfo info, int side) { this.borderInfo[side] = info; } @@ -307,14 +410,6 @@ public class CommonBorderPaddingBackground { } } - /** - * Set padding. - * @param source the padding info to copy from - */ - public void setPadding(CommonBorderPaddingBackground source) { - this.padding = source.padding; - } - /** * @return the background image info object, null if there is * no background image. @@ -324,64 +419,102 @@ public class CommonBorderPaddingBackground { } /** - * @param bDiscard indicates whether the .conditionality component should be + * @param discard indicates whether the .conditionality component should be * considered (start of a reference-area) + * @return the width of the start-border, taking into account the specified conditionality */ - public int getBorderStartWidth(boolean bDiscard) { - return getBorderWidth(START, bDiscard); + public int getBorderStartWidth(boolean discard) { + return getBorderWidth(START, discard); } /** - * @param bDiscard indicates whether the .conditionality component should be + * @param discard indicates whether the .conditionality component should be * considered (end of a reference-area) + * @return the width of the end-border, taking into account the specified conditionality */ - public int getBorderEndWidth(boolean bDiscard) { - return getBorderWidth(END, bDiscard); + public int getBorderEndWidth(boolean discard) { + return getBorderWidth(END, discard); } /** - * @param bDiscard indicates whether the .conditionality component should be + * @param discard indicates whether the .conditionality component should be * considered (start of a reference-area) + * @return the width of the before-border, taking into account the specified conditionality */ - public int getBorderBeforeWidth(boolean bDiscard) { - return getBorderWidth(BEFORE, bDiscard); + public int getBorderBeforeWidth(boolean discard) { + return getBorderWidth(BEFORE, discard); } /** - * @param bDiscard indicates whether the .conditionality component should be + * @param discard indicates whether the .conditionality component should be * considered (end of a reference-area) + * @return the width of the after-border, taking into account the specified conditionality */ - public int getBorderAfterWidth(boolean bDiscard) { - return getBorderWidth(AFTER, bDiscard); + public int getBorderAfterWidth(boolean discard) { + return getBorderWidth(AFTER, discard); } - public int getPaddingStart(boolean bDiscard, PercentBaseContext context) { - return getPadding(START, bDiscard, context); + /** + * @param discard indicates whether the .conditionality component should be + * considered (start of a reference-area) + * @param context the context to evaluate percentage values + * @return the width of the start-padding, taking into account the specified conditionality + */ + public int getPaddingStart(boolean discard, PercentBaseContext context) { + return getPadding(START, discard, context); } - public int getPaddingEnd(boolean bDiscard, PercentBaseContext context) { - return getPadding(END, bDiscard, context); + /** + * @param discard indicates whether the .conditionality component should be + * considered (start of a reference-area) + * @param context the context to evaluate percentage values + * @return the width of the end-padding, taking into account the specified conditionality + */ + public int getPaddingEnd(boolean discard, PercentBaseContext context) { + return getPadding(END, discard, context); } - public int getPaddingBefore(boolean bDiscard, PercentBaseContext context) { - return getPadding(BEFORE, bDiscard, context); + /** + * @param discard indicates whether the .conditionality component should be + * considered (start of a reference-area) + * @param context the context to evaluate percentage values + * @return the width of the before-padding, taking into account the specified conditionality + */ + public int getPaddingBefore(boolean discard, PercentBaseContext context) { + return getPadding(BEFORE, discard, context); } - public int getPaddingAfter(boolean bDiscard, PercentBaseContext context) { - return getPadding(AFTER, bDiscard, context); + /** + * @param discard indicates whether the .conditionality component should be + * considered (start of a reference-area) + * @param context the context to evaluate percentage values + * @return the width of the after-padding, taking into account the specified conditionality + */ + public int getPaddingAfter(boolean discard, PercentBaseContext context) { + return getPadding(AFTER, discard, context); } - public int getBorderWidth(int side, boolean bDiscard) { + /** + * @param discard indicates whether the .conditionality component should be + * considered (end of a reference-area) + * @return the width of the start-border, taking into account the specified conditionality + */ + public int getBorderWidth(int side, boolean discard) { if ((borderInfo[side] == null) || (borderInfo[side].mStyle == Constants.EN_NONE) || (borderInfo[side].mStyle == Constants.EN_HIDDEN) - || (bDiscard && borderInfo[side].mWidth.isDiscard())) { + || (discard && borderInfo[side].mWidth.isDiscard())) { return 0; } else { return borderInfo[side].mWidth.getLengthValue(); } } + /** + * + * @param side + * @return + */ public Color getBorderColor(int side) { if (borderInfo[side] != null) { return borderInfo[side].getColor(); @@ -390,6 +523,11 @@ public class CommonBorderPaddingBackground { } } + /** + * + * @param side + * @return + */ public int getBorderStyle(int side) { if (borderInfo[side] != null) { return borderInfo[side].mStyle; @@ -398,8 +536,15 @@ public class CommonBorderPaddingBackground { } } - public int getPadding(int side, boolean bDiscard, PercentBaseContext context) { - if ((padding[side] == null) || (bDiscard && padding[side].isDiscard())) { + /** + * + * @param side + * @param discard + * @param context + * @return + */ + public int getPadding(int side, boolean discard, PercentBaseContext context) { + if ((padding[side] == null) || (discard && padding[side].isDiscard())) { return 0; } else { return padding[side].getLengthValue(context); @@ -418,27 +563,27 @@ public class CommonBorderPaddingBackground { /** * Return all the border and padding width in the inline progression * dimension. - * @param bDiscard the discard flag. + * @param discard the discard flag. * @param context for percentage evaluation. * @return all the padding and border width. */ - public int getIPPaddingAndBorder(boolean bDiscard, PercentBaseContext context) { - return getPaddingStart(bDiscard, context) - + getPaddingEnd(bDiscard, context) - + getBorderStartWidth(bDiscard) - + getBorderEndWidth(bDiscard); + public int getIPPaddingAndBorder(boolean discard, PercentBaseContext context) { + return getPaddingStart(discard, context) + + getPaddingEnd(discard, context) + + getBorderStartWidth(discard) + + getBorderEndWidth(discard); } /** * Return all the border and padding height in the block progression * dimension. - * @param bDiscard the discard flag. + * @param discard the discard flag. * @param context for percentage evaluation * @return all the padding and border height. */ - public int getBPPaddingAndBorder(boolean bDiscard, PercentBaseContext context) { - return getPaddingBefore(bDiscard, context) + getPaddingAfter(bDiscard, context) - + getBorderBeforeWidth(bDiscard) + getBorderAfterWidth(bDiscard); + public int getBPPaddingAndBorder(boolean discard, PercentBaseContext context) { + return getPaddingBefore(discard, context) + getPaddingAfter(discard, context) + + getBorderBeforeWidth(discard) + getBorderAfterWidth(discard); } /** {@inheritDoc} */ @@ -479,4 +624,54 @@ public class CommonBorderPaddingBackground { return (borderInfo[BEFORE] != null || borderInfo[AFTER] != null || borderInfo[START] != null || borderInfo[END] != null); } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof CommonBorderPaddingBackground) { + CommonBorderPaddingBackground cbpb = (CommonBorderPaddingBackground)obj; + return (this.backgroundAttachment == cbpb.backgroundAttachment + && this.backgroundColor == cbpb.backgroundColor + && this.backgroundImage.equals(cbpb.backgroundImage) + && this.backgroundPositionHorizontal == cbpb.backgroundPositionHorizontal + && this.backgroundPositionVertical == cbpb.backgroundPositionVertical + && this.backgroundRepeat == cbpb.backgroundRepeat + && this.borderInfo[BEFORE] == cbpb.borderInfo[BEFORE] + && this.borderInfo[AFTER] == cbpb.borderInfo[AFTER] + && this.borderInfo[START] == cbpb.borderInfo[START] + && this.borderInfo[END] == cbpb.borderInfo[END] + && this.padding[BEFORE] == cbpb.padding[BEFORE] + && this.padding[AFTER] == cbpb.padding[AFTER] + && this.padding[START] == cbpb.padding[START] + && this.padding[END] == cbpb.padding[END]); + } + + return false; + } + + /** {@inheritDoc} */ + public int hashCode() { + if (this.hash == -1) { + int hash = 17; + hash = 37 * hash + backgroundAttachment; + hash = 37 * hash + (backgroundColor == null ? 0 : backgroundColor.hashCode()); + hash = 37 * hash + (backgroundImage == null ? 0 : backgroundImage.hashCode()); + hash = 37 * hash + (backgroundPositionHorizontal == null ? 0 : backgroundPositionHorizontal.hashCode()); + hash = 37 * hash + (backgroundPositionVertical == null ? 0 : backgroundPositionVertical.hashCode()); + hash = 37 * hash + backgroundRepeat; + hash = 37 * hash + (borderInfo[BEFORE] == null ? 0 : borderInfo[BEFORE].hashCode()); + hash = 37 * hash + (borderInfo[AFTER] == null ? 0 : borderInfo[AFTER].hashCode()); + hash = 37 * hash + (borderInfo[START] == null ? 0 : borderInfo[START].hashCode()); + hash = 37 * hash + (borderInfo[END] == null ? 0 : borderInfo[END].hashCode()); + hash = 37 * hash + (padding[BEFORE] == null ? 0 : padding[BEFORE].hashCode()); + hash = 37 * hash + (padding[AFTER] == null ? 0 : padding[AFTER].hashCode()); + hash = 37 * hash + (padding[START] == null ? 0 : padding[START].hashCode()); + hash = 37 * hash + (padding[END] == null ? 0 : padding[END].hashCode()); + this.hash = hash; + } + + return this.hash; + } } diff --git a/src/java/org/apache/fop/fo/properties/CondLengthProperty.java b/src/java/org/apache/fop/fo/properties/CondLengthProperty.java index 34e72b09d..15d430051 100644 --- a/src/java/org/apache/fop/fo/properties/CondLengthProperty.java +++ b/src/java/org/apache/fop/fo/properties/CondLengthProperty.java @@ -31,8 +31,16 @@ import org.apache.fop.fo.expr.PropertyException; * Superclass for properties that have conditional lengths */ public class CondLengthProperty extends Property implements CompoundDatatype { + + /** cache holding canonical instances (for absolute conditional lengths) */ + private static final PropertyCache cache = new PropertyCache(CondLengthProperty.class); + + /** components */ private Property length; private EnumProperty conditionality; + + private boolean isCached = false; + private int hash = -1; /** * Inner class for creating instances of CondLengthProperty @@ -71,6 +79,11 @@ public class CondLengthProperty extends Property implements CompoundDatatype { */ public void setComponent(int cmpId, Property cmpnValue, boolean bIsDefault) { + if (isCached) { + throw new IllegalStateException( + "CondLengthProperty.setComponent() called on a cached value!"); + } + if (cmpId == CP_LENGTH) { length = cmpnValue; } else if (cmpId == CP_CONDITIONALITY) { @@ -144,7 +157,15 @@ public class CondLengthProperty extends Property implements CompoundDatatype { * @return this.condLength */ public CondLengthProperty getCondLength() { - return this; + if (this.length.getLength().isAbsolute()) { + CondLengthProperty clp = (CondLengthProperty) cache.fetch(this); + if (clp == this) { + isCached = true; + } + return clp; + } else { + return this; + } } /** @@ -162,4 +183,28 @@ public class CondLengthProperty extends Property implements CompoundDatatype { return this; } + /** {@inheritDoc} */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof CondLengthProperty) { + CondLengthProperty clp = (CondLengthProperty)obj; + return (this.length == clp.length + && this.conditionality == clp.conditionality); + } + return false; + } + + /** {@inheritDoc} */ + public int hashCode() { + if (this.hash == -1) { + int hash = 17; + hash = 37 * hash + (length == null ? 0 : length.hashCode()); + hash = 37 * hash + (conditionality == null ? 0 : conditionality.hashCode()); + this.hash = hash; + } + return this.hash; + } } diff --git a/src/java/org/apache/fop/fo/properties/PropertyCache.java b/src/java/org/apache/fop/fo/properties/PropertyCache.java index b5f4f90ba..6f87c0c45 100644 --- a/src/java/org/apache/fop/fo/properties/PropertyCache.java +++ b/src/java/org/apache/fop/fo/properties/PropertyCache.java @@ -344,6 +344,32 @@ public final class PropertyCache { return (CommonFont) fetch((Object) cf); } + /** + * Checks if the given {@link CommonBorderPaddingBackground} is present in the cache - + * if so, returns a reference to the cached instance. + * Otherwise the given object is added to the cache and returned. + * + * @param cbpb the CommonBorderPaddingBackground instance to check for + * @return the cached instance + */ + public final CommonBorderPaddingBackground fetch(CommonBorderPaddingBackground cbpb) { + + return (CommonBorderPaddingBackground) fetch((Object) cbpb); + } + + /** + * Checks if the given {@link CommonBorderPaddingBackground.BorderInfo} is present in the cache - + * if so, returns a reference to the cached instance. + * Otherwise the given object is added to the cache and returned. + * + * @param bi the BorderInfo instance to check for + * @return the cached instance + */ + public final CommonBorderPaddingBackground.BorderInfo fetch(CommonBorderPaddingBackground.BorderInfo bi) { + + return (CommonBorderPaddingBackground.BorderInfo) fetch((Object) bi); + } + /** {@inheritDoc} */ public String toString() { return super.toString() + "[runtimeType=" + this.runtimeType + "]"; -- cgit v1.2.3 From 3a673b30d2500d848fb1c2bfdd74c9b686484f92 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 12 May 2008 15:24:06 +0000 Subject: Tweak: avoid preloading the background-image with each pass through the constructor; only do so for non-cached instances git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655522 13f79535-47bb-0310-9956-ffa450edef68 --- .../properties/CommonBorderPaddingBackground.java | 59 +++++++++++++--------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index 1c54d63db..2a3c880d0 100755 --- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java +++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java @@ -306,20 +306,6 @@ public class CommonBorderPaddingBackground { Constants.PR_BACKGROUND_POSITION_HORIZONTAL).getLength(); backgroundPositionVertical = pList.get( Constants.PR_BACKGROUND_POSITION_VERTICAL).getLength(); - - //Additional processing: preload image - String uri = URISpecification.getURL(backgroundImage); - FOUserAgent userAgent = pList.getFObj().getUserAgent(); - ImageManager manager = userAgent.getFactory().getImageManager(); - ImageSessionContext sessionContext = userAgent.getImageSessionContext(); - ImageInfo info; - try { - info = manager.getImageInfo(uri, sessionContext); - this.backgroundImageInfo = info; - } catch (Exception e) { - Property.log.error("Background image not available: " + uri); - } - //TODO Report to caller so he can decide to throw an exception } initBorderInfo(pList, BEFORE, @@ -358,7 +344,7 @@ public class CommonBorderPaddingBackground { CommonBorderPaddingBackground newInstance = new CommonBorderPaddingBackground(pList); - + CommonBorderPaddingBackground cachedInstance = null; /* if padding-* and background-position-* resolve to absolute lengths * the whole instance can be cached */ if ((newInstance.padding[BEFORE] == null || newInstance.padding[BEFORE].getLength().isAbsolute()) @@ -367,10 +353,28 @@ public class CommonBorderPaddingBackground { && (newInstance.padding[END] == null || newInstance.padding[END].getLength().isAbsolute()) && (newInstance.backgroundPositionHorizontal == null || newInstance.backgroundPositionHorizontal.isAbsolute()) && (newInstance.backgroundPositionVertical == null || newInstance.backgroundPositionVertical.isAbsolute())) { - return cache.fetch(newInstance); + cachedInstance = cache.fetch(newInstance); + } + + /* for non-cached, or not-yet-cached instances, preload the image */ + if (cachedInstance == null + || (cachedInstance == newInstance)) { + //Additional processing: preload image + String uri = URISpecification.getURL(newInstance.backgroundImage); + FOUserAgent userAgent = pList.getFObj().getUserAgent(); + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageSessionContext sessionContext = userAgent.getImageSessionContext(); + ImageInfo info; + try { + info = manager.getImageInfo(uri, sessionContext); + newInstance.backgroundImageInfo = info; + } catch (Exception e) { + Property.log.error("Background image not available: " + uri); + } + //TODO Report to caller so he can decide to throw an exception } - return newInstance; + return (cachedInstance != null ? cachedInstance : newInstance); } private void initBorderInfo(PropertyList pList, int side, @@ -511,9 +515,10 @@ public class CommonBorderPaddingBackground { } /** + * The border-color for the given side * - * @param side - * @return + * @param side one of {@link #BEFORE}, {@link #AFTER}, {@link #START}, {@link #END} + * @return the border-color for the given side */ public Color getBorderColor(int side) { if (borderInfo[side] != null) { @@ -524,9 +529,10 @@ public class CommonBorderPaddingBackground { } /** + * The border-style for the given side * - * @param side - * @return + * @param side one of {@link #BEFORE}, {@link #AFTER}, {@link #START}, {@link #END} + * @return the border-style for the given side */ public int getBorderStyle(int side) { if (borderInfo[side] != null) { @@ -537,11 +543,14 @@ public class CommonBorderPaddingBackground { } /** + * Return the padding for the given side, taking into account + * the conditionality and evaluating any percentages in the given + * context. * - * @param side - * @param discard - * @param context - * @return + * @param side one of {@link #BEFORE}, {@link #AFTER}, {@link #START}, {@link #END} + * @param discard true if the conditionality component should be considered + * @param context the context for percentage-resolution + * @return the computed padding for the given side */ public int getPadding(int side, boolean discard, PercentBaseContext context) { if ((padding[side] == null) || (discard && padding[side].isDiscard())) { -- cgit v1.2.3 From 5628bad5f30397f9ec328c43f4009b4ca7044f62 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 12 May 2008 15:34:49 +0000 Subject: Avoid an error if unspecified... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655531 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/properties/CommonBorderPaddingBackground.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index 2a3c880d0..35913ce3a 100755 --- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java +++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java @@ -357,8 +357,9 @@ public class CommonBorderPaddingBackground { } /* for non-cached, or not-yet-cached instances, preload the image */ - if (cachedInstance == null - || (cachedInstance == newInstance)) { + if ((cachedInstance == null + || cachedInstance == newInstance) + && !("".equals(newInstance.backgroundImage))) { //Additional processing: preload image String uri = URISpecification.getURL(newInstance.backgroundImage); FOUserAgent userAgent = pList.getFObj().getUserAgent(); -- cgit v1.2.3 From 53e9608f1b360ac04379385522f95acbb60d91d6 Mon Sep 17 00:00:00 2001 From: Simon Pepping Date: Mon, 12 May 2008 17:53:21 +0000 Subject: Restore the previous behaviour of the column-number property, viz. if it is negative, it is set the next free column git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655578 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/table/TableFObj.java | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index ca1afa622..adeb2eadd 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -28,8 +28,11 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.fo.properties.EnumNumber; +import org.apache.fop.fo.properties.EnumProperty; import org.apache.fop.fo.properties.NumberProperty; import org.apache.fop.fo.properties.Property; +import org.apache.fop.fo.properties.PropertyMaker; import org.apache.fop.layoutmgr.table.CollapsingBorderModel; /** @@ -117,7 +120,7 @@ public abstract class TableFObj extends FObj { * PropertyMaker subclass for the column-number property * */ - public static class ColumnNumberPropertyMaker extends NumberProperty.PositiveIntegerMaker { + public static class ColumnNumberPropertyMaker extends PropertyMaker { /** * Constructor @@ -172,6 +175,32 @@ public abstract class TableFObj extends FObj { return p; } + + /** + * If the value is not positive, return a property whose value is the next column number + * + * {@inheritDoc} + */ + public Property convertProperty(Property p, + PropertyList propertyList, FObj fo) + throws PropertyException { + if (p instanceof EnumProperty) { + return EnumNumber.getInstance(p); + } + Number val = p.getNumber(); + if (val != null) { + int i = Math.round(val.floatValue()); + if (i <= 0) { + ColumnNumberManagerHolder parent = + (ColumnNumberManagerHolder) propertyList.getParentFObj(); + ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); + i = columnIndexManager.getCurrentColumnNumber(); + } + return NumberProperty.getInstance(i); + } + return convertPropertyDatatype(p, propertyList, fo); + } + } /** {@inheritDoc} */ -- cgit v1.2.3 From 48d184be76c8760b3bace47b118087969145b646 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 12 May 2008 19:06:04 +0000 Subject: Added missing file from r655500 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655601 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/PropertyList.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java index b6766bfe9..e3e9f9f83 100644 --- a/src/java/org/apache/fop/fo/PropertyList.java +++ b/src/java/org/apache/fop/fo/PropertyList.java @@ -349,13 +349,10 @@ public abstract class PropertyList { findBasePropertyName(propertyName)); int subpropId = FOPropertyMapping.getSubPropertyId( findSubPropertyName(propertyName)); - - if (propId == -1 - || (subpropId == -1 - && findSubPropertyName(propertyName) != null)) { - return false; - } - return true; + + return !(propId == -1 + || (subpropId == -1 + && findSubPropertyName(propertyName) != null)); } /** @@ -574,7 +571,7 @@ public abstract class PropertyList { */ public CommonBorderPaddingBackground getBorderPaddingBackgroundProps() throws PropertyException { - return new CommonBorderPaddingBackground(this); + return CommonBorderPaddingBackground.getInstance(this); } /** -- cgit v1.2.3 From fd57079cbeda429803cff6cf2b8142146f5fef45 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 12 May 2008 19:37:39 +0000 Subject: Put the resolutions of collapsed borders together into the CollapsingBorderResolver class. The previous scheme allowed for early resolution of borders where possible, but made it hard to understand since the resolution was spread in the various table classes. Now everything is done inside a single class git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655614 13f79535-47bb-0310-9956-ffa450edef68 --- .../fo/flow/table/CollapsingBorderResolver.java | 43 +++++++++++++++++++--- .../org/apache/fop/fo/flow/table/GridUnit.java | 18 +++++++++ src/java/org/apache/fop/fo/flow/table/Table.java | 10 +---- .../org/apache/fop/fo/flow/table/TableBody.java | 9 ----- .../org/apache/fop/fo/flow/table/TableCell.java | 8 ---- .../org/apache/fop/fo/flow/table/TableColumn.java | 9 ----- .../org/apache/fop/fo/flow/table/TableFObj.java | 38 ++++--------------- .../org/apache/fop/fo/flow/table/TableRow.java | 9 ----- 8 files changed, 63 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index 86bf40f2f..2d48380ee 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -24,6 +24,7 @@ import java.util.Iterator; import java.util.List; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.layoutmgr.table.CollapsingBorderModel; /** * A class that implements the border-collapsing model. @@ -32,6 +33,8 @@ class CollapsingBorderResolver implements BorderResolver { private Table table; + private CollapsingBorderModel collapsingBorderModel; + /** * The previously registered row, either in the header or the body(-ies), but not in * the footer (handled separately). @@ -74,6 +77,9 @@ class CollapsingBorderResolver implements BorderResolver { protected boolean firstInPart; + private BorderSpecification borderStartTableAndBody; + private BorderSpecification borderEndTableAndBody; + /** * Integrates border-before specified on the table and its column. * @@ -174,6 +180,10 @@ class CollapsingBorderResolver implements BorderResolver { void startPart(TableBody part) { tablePart = part; firstInPart = true; + borderStartTableAndBody = collapsingBorderModel.determineWinner(table.borderStart, + tablePart.borderStart); + borderEndTableAndBody = collapsingBorderModel.determineWinner(table.borderEnd, + tablePart.borderEnd); } /** @@ -188,6 +198,8 @@ class CollapsingBorderResolver implements BorderResolver { * @param container the containing element */ void endRow(List/**/ row, TableCellContainer container) { + BorderSpecification borderStart = borderStartTableAndBody; + BorderSpecification borderEnd = borderEndTableAndBody; // Resolve before- and after-borders for the table-row if (container instanceof TableRow) { TableRow tableRow = (TableRow) container; @@ -200,6 +212,10 @@ class CollapsingBorderResolver implements BorderResolver { gu.integrateBorderSegment(CommonBorderPaddingBackground.AFTER, tableRow, last, last, true); } + borderStart = collapsingBorderModel.determineWinner(borderStart, + tableRow.borderStart); + borderEnd = collapsingBorderModel.determineWinner(borderEnd, + tableRow.borderEnd); } if (firstInPart) { // Integrate the border-before of the part @@ -215,7 +231,7 @@ class CollapsingBorderResolver implements BorderResolver { Iterator colIter = table.getColumns().iterator(); TableColumn col = (TableColumn) colIter.next(); gu.integrateBorderSegment(CommonBorderPaddingBackground.START, col); - gu.integrateBorderSegment(CommonBorderPaddingBackground.START, container); + gu.integrateBorderSegment(CommonBorderPaddingBackground.START, borderStart); while (guIter.hasNext()) { GridUnit nextGU = (GridUnit) guIter.next(); TableColumn nextCol = (TableColumn) colIter.next(); @@ -228,7 +244,7 @@ class CollapsingBorderResolver implements BorderResolver { col = nextCol; } gu.integrateBorderSegment(CommonBorderPaddingBackground.END, col); - gu.integrateBorderSegment(CommonBorderPaddingBackground.END, container); + gu.integrateBorderSegment(CommonBorderPaddingBackground.END, borderEnd); } void endPart() { @@ -371,7 +387,26 @@ class CollapsingBorderResolver implements BorderResolver { CollapsingBorderResolver(Table table) { this.table = table; + collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table.getBorderCollapse()); firstInTable = true; + // Resolve before and after borders between the table and each table-column + int index = 0; + do { + TableColumn col = table.getColumn(index); + // See endRow method in ResolverInHeader for an explanation of the hack + col.borderBefore.integrateSegment(table.borderBefore, true, false, true); + col.borderBefore.leadingTrailing = col.borderBefore.rest; + col.borderAfter.integrateSegment(table.borderAfter, true, false, true); + col.borderAfter.leadingTrailing = col.borderAfter.rest; + /* + * TODO The border resolution must be done only once for each table column, + * even if it's repeated; otherwise, re-resolving against the table's borders + * will lead to null border specifications. + * + * Eventually table columns should probably be cloned instead. + */ + index += col.getNumberColumnsRepeated(); + } while (index < table.getNumberOfColumns()); } /** {@inheritDoc} */ @@ -388,9 +423,7 @@ class CollapsingBorderResolver implements BorderResolver { // No header, leading borders determined by the table leadingBorders = new ArrayList(table.getNumberOfColumns()); for (Iterator colIter = table.getColumns().iterator(); colIter.hasNext();) { - // See endRow method in ResolverInHeader for an explanation of the hack ConditionalBorder border = ((TableColumn) colIter.next()).borderBefore; - border.leadingTrailing = border.rest; leadingBorders.add(border); } } @@ -402,9 +435,7 @@ class CollapsingBorderResolver implements BorderResolver { // No footer, trailing borders determined by the table trailingBorders = new ArrayList(table.getNumberOfColumns()); for (Iterator colIter = table.getColumns().iterator(); colIter.hasNext();) { - // See endRow method in ResolverInHeader for an explanation of the hack ConditionalBorder border = ((TableColumn) colIter.next()).borderAfter; - border.leadingTrailing = border.rest; trailingBorders.add(border); } } diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java index ec84dd200..3d48a6836 100644 --- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java @@ -374,6 +374,24 @@ public class GridUnit { } } + /** + * For the given side, integrates in the conflict resolution the given border segment. + * + * @param side the side to consider (one of CommonBorderPaddingBackground.START|END) + * @param segment a border specification to integrate at the given side + */ + void integrateBorderSegment(int side, BorderSpecification segment) { + switch(side) { + case CommonBorderPaddingBackground.START: + borderStart = collapsingBorderModel.determineWinner(borderStart, segment); + break; + case CommonBorderPaddingBackground.END: + borderEnd = collapsingBorderModel.determineWinner(borderEnd, segment); + break; + default: assert false; + } + } + void integrateCompetingBorder(int side, ConditionalBorder competitor, boolean withNormal, boolean withLeadingTrailing, boolean withRest) { switch (side) { diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index 69d5fbb9d..5b96a668e 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -265,7 +265,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { case FO_TABLE_HEADER: case FO_TABLE_FOOTER: case FO_TABLE_BODY: - if (!columnsFinalized) { + if (!inMarker() && !columnsFinalized) { columnsFinalized = true; if (hasExplicitColumns) { finalizeColumns(); @@ -291,14 +291,6 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } } - /** {@inheritDoc} */ - protected void setCollapsedBorders() { - createBorder(CommonBorderPaddingBackground.START); - createBorder(CommonBorderPaddingBackground.END); - createBorder(CommonBorderPaddingBackground.BEFORE); - createBorder(CommonBorderPaddingBackground.AFTER); - } - private void finalizeColumns() throws FOPException { for (int i = 0; i < columns.size(); i++) { if (columns.get(i) == null) { diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index 0214e7336..b4e48d2e6 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -211,15 +211,6 @@ public class TableBody extends TableCellContainer { super.addChildNode(child); } - /** {inheritDoc} */ - protected void setCollapsedBorders() { - Table table = (Table) parent; - createBorder(CommonBorderPaddingBackground.START, table); - createBorder(CommonBorderPaddingBackground.END, table); - createBorder(CommonBorderPaddingBackground.BEFORE); - createBorder(CommonBorderPaddingBackground.AFTER); - } - void addRowGroup(List rowGroup) { rowGroups.add(rowGroup); } diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java index b1dfd86c3..2781bf082 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCell.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java @@ -133,14 +133,6 @@ public class TableCell extends TableFObj { } } - /** {@inheritDoc} */ - protected void setCollapsedBorders() { - createBorder(CommonBorderPaddingBackground.BEFORE); - createBorder(CommonBorderPaddingBackground.AFTER); - createBorder(CommonBorderPaddingBackground.START); - createBorder(CommonBorderPaddingBackground.END); - } - /** {@inheritDoc} */ public boolean generatesReferenceAreas() { return true; diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java index 0ace2c311..6916e090b 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java +++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java @@ -133,15 +133,6 @@ public class TableColumn extends TableFObj { setCollapsedBorders(); } - /** {@inheritDoc} */ - protected void setCollapsedBorders() { - Table table = (Table) parent; - createBorder(CommonBorderPaddingBackground.BEFORE, table); - createBorder(CommonBorderPaddingBackground.AFTER, table); - createBorder(CommonBorderPaddingBackground.START); - createBorder(CommonBorderPaddingBackground.END); - } - /** {@inheritDoc} */ public void endOfNode() throws FOPException { getFOEventHandler().endColumn(this); diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index adeb2eadd..6bc113fd0 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -226,7 +226,12 @@ public abstract class TableFObj extends FObj { * Prepares the borders of this element if the collapsing-border model is in use. * Conflict resolution with parent elements is done where applicable. */ - protected abstract void setCollapsedBorders(); + protected void setCollapsedBorders() { + createBorder(CommonBorderPaddingBackground.START); + createBorder(CommonBorderPaddingBackground.END); + createBorder(CommonBorderPaddingBackground.BEFORE); + createBorder(CommonBorderPaddingBackground.AFTER); + } /** * Creates a BorderSpecification from the border set on the given side. If no border @@ -234,7 +239,7 @@ public abstract class TableFObj extends FObj { * * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END */ - protected void createBorder(int side) { + private void createBorder(int side) { BorderSpecification borderSpec = new BorderSpecification( getCommonBorderPaddingBackground().getBorderInfo(side), getNameId()); switch (side) { @@ -253,33 +258,4 @@ public abstract class TableFObj extends FObj { default: assert false; } } - - /** - * Creates a BorderSpecification from the border set on the given side, performing - * conflict resolution with the same border on the given object. - * - * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END - * @param competitor a parent table element whose side coincides with the given side - * on this element - */ - protected void createBorder(int side, TableFObj competitor) { - createBorder(side); - switch (side) { - case CommonBorderPaddingBackground.BEFORE: - borderBefore.integrateSegment(competitor.borderBefore, true, true, true); - break; - case CommonBorderPaddingBackground.AFTER: - borderAfter.integrateSegment(competitor.borderAfter, true, true, true); - break; - case CommonBorderPaddingBackground.START: - borderStart = collapsingBorderModel.determineWinner(borderStart, - competitor.borderStart); - break; - case CommonBorderPaddingBackground.END: - borderEnd = collapsingBorderModel.determineWinner(borderEnd, - competitor.borderEnd); - break; - default: assert false; - } - } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java index bf7b16dca..3be794fbd 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableRow.java +++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java @@ -138,15 +138,6 @@ public class TableRow extends TableCellContainer { return true; } - /** {@inheritDoc} */ - protected void setCollapsedBorders() { - TableBody body = (TableBody) parent; - createBorder(CommonBorderPaddingBackground.START, body); - createBorder(CommonBorderPaddingBackground.END, body); - createBorder(CommonBorderPaddingBackground.BEFORE); - createBorder(CommonBorderPaddingBackground.AFTER); - } - /** @return the "break-after" property. */ public int getBreakAfter() { return breakAfter; -- cgit v1.2.3 From 6ddc5c33ed8f5281590b6242520171b7cc7ca7ae Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Tue, 13 May 2008 07:58:31 +0000 Subject: Added support for auto-generated initial value for the "id" property. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655766 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOEventHandler.java | 12 ++++++ src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- .../apache/fop/fo/properties/StringProperty.java | 47 ++++++++++++++++++++++ test/fotree/testcases/id_auto.fo | 28 +++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 test/fotree/testcases/id_auto.fo (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 5a9a5bb9d..a2a67d594 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -95,6 +95,11 @@ public abstract class FOEventHandler { */ private boolean inMarker = false; + /** + * Keeps track of automatically generated ids in the current document + */ + private long lastGeneratedId = 1; + /** * Main constructor * @param foUserAgent the apps.FOUserAgent instance for this process @@ -168,6 +173,13 @@ public abstract class FOEventHandler { return this.inMarker; } + /** + * Return the next value for automatically generated ids + */ + public long getNextId() { + return this.lastGeneratedId++; + } + /** * This method is called to indicate the start of a new document run. * @throws SAXException In case of a problem diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 8fed90a35..96cbc5329 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -2503,7 +2503,7 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("content-type", m); // id - m = new StringProperty.Maker(PR_ID); + m = new StringProperty.IdMaker(PR_ID); m.setInherited(false); m.setDefault(""); addPropertyMaker("id", m); diff --git a/src/java/org/apache/fop/fo/properties/StringProperty.java b/src/java/org/apache/fop/fo/properties/StringProperty.java index 194170fec..e7c477a27 100644 --- a/src/java/org/apache/fop/fo/properties/StringProperty.java +++ b/src/java/org/apache/fop/fo/properties/StringProperty.java @@ -21,6 +21,11 @@ package org.apache.fop.fo.properties; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.FOValidationEventProducer; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.expr.PropertyException; + +import java.util.Set; /** * Exists primarily as a container for its Maker inner class, which is @@ -77,6 +82,48 @@ public final class StringProperty extends Property { } + /** + * Inner class dedicated to the "id" property, which should provide a random + * unique identifier as an initial value. + * The values for "id" are never cached, as they're typically valid for one + * document. + */ + public static class IdMaker extends PropertyMaker { + + /** + * @param propId the id of the property for which the maker should be created + */ + public IdMaker(int propId) { + super(propId); + } + + /** {@inheritDoc} */ + public Property make(PropertyList propertyList) throws PropertyException { + String newId = "FO#"; + newId += propertyList.getFObj().getFOEventHandler().getNextId(); + return new StringProperty(newId); + } + + /** {@inheritDoc} */ + public Property make(PropertyList propertyList, + String value, + FObj fo) throws PropertyException { + + Property idProp; + + //no parsing necessary; just return a new StringProperty + //TODO: Should we move validation here? (see FObj#checkId()) + if ("".equals(value)) { + //if an empty string was specified, return the default + idProp = this.make(propertyList); + } else { + idProp = new StringProperty(value); + } + + return idProp; + } + } + /** cache containing all canonical StringProperty instances */ private static final PropertyCache cache = new PropertyCache(StringProperty.class); diff --git a/test/fotree/testcases/id_auto.fo b/test/fotree/testcases/id_auto.fo new file mode 100644 index 000000000..414cbea8a --- /dev/null +++ b/test/fotree/testcases/id_auto.fo @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + Hello + + World! + + + + ઎ + + + + + -- cgit v1.2.3 From d1c9f01c49ee2c03ea698861c4c8e339573a2009 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Tue, 13 May 2008 08:11:12 +0000 Subject: Alter auto-id naming to avoid confusion with URI fragment identifiers git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655771 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/properties/StringProperty.java | 2 +- test/fotree/testcases/id_auto.fo | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/properties/StringProperty.java b/src/java/org/apache/fop/fo/properties/StringProperty.java index e7c477a27..8880921de 100644 --- a/src/java/org/apache/fop/fo/properties/StringProperty.java +++ b/src/java/org/apache/fop/fo/properties/StringProperty.java @@ -99,7 +99,7 @@ public final class StringProperty extends Property { /** {@inheritDoc} */ public Property make(PropertyList propertyList) throws PropertyException { - String newId = "FO#"; + String newId = "FO_"; newId += propertyList.getFObj().getFOEventHandler().getNextId(); return new StringProperty(newId); } diff --git a/test/fotree/testcases/id_auto.fo b/test/fotree/testcases/id_auto.fo index 414cbea8a..8e8d03b7e 100644 --- a/test/fotree/testcases/id_auto.fo +++ b/test/fotree/testcases/id_auto.fo @@ -1,27 +1,27 @@ - + - + - + - + - + - + Hello World! - + ઎ - + -- cgit v1.2.3 From 1781e21b478c18a34a8050ad5a31b36292905ca6 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Tue, 13 May 2008 08:20:57 +0000 Subject: Javadoc fixups git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655775 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOEventHandler.java | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index a2a67d594..149e614d0 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -79,7 +79,11 @@ public abstract class FOEventHandler { * This is used so we know if the FO tree contains duplicates. */ private Set idReferences = new HashSet(); - + /** + * Keeps track of the last automatically generated id in the current document + */ + private long lastGeneratedId = 1; + /** * The property list maker. */ @@ -95,11 +99,6 @@ public abstract class FOEventHandler { */ private boolean inMarker = false; - /** - * Keeps track of automatically generated ids in the current document - */ - private long lastGeneratedId = 1; - /** * Main constructor * @param foUserAgent the apps.FOUserAgent instance for this process @@ -136,13 +135,17 @@ public abstract class FOEventHandler { /** * Return the propertyListMaker. - */ + * + * @return the currently active {@link PropertyListMaker} + */ public PropertyListMaker getPropertyListMaker() { return propertyListMaker; } /** * Set a new propertyListMaker. + * + * @param propertyListMaker the new {@link PropertyListMaker} to use */ public void setPropertyListMaker(PropertyListMaker propertyListMaker) { this.propertyListMaker = propertyListMaker; @@ -160,6 +163,9 @@ public abstract class FOEventHandler { * Switch to or from marker context * (used by FOTreeBuilder when processing * a marker) + * + * @param inMarker true if a marker is being processed; + * false otherwise * */ protected void switchMarkerContext(boolean inMarker) { @@ -168,6 +174,8 @@ public abstract class FOEventHandler { /** * Check whether in marker context + * + * @return true if a marker is being processed */ protected boolean inMarker() { return this.inMarker; @@ -175,6 +183,8 @@ public abstract class FOEventHandler { /** * Return the next value for automatically generated ids + * + * @return the next value to append to automatically generated ids */ public long getNextId() { return this.lastGeneratedId++; -- cgit v1.2.3 From 2c493c4789790b291b7c0213c9e82c6b7e63cf80 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Tue, 13 May 2008 09:58:01 +0000 Subject: Undo r655765, which was causing NPEs in the layout-tests git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655791 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOEventHandler.java | 13 ------- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- .../apache/fop/fo/properties/StringProperty.java | 44 +--------------------- test/fotree/testcases/id_auto.fo | 28 -------------- 4 files changed, 2 insertions(+), 85 deletions(-) delete mode 100644 test/fotree/testcases/id_auto.fo (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 149e614d0..7521d398c 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -79,10 +79,6 @@ public abstract class FOEventHandler { * This is used so we know if the FO tree contains duplicates. */ private Set idReferences = new HashSet(); - /** - * Keeps track of the last automatically generated id in the current document - */ - private long lastGeneratedId = 1; /** * The property list maker. @@ -181,15 +177,6 @@ public abstract class FOEventHandler { return this.inMarker; } - /** - * Return the next value for automatically generated ids - * - * @return the next value to append to automatically generated ids - */ - public long getNextId() { - return this.lastGeneratedId++; - } - /** * This method is called to indicate the start of a new document run. * @throws SAXException In case of a problem diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 96cbc5329..8fed90a35 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -2503,7 +2503,7 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("content-type", m); // id - m = new StringProperty.IdMaker(PR_ID); + m = new StringProperty.Maker(PR_ID); m.setInherited(false); m.setDefault(""); addPropertyMaker("id", m); diff --git a/src/java/org/apache/fop/fo/properties/StringProperty.java b/src/java/org/apache/fop/fo/properties/StringProperty.java index 8880921de..087feb350 100644 --- a/src/java/org/apache/fop/fo/properties/StringProperty.java +++ b/src/java/org/apache/fop/fo/properties/StringProperty.java @@ -81,49 +81,7 @@ public final class StringProperty extends Property { } } - - /** - * Inner class dedicated to the "id" property, which should provide a random - * unique identifier as an initial value. - * The values for "id" are never cached, as they're typically valid for one - * document. - */ - public static class IdMaker extends PropertyMaker { - - /** - * @param propId the id of the property for which the maker should be created - */ - public IdMaker(int propId) { - super(propId); - } - - /** {@inheritDoc} */ - public Property make(PropertyList propertyList) throws PropertyException { - String newId = "FO_"; - newId += propertyList.getFObj().getFOEventHandler().getNextId(); - return new StringProperty(newId); - } - - /** {@inheritDoc} */ - public Property make(PropertyList propertyList, - String value, - FObj fo) throws PropertyException { - - Property idProp; - - //no parsing necessary; just return a new StringProperty - //TODO: Should we move validation here? (see FObj#checkId()) - if ("".equals(value)) { - //if an empty string was specified, return the default - idProp = this.make(propertyList); - } else { - idProp = new StringProperty(value); - } - - return idProp; - } - } - + /** cache containing all canonical StringProperty instances */ private static final PropertyCache cache = new PropertyCache(StringProperty.class); diff --git a/test/fotree/testcases/id_auto.fo b/test/fotree/testcases/id_auto.fo deleted file mode 100644 index 8e8d03b7e..000000000 --- a/test/fotree/testcases/id_auto.fo +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - Hello - - World! - - - - ઎ - - - - - -- cgit v1.2.3 From 887cdbf9e0cbf8f9891745f0333399d7d10e6083 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Tue, 13 May 2008 10:37:59 +0000 Subject: Use absolute initial value instead of percentage (better for memory consumption) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@655801 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOPropertyMapping.java | 34 +++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 8fed90a35..60317cf0d 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -601,8 +601,8 @@ public final class FOPropertyMapping implements Constants { // background-position-horizontal m = new LengthProperty.Maker(PR_BACKGROUND_POSITION_HORIZONTAL); m.setInherited(false); - m.setDefault("0%"); - m.addKeyword("left", "0%"); + m.setDefault("0pt"); + m.addKeyword("left", "0pt"); m.addKeyword("center", "50%"); m.addKeyword("right", "100%"); m.setPercentBase(LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL); @@ -612,8 +612,8 @@ public final class FOPropertyMapping implements Constants { // background-position-vertical m = new LengthProperty.Maker(PR_BACKGROUND_POSITION_VERTICAL); m.setInherited(false); - m.setDefault("0%"); - m.addKeyword("top", "0%"); + m.setDefault("0pt"); + m.addKeyword("top", "0pt"); m.addKeyword("center", "50%"); m.addKeyword("bottom", "100%"); m.setPercentBase(LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL); @@ -2568,29 +2568,29 @@ public final class FOPropertyMapping implements Constants { // background-position m = new BackgroundPositionShorthand.Maker(PR_BACKGROUND_POSITION); m.setInherited(false); - m.addKeyword("left", "0% 50%"); - m.addKeyword("left center", "0% 50%"); - m.addKeyword("center left", "0% 50%"); + m.addKeyword("left", "0pt 50%"); + m.addKeyword("left center", "0pt 50%"); + m.addKeyword("center left", "0pt 50%"); m.addKeyword("right", "100% 50%"); m.addKeyword("right center", "100% 50%"); m.addKeyword("center right", "100% 50%"); m.addKeyword("center", "50% 50%"); m.addKeyword("center center", "50% 50%"); - m.addKeyword("top", "50% 0%"); - m.addKeyword("top center", "50% 0%"); - m.addKeyword("center top", "50% 0%"); + m.addKeyword("top", "50% 0pt"); + m.addKeyword("top center", "50% 0pt"); + m.addKeyword("center top", "50% 0pt"); m.addKeyword("bottom", "50% 100%"); m.addKeyword("bottom center", "50% 100%"); m.addKeyword("center bottom", "50% 100%"); - m.addKeyword("top left", "0% 0%"); - m.addKeyword("left top", "0% 0%"); - m.addKeyword("top right", "100% 0%"); - m.addKeyword("right top", "100% 0%"); - m.addKeyword("bottom left", "0% 100%"); - m.addKeyword("left bottom", "0% 100%"); + m.addKeyword("top left", "0pt 0pt"); + m.addKeyword("left top", "0pt 0pt"); + m.addKeyword("top right", "100% 0pt"); + m.addKeyword("right top", "100% 0pt"); + m.addKeyword("bottom left", "0pt 100%"); + m.addKeyword("left bottom", "0pt 100%"); m.addKeyword("bottom right", "100% 100%"); m.addKeyword("right bottom", "100% 100%"); - m.setDefault("0% 0%"); + m.setDefault("0pt 0pt"); m.setPercentBase(LengthBase.CUSTOM_BASE); m.setDatatypeParser(new BackgroundPositionShorthand.Parser()); addPropertyMaker("background-position", m); -- cgit v1.2.3 From 5ddc5de10c12ff703a4e26a8a5e5c25bb45dcfe3 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Wed, 14 May 2008 05:11:15 +0000 Subject: Avoid error-message if the text-node is white-space only. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@656104 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FObjMixed.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java index 698fc58f2..bf7383398 100644 --- a/src/java/org/apache/fop/fo/FObjMixed.java +++ b/src/java/org/apache/fop/fo/FObjMixed.java @@ -134,7 +134,8 @@ public abstract class FObjMixed extends FObj { if (foNameId == FO_BLOCK) { tmpText.createBlockPointers((org.apache.fop.fo.flow.Block) fo); ((FObjMixed) fo).lastFOTextProcessed = tmpText; - } else if (foNameId == FO_PAGE_SEQUENCE) { + } else if (foNameId == FO_PAGE_SEQUENCE + && tmpText.willCreateArea()) { log.error("Could not create block pointers." + " FOText w/o Block ancestor."); } -- cgit v1.2.3 From 45b7f434f711e1725bd43585006eb98d0e28b343 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 15 May 2008 08:33:19 +0000 Subject: Tweak: make sure the fo:flow's id is bound to the FObj git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@656546 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/pagination/Flow.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/pagination/Flow.java b/src/java/org/apache/fop/fo/pagination/Flow.java index 8e114c47f..d3682fa81 100644 --- a/src/java/org/apache/fop/fo/pagination/Flow.java +++ b/src/java/org/apache/fop/fo/pagination/Flow.java @@ -50,6 +50,7 @@ public class Flow extends FObj { /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { + super.bind(pList); flowName = pList.get(PR_FLOW_NAME).getString(); } -- cgit v1.2.3 From 00cfbeeb22039e7e37d123c318292e625eaddf79 Mon Sep 17 00:00:00 2001 From: Simon Pepping Date: Mon, 19 May 2008 19:02:18 +0000 Subject: Added event TableEventProducer.forceNextColumnNumber when TableFObj.ColumnNumberPropertyMaker forces a zero or negative column-number property to the next available column, because this is a FOP extension. Fixed TableFObj.ColumnNumberPropertyMaker.make to really report a cell overlap event. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@657921 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/EventFormatter.xml | 1 + src/java/org/apache/fop/fo/flow/table/TableEventProducer.java | 11 +++++++++++ src/java/org/apache/fop/fo/flow/table/TableFObj.java | 9 ++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml index 4bff75f85..3e6cc181e 100644 --- a/src/java/org/apache/fop/events/EventFormatter.xml +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -65,6 +65,7 @@ Any reference to it will be considered a reference to the first occurrence in th table-layout=\"fixed\" and column-width unspecified => falling back to proportional-column-width(1){{locator}} padding-* properties are not applicable to {elementName}, but a non-zero value for padding was found.{{locator}} {elementName} overlaps in column {column}. + Negative value {propValue} of property column-number of element {elementName} forced into the next available column number {columnNumber}.{{locator}} {breakBefore,if,break-before,break-after} ignored on {elementName} because of row spanning in progress (See XSL 1.1, {breakBefore,if,7.20.2,7.20.1}){{locator}} Image not found.[ URI: {uri}.]{{locator}} Image not available.[ URI: {uri}.] Reason:[ {reason}][ {e}]{{locator}} diff --git a/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java b/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java index 44ddcc038..9c4a82dd6 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java +++ b/src/java/org/apache/fop/fo/flow/table/TableEventProducer.java @@ -144,6 +144,17 @@ public interface TableEventProducer extends EventProducer { void cellOverlap(Object source, String elementName, int column, Locator loc) throws PropertyException; + /** + * @param source the event source + * @param elementName the name of the context node + * @param propValue the user-specified value of the column-number property + * @param columnNumber the generated value for the column-number property + * @param loc the location of the error or null + * @event.severity WARN + */ + void forceNextColumnNumber(Object source, String elementName, Number propValue, + int columnNumber, Locator loc); + /** * Break ignored due to row spanning. * @param source the event source diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 6bc113fd0..016046ae2 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -159,9 +159,8 @@ public abstract class TableFObj extends FObj { int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED) .getNumeric().getValue(); - int i = columnIndex - 1; - int lastIndex = (columnIndex + colSpan) - 1; - while (++i < lastIndex) { + int lastIndex = columnIndex - 1 + colSpan; + for (int i = columnIndex; i <= lastIndex; ++i) { if (columnIndexManager.isColumnNumberUsed(i)) { /* if column-number is already in use by another * cell/column => error! @@ -195,6 +194,10 @@ public abstract class TableFObj extends FObj { (ColumnNumberManagerHolder) propertyList.getParentFObj(); ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); i = columnIndexManager.getCurrentColumnNumber(); + TableEventProducer eventProducer = + TableEventProducer.Provider.get(fo.getUserAgent().getEventBroadcaster()); + eventProducer.forceNextColumnNumber(this, propertyList.getFObj().getName(), + val, i, fo.getLocator()); } return NumberProperty.getInstance(i); } -- cgit v1.2.3 From 3f7898c97421c9617c0b352ca8b0f23bf82d38ef Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Wed, 28 May 2008 15:24:23 +0000 Subject: Bugzilla 37579: added support for footnotes in lists and table bodies (not header nor footer). This is /not/ to be considered a final fix: similar code is duplicated over several classes (LineLayoutManager, ListItemLayoutManager and to less extent TableStepper). Footnotes should probably be handled another way. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@660979 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/list/ListItemLayoutManager.java | 30 +++- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 25 ++- .../apache/fop/layoutmgr/table/TableStepper.java | 11 +- test/layoutengine/disabled-testcases.xml | 18 -- .../standard-testcases/footnote_in_list.xml | 2 + .../standard-testcases/footnote_in_list_2.xml | 125 ++++++++++++++ .../standard-testcases/footnote_in_table.xml | 2 + .../standard-testcases/footnote_in_table_2.xml | 185 +++++++++++++++++++++ 8 files changed, 374 insertions(+), 24 deletions(-) create mode 100644 test/layoutengine/standard-testcases/footnote_in_list_2.xml create mode 100644 test/layoutengine/standard-testcases/footnote_in_table_2.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 6a3a38db1..9d08415ff 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -26,7 +26,6 @@ import java.util.ListIterator; 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.fo.flow.ListItem; @@ -39,12 +38,14 @@ import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.NonLeafPosition; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; @@ -279,8 +280,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO; LinkedList returnList = new LinkedList(); - while ((step = getNextStep(elementLists, start, end, partialHeights)) - > 0) { + while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { if (end[0] + 1 == elementLists[0].size()) { keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel); @@ -312,11 +312,33 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int boxHeight = step - addedBoxHeight - penaltyHeight; penaltyHeight += additionalPenaltyHeight; //Add AFTER calculating boxHeight! + // collect footnote information + // TODO this should really not be done like this. ListItemLM should remain as + // footnote-agnostic as possible + LinkedList footnoteList = null; + ListElement el; + for (int i = 0; i < elementLists.length; i++) { + for (int j = start[i]; j <= end[i]; j++) { + el = (ListElement) elementLists[i].get(j); + if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) { + if (footnoteList == null) { + footnoteList = new LinkedList(); + } + footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs()); + } + } + } + // add the new elements addedBoxHeight += boxHeight; ListItemPosition stepPosition = new ListItemPosition(this, start[0], end[0], start[1], end[1]); - returnList.add(new KnuthBox(boxHeight, stepPosition, false)); + if (footnoteList == null) { + returnList.add(new KnuthBox(boxHeight, stepPosition, false)); + } else { + returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false)); + } + if (addedBoxHeight < totalHeight) { int strength = BlockLevelLayoutManager.KEEP_AUTO; strength = Math.max(strength, keepWithNextActive); diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index feb4b67ac..4012b0c00 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -19,12 +19,12 @@ package org.apache.fop.layoutmgr.table; +import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.EffRow; @@ -32,6 +32,7 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.ElementListUtils; +import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; @@ -101,6 +102,8 @@ class ActiveCell { private int penaltyLength; /** Value of the penalty ending this step, 0 if the step does not end on a penalty. */ private int penaltyValue; + /** List of footnotes for this step. */ + private List footnoteList; /** * One of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, @@ -130,6 +133,7 @@ class ActiveCell { this.totalLength = other.totalLength; this.penaltyLength = other.penaltyLength; this.penaltyValue = other.penaltyValue; + this.footnoteList = other.footnoteList; this.condBeforeContentLength = other.condBeforeContentLength; this.breakClass = other.breakClass; } @@ -293,6 +297,7 @@ class ActiveCell { afterNextStep.penaltyValue = 0; afterNextStep.condBeforeContentLength = 0; afterNextStep.breakClass = Constants.EN_AUTO; + afterNextStep.footnoteList = null; boolean breakFound = false; boolean prevIsBox = false; boolean boxFound = false; @@ -322,6 +327,12 @@ class ActiveCell { } prevIsBox = false; } else { + if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) { + if (afterNextStep.footnoteList == null) { + afterNextStep.footnoteList = new LinkedList(); + } + afterNextStep.footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs()); + } prevIsBox = true; boxFound = true; afterNextStep.contentLength += el.getW(); @@ -543,6 +554,18 @@ class ActiveCell { } } + /** + * Adds the footnotes (if any) that are part of the next step, if this cell + * contributes content to the next step. + * + * @param footnoteList the list to which this cell must add its footnotes + */ + void addFootnotes(List footnoteList) { + if (includedInLastStep() && nextStep.footnoteList != null) { + footnoteList.addAll(nextStep.footnoteList); + } + } + int getKeepWithNextStrength() { return keepWithNextStrength; } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index f514844ac..7c963338f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -33,6 +33,7 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; @@ -199,12 +200,14 @@ public class TableStepper { } } + LinkedList footnoteList = new LinkedList(); //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); + activeCell.addFootnotes(footnoteList); } //Create elements for step @@ -217,7 +220,13 @@ public class TableStepper { tcpos.setFlag(TableContentPosition.FIRST_IN_ROWGROUP, true); } lastTCPos = tcpos; - returnList.add(new KnuthBox(boxLen, tcpos, false)); + + // TODO TableStepper should remain as footnote-agnostic as possible + if (footnoteList.isEmpty()) { + returnList.add(new KnuthBox(boxLen, tcpos, false)); + } else { + returnList.add(new KnuthBlockBox(boxLen, footnoteList, tcpos, false)); + } int effPenaltyLen = Math.max(0, penaltyOrGlueLen); TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM()); diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index 476db249e..ba985bf8d 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -97,24 +97,6 @@ Space resolution does not work between footnote regions. - - Footnotes swallowed in lists - footnote_in_list.xml - Element lists for lists are created by combining the - element lists from list-item-label and list-item-body. The - footnotes contained in the KnuthBlockBoxes are not propagated to - the combined element list. - http://issues.apache.org/bugzilla/show_bug.cgi?id=37579 - - - Footnotes swallowed in tables - footnote_in_table.xml - Element lists for tables are created by combining the - element lists from the individual table-cells. The footnotes - contained in the KnuthBlockBoxes are not propagated to the combined - element list. - http://issues.apache.org/bugzilla/show_bug.cgi?id=37579 - NPE for table inside an inline inline_block_nested_3.xml diff --git a/test/layoutengine/standard-testcases/footnote_in_list.xml b/test/layoutengine/standard-testcases/footnote_in_list.xml index 13bfa2ba4..716f07fc8 100644 --- a/test/layoutengine/standard-testcases/footnote_in_list.xml +++ b/test/layoutengine/standard-testcases/footnote_in_list.xml @@ -65,5 +65,7 @@ + + diff --git a/test/layoutengine/standard-testcases/footnote_in_list_2.xml b/test/layoutengine/standard-testcases/footnote_in_list_2.xml new file mode 100644 index 000000000..a0e477d57 --- /dev/null +++ b/test/layoutengine/standard-testcases/footnote_in_list_2.xml @@ -0,0 +1,125 @@ + + + + + +

      + This test checks footnotes as descendants of list-item-body elements. +

      + + + + + + + + + + + Before the list. + + + + – + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque + (1) + + + (1) First footnote from the list. + + hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices + facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl + (2) + + + (2) Second footnote from the list. + + . + + + + + + – + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque + (3) + + + (3) Third footnote from the list. + + hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices + facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl + (4) + + + (4) Fourth footnote from the list. + + . + + + + + + + + + Before the list. + + + + – + + + Lorem ipsum dolor sit amet, consectetuer adipiscing + elit. Pellentesque + (1) + + (1) First footnote from the list. + + hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices + facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl + (2) + + (2) Second footnote from the list. + + . + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/footnote_in_table.xml b/test/layoutengine/standard-testcases/footnote_in_table.xml index 5011b48c6..d9e252ce6 100644 --- a/test/layoutengine/standard-testcases/footnote_in_table.xml +++ b/test/layoutengine/standard-testcases/footnote_in_table.xml @@ -69,5 +69,7 @@ + + diff --git a/test/layoutengine/standard-testcases/footnote_in_table_2.xml b/test/layoutengine/standard-testcases/footnote_in_table_2.xml new file mode 100644 index 000000000..f0514a889 --- /dev/null +++ b/test/layoutengine/standard-testcases/footnote_in_table_2.xml @@ -0,0 +1,185 @@ + + + + + +

      + This test checks footnotes as descendants of table-body elements. +

      +
      + + + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + (2) + + (2) Second footnote from the table. + + + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + (1) + + (1) First footnote from the table. + + . + + + + + + Cell + (3) + + (3) Third footnote from the table. + + 2.2 + + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + (2) + + (2) Second footnote from the table. + + + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + (1) + + (1) First footnote from the table. + + . + + + + + + Cell + (3) + + (3) Third footnote from the table. + + 2.2 + + + + + + + + + Before the table + + + + + + + Cell 1.1 + Cell 1.1 + Cell 1.1 + (2) + + (2) Second footnote from the table. + + + Cell 1.1 + + + Cell 1.2 + Cell 1.2 + (1) + + (1) First footnote from the table. + + . + + + + + + Cell + (3) + + (3) Third footnote from the table. + + 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + +
      -- cgit v1.2.3 From a2e6bdf461aa7686d55ebba10eb70b9f787f1fd7 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Wed, 28 May 2008 16:10:32 +0000 Subject: Implemented Font auto-selection word-by-word git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@660998 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOText.java | 2 +- src/java/org/apache/fop/fonts/FontSelector.java | 142 +++++++++++++++++++++ .../layoutmgr/inline/CharacterLayoutManager.java | 32 +---- .../fop/layoutmgr/inline/TextLayoutManager.java | 126 ++++++++++-------- .../standard-testcases/block_font-autoselect.xml | 54 ++++++++ 5 files changed, 275 insertions(+), 81 deletions(-) create mode 100644 src/java/org/apache/fop/fonts/FontSelector.java create mode 100644 test/layoutengine/standard-testcases/block_font-autoselect.xml (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index 8c85bb039..f21386075 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -37,7 +37,7 @@ import org.apache.fop.fo.properties.SpaceProperty; /** * A text node (PCDATA) in the formatting object tree. * - * Unfortunately the BufferManager implementatation holds + * Unfortunately the BufferManager implementation holds * onto references to the character data in this object * longer than the lifetime of the object itself, causing * excessive memory consumption and OOM errors. diff --git a/src/java/org/apache/fop/fonts/FontSelector.java b/src/java/org/apache/fop/fonts/FontSelector.java new file mode 100644 index 000000000..b18e24eb9 --- /dev/null +++ b/src/java/org/apache/fop/fonts/FontSelector.java @@ -0,0 +1,142 @@ +/* + * 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: FontCollection.java 654783 2008-05-09 12:30:40Z vhennebert $ */ + +package org.apache.fop.fonts; + +import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOText; +import org.apache.fop.fo.flow.Character; +import org.apache.fop.fo.properties.CommonFont; + +/** + * Helper class for automatic font selection. + *

      + * TODO: Check if this could be merged with another font class, such as + * {@link FontManager}. + */ +public final class FontSelector { + private FontSelector() { + // Static since this is an utility class. + } + + private static Font selectFontForCharacter(char c, FONode fonode, + CommonFont commonFont, PercentBaseContext context) { + FontInfo fi = fonode.getFOEventHandler().getFontInfo(); + FontTriplet[] fontkeys = commonFont.getFontState(fi); + for (int i = 0; i < fontkeys.length; i++) { + Font font = fi.getFontInstance(fontkeys[i], commonFont.fontSize + .getValue(context)); + if (font.hasChar(c)) { + return font; + } + } + return fi.getFontInstance(fontkeys[0], commonFont.fontSize + .getValue(context)); + + } + + /** + * Selects a font which is able to display the given character. + * + * @param fobj + * a Character object containing the character and its + * attributes. + * @param context + * the Percent-based context needed for creating the actual font. + * @return a Font object. + */ + public static Font selectFontForCharacter(Character fobj, + PercentBaseContext context) { + return FontSelector.selectFontForCharacter(fobj.getCharacter(), fobj, + fobj.getCommonFont(), context); + } + + /** + * Selects a font which is able to display the given character. + * + * @param c + * character to find. + * @param text + * the text object which contains the character + * @param context + * the Percent-based context needed for creating the actual font. + * @return a Font object. + */ + public static Font selectFontForCharacterInText(char c, FOText text, + PercentBaseContext context) { + return FontSelector.selectFontForCharacter(c, text, text + .getCommonFont(), context); + } + + /** + * Selects a font which is able to display the most of the given characters. + * + * @param textArray + * Text to go through + * @param firstIndex + * first index within text. + * @param breakIndex + * last index +1 within text. + * @param text + * the text object which contains the character + * @param context + * the Percent-based context needed for creating the actual font. + * @return a Font object. + */ + public static Font selectFontForCharactersInText(char[] textArray, + int firstIndex, int breakIndex, FOText text, + PercentBaseContext context) { + final FontInfo fi = text.getFOEventHandler().getFontInfo(); + final CommonFont commonFont = text.getCommonFont(); + final FontTriplet[] fontkeys = commonFont.getFontState(fi); + final int numFonts = fontkeys.length; + final Font[] fonts = new Font[numFonts]; + final int[] fontCount = new int[numFonts]; + + for (int fontnum = 0; fontnum < numFonts; fontnum++) { + final Font font = fi.getFontInstance(fontkeys[fontnum], + commonFont.fontSize.getValue(context)); + fonts[fontnum] = font; + for (int pos = firstIndex; pos < breakIndex; pos++) { + if (font.hasChar(textArray[pos])) { + fontCount[fontnum]++; + } + } + + // quick fall through if all characters can be displayed + if (fontCount[fontnum] == (breakIndex - firstIndex)) { + return font; + } + } + + Font font = fonts[0]; + int max = fontCount[0]; + + for (int fontnum = 1; fontnum < numFonts; fontnum++) { + final int curCount = fontCount[fontnum]; + if (curCount > max) { + font = fonts[fontnum]; + max = curCount; + } + } + return font; + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index b292d97bf..a6f9be7af 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -26,8 +26,7 @@ import org.apache.fop.area.Trait; import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fonts.Font; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.FontSelector; import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; @@ -62,7 +61,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public void initialize() { Character fobj = (Character)this.fobj; - font = this.selectFontForCharacter(fobj); + font = FontSelector.selectFontForCharacter(fobj, this); SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing()); letterSpaceIPD = ls.getSpace(); hyphIPD = fobj.getCommonHyphenation().getHyphIPD(font); @@ -72,33 +71,6 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { chArea.setBaselineOffset(font.getAscender()); setCurrentArea(chArea); } - - /** - * Selects a font which is able to display the given character. - *

      - * Please note: this implements the font-selection-strategy - * character-by-character. - *

      - * TODO: The same function could apply to other elements as well. - * - * @param fobj - * a Character object containing the character and its - * attributed. - * @return a Font object. - */ - private Font selectFontForCharacter(Character fobj) { - FontInfo fi = fobj.getFOEventHandler().getFontInfo(); - FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); - for (int i = 0; i < fontkeys.length; i++) { - font = fi.getFontInstance(fontkeys[i], - fobj.getCommonFont().fontSize.getValue(this)); - if (font.hasChar(fobj.getCharacter())) { - return font; - } - } - return fi.getFontInstance(fontkeys[0], - fobj.getCommonFont().fontSize.getValue(this)); - } private org.apache.fop.area.inline.TextArea getCharacterInlineArea(Character node) { org.apache.fop.area.inline.TextArea text diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index be8a13d50..ffd364626 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -32,6 +32,7 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOText; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontSelector; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthBox; @@ -70,6 +71,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private boolean isHyphenated; private boolean isSpace; private boolean breakOppAfter; + private final Font font; AreaInfo(short startIndex, short breakIndex, @@ -78,7 +80,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, - boolean breakOppAfter) { + boolean breakOppAfter, + Font font) { this.startIndex = startIndex; this.breakIndex = breakIndex; this.wordSpaceCount = wordSpaceCount; @@ -87,6 +90,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.isHyphenated = isHyphenated; this.isSpace = isSpace; this.breakOppAfter = breakOppAfter; + this.font = font; } public String toString() { @@ -97,6 +101,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { + ", bidx=" + breakIndex + ", hyph=" + isHyphenated + ", space=" + isSpace + + ", font=" + font + "]"; } @@ -139,7 +144,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private static final char NEWLINE = '\n'; - private Font font = null; + /** Font used for the space between words. */ + private Font spaceFont = null; /** Start index of next TextArea */ private short nextStart = 0; /** size of a space character (U+0020) glyph in current font */ @@ -150,10 +156,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private int hyphIPD; /** 1/1 of word-spacing value */ private SpaceVal ws; - /** 1/2 of word-spacing value */ - private SpaceVal halfWS; - /** 1/2 of letter-spacing value */ - private SpaceVal halfLS; private boolean hasChanged = false; private int returnedIndex = 0; @@ -206,23 +208,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public void initialize() { - FontInfo fi = foText.getFOEventHandler().getFontInfo(); - FontTriplet[] fontkeys = foText.getCommonFont().getFontState(fi); - font = fi.getFontInstance(fontkeys[0], foText.getCommonFont().fontSize.getValue(this)); + + spaceFont = FontSelector.selectFontForCharacterInText(' ', foText, this); // With CID fonts, space isn't neccesary currentFontState.width(32) - spaceCharIPD = font.getCharWidth(' '); + spaceCharIPD = spaceFont.getCharWidth(' '); // Use hyphenationChar property - hyphIPD = foText.getCommonHyphenation().getHyphIPD(font); + + // TODO: Use hyphen based on actual font used! + hyphIPD = foText.getCommonHyphenation().getHyphIPD(spaceFont); SpaceVal ls = SpaceVal.makeLetterSpacing(foText.getLetterSpacing()); - halfLS = new SpaceVal(MinOptMax.multiply(ls.getSpace(), 0.5), - ls.isConditional(), ls.isForcing(), ls.getPrecedence()); - ws = SpaceVal.makeWordSpacing(foText.getWordSpacing(), ls, font); - // Make half-space: on either side of a word-space) - halfWS = new SpaceVal(MinOptMax.multiply(ws.getSpace(), 0.5), - ws.isConditional(), ws.isForcing(), ws.getPrecedence()); + ws = SpaceVal.makeWordSpacing(foText.getWordSpacing(), ls, spaceFont); // letter space applies only to consecutive non-space characters, // while word space applies to space characters; @@ -255,7 +253,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { public void addAreas(PositionIterator posIter, LayoutContext context) { // Add word areas - AreaInfo ai = null; + AreaInfo ai; int wordSpaceCount = 0; int letterSpaceCount = 0; int firstAreaInfoIndex = -1; @@ -265,6 +263,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /* On first area created, add any leading space. * Calculate word-space stretch value. */ + AreaInfo lastAi = null; while (posIter.hasNext()) { LeafPosition tbpNext = (LeafPosition) posIter.next(); if (tbpNext == null) { @@ -272,18 +271,38 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } if (tbpNext.getLeafPos() != -1) { ai = (AreaInfo) vecAreaInfo.get(tbpNext.getLeafPos()); - if (firstAreaInfoIndex == -1) { + if (lastAi == null || ai.font != lastAi.font) { + if (lastAi != null) { + this.addAreaInfoAreas(lastAi, wordSpaceCount, + letterSpaceCount, firstAreaInfoIndex, + lastAreaInfoIndex, realWidth, context); + } firstAreaInfoIndex = tbpNext.getLeafPos(); - } + wordSpaceCount = 0; + letterSpaceCount = 0; + realWidth = new MinOptMax(0); + } wordSpaceCount += ai.wordSpaceCount; letterSpaceCount += ai.letterSpaceCount; realWidth.add(ai.areaIPD); lastAreaInfoIndex = tbpNext.getLeafPos(); + lastAi = ai; } } - if (ai == null) { - return; + if (lastAi != null) { + this.addAreaInfoAreas(lastAi, wordSpaceCount, letterSpaceCount, + firstAreaInfoIndex, lastAreaInfoIndex, realWidth, context); } + } + + private void addAreaInfoAreas(AreaInfo ai, int wordSpaceCount, + int letterSpaceCount, int firstAreaInfoIndex, + int lastAreaInfoIndex, MinOptMax realWidth, LayoutContext context) { + + // TODO: These two statements (if, for) where like this before my recent + // changes. However, it seems as if they should use the AreaInfo from + // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last ai. + // This needs to be checked. int textLength = ai.breakIndex - ai.startIndex; if (ai.letterSpaceCount == textLength && !ai.isHyphenated && context.isLastArea()) { @@ -353,9 +372,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } TextArea t = createTextArea(realWidth, totalAdjust, context, - wordSpaceIPD.opt - spaceCharIPD, - firstAreaInfoIndex, lastAreaInfoIndex, - context.isLastArea()); + wordSpaceIPD.opt - spaceCharIPD, firstAreaInfoIndex, + lastAreaInfoIndex, context.isLastArea(), ai.font); // wordSpaceDim is computed in relation to wordSpaceIPD.opt // but the renderer needs to know the adjustment in relation @@ -391,11 +409,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * @param firstIndex the index of the first AreaInfo used for the TextArea * @param lastIndex the index of the last AreaInfo used for the TextArea * @param isLastArea is this TextArea the last in a line? + * @param font Font to be used in this particular TextArea * @return the new text area */ protected TextArea createTextArea(MinOptMax width, int adjust, - LayoutContext context, int spaceDiff, - int firstIndex, int lastIndex, boolean isLastArea) { + LayoutContext context, int spaceDiff, int firstIndex, + int lastIndex, boolean isLastArea, Font font) { TextArea textArea; if (context.getIPDAdjust() == 0.0) { // create just a TextArea @@ -409,6 +428,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } textArea.setIPD(width.opt + adjust); textArea.setBPD(font.getAscender() - font.getDescender()); + textArea.setBaselineOffset(font.getAscender()); if (textArea.getBPD() == alignmentContext.getHeight()) { textArea.setOffset(0); @@ -548,6 +568,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { while (lastIndex > 0 && textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { lastIndex--; } + final Font font = FontSelector + .selectFontForCharactersInText(textArray, + thisStart, lastIndex, foText, this); int wordLength = lastIndex - thisStart; boolean kerning = font.hasKerning(); MinOptMax wordIPD = new MinOptMax(0); @@ -592,8 +615,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // create the AreaInfo object ai = new AreaInfo(thisStart, lastIndex, (short) 0, - (short) iLetterSpaces, - wordIPD, textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, false, breakOpportunity); + (short) iLetterSpaces, wordIPD, + textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, + false, breakOpportunity, font); prevAi = ai; vecAreaInfo.add(ai); tempStart = nextStart; @@ -610,8 +634,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // create the AreaInfo object ai = new AreaInfo(thisStart, nextStart, (short) (nextStart - thisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), - false, true, breakOpportunity); + MinOptMax.multiply(wordSpaceIPD, nextStart + - thisStart), false, true, + breakOpportunity, spaceFont); vecAreaInfo.add(ai); prevAi = ai; @@ -647,15 +672,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // preserved space or non-breaking space: // create the AreaInfo object ai = new AreaInfo(nextStart, (short) (nextStart + 1), - (short) 1, (short) 0, - wordSpaceIPD, false, true, breakOpportunity); + (short) 1, (short) 0, wordSpaceIPD, false, true, + breakOpportunity, spaceFont); thisStart = (short) (nextStart + 1); } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) { // create the AreaInfo object + final Font font = FontSelector.selectFontForCharacterInText(ch, + foText, this); MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); ai = new AreaInfo(nextStart, (short) (nextStart + 1), - (short) 0, (short) 0, - ipd, false, true, breakOpportunity); + (short) 0, (short) 0, ipd, false, true, + breakOpportunity, font); thisStart = (short) (nextStart + 1); } else if (ch == NEWLINE) { // linefeed; this can happen when linefeed-treatment="preserve" @@ -673,6 +700,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { lastIndex--; } int wordLength = lastIndex - thisStart; + final Font font = FontSelector.selectFontForCharactersInText( + textArray, thisStart, lastIndex, foText, this); boolean kerning = font.hasKerning(); MinOptMax wordIPD = new MinOptMax(0); for (int i = thisStart; i < lastIndex; i++) { @@ -703,9 +732,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); // create the AreaInfo object - ai = new AreaInfo(thisStart, (short)lastIndex, (short) 0, - (short) iLetterSpaces, - wordIPD, false, false, false); + ai = new AreaInfo(thisStart, (short) lastIndex, (short) 0, + (short) iLetterSpaces, wordIPD, false, false, false, font); vecAreaInfo.add(ai); tempStart = nextStart; @@ -715,9 +743,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { ai = null; } else if (inWhitespace) { ai = new AreaInfo(thisStart, (short) (nextStart), - (short) (nextStart - thisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), - false, true, true); + (short) (nextStart - thisStart), (short) 0, MinOptMax + .multiply(wordSpaceIPD, nextStart - thisStart), + false, true, true, spaceFont); vecAreaInfo.add(ai); // create the elements @@ -828,6 +856,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { int startIndex = ai.startIndex; int stopIndex; boolean nothingChanged = true; + final Font font = ai.font; while (startIndex < ai.breakIndex) { MinOptMax newIPD = new MinOptMax(0); @@ -881,15 +910,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (changeList == null) { changeList = new LinkedList(); } - changeList.add - (new PendingChange - (new AreaInfo((short) startIndex, (short) stopIndex, - (short) 0, - (short) (isWordEnd - ? (stopIndex - startIndex - 1) - : (stopIndex - startIndex)), - newIPD, hyphenFollows, false, false), - ((LeafPosition) pos).getLeafPos())); + changeList.add(new PendingChange(new AreaInfo( + (short) startIndex, (short) stopIndex, (short) 0, + (short) (isWordEnd ? (stopIndex - startIndex - 1) + : (stopIndex - startIndex)), newIPD, + hyphenFollows, false, false, font), + ((LeafPosition) pos).getLeafPos())); nothingChanged = false; } startIndex = stopIndex; diff --git a/test/layoutengine/standard-testcases/block_font-autoselect.xml b/test/layoutengine/standard-testcases/block_font-autoselect.xml new file mode 100644 index 000000000..420ab84ae --- /dev/null +++ b/test/layoutengine/standard-testcases/block_font-autoselect.xml @@ -0,0 +1,54 @@ + + + + + +

      + This test checks the font auto selection. +

      + + + + + + + + + + + font-family not given + this text contains a ∑ symbol in the middle + mixed contents should be + ∑∑text + ∑∑∑∑text + ∑∑∑∑sym + + + + + + + + + + + + + + + -- cgit v1.2.3 From b38b43d58cdc947fdaf23a007e0664160f9a72bf Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 29 May 2008 09:58:06 +0000 Subject: Set svn:keywords and svn:eol-style properties for files added in revision 660998 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@661276 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontSelector.java | 2 +- test/layoutengine/standard-testcases/block_font-autoselect.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/FontSelector.java b/src/java/org/apache/fop/fonts/FontSelector.java index b18e24eb9..ec5ea26bf 100644 --- a/src/java/org/apache/fop/fonts/FontSelector.java +++ b/src/java/org/apache/fop/fonts/FontSelector.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: FontCollection.java 654783 2008-05-09 12:30:40Z vhennebert $ */ +/* $Id$ */ package org.apache.fop.fonts; diff --git a/test/layoutengine/standard-testcases/block_font-autoselect.xml b/test/layoutengine/standard-testcases/block_font-autoselect.xml index 420ab84ae..55406ad73 100644 --- a/test/layoutengine/standard-testcases/block_font-autoselect.xml +++ b/test/layoutengine/standard-testcases/block_font-autoselect.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - +

      -- cgit v1.2.3 From 5c497ef1635e4141fb4bbba0d85ebe9fcabd0f5c Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Thu, 29 May 2008 12:03:48 +0000 Subject: Added docs for my recent commit (word-by-word character selection) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@661310 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/fonts.xml | 50 ++++++++++++++++--------- status.xml | 3 ++ 2 files changed, 35 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/fonts.xml b/src/documentation/content/xdocs/trunk/fonts.xml index 30b72ffac..e713fe08a 100644 --- a/src/documentation/content/xdocs/trunk/fonts.xml +++ b/src/documentation/content/xdocs/trunk/fonts.xml @@ -22,7 +22,7 @@ Apache FOP: Fonts $Revision$ - + @@ -96,14 +96,14 @@ yes (used for layout but not for output) no - - +

    Auto-Detect and auto-embed feature @@ -425,14 +426,14 @@
    - Substitution -

    When a <substitutions/> section is defined in the configuration, FOP will re-map any font-family references found in your FO input to a given substitution font.

    -
      -
    • If a <substitution/> is declared, it is mandatory that both a <from/> and <to/> child element is declared with a font-family attribute.
    • -
    • Both font-weight and font-style are optional attributes, if they are provided then a value of 'normal' is assumed.
    • -
    -

    For example you could make all FO font-family references to 'Arial' with weights between 700 and 900 reference the normal 'Arial Black' font.

    - Substitution +

    When a <substitutions/> section is defined in the configuration, FOP will re-map any font-family references found in your FO input to a given substitution font.

    +
      +
    • If a <substitution/> is declared, it is mandatory that both a <from/> and <to/> child element is declared with a font-family attribute.
    • +
    • Both font-weight and font-style are optional attributes, if they are provided then a value of 'normal' is assumed.
    • +
    +

    For example you could make all FO font-family references to 'Arial' with weights between 700 and 900 reference the normal 'Arial Black' font.

    + @@ -448,7 +449,7 @@ ]]>
    -
    +
    + Font Selection Strategies +

    + There are two font selection strategies: character-by-character or auto. The default is auto.

    +

    Auto selected the first font from the list which is able to display the most characters in a given word. This means (assume font A has characters for abclmn, font B for lnmxyz, fontlist is A,B):

    +
      +
    • aaa lll xxx would be displayed in fonts A A B
    • +
    • aaaxx would be displayed in font A
    • +
    • aaaxxx would be displayed in font A
    • +
    • aaaxxxx would be displayed in font B
    • +
    +

    Character-by-Character is NOT yet supported!

    +
    diff --git a/status.xml b/status.xml index 2f0df7c31..6bf44759a 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,9 @@ Added SVG support for AFP (GOCA). + + Implemented word-by-ford font-selection strategy on text. + Support character-by-character font-selection strategy on fo:character element. -- cgit v1.2.3 From 317f7adb1f67ae5da04b91c507611987c29c41b9 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 31 May 2008 10:56:05 +0000 Subject: Bugzilla 45097: Leading/trailing white-space not removed from nested inline-content when there is no preceding/following text. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@661999 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/XMLWhiteSpaceHandler.java | 144 +++++++++++++-------- status.xml | 4 + .../inline_white-space-treatment_bugzilla45097.xml | 79 +++++++++++ 3 files changed, 174 insertions(+), 53 deletions(-) create mode 100644 test/layoutengine/standard-testcases/inline_white-space-treatment_bugzilla45097.xml (limited to 'src') diff --git a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java index 557a1778e..d8915b124 100644 --- a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java +++ b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java @@ -87,39 +87,49 @@ public class XMLWhiteSpaceHandler { * @param nextChild the node that will be added to the list * after firstTextNode */ - public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode, FONode nextChild) { - + public void handleWhiteSpace(FObjMixed fo, + FONode firstTextNode, + FONode nextChild) { + Block currentBlock = null; int foId = fo.getNameId(); - if (foId == Constants.FO_BLOCK) { - currentBlock = (Block) fo; - if (nestedBlockStack.isEmpty() || fo != nestedBlockStack.peek()) { - if (nextChild != null) { - /* if already in a block, push the current block - * onto the stack of nested blocks - */ - nestedBlockStack.push(currentBlock); + /* set the current block */ + switch (foId) { + case Constants.FO_BLOCK: + currentBlock = (Block) fo; + if (nestedBlockStack.empty() || fo != nestedBlockStack.peek()) { + if (nextChild != null) { + /* if already in a block, push the current block + * onto the stack of nested blocks + */ + nestedBlockStack.push(currentBlock); + } + } else { + if (nextChild == null) { + nestedBlockStack.pop(); + } } - } else { - if (nextChild == null) { - nestedBlockStack.pop(); + break; + + case Constants.FO_RETRIEVE_MARKER: + /* look for the nearest block ancestor, if any */ + FONode ancestor = fo; + do { + ancestor = ancestor.getParent(); + } while (ancestor.getNameId() != Constants.FO_BLOCK + && ancestor.getNameId() != Constants.FO_STATIC_CONTENT); + + if (ancestor.getNameId() == Constants.FO_BLOCK) { + currentBlock = (Block) ancestor; + nestedBlockStack.push(currentBlock); } - } - } else if (foId == Constants.FO_RETRIEVE_MARKER) { - /* look for the nearest block ancestor, if any */ - FONode ancestor = fo; - do { - ancestor = ancestor.getParent(); - } while (ancestor.getNameId() != Constants.FO_BLOCK - && ancestor.getNameId() != Constants.FO_STATIC_CONTENT); + break; - if (ancestor.getNameId() == Constants.FO_BLOCK) { - currentBlock = (Block) ancestor; - nestedBlockStack.push(currentBlock); - } - } else if (!nestedBlockStack.isEmpty()) { - currentBlock = (Block) nestedBlockStack.peek(); + default: + if (!nestedBlockStack.empty()) { + currentBlock = (Block) nestedBlockStack.peek(); + } } if (currentBlock != null) { @@ -132,8 +142,15 @@ public class XMLWhiteSpaceHandler { whiteSpaceTreatment = Constants.EN_IGNORE_IF_SURROUNDING_LINEFEED; } + endOfBlock = (nextChild == null && fo == currentBlock); + if (firstTextNode == null) { - //nothing to do but initialize related properties + //no text means no white-space to handle; return early + afterLinefeed = (fo == currentBlock && fo.firstChild == null); + nonWhiteSpaceCount = 0; + if (endOfBlock) { + handlePendingInlines(); + } return; } @@ -144,13 +161,32 @@ public class XMLWhiteSpaceHandler { || currentBlock == null || (foId == Constants.FO_RETRIEVE_MARKER && fo.getParent() == currentBlock)) { - afterLinefeed = ( - (firstTextNode == fo.firstChild) - || (firstTextNode.siblings[0].getNameId() - == Constants.FO_BLOCK)); + if (firstTextNode == fo.firstChild) { + afterLinefeed = true; + } else { + int previousChildId = firstTextNode.siblings[0].getNameId(); + afterLinefeed = (previousChildId == Constants.FO_BLOCK + || previousChildId == Constants.FO_TABLE_AND_CAPTION + || previousChildId == Constants.FO_TABLE + || previousChildId == Constants.FO_LIST_BLOCK + || previousChildId == Constants.FO_BLOCK_CONTAINER); + } } - endOfBlock = (nextChild == null && fo == currentBlock); + if (foId == Constants.FO_WRAPPER) { + FONode parent = fo.parent; + int parentId = parent.getNameId(); + while (parentId == Constants.FO_WRAPPER) { + parent = parent.parent; + parentId = parent.getNameId(); + } + if (parentId == Constants.FO_FLOW + || parentId == Constants.FO_STATIC_CONTENT + || parentId == Constants.FO_BLOCK_CONTAINER + || parentId == Constants.FO_TABLE_CELL) { + endOfBlock = (nextChild == null); + } + } if (nextChild != null) { int nextChildId = nextChild.getNameId(); @@ -167,26 +203,8 @@ public class XMLWhiteSpaceHandler { handleWhiteSpace(); if (fo == currentBlock - && pendingInlines != null - && !pendingInlines.isEmpty()) { - /* current FO is a block, and has pending inlines */ - if (endOfBlock || nextChildIsBlockLevel) { - if (nonWhiteSpaceCount == 0) { - /* handle white-space for all pending inlines*/ - PendingInline p; - for (int i = pendingInlines.size(); --i >= 0;) { - p = (PendingInline)pendingInlines.get(i); - charIter = (RecursiveCharIterator)p.firstTrailingWhiteSpace; - handleWhiteSpace(); - pendingInlines.remove(p); - } - } else { - /* there is non-white-space text between the pending - * inline(s) and the end of the block; - * clear list of pending inlines */ - pendingInlines.clear(); - } - } + && (endOfBlock || nextChildIsBlockLevel)) { + handlePendingInlines(); } if (nextChild == null) { @@ -333,6 +351,26 @@ public class XMLWhiteSpaceHandler { pendingInlines.add(new PendingInline(fo, firstWhiteSpaceInSeq)); } + private void handlePendingInlines() { + if (!(pendingInlines == null || pendingInlines.isEmpty())) { + if (nonWhiteSpaceCount == 0) { + /* handle white-space for all pending inlines*/ + PendingInline p; + for (int i = pendingInlines.size(); --i >= 0;) { + p = (PendingInline)pendingInlines.get(i); + charIter = (RecursiveCharIterator)p.firstTrailingWhiteSpace; + handleWhiteSpace(); + pendingInlines.remove(p); + } + } else { + /* there is non-white-space text between the pending + * inline(s) and the end of the block; + * clear list of pending inlines */ + pendingInlines.clear(); + } + } + } + /** * Helper class, used during white-space handling to look ahead, and * see if the next character is a linefeed (or if there will be diff --git a/status.xml b/status.xml index 6bf44759a..2cfc7658e 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,10 @@ Added SVG support for AFP (GOCA). + + Corrected white-space-treatment for situations where an inline-node is the first/last + child node of an fo:block, without preceding/following text. + Implemented word-by-ford font-selection strategy on text. diff --git a/test/layoutengine/standard-testcases/inline_white-space-treatment_bugzilla45097.xml b/test/layoutengine/standard-testcases/inline_white-space-treatment_bugzilla45097.xml new file mode 100644 index 000000000..bfe89c673 --- /dev/null +++ b/test/layoutengine/standard-testcases/inline_white-space-treatment_bugzilla45097.xml @@ -0,0 +1,79 @@ + + + + + +

    + This test checks for white-space related bugs as reported in Bugzilla 45097. +

    +
    + + + + + + + + + + + + + + + + Example 1: white-space-collapse="false" linefeed-treatment="preserve" white-space-treatment="preserve" + *** ************* *** + + + Example 2: white-space-collapse="false" linefeed-treatment="preserve" w/ inlines + *** ************* *** + + + + Example 1: white-space-collapse="false" linefeed-treatment="preserve" white-space-treatment="preserve" + *** ************* *** + + + Example 2: white-space-collapse="false" linefeed-treatment="preserve" w/ inlines + *** ************* *** + + + + + + + + + + + + + + +
    \ No newline at end of file -- cgit v1.2.3 From 7f11424173df06e70b991527a617124221aa351f Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sat, 31 May 2008 11:45:55 +0000 Subject: Code Cleanups (no functional change) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@662009 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/inline/TextLayoutManager.java | 912 +++++++++++---------- 1 file changed, 470 insertions(+), 442 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index ffd364626..3f4fc44bc 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -5,9 +5,9 @@ * 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. @@ -31,9 +31,7 @@ import org.apache.fop.area.inline.TextArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOText; import org.apache.fop.fonts.Font; -import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSelector; -import org.apache.fop.fonts.FontTriplet; import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -63,25 +61,25 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * Number of word-spaces? */ private class AreaInfo { - private short startIndex; - private short breakIndex; - private short wordSpaceCount; + private final short startIndex; + private final short breakIndex; + private final short wordSpaceCount; private short letterSpaceCount; - private MinOptMax areaIPD; - private boolean isHyphenated; - private boolean isSpace; + private final MinOptMax areaIPD; + private final boolean isHyphenated; + private final boolean isSpace; private boolean breakOppAfter; private final Font font; - AreaInfo(short startIndex, - short breakIndex, - short wordSpaceCount, - short letterSpaceCount, - MinOptMax areaIPD, - boolean isHyphenated, - boolean isSpace, - boolean breakOppAfter, - Font font) { + AreaInfo(final short startIndex, + final short breakIndex, + final short wordSpaceCount, + final short letterSpaceCount, + final MinOptMax areaIPD, + final boolean isHyphenated, + final boolean isSpace, + final boolean breakOppAfter, + final Font font) { this.startIndex = startIndex; this.breakIndex = breakIndex; this.wordSpaceCount = wordSpaceCount; @@ -94,14 +92,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } public String toString() { - return "[ lscnt=" + letterSpaceCount - + ", wscnt=" + wordSpaceCount - + ", ipd=" + areaIPD.toString() - + ", sidx=" + startIndex - + ", bidx=" + breakIndex - + ", hyph=" + isHyphenated - + ", space=" + isSpace - + ", font=" + font + return "[ lscnt=" + this.letterSpaceCount + + ", wscnt=" + this.wordSpaceCount + + ", ipd=" + this.areaIPD.toString() + + ", sidx=" + this.startIndex + + ", bidx=" + this.breakIndex + + ", hyph=" + this.isHyphenated + + ", space=" + this.isSpace + + ", font=" + this.font + "]"; } @@ -109,11 +107,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // this class stores information about changes in vecAreaInfo // which are not yet applied - private class PendingChange { - public AreaInfo ai; - public int index; + private final class PendingChange { + private final AreaInfo ai; + private final int index; - public PendingChange(AreaInfo ai, int index) { + private PendingChange(final AreaInfo ai, final int index) { this.ai = ai; this.index = index; } @@ -122,10 +120,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** * logging instance */ - private static Log log = LogFactory.getLog(TextLayoutManager.class); + private static final Log LOG = LogFactory.getLog(TextLayoutManager.class); // Hold all possible breaks for the text in this LM's FO. - private ArrayList vecAreaInfo; + private final List vecAreaInfo; /** Non-space characters on which we can end a line. */ private static final String BREAK_CHARS = "-/"; @@ -133,14 +131,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** Used to reduce instantiation of MinOptMax with zero length. Do not modify! */ private static final MinOptMax ZERO_MINOPTMAX = new MinOptMax(0); - private FOText foText; - private char[] textArray; + private final FOText foText; + private final char[] textArray; /** * Contains an array of widths to adjust for kerning. The first entry can * be used to influence the start position of the first letter. The entry i+1 defines the * cursor advancement after the character i. A null entry means no special advancement. */ - private MinOptMax[] letterAdjustArray; //size = textArray.length + 1 + private final MinOptMax[] letterAdjustArray; //size = textArray.length + 1 private static final char NEWLINE = '\n'; @@ -161,7 +159,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private int returnedIndex = 0; private short thisStart = 0; private short tempStart = 0; - private LinkedList changeList = null; + private List changeList = null; private AlignmentContext alignmentContext = null; @@ -177,24 +175,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * * @param node The FOText object to be rendered */ - public TextLayoutManager(FOText node) { + public TextLayoutManager(final FOText node) { super(); - foText = node; + this.foText = node; - textArray = new char[node.endIndex - node.startIndex]; - System.arraycopy(node.ca, node.startIndex, textArray, 0, + this.textArray = new char[node.endIndex - node.startIndex]; + System.arraycopy(node.ca, node.startIndex, this.textArray, 0, node.endIndex - node.startIndex); - letterAdjustArray = new MinOptMax[textArray.length + 1]; + this.letterAdjustArray = new MinOptMax[this.textArray.length + 1]; - vecAreaInfo = new java.util.ArrayList(); + this.vecAreaInfo = new java.util.ArrayList(); } - private KnuthPenalty makeZeroWidthPenalty(int penaltyValue) { + private KnuthPenalty makeZeroWidthPenalty(final int penaltyValue) { return new KnuthPenalty( 0, penaltyValue, false, - auxiliaryPosition, + this.auxiliaryPosition, true); } @@ -202,25 +200,25 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return new KnuthInlineBox( 0, null, - notifyPos(new LeafPosition(this, -1)), + this.notifyPos(new LeafPosition(this, -1)), true); } /** {@inheritDoc} */ public void initialize() { - - spaceFont = FontSelector.selectFontForCharacterInText(' ', foText, this); + + this.spaceFont = FontSelector.selectFontForCharacterInText(' ', this.foText, this); // With CID fonts, space isn't neccesary currentFontState.width(32) - spaceCharIPD = spaceFont.getCharWidth(' '); + this.spaceCharIPD = this.spaceFont.getCharWidth(' '); // Use hyphenationChar property - + // TODO: Use hyphen based on actual font used! - hyphIPD = foText.getCommonHyphenation().getHyphIPD(spaceFont); + this.hyphIPD = this.foText.getCommonHyphenation().getHyphIPD(this.spaceFont); - SpaceVal ls = SpaceVal.makeLetterSpacing(foText.getLetterSpacing()); + final SpaceVal ls = SpaceVal.makeLetterSpacing(this.foText.getLetterSpacing()); - ws = SpaceVal.makeWordSpacing(foText.getWordSpacing(), ls, spaceFont); + this.ws = SpaceVal.makeWordSpacing(this.foText.getWordSpacing(), ls, this.spaceFont); // letter space applies only to consecutive non-space characters, // while word space applies to space characters; @@ -233,10 +231,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // set letter space and word space dimension; // the default value "normal" was converted into a MinOptMax value // in the SpaceVal.makeWordSpacing() method - letterSpaceIPD = ls.getSpace(); - wordSpaceIPD = MinOptMax.add(new MinOptMax(spaceCharIPD), ws.getSpace()); + this.letterSpaceIPD = ls.getSpace(); + this.wordSpaceIPD = MinOptMax.add(new MinOptMax(this.spaceCharIPD), this.ws.getSpace()); - keepTogether = foText.getKeepTogether().getWithinLine().getEnum() == Constants.EN_ALWAYS; + this.keepTogether = this.foText.getKeepTogether().getWithinLine() + .getEnum() == Constants.EN_ALWAYS; } @@ -250,10 +249,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * by this LayoutManager. * @param context LayoutContext for adjustments */ - public void addAreas(PositionIterator posIter, LayoutContext context) { + public void addAreas(final PositionIterator posIter, final LayoutContext context) { // Add word areas - AreaInfo ai; + AreaInfo ai; int wordSpaceCount = 0; int letterSpaceCount = 0; int firstAreaInfoIndex = -1; @@ -265,12 +264,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { */ AreaInfo lastAi = null; while (posIter.hasNext()) { - LeafPosition tbpNext = (LeafPosition) posIter.next(); + final LeafPosition tbpNext = (LeafPosition) posIter.next(); if (tbpNext == null) { continue; //Ignore elements without Positions } if (tbpNext.getLeafPos() != -1) { - ai = (AreaInfo) vecAreaInfo.get(tbpNext.getLeafPos()); + ai = (AreaInfo) this.vecAreaInfo.get(tbpNext.getLeafPos()); if (lastAi == null || ai.font != lastAi.font) { if (lastAi != null) { this.addAreaInfoAreas(lastAi, wordSpaceCount, @@ -280,8 +279,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { firstAreaInfoIndex = tbpNext.getLeafPos(); wordSpaceCount = 0; letterSpaceCount = 0; - realWidth = new MinOptMax(0); - } + realWidth = new MinOptMax(0); + } wordSpaceCount += ai.wordSpaceCount; letterSpaceCount += ai.letterSpaceCount; realWidth.add(ai.areaIPD); @@ -294,26 +293,26 @@ public class TextLayoutManager extends LeafNodeLayoutManager { firstAreaInfoIndex, lastAreaInfoIndex, realWidth, context); } } - - private void addAreaInfoAreas(AreaInfo ai, int wordSpaceCount, - int letterSpaceCount, int firstAreaInfoIndex, - int lastAreaInfoIndex, MinOptMax realWidth, LayoutContext context) { - + + private void addAreaInfoAreas(final AreaInfo ai, final int wordSpaceCount, + int letterSpaceCount, final int firstAreaInfoIndex, + final int lastAreaInfoIndex, final MinOptMax realWidth, final LayoutContext context) { + // TODO: These two statements (if, for) where like this before my recent // changes. However, it seems as if they should use the AreaInfo from // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last ai. // This needs to be checked. - int textLength = ai.breakIndex - ai.startIndex; + final int textLength = ai.breakIndex - ai.startIndex; if (ai.letterSpaceCount == textLength && !ai.isHyphenated && context.isLastArea()) { // the line ends at a character like "/" or "-"; // remove the letter space after the last character - realWidth.add(MinOptMax.multiply(letterSpaceIPD, -1)); + realWidth.add(MinOptMax.multiply(this.letterSpaceIPD, -1)); letterSpaceCount--; } for (int i = ai.startIndex; i < ai.breakIndex; i++) { - MinOptMax ladj = letterAdjustArray[i + 1]; + final MinOptMax ladj = this.letterAdjustArray[i + 1]; if (ladj != null && ladj.isElastic()) { letterSpaceCount++; } @@ -321,58 +320,56 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // add hyphenation character if the last word is hyphenated if (context.isLastArea() && ai.isHyphenated) { - realWidth.add(new MinOptMax(hyphIPD)); + realWidth.add(new MinOptMax(this.hyphIPD)); } // Calculate adjustments int difference = 0; int totalAdjust = 0; - int wordSpaceDim = wordSpaceIPD.opt; - int letterSpaceDim = letterSpaceIPD.opt; - double ipdAdjust = context.getIPDAdjust(); - double dSpaceAdjust = context.getSpaceAdjust(); // not used + int wordSpaceDim = this.wordSpaceIPD.opt; + int letterSpaceDim = this.letterSpaceIPD.opt; + final double ipdAdjust = context.getIPDAdjust(); // calculate total difference between real and available width if (ipdAdjust > 0.0) { - difference = (int) ((double) (realWidth.max - realWidth.opt) + difference = (int) ((realWidth.max - realWidth.opt) * ipdAdjust); } else { - difference = (int) ((double) (realWidth.opt - realWidth.min) + difference = (int) ((realWidth.opt - realWidth.min) * ipdAdjust); } // set letter space adjustment if (ipdAdjust > 0.0) { letterSpaceDim - += (int) ((double) (letterSpaceIPD.max - letterSpaceIPD.opt) + += (int) ((this.letterSpaceIPD.max - this.letterSpaceIPD.opt) * ipdAdjust); } else { letterSpaceDim - += (int) ((double) (letterSpaceIPD.opt - letterSpaceIPD.min) + += (int) ((this.letterSpaceIPD.opt - this.letterSpaceIPD.min) * ipdAdjust); } - totalAdjust += (letterSpaceDim - letterSpaceIPD.opt) * letterSpaceCount; + totalAdjust += (letterSpaceDim - this.letterSpaceIPD.opt) * letterSpaceCount; // set word space adjustment // if (wordSpaceCount > 0) { wordSpaceDim += (difference - totalAdjust) / wordSpaceCount; - } else { - // there are no word spaces in this area } - totalAdjust += (wordSpaceDim - wordSpaceIPD.opt) * wordSpaceCount; + totalAdjust += (wordSpaceDim - this.wordSpaceIPD.opt) * wordSpaceCount; if (totalAdjust != difference) { // the applied adjustment is greater or smaller than the needed one - log.trace("TextLM.addAreas: error in word / letter space adjustment = " - + (totalAdjust - difference)); + TextLayoutManager.LOG + .trace("TextLM.addAreas: error in word / letter space adjustment = " + + (totalAdjust - difference)); // set totalAdjust = difference, so that the width of the TextArea // will counterbalance the error and the other inline areas will be // placed correctly totalAdjust = difference; } - TextArea t = createTextArea(realWidth, totalAdjust, context, - wordSpaceIPD.opt - spaceCharIPD, firstAreaInfoIndex, + final TextArea t = this.createTextArea(realWidth, totalAdjust, context, + this.wordSpaceIPD.opt - this.spaceCharIPD, firstAreaInfoIndex, lastAreaInfoIndex, context.isLastArea(), ai.font); // wordSpaceDim is computed in relation to wordSpaceIPD.opt @@ -388,14 +385,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // + (wordSpaceDim - spaceCharIPD - 2 * letterSpaceAdjust) // = wordSpaceDim - letterSpaceAdjust t.setTextLetterSpaceAdjust(letterSpaceDim); - t.setTextWordSpaceAdjust(wordSpaceDim - spaceCharIPD + t.setTextWordSpaceAdjust(wordSpaceDim - this.spaceCharIPD - 2 * t.getTextLetterSpaceAdjust()); if (context.getIPDAdjust() != 0) { // add information about space width - t.setSpaceDifference(wordSpaceIPD.opt - spaceCharIPD + t.setSpaceDifference(this.wordSpaceIPD.opt - this.spaceCharIPD - 2 * t.getTextLetterSpaceAdjust()); } - parentLM.addChildArea(t); + this.parentLM.addChildArea(t); } /** @@ -412,9 +409,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * @param font Font to be used in this particular TextArea * @return the new text area */ - protected TextArea createTextArea(MinOptMax width, int adjust, - LayoutContext context, int spaceDiff, int firstIndex, - int lastIndex, boolean isLastArea, Font font) { + protected TextArea createTextArea(final MinOptMax width, final int adjust, + final LayoutContext context, final int spaceDiff, final int firstIndex, + final int lastIndex, final boolean isLastArea, final Font font) { TextArea textArea; if (context.getIPDAdjust() == 0.0) { // create just a TextArea @@ -428,12 +425,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } textArea.setIPD(width.opt + adjust); textArea.setBPD(font.getAscender() - font.getDescender()); - + textArea.setBaselineOffset(font.getAscender()); - if (textArea.getBPD() == alignmentContext.getHeight()) { + if (textArea.getBPD() == this.alignmentContext.getHeight()) { textArea.setOffset(0); } else { - textArea.setOffset(alignmentContext.getOffset()); + textArea.setOffset(this.alignmentContext.getOffset()); } // set the text of the TextArea, split into words and spaces @@ -441,12 +438,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { AreaInfo areaInfo; int len = 0; for (int i = firstIndex; i <= lastIndex; i++) { - areaInfo = (AreaInfo) vecAreaInfo.get(i); + areaInfo = (AreaInfo) this.vecAreaInfo.get(i); if (areaInfo.isSpace) { // areaInfo stores information about spaces // add the spaces - except zero-width spaces - to the TextArea for (int j = areaInfo.startIndex; j < areaInfo.breakIndex; j++) { - char spaceChar = textArray[j]; + final char spaceChar = this.textArray[j]; if (!CharUtilities.isZeroWidthSpace(spaceChar)) { textArea.addSpace(spaceChar, 0, CharUtilities.isAdjustableSpace(spaceChar)); @@ -460,7 +457,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { len = 0; } len += areaInfo.breakIndex - areaInfo.startIndex; - if (i == lastIndex || ((AreaInfo) vecAreaInfo.get(i + 1)).isSpace) { + if (i == lastIndex || ((AreaInfo) this.vecAreaInfo.get(i + 1)).isSpace) { // here ends a new word // add a word to the TextArea if (isLastArea @@ -468,17 +465,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { && areaInfo.isHyphenated) { len++; } - StringBuffer wordChars = new StringBuffer(len); - int[] letterAdjust = new int[len]; + final StringBuffer wordChars = new StringBuffer(len); + final int[] letterAdjust = new int[len]; int letter = 0; for (int j = wordStartIndex; j <= i; j++) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(j); + final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(j); int lsCount = ai.letterSpaceCount; - wordChars.append(textArray, ai.startIndex, ai.breakIndex - ai.startIndex); + wordChars.append(this.textArray, ai.startIndex, + ai.breakIndex - ai.startIndex); for (int k = 0; k < ai.breakIndex - ai.startIndex; k++) { - MinOptMax adj = letterAdjustArray[ai.startIndex + k]; + final MinOptMax adj = this.letterAdjustArray[ai.startIndex + k]; if (letter > 0) { - letterAdjust[letter] = (adj != null ? adj.opt : 0); + letterAdjust[letter] = adj == null ? 0 + : adj.opt; } if (lsCount > 0) { letterAdjust[letter] += textArea.getTextLetterSpaceAdjust(); @@ -492,7 +491,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { && i == lastIndex && areaInfo.isHyphenated) { // add the hyphenation character - wordChars.append(foText.getCommonHyphenation().getHyphChar(font)); + wordChars.append(this.foText.getCommonHyphenation().getHyphChar(font)); } textArea.addWord(wordChars.toString(), 0, letterAdjust); wordStartIndex = -1; @@ -500,18 +499,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } TraitSetter.addFontTraits(textArea, font); - textArea.addTrait(Trait.COLOR, foText.getColor()); + textArea.addTrait(Trait.COLOR, this.foText.getColor()); - TraitSetter.addTextDecoration(textArea, foText.getTextDecoration()); + TraitSetter.addTextDecoration(textArea, this.foText.getTextDecoration()); return textArea; } - private void addToLetterAdjust(int index, int width) { - if (letterAdjustArray[index] == null) { - letterAdjustArray[index] = new MinOptMax(width); + private void addToLetterAdjust(final int index, final int width) { + if (this.letterAdjustArray[index] == null) { + this.letterAdjustArray[index] = new MinOptMax(width); } else { - letterAdjustArray[index].add(width); + this.letterAdjustArray[index].add(width); } } @@ -527,26 +526,27 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { - lineStartBAP = context.getLineStartBorderAndPaddingWidth(); - lineEndBAP = context.getLineEndBorderAndPaddingWidth(); - alignmentContext = context.getAlignmentContext(); + public LinkedList getNextKnuthElements(final LayoutContext context, final int alignment) { + this.lineStartBAP = context.getLineStartBorderAndPaddingWidth(); + this.lineEndBAP = context.getLineEndBorderAndPaddingWidth(); + this.alignmentContext = context.getAlignmentContext(); - LinkedList returnList = new LinkedList(); + final LinkedList returnList = new LinkedList(); KnuthSequence sequence = new InlineKnuthSequence(); AreaInfo ai = null; AreaInfo prevAi = null; returnList.add(sequence); - LineBreakStatus lbs = new LineBreakStatus(); - thisStart = nextStart; + final LineBreakStatus lbs = new LineBreakStatus(); + this.thisStart = this.nextStart; boolean inWord = false; boolean inWhitespace = false; char ch = 0; - while (nextStart < textArray.length) { - ch = textArray[nextStart]; + while (this.nextStart < this.textArray.length) { + ch = this.textArray[this.nextStart]; boolean breakOpportunity = false; - byte breakAction = keepTogether ? LineBreakStatus.PROHIBITED_BREAK : lbs.nextChar(ch); + final byte breakAction = this.keepTogether ? LineBreakStatus.PROHIBITED_BREAK + : lbs.nextChar(ch); switch (breakAction) { case LineBreakStatus.COMBINING_PROHIBITED_BREAK: case LineBreakStatus.PROHIBITED_BREAK: @@ -559,106 +559,113 @@ public class TextLayoutManager extends LeafNodeLayoutManager { breakOpportunity = true; break; default: - log.error("Unexpected breakAction: " + breakAction); + TextLayoutManager.LOG.error("Unexpected breakAction: " + breakAction); } if (inWord) { - if (breakOpportunity || isSpace(ch) || ch == NEWLINE) { + if (breakOpportunity || TextLayoutManager.isSpace(ch) + || ch == TextLayoutManager.NEWLINE) { //Word boundary found, process widths and kerning - short lastIndex = nextStart; - while (lastIndex > 0 && textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { + short lastIndex = this.nextStart; + while (lastIndex > 0 + && this.textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { lastIndex--; } final Font font = FontSelector - .selectFontForCharactersInText(textArray, - thisStart, lastIndex, foText, this); - int wordLength = lastIndex - thisStart; - boolean kerning = font.hasKerning(); - MinOptMax wordIPD = new MinOptMax(0); - for (int i = thisStart; i < lastIndex; i++) { - char c = textArray[i]; + .selectFontForCharactersInText(this.textArray, + this.thisStart, lastIndex, this.foText, this); + final int wordLength = lastIndex - this.thisStart; + final boolean kerning = font.hasKerning(); + final MinOptMax wordIPD = new MinOptMax(0); + for (int i = this.thisStart; i < lastIndex; i++) { + final char c = this.textArray[i]; //character width - int charWidth = font.getCharWidth(c); + final int charWidth = font.getCharWidth(c); wordIPD.add(charWidth); //kerning if (kerning) { int kern = 0; - if (i > thisStart) { - char previous = textArray[i - 1]; + if (i > this.thisStart) { + final char previous = this.textArray[i - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { - char previous = textArray[prevAi.breakIndex - 1]; + final char previous = this.textArray[prevAi.breakIndex - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } if (kern != 0) { - //log.info("Kerning between " + previous + " and " + c + ": " + kern); - addToLetterAdjust(i, kern); + this.addToLetterAdjust(i, kern); wordIPD.add(kern); } } } - if (kerning && breakOpportunity && !isSpace(ch) && lastIndex > 0 && textArray[lastIndex] == CharUtilities.SOFT_HYPHEN) { - int kern = font.getKernValue(textArray[lastIndex - 1], ch) * font.getFontSize() / 1000; + if (kerning + && breakOpportunity + && !TextLayoutManager.isSpace(ch) + && lastIndex > 0 + && this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN) { + final int kern = font.getKernValue( + this.textArray[lastIndex - 1], ch) + * font.getFontSize() / 1000; if (kern != 0) { - addToLetterAdjust(lastIndex, kern); + this.addToLetterAdjust(lastIndex, kern); } } int iLetterSpaces = wordLength - 1; // if there is a break opportunity and the next one // is not a space, it could be used as a line end; // add one more letter space, in case other text follows - if (breakOpportunity && !isSpace(ch)) { + if (breakOpportunity && !TextLayoutManager.isSpace(ch)) { iLetterSpaces++; } - wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); + wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); // create the AreaInfo object - ai = new AreaInfo(thisStart, lastIndex, (short) 0, + ai = new AreaInfo(this.thisStart, lastIndex, (short) 0, (short) iLetterSpaces, wordIPD, - textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, + this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, false, breakOpportunity, font); prevAi = ai; - vecAreaInfo.add(ai); - tempStart = nextStart; + this.vecAreaInfo.add(ai); + this.tempStart = this.nextStart; //add the elements - addElementsForAWordFragment(sequence, alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD); + this.addElementsForAWordFragment(sequence, alignment, ai, + this.vecAreaInfo.size() - 1, this.letterSpaceIPD); ai = null; - thisStart = nextStart; + this.thisStart = this.nextStart; } } else if (inWhitespace) { if (ch != CharUtilities.SPACE || breakOpportunity) { // End of whitespace // create the AreaInfo object - ai = new AreaInfo(thisStart, nextStart, - (short) (nextStart - thisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, nextStart - - thisStart), false, true, - breakOpportunity, spaceFont); - vecAreaInfo.add(ai); + ai = new AreaInfo(this.thisStart, this.nextStart, + (short) (this.nextStart - this.thisStart), (short) 0, + MinOptMax.multiply(this.wordSpaceIPD, this.nextStart + - this.thisStart), false, true, + breakOpportunity, this.spaceFont); + this.vecAreaInfo.add(ai); prevAi = ai; // create the elements - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); + this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); ai = null; - thisStart = nextStart; + this.thisStart = this.nextStart; } } else { if (ai != null) { - vecAreaInfo.add(ai); + this.vecAreaInfo.add(ai); prevAi = ai; - ai.breakOppAfter = (ch == CharUtilities.SPACE) || breakOpportunity; - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); + ai.breakOppAfter = ch == CharUtilities.SPACE || breakOpportunity; + this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); ai = null; } if (breakAction == LineBreakStatus.EXPLICIT_BREAK) { - if (lineEndBAP != 0) { + if (this.lineEndBAP != 0) { sequence.add( - new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, true)); + new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -666,101 +673,102 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - if ((ch == CharUtilities.SPACE - && foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) + if (ch == CharUtilities.SPACE + && this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE || ch == CharUtilities.NBSPACE) { // preserved space or non-breaking space: // create the AreaInfo object - ai = new AreaInfo(nextStart, (short) (nextStart + 1), - (short) 1, (short) 0, wordSpaceIPD, false, true, - breakOpportunity, spaceFont); - thisStart = (short) (nextStart + 1); + ai = new AreaInfo(this.nextStart, (short) (this.nextStart + 1), + (short) 1, (short) 0, this.wordSpaceIPD, false, true, + breakOpportunity, this.spaceFont); + this.thisStart = (short) (this.nextStart + 1); } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) { // create the AreaInfo object final Font font = FontSelector.selectFontForCharacterInText(ch, - foText, this); - MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); - ai = new AreaInfo(nextStart, (short) (nextStart + 1), + this.foText, this); + final MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); + ai = new AreaInfo(this.nextStart, (short) (this.nextStart + 1), (short) 0, (short) 0, ipd, false, true, breakOpportunity, font); - thisStart = (short) (nextStart + 1); - } else if (ch == NEWLINE) { + this.thisStart = (short) (this.nextStart + 1); + } else if (ch == TextLayoutManager.NEWLINE) { // linefeed; this can happen when linefeed-treatment="preserve" - thisStart = (short) (nextStart + 1); + this.thisStart = (short) (this.nextStart + 1); } - inWord = !isSpace(ch) && ch != NEWLINE; - inWhitespace = ch == CharUtilities.SPACE && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; - nextStart++; + inWord = !TextLayoutManager.isSpace(ch) + && ch != TextLayoutManager.NEWLINE; + inWhitespace = ch == CharUtilities.SPACE + && this.foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; + this.nextStart++; } // end of while // Process any last elements if (inWord) { - int lastIndex = nextStart; - if (textArray[nextStart - 1] == CharUtilities.SOFT_HYPHEN) { + int lastIndex = this.nextStart; + if (this.textArray[this.nextStart - 1] == CharUtilities.SOFT_HYPHEN) { lastIndex--; } - int wordLength = lastIndex - thisStart; + final int wordLength = lastIndex - this.thisStart; final Font font = FontSelector.selectFontForCharactersInText( - textArray, thisStart, lastIndex, foText, this); - boolean kerning = font.hasKerning(); - MinOptMax wordIPD = new MinOptMax(0); - for (int i = thisStart; i < lastIndex; i++) { - char c = textArray[i]; + this.textArray, this.thisStart, lastIndex, this.foText, this); + final boolean kerning = font.hasKerning(); + final MinOptMax wordIPD = new MinOptMax(0); + for (int i = this.thisStart; i < lastIndex; i++) { + final char c = this.textArray[i]; //character width - int charWidth = font.getCharWidth(c); + final int charWidth = font.getCharWidth(c); wordIPD.add(charWidth); //kerning if (kerning) { int kern = 0; - if (i > thisStart) { - char previous = textArray[i - 1]; + if (i > this.thisStart) { + final char previous = this.textArray[i - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } else if (prevAi != null && !prevAi.isSpace) { - char previous = textArray[prevAi.breakIndex - 1]; + final char previous = this.textArray[prevAi.breakIndex - 1]; kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } if (kern != 0) { - //log.info("Kerning between " + previous + " and " + c + ": " + kern); - addToLetterAdjust(i, kern); + this.addToLetterAdjust(i, kern); wordIPD.add(kern); } } } - int iLetterSpaces = wordLength - 1; - wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); + final int iLetterSpaces = wordLength - 1; + wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); // create the AreaInfo object - ai = new AreaInfo(thisStart, (short) lastIndex, (short) 0, + ai = new AreaInfo(this.thisStart, (short) lastIndex, (short) 0, (short) iLetterSpaces, wordIPD, false, false, false, font); - vecAreaInfo.add(ai); - tempStart = nextStart; + this.vecAreaInfo.add(ai); + this.tempStart = this.nextStart; // create the elements - addElementsForAWordFragment(sequence, alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD); + this.addElementsForAWordFragment(sequence, alignment, ai, + this.vecAreaInfo.size() - 1, this.letterSpaceIPD); ai = null; } else if (inWhitespace) { - ai = new AreaInfo(thisStart, (short) (nextStart), - (short) (nextStart - thisStart), (short) 0, MinOptMax - .multiply(wordSpaceIPD, nextStart - thisStart), - false, true, true, spaceFont); - vecAreaInfo.add(ai); + ai = new AreaInfo(this.thisStart, this.nextStart, + (short) (this.nextStart - this.thisStart), (short) 0, MinOptMax + .multiply(this.wordSpaceIPD, this.nextStart - this.thisStart), + false, true, true, this.spaceFont); + this.vecAreaInfo.add(ai); // create the elements - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); + this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); ai = null; } else if (ai != null) { - vecAreaInfo.add(ai); + this.vecAreaInfo.add(ai); ai.breakOppAfter = ch == CharUtilities.ZERO_WIDTH_SPACE; - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); + this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); ai = null; - } else if (ch == NEWLINE) { - if (lineEndBAP != 0) { + } else if (ch == TextLayoutManager.NEWLINE) { + if (this.lineEndBAP != 0) { sequence.add - (new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, true)); + (new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -771,49 +779,54 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //Remove an empty sequence because of a trailing newline returnList.removeLast(); } - setFinished(true); - if (returnList.size() > 0) { - return returnList; - } else { + this.setFinished(true); + if (returnList.isEmpty()) { return null; + } else { + return returnList; } } /** {@inheritDoc} */ - public List addALetterSpaceTo(List oldList) { + public List addALetterSpaceTo(final List oldList) { // old list contains only a box, or the sequence: box penalty glue box; // look at the Position stored in the first element in oldList // which is always a box ListIterator oldListIterator = oldList.listIterator(); - KnuthElement el = (KnuthElement)oldListIterator.next(); - LeafPosition pos = (LeafPosition) ((KnuthBox) el).getPosition(); - int idx = pos.getLeafPos(); + final KnuthElement el = (KnuthElement)oldListIterator.next(); + final LeafPosition pos = (LeafPosition) ((KnuthBox) el).getPosition(); + final int idx = pos.getLeafPos(); //element could refer to '-1' position, for non-collapsed spaces (?) if (idx > -1) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(idx); + final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(idx); ai.letterSpaceCount++; - ai.areaIPD.add(letterSpaceIPD); - if (BREAK_CHARS.indexOf(textArray[tempStart - 1]) >= 0) { + ai.areaIPD.add(this.letterSpaceIPD); + if (TextLayoutManager.BREAK_CHARS.indexOf(this.textArray[this.tempStart - 1]) >= 0) { // the last character could be used as a line break // append new elements to oldList oldListIterator = oldList.listIterator(oldList.size()); oldListIterator.add(new KnuthPenalty(0, KnuthPenalty.FLAGGED_PENALTY, true, - auxiliaryPosition, false)); - oldListIterator.add(new KnuthGlue(letterSpaceIPD.opt, - letterSpaceIPD.max - letterSpaceIPD.opt, - letterSpaceIPD.opt - letterSpaceIPD.min, - auxiliaryPosition, false)); - } else if (letterSpaceIPD.min == letterSpaceIPD.max) { + this.auxiliaryPosition, false)); + oldListIterator.add(new KnuthGlue(this.letterSpaceIPD.opt, + this.letterSpaceIPD.max - this.letterSpaceIPD.opt, + this.letterSpaceIPD.opt - this.letterSpaceIPD.min, + this.auxiliaryPosition, false)); + } else if (this.letterSpaceIPD.min == this.letterSpaceIPD.max) { // constant letter space: replace the box - oldListIterator.set(new KnuthInlineBox(ai.areaIPD.opt, alignmentContext, pos, false)); + oldListIterator.set(new KnuthInlineBox(ai.areaIPD.opt, + this.alignmentContext, pos, false)); } else { // adjustable letter space: replace the glue oldListIterator.next(); // this would return the penalty element oldListIterator.next(); // this would return the glue element - oldListIterator.set(new KnuthGlue(ai.letterSpaceCount * letterSpaceIPD.opt, - ai.letterSpaceCount * (letterSpaceIPD.max - letterSpaceIPD.opt), - ai.letterSpaceCount * (letterSpaceIPD.opt - letterSpaceIPD.min), - auxiliaryPosition, true)); + oldListIterator + .set(new KnuthGlue( + ai.letterSpaceCount * this.letterSpaceIPD.opt, + ai.letterSpaceCount + * (this.letterSpaceIPD.max - this.letterSpaceIPD.opt), + ai.letterSpaceCount + * (this.letterSpaceIPD.opt - this.letterSpaceIPD.min), + this.auxiliaryPosition, true)); } } return oldList; @@ -826,10 +839,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * * @param oldList the elements representing the word space */ - public void removeWordSpace(List oldList) { + public void removeWordSpace(final List oldList) { // find the element storing the Position whose value // points to the AreaInfo object - ListIterator oldListIterator = oldList.listIterator(); + final ListIterator oldListIterator = oldList.listIterator(); if (((KnuthElement) ((LinkedList) oldList).getFirst()).isPenalty()) { // non breaking space: oldList starts with a penalty oldListIterator.next(); @@ -840,31 +853,31 @@ public class TextLayoutManager extends LeafNodeLayoutManager { oldListIterator.next(); oldListIterator.next(); } - int leafValue = ((LeafPosition) ((KnuthElement) oldListIterator.next()).getPosition()).getLeafPos(); + final int leafValue = ((LeafPosition) ((KnuthElement) oldListIterator + .next()).getPosition()).getLeafPos(); // only the last word space can be a trailing space! - if (leafValue == vecAreaInfo.size() - 1) { - vecAreaInfo.remove(leafValue); + if (leafValue == this.vecAreaInfo.size() - 1) { + this.vecAreaInfo.remove(leafValue); } else { - log.error("trying to remove a non-trailing word space"); + TextLayoutManager.LOG.error("trying to remove a non-trailing word space"); } } /** {@inheritDoc} */ - public void hyphenate(Position pos, HyphContext hc) { - AreaInfo ai - = (AreaInfo) vecAreaInfo.get(((LeafPosition) pos).getLeafPos()); + public void hyphenate(final Position pos, final HyphContext hc) { + final AreaInfo ai + = (AreaInfo) this.vecAreaInfo.get(((LeafPosition) pos).getLeafPos()); int startIndex = ai.startIndex; int stopIndex; boolean nothingChanged = true; final Font font = ai.font; while (startIndex < ai.breakIndex) { - MinOptMax newIPD = new MinOptMax(0); + final MinOptMax newIPD = new MinOptMax(0); boolean hyphenFollows; - if (hc.hasMoreHyphPoints() - && (stopIndex = startIndex + hc.getNextHyphPoint()) - <= ai.breakIndex) { + stopIndex = startIndex + hc.getNextHyphPoint(); + if (hc.hasMoreHyphPoints() && stopIndex <= ai.breakIndex) { // stopIndex is the index of the first character // after a hyphenation point hyphenFollows = true; @@ -879,12 +892,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //log.info("Word: " + new String(textArray, startIndex, stopIndex - startIndex)); for (int i = startIndex; i < stopIndex; i++) { - char c = textArray[i]; + final char c = this.textArray[i]; newIPD.add(new MinOptMax(font.getCharWidth(c))); //if (i > startIndex) { if (i < stopIndex) { MinOptMax la = this.letterAdjustArray[i + 1]; - if ((i == stopIndex - 1) && hyphenFollows) { + if (i == stopIndex - 1 && hyphenFollows) { //the letter adjust here needs to be handled further down during //element generation because it depends on hyph/no-hyph condition la = null; @@ -895,112 +908,113 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } // add letter spaces - boolean isWordEnd + final boolean isWordEnd = stopIndex == ai.breakIndex - && ai.letterSpaceCount < (ai.breakIndex - ai.startIndex); - newIPD.add(MinOptMax.multiply(letterSpaceIPD, + && ai.letterSpaceCount < ai.breakIndex - ai.startIndex; + newIPD.add(MinOptMax.multiply(this.letterSpaceIPD, (isWordEnd - ? (stopIndex - startIndex - 1) - : (stopIndex - startIndex)))); + ? stopIndex - startIndex - 1 + : stopIndex - startIndex))); if (!(nothingChanged && stopIndex == ai.breakIndex && !hyphenFollows)) { // the new AreaInfo object is not equal to the old one - if (changeList == null) { - changeList = new LinkedList(); + if (this.changeList == null) { + this.changeList = new LinkedList(); } - changeList.add(new PendingChange(new AreaInfo( + this.changeList.add(new PendingChange(new AreaInfo( (short) startIndex, (short) stopIndex, (short) 0, - (short) (isWordEnd ? (stopIndex - startIndex - 1) - : (stopIndex - startIndex)), newIPD, + (short) (isWordEnd ? stopIndex - startIndex - 1 + : stopIndex - startIndex), newIPD, hyphenFollows, false, false, font), ((LeafPosition) pos).getLeafPos())); nothingChanged = false; } startIndex = stopIndex; } - hasChanged = !nothingChanged; + this.hasChanged = !nothingChanged; } /** {@inheritDoc} */ - public boolean applyChanges(List oldList) { - setFinished(false); + public boolean applyChanges(final List oldList) { + this.setFinished(false); - if (changeList != null && !changeList.isEmpty()) { + if (this.changeList != null && !this.changeList.isEmpty()) { int areaInfosAdded = 0; int areaInfosRemoved = 0; int oldIndex = -1, changeIndex; PendingChange currChange; - ListIterator changeListIterator = changeList.listIterator(); + final ListIterator changeListIterator = this.changeList.listIterator(); while (changeListIterator.hasNext()) { currChange = (PendingChange) changeListIterator.next(); - if (currChange.index != oldIndex) { - areaInfosRemoved++; + if (currChange.index == oldIndex) { areaInfosAdded++; - oldIndex = currChange.index; changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; - vecAreaInfo.remove(changeIndex); } else { + areaInfosRemoved++; areaInfosAdded++; + oldIndex = currChange.index; changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; + this.vecAreaInfo.remove(changeIndex); } - vecAreaInfo.add(changeIndex, currChange.ai); + this.vecAreaInfo.add(changeIndex, currChange.ai); } - changeList.clear(); + this.changeList.clear(); } - returnedIndex = 0; - return hasChanged; + this.returnedIndex = 0; + return this.hasChanged; } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, - int alignment) { - if (isFinished()) { + public LinkedList getChangedKnuthElements(final List oldList, + final int alignment) { + if (this.isFinished()) { return null; } - LinkedList returnList = new LinkedList(); + final LinkedList returnList = new LinkedList(); - while (returnedIndex < vecAreaInfo.size()) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(returnedIndex); + while (this.returnedIndex < this.vecAreaInfo.size()) { + final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(this.returnedIndex); if (ai.wordSpaceCount == 0) { // ai refers either to a word or a word fragment - addElementsForAWordFragment(returnList, alignment, ai, returnedIndex, letterSpaceIPD); + this.addElementsForAWordFragment(returnList, alignment, ai, + this.returnedIndex, this.letterSpaceIPD); } else { // ai refers to a space - addElementsForASpace(returnList, alignment, ai, returnedIndex); + this.addElementsForASpace(returnList, alignment, ai, this.returnedIndex); } - returnedIndex++; + this.returnedIndex++; } // end of while - setFinished(true); + this.setFinished(true); //ElementListObserver.observe(returnList, "text-changed", null); return returnList; } /** {@inheritDoc} */ - public void getWordChars(StringBuffer sbChars, Position pos) { - int leafValue = ((LeafPosition) pos).getLeafPos(); + public void getWordChars(final StringBuffer sbChars, final Position pos) { + final int leafValue = ((LeafPosition) pos).getLeafPos(); if (leafValue != -1) { - AreaInfo ai = (AreaInfo) vecAreaInfo.get(leafValue); - sbChars.append(textArray, ai.startIndex, ai.breakIndex - ai.startIndex); + final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(leafValue); + sbChars.append(this.textArray, ai.startIndex, ai.breakIndex - ai.startIndex); } } - private void addElementsForASpace(List baseList, - int alignment, - AreaInfo ai, - int leafValue) { - LeafPosition mainPosition = new LeafPosition(this, leafValue); + private void addElementsForASpace(final List baseList, + final int alignment, + final AreaInfo ai, + final int leafValue) { + final LeafPosition mainPosition = new LeafPosition(this, leafValue); if (!ai.breakOppAfter) { // a non-breaking space - if (alignment == EN_JUSTIFY) { + if (alignment == Constants.EN_JUSTIFY) { // the space can stretch and shrink, and must be preserved // when starting a line - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); } else { @@ -1010,8 +1024,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { mainPosition, true)); } } else { - if (textArray[ai.startIndex] != CharUtilities.SPACE - || foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { + if (this.textArray[ai.startIndex] != CharUtilities.SPACE + || this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved switch (alignment) { case EN_CENTER: @@ -1019,17 +1033,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line and at the // beginning of the next one, otherwise they don't add any stretch - baseList.add(new KnuthGlue(lineEndBAP, + baseList.add(new KnuthGlue(this.lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), -6 + -(this.lineStartBAP + this.lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, + this.auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(ai.areaIPD.opt + this.lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); break; @@ -1040,49 +1054,49 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line, otherwise // they don't add any stretch - baseList.add(new KnuthGlue(lineEndBAP, + baseList.add(new KnuthGlue(this.lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), -3 + -(this.lineStartBAP + this.lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(ai.areaIPD.opt + lineStartBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(ai.areaIPD.opt + this.lineStartBAP, 0, 0, mainPosition, false)); break; case EN_JUSTIFY: // justified text: // the stretch and shrink depends on the space width - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), ai.areaIPD.max + -(this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); break; default: // last line justified, the other lines unjustified: // use only the space stretch - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - - (lineStartBAP + lineEndBAP), ai.areaIPD.max + -(this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP + ai.areaIPD.opt, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + ai.areaIPD.opt, 0, 0, mainPosition, false)); } } else { @@ -1093,19 +1107,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line and at the // beginning of the next one, otherwise they don't add any stretch - baseList.add(new KnuthGlue(lineEndBAP, + baseList.add(new KnuthGlue(this.lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue(ai.areaIPD.opt - - (lineStartBAP + lineEndBAP), -6 + - (this.lineStartBAP + this.lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); + this.auxiliaryPosition, false)); break; case EN_START: // fall through @@ -1114,24 +1128,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line, otherwise // they don't add any stretch - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, + if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue(ai.areaIPD.opt - - (lineStartBAP + lineEndBAP), -3 + - (this.lineStartBAP + this.lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, + this.auxiliaryPosition, false)); } else { baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); @@ -1141,19 +1155,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { case EN_JUSTIFY: // justified text: // the stretch and shrink depends on the space width - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - ai.areaIPD.opt - (lineStartBAP + lineEndBAP), + ai.areaIPD.opt - (this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, + this.auxiliaryPosition, false)); } else { baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, @@ -1165,18 +1179,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { default: // last line justified, the other lines unjustified: // use only the space stretch - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); + if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); baseList.add(new KnuthGlue( - ai.areaIPD.opt - (lineStartBAP + lineEndBAP), + ai.areaIPD.opt - (this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max - ai.areaIPD.opt, 0, mainPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, + this.auxiliaryPosition, false)); } else { baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, 0, @@ -1187,18 +1201,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - private void addElementsForAWordFragment(List baseList, - int alignment, - AreaInfo ai, - int leafValue, - MinOptMax letterSpaceWidth) { + private void addElementsForAWordFragment(final List baseList, + final int alignment, + final AreaInfo ai, + final int leafValue, + final MinOptMax letterSpaceWidth) { - LeafPosition mainPosition = new LeafPosition(this, leafValue); + final LeafPosition mainPosition = new LeafPosition(this, leafValue); // if the last character of the word fragment is '-' or '/', // the fragment could end a line; in this case, it loses one // of its letter spaces; - boolean suppressibleLetterSpace = ai.breakOppAfter && !ai.isHyphenated; + final boolean suppressibleLetterSpace = ai.breakOppAfter && !ai.isHyphenated; if (letterSpaceWidth.min == letterSpaceWidth.max) { // constant letter spacing @@ -1206,138 +1220,152 @@ public class TextLayoutManager extends LeafNodeLayoutManager { suppressibleLetterSpace ? ai.areaIPD.opt - letterSpaceWidth.opt : ai.areaIPD.opt, - alignmentContext, - notifyPos(mainPosition), false)); + this.alignmentContext, + this.notifyPos(mainPosition), false)); } else { // adjustable letter spacing - int unsuppressibleLetterSpaces + final int unsuppressibleLetterSpaces = suppressibleLetterSpace ? ai.letterSpaceCount - 1 : ai.letterSpaceCount; baseList.add (new KnuthInlineBox(ai.areaIPD.opt - ai.letterSpaceCount * letterSpaceWidth.opt, - alignmentContext, - notifyPos(mainPosition), false)); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + this.alignmentContext, + this.notifyPos(mainPosition), false)); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); baseList.add (new KnuthGlue(unsuppressibleLetterSpaces * letterSpaceWidth.opt, unsuppressibleLetterSpaces * (letterSpaceWidth.max - letterSpaceWidth.opt), unsuppressibleLetterSpaces * (letterSpaceWidth.opt - letterSpaceWidth.min), - auxiliaryPosition, true)); - baseList.add(makeAuxiliaryZeroWidthBox()); + this.auxiliaryPosition, true)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); } // extra-elements if the word fragment is the end of a syllable, // or it ends with a character that can be used as a line break if (ai.isHyphenated) { MinOptMax widthIfNoBreakOccurs = null; - if (ai.breakIndex < textArray.length) { + if (ai.breakIndex < this.textArray.length) { //Add in kerning in no-break condition - widthIfNoBreakOccurs = letterAdjustArray[ai.breakIndex]; + widthIfNoBreakOccurs = this.letterAdjustArray[ai.breakIndex]; } //if (ai.breakIndex) // the word fragment ends at the end of a syllable: // if a break occurs the content width increases, // otherwise nothing happens - addElementsForAHyphen(baseList, alignment, hyphIPD, widthIfNoBreakOccurs, ai.breakOppAfter && ai.isHyphenated); + this.addElementsForAHyphen(baseList, alignment, this.hyphIPD, + widthIfNoBreakOccurs, ai.breakOppAfter && ai.isHyphenated); } else if (suppressibleLetterSpace) { // the word fragment ends with a character that acts as a hyphen // if a break occurs the width does not increase, // otherwise there is one more letter space - addElementsForAHyphen(baseList, alignment, 0, letterSpaceWidth, true); + this.addElementsForAHyphen(baseList, alignment, 0, letterSpaceWidth, true); } } // static final int SOFT_HYPHEN_PENALTY = KnuthPenalty.FLAGGED_PENALTY / 10; - static final int SOFT_HYPHEN_PENALTY = 1; + private static final int SOFT_HYPHEN_PENALTY = 1; - private void addElementsForAHyphen(List baseList, - int alignment, - int widthIfBreakOccurs, + private void addElementsForAHyphen(final List baseList, + final int alignment, + final int widthIfBreakOccurs, MinOptMax widthIfNoBreakOccurs, - boolean unflagged) { + final boolean unflagged) { if (widthIfNoBreakOccurs == null) { - widthIfNoBreakOccurs = ZERO_MINOPTMAX; + widthIfNoBreakOccurs = TextLayoutManager.ZERO_MINOPTMAX; } switch (alignment) { case EN_CENTER : // centered text: - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, true)); - baseList.add(new KnuthPenalty(hyphIPD, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); - baseList.add(new KnuthGlue(-(lineEndBAP + lineStartBAP), - -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, true)); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, true)); + baseList.add(new KnuthPenalty(this.hyphIPD, + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); + baseList.add(new KnuthGlue(-(this.lineEndBAP + this.lineStartBAP), + -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, true)); break; case EN_START : // fall through case EN_END : // left- or right-aligned text: - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); + if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); - baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), - -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt + - (this.lineStartBAP + this.lineEndBAP), -3 + * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, + this.auxiliaryPosition, false)); } else { - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); + this.auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); + this.auxiliaryPosition, false)); } break; default: // justified text, or last line justified: // just a flagged penalty - if (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, false)); + if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 || widthIfNoBreakOccurs.max != 0) { - baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), - widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, - widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - auxiliaryPosition, false)); + baseList + .add(new KnuthGlue(widthIfNoBreakOccurs.opt + - (this.lineStartBAP + this.lineEndBAP), + widthIfNoBreakOccurs.max + - widthIfNoBreakOccurs.opt, + widthIfNoBreakOccurs.opt + - widthIfNoBreakOccurs.min, + this.auxiliaryPosition, false)); } else { - baseList.add(new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, - auxiliaryPosition, false)); + baseList.add(new KnuthGlue(-(this.lineStartBAP + this.lineEndBAP), 0, 0, + this.auxiliaryPosition, false)); } - baseList.add(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, + this.auxiliaryPosition, false)); } else { baseList.add(new KnuthPenalty(widthIfBreakOccurs, - unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - auxiliaryPosition, false)); + unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, + this.auxiliaryPosition, false)); // extra elements representing a letter space that is suppressed // if a break occurs if (widthIfNoBreakOccurs.min != 0 @@ -1345,11 +1373,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - auxiliaryPosition, false)); + this.auxiliaryPosition, false)); } } } - + } } -- cgit v1.2.3 From a3f12ad2eaf2d0edf78ed9e126803db1ebd296b8 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sun, 1 Jun 2008 11:57:33 +0000 Subject: More code Cleanups (no functional changes) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@662203 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/inline/TextLayoutManager.java | 563 +++++++++------------ 1 file changed, 237 insertions(+), 326 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 3f4fc44bc..6ae909cd7 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr.inline; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -564,112 +563,23 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (inWord) { if (breakOpportunity || TextLayoutManager.isSpace(ch) || ch == TextLayoutManager.NEWLINE) { - //Word boundary found, process widths and kerning - short lastIndex = this.nextStart; - while (lastIndex > 0 - && this.textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { - lastIndex--; - } - final Font font = FontSelector - .selectFontForCharactersInText(this.textArray, - this.thisStart, lastIndex, this.foText, this); - final int wordLength = lastIndex - this.thisStart; - final boolean kerning = font.hasKerning(); - final MinOptMax wordIPD = new MinOptMax(0); - for (int i = this.thisStart; i < lastIndex; i++) { - final char c = this.textArray[i]; - - //character width - final int charWidth = font.getCharWidth(c); - wordIPD.add(charWidth); - - //kerning - if (kerning) { - int kern = 0; - if (i > this.thisStart) { - final char previous = this.textArray[i - 1]; - kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { - final char previous = this.textArray[prevAi.breakIndex - 1]; - kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } - if (kern != 0) { - this.addToLetterAdjust(i, kern); - wordIPD.add(kern); - } - } - } - if (kerning - && breakOpportunity - && !TextLayoutManager.isSpace(ch) - && lastIndex > 0 - && this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN) { - final int kern = font.getKernValue( - this.textArray[lastIndex - 1], ch) - * font.getFontSize() / 1000; - if (kern != 0) { - this.addToLetterAdjust(lastIndex, kern); - } - } - int iLetterSpaces = wordLength - 1; - // if there is a break opportunity and the next one - // is not a space, it could be used as a line end; - // add one more letter space, in case other text follows - if (breakOpportunity && !TextLayoutManager.isSpace(ch)) { - iLetterSpaces++; - } - wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); - - // create the AreaInfo object - ai = new AreaInfo(this.thisStart, lastIndex, (short) 0, - (short) iLetterSpaces, wordIPD, - this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, - false, breakOpportunity, font); - prevAi = ai; - this.vecAreaInfo.add(ai); - this.tempStart = this.nextStart; - - //add the elements - this.addElementsForAWordFragment(sequence, alignment, ai, - this.vecAreaInfo.size() - 1, this.letterSpaceIPD); - ai = null; - this.thisStart = this.nextStart; + // this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN + prevAi = this.processWord(alignment, sequence, prevAi, ch, + breakOpportunity, true); } } else if (inWhitespace) { if (ch != CharUtilities.SPACE || breakOpportunity) { - // End of whitespace - // create the AreaInfo object - ai = new AreaInfo(this.thisStart, this.nextStart, - (short) (this.nextStart - this.thisStart), (short) 0, - MinOptMax.multiply(this.wordSpaceIPD, this.nextStart - - this.thisStart), false, true, - breakOpportunity, this.spaceFont); - this.vecAreaInfo.add(ai); - prevAi = ai; - - // create the elements - this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); - ai = null; - - this.thisStart = this.nextStart; + prevAi = this.processWhitespace(alignment, sequence, + breakOpportunity); } } else { if (ai != null) { - this.vecAreaInfo.add(ai); prevAi = ai; - ai.breakOppAfter = ch == CharUtilities.SPACE || breakOpportunity; - this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); - ai = null; + ai = this.processLeftoverAi(alignment, sequence, ai, ch, + ch == CharUtilities.SPACE || breakOpportunity); } if (breakAction == LineBreakStatus.EXPLICIT_BREAK) { - if (this.lineEndBAP != 0) { - sequence.add( - new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, true)); - } - sequence.endSequence(); - sequence = new InlineKnuthSequence(); - returnList.add(sequence); + sequence = this.processLinebreak(returnList, sequence); } } @@ -704,75 +614,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // Process any last elements if (inWord) { - int lastIndex = this.nextStart; - if (this.textArray[this.nextStart - 1] == CharUtilities.SOFT_HYPHEN) { - lastIndex--; - } - final int wordLength = lastIndex - this.thisStart; - final Font font = FontSelector.selectFontForCharactersInText( - this.textArray, this.thisStart, lastIndex, this.foText, this); - final boolean kerning = font.hasKerning(); - final MinOptMax wordIPD = new MinOptMax(0); - for (int i = this.thisStart; i < lastIndex; i++) { - final char c = this.textArray[i]; - - //character width - final int charWidth = font.getCharWidth(c); - wordIPD.add(charWidth); - - //kerning - if (kerning) { - int kern = 0; - if (i > this.thisStart) { - final char previous = this.textArray[i - 1]; - kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } else if (prevAi != null && !prevAi.isSpace) { - final char previous = this.textArray[prevAi.breakIndex - 1]; - kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; - } - if (kern != 0) { - this.addToLetterAdjust(i, kern); - wordIPD.add(kern); - } - } - } - final int iLetterSpaces = wordLength - 1; - wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); - - // create the AreaInfo object - ai = new AreaInfo(this.thisStart, (short) lastIndex, (short) 0, - (short) iLetterSpaces, wordIPD, false, false, false, font); - this.vecAreaInfo.add(ai); - this.tempStart = this.nextStart; - - // create the elements - this.addElementsForAWordFragment(sequence, alignment, ai, - this.vecAreaInfo.size() - 1, this.letterSpaceIPD); - ai = null; + this.processWord(alignment, sequence, prevAi, ch, false, false); } else if (inWhitespace) { - ai = new AreaInfo(this.thisStart, this.nextStart, - (short) (this.nextStart - this.thisStart), (short) 0, MinOptMax - .multiply(this.wordSpaceIPD, this.nextStart - this.thisStart), - false, true, true, this.spaceFont); - this.vecAreaInfo.add(ai); - - // create the elements - this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); - ai = null; + this.processWhitespace(alignment, sequence, true); } else if (ai != null) { - this.vecAreaInfo.add(ai); - ai.breakOppAfter = ch == CharUtilities.ZERO_WIDTH_SPACE; - this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); - ai = null; + ai = this.processLeftoverAi(alignment, sequence, ai, ch, + ch == CharUtilities.ZERO_WIDTH_SPACE); } else if (ch == TextLayoutManager.NEWLINE) { - if (this.lineEndBAP != 0) { - sequence.add - (new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, true)); - } - sequence.endSequence(); - sequence = new InlineKnuthSequence(); - returnList.add(sequence); + sequence = this.processLinebreak(returnList, sequence); } if (((List)returnList.getLast()).size() == 0) { @@ -787,6 +636,130 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } + private KnuthSequence processLinebreak(final LinkedList returnList, + KnuthSequence sequence) { + if (this.lineEndBAP != 0) { + sequence.add( + new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, true)); + } + sequence.endSequence(); + sequence = new InlineKnuthSequence(); + returnList.add(sequence); + return sequence; + } + + private AreaInfo processLeftoverAi(final int alignment, + final KnuthSequence sequence, AreaInfo ai, final char ch, + final boolean breakOpportunityAfter) { + this.vecAreaInfo.add(ai); + ai.breakOppAfter = breakOpportunityAfter; + this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); + ai = null; + return ai; + } + + private AreaInfo processWhitespace(final int alignment, + final KnuthSequence sequence, final boolean breakOpportunity) { + AreaInfo ai; + AreaInfo prevAi; + // End of whitespace + // create the AreaInfo object + ai = new AreaInfo(this.thisStart, this.nextStart, + (short) (this.nextStart - this.thisStart), (short) 0, + MinOptMax.multiply(this.wordSpaceIPD, this.nextStart + - this.thisStart), false, true, + breakOpportunity, this.spaceFont); + this.vecAreaInfo.add(ai); + prevAi = ai; + + // create the elements + this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); + ai = null; + + this.thisStart = this.nextStart; + return prevAi; + } + + private AreaInfo processWord(final int alignment, final KnuthSequence sequence, + AreaInfo prevAi, final char ch, final boolean breakOpportunity, + final boolean checkEndsWithHyphen) { + AreaInfo ai; + //Word boundary found, process widths and kerning + short lastIndex = this.nextStart; + while (lastIndex > 0 + && this.textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { + lastIndex--; + } + final boolean endsWithHyphen = checkEndsWithHyphen + && this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN; + final Font font = FontSelector + .selectFontForCharactersInText(this.textArray, + this.thisStart, lastIndex, this.foText, this); + final int wordLength = lastIndex - this.thisStart; + final boolean kerning = font.hasKerning(); + final MinOptMax wordIPD = new MinOptMax(0); + for (int i = this.thisStart; i < lastIndex; i++) { + final char c = this.textArray[i]; + + //character width + final int charWidth = font.getCharWidth(c); + wordIPD.add(charWidth); + + //kerning + if (kerning) { + int kern = 0; + if (i > this.thisStart) { + final char previous = this.textArray[i - 1]; + kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; + } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { + final char previous = this.textArray[prevAi.breakIndex - 1]; + kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; + } + if (kern != 0) { + this.addToLetterAdjust(i, kern); + wordIPD.add(kern); + } + } + } + if (kerning + && breakOpportunity + && !TextLayoutManager.isSpace(ch) + && lastIndex > 0 + && endsWithHyphen) { + final int kern = font.getKernValue( + this.textArray[lastIndex - 1], ch) + * font.getFontSize() / 1000; + if (kern != 0) { + this.addToLetterAdjust(lastIndex, kern); + } + } + int iLetterSpaces = wordLength - 1; + // if there is a break opportunity and the next one + // is not a space, it could be used as a line end; + // add one more letter space, in case other text follows + if (breakOpportunity && !TextLayoutManager.isSpace(ch)) { + iLetterSpaces++; + } + wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); + + // create the AreaInfo object + ai = new AreaInfo(this.thisStart, lastIndex, (short) 0, + (short) iLetterSpaces, wordIPD, + endsWithHyphen, + false, breakOpportunity, font); + prevAi = ai; + this.vecAreaInfo.add(ai); + this.tempStart = this.nextStart; + + //add the elements + this.addElementsForAWordFragment(sequence, alignment, ai, + this.vecAreaInfo.size() - 1, this.letterSpaceIPD); + ai = null; + this.thisStart = this.nextStart; + return prevAi; + } + /** {@inheritDoc} */ public List addALetterSpaceTo(final List oldList) { // old list contains only a box, or the sequence: box penalty glue box; @@ -1027,176 +1000,114 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (this.textArray[ai.startIndex] != CharUtilities.SPACE || this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved - switch (alignment) { - case EN_CENTER: - // centered text: - // if the second element is chosen as a line break these elements - // add a constant amount of stretch at the end of a line and at the - // beginning of the next one, otherwise they don't add any stretch - baseList.add(new KnuthGlue(this.lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - -(this.lineStartBAP + this.lineEndBAP), -6 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(ai.areaIPD.opt + this.lineStartBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - break; - - case EN_START: // fall through - case EN_END: - // left- or right-aligned text: - // if the second element is chosen as a line break these elements - // add a constant amount of stretch at the end of a line, otherwise - // they don't add any stretch - baseList.add(new KnuthGlue(this.lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - -(this.lineStartBAP + this.lineEndBAP), -3 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(ai.areaIPD.opt + this.lineStartBAP, 0, 0, - mainPosition, false)); - break; - - case EN_JUSTIFY: - // justified text: - // the stretch and shrink depends on the space width - baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - -(this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max - - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, - this.auxiliaryPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP + ai.areaIPD.opt, 0, 0, - mainPosition, false)); - break; - - default: - // last line justified, the other lines unjustified: - // use only the space stretch - baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - -(this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max - - ai.areaIPD.opt, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP + ai.areaIPD.opt, 0, 0, - mainPosition, false)); - } + this + .addElementsForBreakingSpace(baseList, alignment, ai, + this.auxiliaryPosition, 0, mainPosition, + ai.areaIPD.opt, true); } else { // a (possible block) of breaking spaces - switch (alignment) { - case EN_CENTER: - // centered text: - // if the second element is chosen as a line break these elements - // add a constant amount of stretch at the end of a line and at the - // beginning of the next one, otherwise they don't add any stretch - baseList.add(new KnuthGlue(this.lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(ai.areaIPD.opt - - (this.lineStartBAP + this.lineEndBAP), -6 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - break; + this + .addElementsForBreakingSpace(baseList, alignment, ai, + mainPosition, ai.areaIPD.opt, + this.auxiliaryPosition, 0, false); + } + } + } - case EN_START: // fall through - case EN_END: - // left- or right-aligned text: - // if the second element is chosen as a line break these elements - // add a constant amount of stretch at the end of a line, otherwise - // they don't add any stretch - if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { - baseList.add(new KnuthGlue(this.lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(ai.areaIPD.opt + private void addElementsForBreakingSpace(final List baseList, + final int alignment, final AreaInfo ai, final Position pos2, + final int p2WidthOffset, final Position pos3, + final int p3WidthOffset, final boolean skipZeroCheck) { + switch (alignment) { + case EN_CENTER: + // centered text: + // if the second element is chosen as a line break these elements + // add a constant amount of stretch at the end of a line and at the + // beginning of the next one, otherwise they don't add any stretch + baseList.add(new KnuthGlue(this.lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(p2WidthOffset + - (this.lineStartBAP + this.lineEndBAP), -6 + * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos3, false)); + break; + + case EN_START: // fall through + case EN_END: + // left- or right-aligned text: + // if the second element is chosen as a line break these elements + // add a constant amount of stretch at the end of a line, otherwise + // they don't add any stretch + if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList + .add(new KnuthGlue(p2WidthOffset - (this.lineStartBAP + this.lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, - this.auxiliaryPosition, false)); - } else { - baseList.add(new KnuthGlue(0, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 + pos2, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + 0, 0, pos3, false)); + } else { + baseList.add(new KnuthGlue(0, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList + .add(new KnuthGlue(ai.areaIPD.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - mainPosition, false)); - } - break; + pos2, false)); + } + break; - case EN_JUSTIFY: - // justified text: - // the stretch and shrink depends on the space width - if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { - baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - ai.areaIPD.opt - (this.lineStartBAP + this.lineEndBAP), - ai.areaIPD.max - ai.areaIPD.opt, - ai.areaIPD.opt - ai.areaIPD.min, - mainPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, - this.auxiliaryPosition, false)); - } else { - baseList.add(new KnuthGlue(ai.areaIPD.opt, - ai.areaIPD.max - ai.areaIPD.opt, - ai.areaIPD.opt - ai.areaIPD.min, - mainPosition, false)); - } - break; + case EN_JUSTIFY: + // justified text: + // the stretch and shrink depends on the space width + if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(p2WidthOffset + - (this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max + - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, + pos2, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + 0, 0, pos3, false)); + } else { + baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max + - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, + pos2, false)); + } + break; - default: - // last line justified, the other lines unjustified: - // use only the space stretch - if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { - baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - ai.areaIPD.opt - (this.lineStartBAP + this.lineEndBAP), - ai.areaIPD.max - ai.areaIPD.opt, - 0, mainPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, - this.auxiliaryPosition, false)); - } else { - baseList.add(new KnuthGlue(ai.areaIPD.opt, - ai.areaIPD.max - ai.areaIPD.opt, 0, - mainPosition, false)); - } - } + default: + // last line justified, the other lines unjustified: + // use only the space stretch + if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { + baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, + this.auxiliaryPosition, false)); + baseList.add(this.makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(p2WidthOffset + - (this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max + - ai.areaIPD.opt, 0, pos2, false)); + baseList.add(this.makeAuxiliaryZeroWidthBox()); + baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + 0, 0, pos3, false)); + } else { + baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max + - ai.areaIPD.opt, 0, pos2, false)); } } } -- cgit v1.2.3 From f384a587d01937d1f0ddc2318070157c563b072b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 2 Jun 2008 12:50:55 +0000 Subject: Integer keeps inside multi-line blocks and in between block-paragraphs. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@662417 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/inline/LineLayoutManager.java | 31 +++++++++++++--------- .../block_keep-together_integers_1.xml | 17 ++++++++++++ 2 files changed, 36 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 8c46796eb..c9f72e64f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -46,6 +46,7 @@ import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.BreakingAlgorithm; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.InlineKnuthSequence; +import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -1052,11 +1053,14 @@ public class LineLayoutManager extends InlineStackingLayoutManager LinkedList returnList = new LinkedList(); for (int p = 0; p < knuthParagraphs.size(); p++) { - // null penalty between paragraphs - if (p > 0 && !((BlockLevelLayoutManager) parentLM).mustKeepTogether()) { - returnList.add(new BreakElement( - new Position(this), 0, context)); - //returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); + // penalty between paragraphs + if (p > 0) { + int strength = getKeepTogetherStrength(); + int penalty = KeepUtil.getPenaltyForKeep(strength); + if (penalty < KnuthElement.INFINITE) { + returnList.add(new BreakElement( + new Position(this), penalty, context)); + } } LineLayoutPossibilities llPoss; @@ -1090,14 +1094,17 @@ public class LineLayoutManager extends InlineStackingLayoutManager for (int i = 0; i < llPoss.getChosenLineCount(); i++) { - if (!((BlockLevelLayoutManager) parentLM).mustKeepTogether() + if (returnList.size() > 0 + && i > 0 //if i==0 break generated above already && i >= fobj.getOrphans() - && i <= llPoss.getChosenLineCount() - fobj.getWidows() - && returnList.size() > 0) { - // null penalty allowing a page break between lines - returnList.add(new BreakElement( - returnPosition, 0, context)); - //returnList.add(new KnuthPenalty(0, 0, false, returnPosition, false)); + && i <= llPoss.getChosenLineCount() - fobj.getWidows()) { + // penalty allowing a page break between lines + int strength = getKeepTogetherStrength(); + int penalty = KeepUtil.getPenaltyForKeep(strength); + if (penalty < KnuthElement.INFINITE) { + returnList.add(new BreakElement( + returnPosition, penalty, context)); + } } int endIndex = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos(); diff --git a/test/layoutengine/standard-testcases/block_keep-together_integers_1.xml b/test/layoutengine/standard-testcases/block_keep-together_integers_1.xml index f6027bf01..8ad263fcb 100644 --- a/test/layoutengine/standard-testcases/block_keep-together_integers_1.xml +++ b/test/layoutengine/standard-testcases/block_keep-together_integers_1.xml @@ -54,6 +54,11 @@ block10 + The quick brown fox jumps over the lazy dog. + The quick brown fox jumps over the lazy dog. + The quick brown fox jumps over the lazy dog. + The quick brown fox jumps over the lazy dog. + @@ -76,7 +81,9 @@ + + @@ -91,7 +98,17 @@ + + + + + + + + + + 3 -- cgit v1.2.3 From 8a862123768654c3e55653d12fc4910dc99184bb Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 3 Jun 2008 14:13:27 +0000 Subject: Bugzilla #45115: Added a PCL-specific extension attribute on simple-page-master for controlling the simplex/duplex mode. Submitted by: Martin Edge git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@662807 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/output.xml | 25 ++++++++++++++++++++++ .../org/apache/fop/render/pcl/PCLGenerator.java | 13 +++++++++++ .../org/apache/fop/render/pcl/PCLRenderer.java | 11 +++++++--- status.xml | 4 ++++ 4 files changed, 50 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index 628df1248..22d916d31 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -422,6 +422,31 @@ out = proc.getOutputStream();]]> Consult the technical reference for your printer for all available values.

    +
    + Page Duplex Mode +

    + The duplex-mode extension attribute on fo:simple-page-master allows to + select the duplex mode to be used for a particular simple-page-master. + Example: +

    + + + ... + + +]]> +

    + Note: the duplex is a positive integer and the value depends on + the target printer. Not all PCL printers support duplexing. + Usually, + "0" is simplex, + "1" is duplex (long-edge binding), + "2" is duplex (short-edge binding). + + Consult the technical reference for your printer for all available values. +

    +
    diff --git a/src/java/org/apache/fop/render/pcl/PCLGenerator.java b/src/java/org/apache/fop/render/pcl/PCLGenerator.java index 5ca9a8bf9..6a4425012 100644 --- a/src/java/org/apache/fop/render/pcl/PCLGenerator.java +++ b/src/java/org/apache/fop/render/pcl/PCLGenerator.java @@ -229,6 +229,19 @@ public class PCLGenerator { writeCommand("&l" + selector + "H"); } + /** + * Selects the duplexing mode for the page. + * The parameter is usually printer-specific. + * "0" means Simplex, + * "1" means Duplex, Long-Edge Binding, + * "2" means Duplex, Short-Edge Binding. + * @param selector the integer representing the duplexing mode of the page + * @throws IOException In case of an I/O error + */ + public void selectDuplexMode(int selector) throws IOException { + writeCommand("&l" + selector + "S"); + } + /** * Clears the horizontal margins. * @throws IOException In case of an I/O error diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 007ce4828..988517cc7 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -395,9 +395,7 @@ public class PCLRenderer extends PrintRenderer { return MIME_TYPE; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderPage(PageViewport page) throws IOException, FOPException { saveGraphicsState(); @@ -408,6 +406,13 @@ public class PCLRenderer extends PrintRenderer { gen.selectPaperSource(Integer.parseInt(paperSource)); } + // Is Page duplex? + String pageDuplex = page.getForeignAttributeValue( + new QName(PCLElementMapping.NAMESPACE, null, "duplex-mode")); + if (pageDuplex != null) { + gen.selectDuplexMode(Integer.parseInt(pageDuplex)); + } + //Page size final long pagewidth = Math.round(page.getViewArea().getWidth()); final long pageheight = Math.round(page.getViewArea().getHeight()); diff --git a/status.xml b/status.xml index 2cfc7658e..c82fca331 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,10 @@ Added SVG support for AFP (GOCA). + + Added a PCL-specific extension attribute on simple-page-master for controlling + the simplex/duplex mode. + Corrected white-space-treatment for situations where an inline-node is the first/last child node of an fo:block, without preceding/following text. -- cgit v1.2.3 From 1b11a108c159b68078e312e44e66840a25d1f73f Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 4 Jun 2008 06:10:37 +0000 Subject: ApacheCon EU 2008 is long over. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@662991 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/skinconf.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/documentation/skinconf.xml b/src/documentation/skinconf.xml index e87baab34..20b12808e 100644 --- a/src/documentation/skinconf.xml +++ b/src/documentation/skinconf.xml @@ -369,6 +369,7 @@ which will be used to configure the chosen Forrest skin. 88 31 + ApacheCon US 2008 http://us.apachecon.com/ -- cgit v1.2.3 From 37d4c4b7aa0cc8983adea4036ddb84e68b909dd3 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Wed, 4 Jun 2008 09:53:15 +0000 Subject: Minor cleanup: remove spurious white-space git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@663045 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/inline/TextLayoutManager.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 6ae909cd7..acdb75f06 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -1000,14 +1000,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (this.textArray[ai.startIndex] != CharUtilities.SPACE || this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved - this - .addElementsForBreakingSpace(baseList, alignment, ai, + this.addElementsForBreakingSpace(baseList, alignment, ai, this.auxiliaryPosition, 0, mainPosition, ai.areaIPD.opt, true); } else { // a (possible block) of breaking spaces - this - .addElementsForBreakingSpace(baseList, alignment, ai, + this.addElementsForBreakingSpace(baseList, alignment, ai, mainPosition, ai.areaIPD.opt, this.auxiliaryPosition, 0, false); } @@ -1048,8 +1046,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, this.auxiliaryPosition, false)); baseList.add(this.makeZeroWidthPenalty(0)); - baseList - .add(new KnuthGlue(p2WidthOffset + baseList.add(new KnuthGlue(p2WidthOffset - (this.lineStartBAP + this.lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); @@ -1062,8 +1059,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, this.auxiliaryPosition, false)); baseList.add(this.makeZeroWidthPenalty(0)); - baseList - .add(new KnuthGlue(ai.areaIPD.opt, -3 + baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); } -- cgit v1.2.3 From 2b6ba7bf56c399fb84604f191e95a2e4d0bf6fdb Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 5 Jun 2008 07:41:06 +0000 Subject: Restored lost overflow warning in static-content. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@663493 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 42ddcc220..8065f9aad 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -364,6 +364,12 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { protected void doPhase3(PageBreakingAlgorithm alg, int partCount, BlockSequence originalList, BlockSequence effectiveList) { + if (partCount > 1) { + PageBreakPosition pos = (PageBreakPosition)alg.getPageBreaks().getFirst(); + int firstPartLength = ElementListUtils.calcContentLength(effectiveList, + effectiveList.ignoreAtStart, pos.getLeafPos()); + overflow += alg.totalWidth - firstPartLength; + } //Rendering all parts (not just the first) at once for the case where the parts that //overflow should be visible. alg.removeAllPageBreaks(); -- cgit v1.2.3 From b66171a4e6bfbe271ea0726815c3f497c7c8ca2b Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 7 Jun 2008 14:49:42 +0000 Subject: Extended behavior of preserved linefeeds to codepoints representing mandatory breaks in Unicode UAX#14: - NEXT LINE (U+0085) - LINE SEPARATOR (U+2028) - PARAGRAPH SEPARATOR (U+2029) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@664347 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/inline/TextLayoutManager.java | 19 ++++--- src/java/org/apache/fop/util/CharUtilities.java | 49 ++++++++++++----- .../block_uax14_explicit-breaks.xml | 64 ++++++++++++++++++++++ 3 files changed, 110 insertions(+), 22 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block_uax14_explicit-breaks.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index acdb75f06..58ab9505f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -140,7 +140,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private final MinOptMax[] letterAdjustArray; //size = textArray.length + 1 private static final char NEWLINE = '\n'; - + /** Font used for the space between words. */ private Font spaceFont = null; /** Start index of next TextArea */ @@ -523,7 +523,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { || CharUtilities.isNonBreakableSpace(ch) || CharUtilities.isFixedWidthSpace(ch); } - + /** {@inheritDoc} */ public LinkedList getNextKnuthElements(final LayoutContext context, final int alignment) { this.lineStartBAP = context.getLineStartBorderAndPaddingWidth(); @@ -561,8 +561,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { TextLayoutManager.LOG.error("Unexpected breakAction: " + breakAction); } if (inWord) { - if (breakOpportunity || TextLayoutManager.isSpace(ch) - || ch == TextLayoutManager.NEWLINE) { + if (breakOpportunity + || TextLayoutManager.isSpace(ch) + || CharUtilities.isExplicitBreak(ch)) { // this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN prevAi = this.processWord(alignment, sequence, prevAi, ch, breakOpportunity, true); @@ -601,12 +602,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { (short) 0, (short) 0, ipd, false, true, breakOpportunity, font); this.thisStart = (short) (this.nextStart + 1); - } else if (ch == TextLayoutManager.NEWLINE) { - // linefeed; this can happen when linefeed-treatment="preserve" + } else if (CharUtilities.isExplicitBreak(ch)) { + //mandatory break-character: only advance index this.thisStart = (short) (this.nextStart + 1); } + inWord = !TextLayoutManager.isSpace(ch) - && ch != TextLayoutManager.NEWLINE; + && !CharUtilities.isExplicitBreak(ch); inWhitespace = ch == CharUtilities.SPACE && this.foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; this.nextStart++; @@ -620,7 +622,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } else if (ai != null) { ai = this.processLeftoverAi(alignment, sequence, ai, ch, ch == CharUtilities.ZERO_WIDTH_SPACE); - } else if (ch == TextLayoutManager.NEWLINE) { + } else if (CharUtilities.isExplicitBreak(ch)) { sequence = this.processLinebreak(returnList, sequence); } @@ -628,6 +630,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //Remove an empty sequence because of a trailing newline returnList.removeLast(); } + this.setFinished(true); if (returnList.isEmpty()) { return null; diff --git a/src/java/org/apache/fop/util/CharUtilities.java b/src/java/org/apache/fop/util/CharUtilities.java index 4910a371c..6baa5c0fd 100644 --- a/src/java/org/apache/fop/util/CharUtilities.java +++ b/src/java/org/apache/fop/util/CharUtilities.java @@ -54,10 +54,16 @@ public class CharUtilities { public static final int XMLWHITESPACE = 4; + /** linefeed character */ + public static final char LINEFEED_CHAR = '\n'; + /** carriage return */ + public static final char CARRIAGE_RETURN = '\r'; /** normal space */ public static final char SPACE = '\u0020'; /** non-breaking space */ public static final char NBSPACE = '\u00A0'; + /** next line control character */ + public static final char NEXT_LINE = '\u0085'; /** zero-width space */ public static final char ZERO_WIDTH_SPACE = '\u200B'; /** word joiner */ @@ -68,6 +74,10 @@ public class CharUtilities { public static final char ZERO_WIDTH_NOBREAK_SPACE = '\uFEFF'; /** soft hyphen */ public static final char SOFT_HYPHEN = '\u00AD'; + /** line-separator */ + public static final char LINE_SEPARATOR = '\u2028'; + /** paragraph-separator */ + public static final char PARAGRAPH_SEPARATOR = '\u2029'; /** missing ideograph */ public static final char MISSING_IDEOGRAPH = '\u25A1'; /** Unicode value indicating the the character is "not a character". */ @@ -174,8 +184,7 @@ public class CharUtilities { * @return True if the character represents any kind of space */ public static boolean isAnySpace(char c) { - boolean ret = (isBreakableSpace(c) || isNonBreakableSpace(c)); - return ret; + return (isBreakableSpace(c) || isNonBreakableSpace(c)); } /** @@ -188,19 +197,31 @@ public class CharUtilities { //Generated from: Other_Alphabetic + Lu + Ll + Lt + Lm + Lo + Nl int generalCategory = Character.getType(ch); switch (generalCategory) { - case Character.UPPERCASE_LETTER: //Lu - case Character.LOWERCASE_LETTER: //Ll - case Character.TITLECASE_LETTER: //Lt - case Character.MODIFIER_LETTER: //Lm - case Character.OTHER_LETTER: //Lo - case Character.LETTER_NUMBER: //Nl - return true; - default: - //TODO if (ch in Other_Alphabetic) return true; (Probably need ICU4J for that) - //Other_Alphabetic contains mostly more exotic characters - return false; + case Character.UPPERCASE_LETTER: //Lu + case Character.LOWERCASE_LETTER: //Ll + case Character.TITLECASE_LETTER: //Lt + case Character.MODIFIER_LETTER: //Lm + case Character.OTHER_LETTER: //Lo + case Character.LETTER_NUMBER: //Nl + return true; + default: + //TODO if (ch in Other_Alphabetic) return true; (Probably need ICU4J for that) + //Other_Alphabetic contains mostly more exotic characters + return false; } } - + + /** + * Indicates whether the given character is an explicit break-character + * @param ch the character to check + * @return true if the character represents an explicit break + */ + public static boolean isExplicitBreak(char ch) { + return (ch == LINEFEED_CHAR + || ch == CARRIAGE_RETURN + || ch == NEXT_LINE + || ch == LINE_SEPARATOR + || ch == PARAGRAPH_SEPARATOR); + } } diff --git a/test/layoutengine/standard-testcases/block_uax14_explicit-breaks.xml b/test/layoutengine/standard-testcases/block_uax14_explicit-breaks.xml new file mode 100644 index 000000000..7636e9ae4 --- /dev/null +++ b/test/layoutengine/standard-testcases/block_uax14_explicit-breaks.xml @@ -0,0 +1,64 @@ + + + + + +

    + This test checks for the handling of explicit breaking characters: + - preserved linefeeds (U+000A) + - Unicode next-line (U+0085), line-separator (U+2028) + or paragraph-separator (U+2029) + Other possibilities defined in UAX#14, but not applicable for XSL-FO: + - carriage return (U+000D) is normalized to a space + - line-tabulation (U+000B) and form-feed (U+000C) are illegal XML characters +

    +
    + + + + + + + + + + This is a piece of text with preserved linefeed character. + + This is a piece of text with a next-line…character. + + + This is a piece of text with a line-separator
character. + + + This is a piece of text with a paragraph-separator
character. + + + There should be 2 empty lines between this one


and this one. + + + + + + + + + + + + +
    -- cgit v1.2.3 From bcf8379cf44f09ed3a78873fda6241f944b6d461 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 7 Jun 2008 14:54:13 +0000 Subject: Minor cleanup: remove unneeded constant git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@664349 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 58ab9505f..903ec84ae 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -139,8 +139,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager { */ private final MinOptMax[] letterAdjustArray; //size = textArray.length + 1 - private static final char NEWLINE = '\n'; - /** Font used for the space between words. */ private Font spaceFont = null; /** Start index of next TextArea */ -- cgit v1.2.3 From ff51233ed95afb0a54a6e47c6bed5890af5b5304 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 7 Jun 2008 15:09:42 +0000 Subject: Improve code-readability; add some clarifying comments git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@664350 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/text/linebreak/LineBreakStatus.java | 139 ++++++++++++--------- 1 file changed, 81 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java b/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java index 2f513c59c..44b27889a 100644 --- a/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java +++ b/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java @@ -73,76 +73,99 @@ public class LineBreakStatus { * @return the break action to be taken */ public byte nextChar(char c) { + byte currentClass = LineBreakUtils.getLineBreakProperty(c); + if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_AI || leftClass == LineBreakUtils.LINE_BREAK_PROPERTY_XX) { + //current "Ambiguous" or previous "Unknown": + // assume current "Alphabetic" currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; - } else if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_NL) { - currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; } - if (leftClass == -1) { - if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; - } else { + + /** Check 1: initial character after a reset/mandatory break? */ + switch (leftClass) { + case -1: + //first character after a reset() leftClass = currentClass; if (leftClass == LineBreakUtils.LINE_BREAK_PROPERTY_CM) { leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_ID; } - } - // LB 2a - return PROHIBITED_BREAK; - } else if (!(leftClass != LineBreakUtils.LINE_BREAK_PROPERTY_BK - && (leftClass != LineBreakUtils.LINE_BREAK_PROPERTY_CR - || currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) - )) { - reset(); - if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; - } - return EXPLICIT_BREAK; - } else if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_BK - || currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_LF) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_BK; - return PROHIBITED_BREAK; - } else if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_CR) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_CR; - return PROHIBITED_BREAK; - } else if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_SP) { - hadSpace = true; - return PROHIBITED_BREAK; - } else { - boolean savedHadSpace = hadSpace; - hadSpace = false; - switch (LineBreakUtils.getLineBreakPairProperty(leftClass, currentClass)) { - case LineBreakUtils.PROHIBITED_BREAK : - leftClass = currentClass; + // LB 2a + return PROHIBITED_BREAK; + + case LineBreakUtils.LINE_BREAK_PROPERTY_BK: + case LineBreakUtils.LINE_BREAK_PROPERTY_LF: + case LineBreakUtils.LINE_BREAK_PROPERTY_NL: + //first character after mandatory break + reset(); + leftClass = currentClass; + return EXPLICIT_BREAK; + + case LineBreakUtils.LINE_BREAK_PROPERTY_CR: + //first character after a carriage return: + // explicit break if it is not a linefeed + if (currentClass != LineBreakUtils.LINE_BREAK_PROPERTY_LF) { + reset(); + return EXPLICIT_BREAK; + } + + default: + //nop + } + + /** Check 2: current is a mandatory break or space? */ + switch (currentClass) { + case LineBreakUtils.LINE_BREAK_PROPERTY_BK: + case LineBreakUtils.LINE_BREAK_PROPERTY_LF: + case LineBreakUtils.LINE_BREAK_PROPERTY_NL: + case LineBreakUtils.LINE_BREAK_PROPERTY_CR: + leftClass = currentClass; + return PROHIBITED_BREAK; + + case LineBreakUtils.LINE_BREAK_PROPERTY_SP: + hadSpace = true; + return PROHIBITED_BREAK; + + default: + //nop + } + + /** Normal treatment, if the first two checks did not return */ + boolean savedHadSpace = hadSpace; + hadSpace = false; + byte breakAction = LineBreakUtils.getLineBreakPairProperty(leftClass, currentClass); + switch (breakAction) { + case PROHIBITED_BREAK: + case DIRECT_BREAK: + leftClass = currentClass; + return breakAction; + + case INDIRECT_BREAK: + leftClass = currentClass; + if (savedHadSpace) { + return INDIRECT_BREAK; + } else { return PROHIBITED_BREAK; - case LineBreakUtils.DIRECT_BREAK : + } + + case COMBINING_INDIRECT_BREAK: + if (savedHadSpace) { leftClass = currentClass; - return DIRECT_BREAK; - case LineBreakUtils.INDIRECT_BREAK : + return COMBINING_INDIRECT_BREAK; + } else { + return PROHIBITED_BREAK; + } + + case COMBINING_PROHIBITED_BREAK: + if (savedHadSpace) { leftClass = currentClass; - if (savedHadSpace) { - return INDIRECT_BREAK; - } else { - return PROHIBITED_BREAK; - } - case LineBreakUtils.COMBINING_INDIRECT_BREAK : - if (savedHadSpace) { - leftClass = currentClass; - return COMBINING_INDIRECT_BREAK; - } else { - return PROHIBITED_BREAK; - } - case LineBreakUtils.COMBINING_PROHIBITED_BREAK : - if (savedHadSpace) { - leftClass = currentClass; - } - return COMBINING_PROHIBITED_BREAK; - default : - throw new RuntimeException("duh"); - } - + } + return COMBINING_PROHIBITED_BREAK; + + default: + assert false; + return breakAction; } } -- cgit v1.2.3 From 925425a93e4c22c3ef81850f5f4256e6ae8790f8 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 9 Jun 2008 14:01:53 +0000 Subject: Merged revisions 636407-637074,637076-637118,637120-637790,637792-637856,637858-637992,637994-638047,638049-638307,638309-638315,638318-664698 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95 ........ r638937 | jeremias | 2008-03-19 18:08:57 +0100 (Mi, 19 Mrz 2008) | 1 line A nit. ........ r640889 | vhennebert | 2008-03-25 17:43:55 +0100 (Di, 25 Mrz 2008) | 2 lines Set the final release date and added a news item about the 0.95beta release (the change was made before updating the website) ........ r642906 | jeremias | 2008-03-31 09:12:40 +0200 (Mo, 31 Mrz 2008) | 3 lines Added version number to xml-apis-ext (as suggested by Karel Vervaeke). Moved xml-apis to same version as xml-apis-ext. Added missing licensing info about xml-apis-ext. ........ r647403 | jeremias | 2008-04-12 11:02:01 +0200 (Sa, 12 Apr 2008) | 1 line Fixed NullPointerException when loading a TrueType font using XML font metric files. ........ r647537 | jeremias | 2008-04-13 09:36:00 +0200 (So, 13 Apr 2008) | 1 line Performance improvement when encoding images: Fixed an important hotspot by extending CloseBlocker from ProxyOutputStream instead of FilterOutputStream as the latter routes all write(byte[]) calls through write(int). ........ r648984 | jeremias | 2008-04-17 09:00:22 +0200 (Do, 17 Apr 2008) | 1 line HeadURL was missing in the properties. ........ r649006 | jeremias | 2008-04-17 10:42:52 +0200 (Do, 17 Apr 2008) | 1 line Fixed text extraction problem with ZapfDingbats and Symbol font in PDF output. These fonts are symbolic and must not use an Encoding value in PDF. Applies to the built-in base 14 variant and to the case where these fonts are explicitely embedded. ........ r649014 | jeremias | 2008-04-17 11:10:15 +0200 (Do, 17 Apr 2008) | 1 line Added missing change information. ........ r650550 | vhennebert | 2008-04-22 17:22:31 +0200 (Di, 22 Apr 2008) | 4 lines Bugzilla 41621: - length of the penalty now correctly computed; - AssertionError fixed. ........ r651302 | jeremias | 2008-04-24 18:08:53 +0200 (Do, 24 Apr 2008) | 3 lines Fixed regression causing bad positioning of block-containers if used as descendant of a table-cell. This was not caught because of the lack of a test case that would have shown the problem in visual testing with BatchDiffer. See also: http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-users/200804.mbox/%3c20080424164128.973A.DEV@jeremias-maerki.ch%3e ........ r653537 | vhennebert | 2008-05-05 19:47:28 +0200 (Mo, 05 Mai 2008) | 2 lines Bugfix: the before border of cells below a column-spanning cell had their value taken from the leading case, instead of the normal one. ........ r654453 | jeremias | 2008-05-08 11:14:04 +0200 (Do, 08 Mai 2008) | 2 lines Added /usr/local/share/fonts as additional possible location for fonts on Unixes. ........ r656286 | jeremias | 2008-05-14 16:16:49 +0200 (Mi, 14 Mai 2008) | 1 line Restored plug-in API compatibility with FOP 0.94. Fixes a NoSuchMethodError when Barcode4J is run. ........ r656524 | jeremias | 2008-05-15 09:07:18 +0200 (Do, 15 Mai 2008) | 1 line Fixed rendering of fixed block-containers in AFP output. The break-out was actually never implemented which is necessary for supporting fixed positioned viewports. ........ r657520 | maxberger | 2008-05-18 11:38:45 +0200 (So, 18 Mai 2008) | 1 line Updated as per suggestions in bug 45019 ........ r661580 | maxberger | 2008-05-30 08:42:17 +0200 (Fr, 30 Mai 2008) | 1 line added my key to KEYS, it is used for signing mvn artifacts ........ r663482 | jeremias | 2008-06-05 09:06:37 +0200 (Do, 05 Jun 2008) | 1 line Fixed positioning of absolutely positioned block-containers in multi-column documents. ........ r664692 | jeremias | 2008-06-09 14:49:45 +0200 (Mo, 09 Jun 2008) | 1 line Restored PSImageUtils. I had deleted it prematurely. Extensions like Barcode4J rely on this class. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@665691 13f79535-47bb-0310-9956-ffa450edef68 --- NOTICE | 2 +- build.xml | 5 + fop.bat | 4 +- lib/xml-apis-1.3.02.jar | Bin 194205 -> 0 bytes lib/xml-apis-1.3.04.jar | Bin 0 -> 194354 bytes lib/xml-apis-ext-1.3.04.jar | Bin 0 -> 85686 bytes lib/xml-apis-ext.LICENSE.dom-documentation.txt | 73 ++++++++ lib/xml-apis-ext.LICENSE.dom-software.txt | 61 +++++++ lib/xml-apis-ext.LICENSE.sac.html | 75 ++++++++ lib/xml-apis-ext.LICENSE.txt | 202 +++++++++++++++++++++ lib/xml-apis-ext.NOTICE.txt | 16 ++ lib/xml-apis-ext.README.dom.txt | 56 ++++++ lib/xml-apis-ext.jar | Bin 85686 -> 0 bytes src/documentation/content/xdocs/news.xml | 8 + src/java/org/apache/fop/fonts/CustomFont.java | 11 +- src/java/org/apache/fop/fonts/FontDescriptor.java | 6 +- src/java/org/apache/fop/fonts/FontReader.java | 9 +- src/java/org/apache/fop/fonts/LazyFont.java | 10 +- .../fop/fonts/autodetect/UnixFontDirFinder.java | 1 + .../org/apache/fop/layoutmgr/table/RowPainter.java | 11 +- .../layoutmgr/table/TableContentLayoutManager.java | 50 +++-- .../apache/fop/layoutmgr/table/TableStepper.java | 9 +- src/java/org/apache/fop/pdf/PDFFactory.java | 7 +- src/java/org/apache/fop/pdf/PDFFont.java | 2 - src/java/org/apache/fop/pdf/PDFResources.java | 8 +- .../fop/render/AbstractGraphics2DAdapter.java | 11 +- .../fop/render/AbstractPathOrientedRenderer.java | 64 +++++++ .../org/apache/fop/render/AbstractRenderer.java | 9 + .../org/apache/fop/render/Graphics2DAdapter.java | 19 ++ .../org/apache/fop/render/afp/AFPRenderer.java | 108 +++++++++-- .../fop/render/java2d/Java2DGraphics2DAdapter.java | 4 +- .../org/apache/fop/render/pcl/PCLRenderer.java | 74 ++++++++ .../apache/fop/render/ps/PSGraphics2DAdapter.java | 4 +- .../org/apache/fop/render/ps/PSImageUtils.java | 29 +++ .../org/apache/fop/render/xml/XMLRenderer.java | 14 +- .../apache/fop/util/CloseBlockerOutputStream.java | 12 +- status.xml | 23 ++- test/java/org/apache/fop/StandardTestSuite.java | 2 + .../org/apache/fop/fonts/TrueTypeAnsiTestCase.java | 107 +++++++++++ test/java/org/apache/fop/fonts/fonttest.xsl | 24 +++ ...ck-container_absolute-position_multi-column.xml | 71 ++++++++ .../standard-testcases/table-cell_bc-child.xml | 65 +++++++ .../table_border-collapse_collapse_spans_3.xml | 79 ++++++++ .../standard-testcases/table_bug44621.xml | 37 +++- 44 files changed, 1307 insertions(+), 75 deletions(-) delete mode 100644 lib/xml-apis-1.3.02.jar create mode 100644 lib/xml-apis-1.3.04.jar create mode 100644 lib/xml-apis-ext-1.3.04.jar create mode 100644 lib/xml-apis-ext.LICENSE.dom-documentation.txt create mode 100644 lib/xml-apis-ext.LICENSE.dom-software.txt create mode 100644 lib/xml-apis-ext.LICENSE.sac.html create mode 100644 lib/xml-apis-ext.LICENSE.txt create mode 100644 lib/xml-apis-ext.NOTICE.txt create mode 100644 lib/xml-apis-ext.README.dom.txt delete mode 100644 lib/xml-apis-ext.jar create mode 100644 src/java/org/apache/fop/render/ps/PSImageUtils.java create mode 100644 test/java/org/apache/fop/fonts/TrueTypeAnsiTestCase.java create mode 100644 test/java/org/apache/fop/fonts/fonttest.xsl create mode 100644 test/layoutengine/standard-testcases/block-container_absolute-position_multi-column.xml create mode 100644 test/layoutengine/standard-testcases/table-cell_bc-child.xml create mode 100644 test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_3.xml (limited to 'src') diff --git a/NOTICE b/NOTICE index 12fc2d569..880e36f18 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache FOP -Copyright 1999-2006 The Apache Software Foundation +Copyright 1999-2008 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/build.xml b/build.xml index c4eb1e94d..d744c16c1 100644 --- a/build.xml +++ b/build.xml @@ -808,6 +808,11 @@ list of possible build targets. + + + + + diff --git a/fop.bat b/fop.bat index c2444a083..a01c5ddb7 100644 --- a/fop.bat +++ b/fop.bat @@ -55,8 +55,8 @@ set LIBDIR=%LOCAL_FOP_HOME%lib set LOCALCLASSPATH=%LOCAL_FOP_HOME%build\fop.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LOCAL_FOP_HOME%build\fop-sandbox.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LOCAL_FOP_HOME%build\fop-hyph.jar -set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xml-apis-1.3.02.jar -set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xml-apis-ext.jar +set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xml-apis-1.3.04.jar +set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xml-apis-ext-1.3.04.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xercesImpl-2.7.1.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xalan-2.7.0.jar set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\serializer-2.7.0.jar diff --git a/lib/xml-apis-1.3.02.jar b/lib/xml-apis-1.3.02.jar deleted file mode 100644 index 243eaeaeb..000000000 Binary files a/lib/xml-apis-1.3.02.jar and /dev/null differ diff --git a/lib/xml-apis-1.3.04.jar b/lib/xml-apis-1.3.04.jar new file mode 100644 index 000000000..d42c0ea6c Binary files /dev/null and b/lib/xml-apis-1.3.04.jar differ diff --git a/lib/xml-apis-ext-1.3.04.jar b/lib/xml-apis-ext-1.3.04.jar new file mode 100644 index 000000000..a7869d68a Binary files /dev/null and b/lib/xml-apis-ext-1.3.04.jar differ diff --git a/lib/xml-apis-ext.LICENSE.dom-documentation.txt b/lib/xml-apis-ext.LICENSE.dom-documentation.txt new file mode 100644 index 000000000..3d84b5d6c --- /dev/null +++ b/lib/xml-apis-ext.LICENSE.dom-documentation.txt @@ -0,0 +1,73 @@ +xml-commons/java/external/LICENSE.dom-documentation.txt $Id: LICENSE.dom-documentation.txt 226215 2005-06-03 22:49:13Z mrglavas $ + + +This license came from: http://www.w3.org/Consortium/Legal/copyright-documents-20021231 + + +W3C® DOCUMENT LICENSE +http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231 + +Public documents on the W3C site are provided by the copyright holders under +the following license. By using and/or copying this document, or the W3C +document from which this statement is linked, you (the licensee) agree that +you have read, understood, and will comply with the following terms and +conditions: + +Permission to copy, and distribute the contents of this document, or the W3C +document from which this statement is linked, in any medium for any purpose +and without fee or royalty is hereby granted, provided that you include the +following on ALL copies of the document, or portions thereof, that you use: + + 1. A link or URL to the original W3C document. + 2. The pre-existing copyright notice of the original author, or if it + doesn't exist, a notice (hypertext is preferred, but a textual + representation is permitted) of the form: "Copyright © [$date-of-document] + World Wide Web Consortium, (Massachusetts Institute of Technology, + European Research Consortium for Informatics and Mathematics, Keio + University). All Rights Reserved. + http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231" + 3. If it exists, the STATUS of the W3C document. + +When space permits, inclusion of the full text of this NOTICE should be +provided. We request that authorship attribution be provided in any software, +documents, or other items or products that you create pursuant to the +implementation of the contents of this document, or any portion thereof. + +No right to create modifications or derivatives of W3C documents is granted +pursuant to this license. However, if additional requirements (documented in +the Copyright FAQ) are satisfied, the right to create modifications or +derivatives is sometimes granted by the W3C to individuals complying with +those requirements. + +THIS DOCUMENT IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO +REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, +NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE SUITABLE +FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT +INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR THE +PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF. + +The name and trademarks of copyright holders may NOT be used in advertising +or publicity pertaining to this document or its contents without specific, +written prior permission. Title to copyright in this document will at all +times remain with copyright holders. + +---------------------------------------------------------------------------- + +This formulation of W3C's notice and license became active on December 31 2002. +This version removes the copyright ownership notice such that this license can +be used with materials other than those owned by the W3C, moves information on +style sheets, DTDs, and schemas to the Copyright FAQ, reflects that ERCIM is +now a host of the W3C, includes references to this specific dated version of +the license, and removes the ambiguous grant of "use". See the older +formulation for the policy prior to this date. Please see our Copyright FAQ for +common questions about using materials from our site, such as the translating +or annotating specifications. Other questions about this notice can be directed +to site-policy@w3.org. + +Joseph Reagle + +Last revised by Reagle $Date: 2005-06-03 18:49:13 -0400 (Fri, 03 Jun 2005) $ diff --git a/lib/xml-apis-ext.LICENSE.dom-software.txt b/lib/xml-apis-ext.LICENSE.dom-software.txt new file mode 100644 index 000000000..c5fe5a48a --- /dev/null +++ b/lib/xml-apis-ext.LICENSE.dom-software.txt @@ -0,0 +1,61 @@ +xml-commons/java/external/LICENSE.dom-software.txt $Id: LICENSE.dom-software.txt 226215 2005-06-03 22:49:13Z mrglavas $ + + +This license came from: http://www.w3.org/Consortium/Legal/copyright-software-20021231 + + +W3C® SOFTWARE NOTICE AND LICENSE +http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +This work (and included software, documentation such as READMEs, or other +related items) is being provided by the copyright holders under the following +license. By obtaining, using and/or copying this work, you (the licensee) agree +that you have read, understood, and will comply with the following terms and +conditions. + +Permission to copy, modify, and distribute this software and its documentation, +with or without modification, for any purpose and without fee or royalty is +hereby granted, provided that you include the following on ALL copies of the +software and documentation or portions thereof, including modifications: + + 1. The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work. + 2. Any pre-existing intellectual property disclaimers, notices, or terms + and conditions. If none exist, the W3C Software Short Notice should be + included (hypertext is preferred, text is permitted) within the body + of any redistributed or derivative code. + 3. Notice of any changes or modifications to the files, including the date + changes were made. (We recommend you provide URIs to the location from + which the code is derived.) + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE +NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT +THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY +PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION. + +The name and trademarks of copyright holders may NOT be used in advertising or +publicity pertaining to the software without specific, written prior permission. +Title to copyright in this software and any associated documentation will at +all times remain with copyright holders. + +____________________________________ + +This formulation of W3C's notice and license became active on December 31 2002. +This version removes the copyright ownership notice such that this license can +be used with materials other than those owned by the W3C, reflects that ERCIM +is now a host of the W3C, includes references to this specific dated version of +the license, and removes the ambiguous grant of "use". Otherwise, this version +is the same as the previous version and is written so as to preserve the Free +Software Foundation's assessment of GPL compatibility and OSI's certification +under the Open Source Definition. Please see our Copyright FAQ for common +questions about using materials from our site, including specific terms and +conditions for packages like libwww, Amaya, and Jigsaw. Other questions about +this notice can be directed to site-policy@w3.org. + +Joseph Reagle + +Last revised by Reagle $Date: 2005-06-03 18:49:13 -0400 (Fri, 03 Jun 2005) $ diff --git a/lib/xml-apis-ext.LICENSE.sac.html b/lib/xml-apis-ext.LICENSE.sac.html new file mode 100644 index 000000000..46abc5c63 --- /dev/null +++ b/lib/xml-apis-ext.LICENSE.sac.html @@ -0,0 +1,75 @@ + + + + + + W3C IPR SOFTWARE NOTICE + + + + + +

    W3C IPR SOFTWARE NOTICE

    + +

    Copyright © 2002 World Wide Web Consortium, (Massachusetts Institute of +Technology, Institut National de Recherche en Informatique et en Automatique, +Keio University). All Rights Reserved.

    + +

    Note: The original version of the W3C Software Copyright Notice and +License could be found at http://www.w3.org/Consortium/Legal/copyright-software-19980720

    + +

    Copyright © 1994-2002 World Wide Web +Consortium, (Massachusetts Institute of +Technology, Institut National de Recherche +en Informatique et en Automatique, Keio +University). All Rights Reserved. http://www.w3.org/Consortium/Legal/

    + +

    This W3C work (including software, documents, or other related items) is +being provided by the copyright holders under the following license. By +obtaining, using and/or copying this work, you (the licensee) agree that you +have read, understood, and will comply with the following terms and +conditions:

    + +

    Permission to use, copy, and modify this software and its documentation, +with or without modification,  for any purpose and without fee or royalty is +hereby granted, provided that you include the following on ALL copies of the +software and documentation or portions thereof, including modifications, that +you make:

    +
      +
    1. The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work.
    2. +
    3. Any pre-existing intellectual property disclaimers, notices, or terms + and conditions. If none exist, a short notice of the following form + (hypertext is preferred, text is permitted) should be used within the body + of any redistributed or derivative code: "Copyright © 2002 + World Wide Web Consortium, (Massachusetts Institute of Technology, + Institut National de Recherche en + Informatique et en Automatique, Keio + University). All Rights Reserved. + http://www.w3.org/Consortium/Legal/"
    4. +
    5. Notice of any changes or modifications to the W3C files, including the + date changes were made. (We recommend you provide URIs to the location + from which the code is derived.)
    6. +
    + +

    THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS +MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR +PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY +THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.

    + +

    COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR +DOCUMENTATION.

    + +

    The name and trademarks of copyright holders may NOT be used in advertising +or publicity pertaining to the software without specific, written prior +permission. Title to copyright in this software and any associated +documentation will at all times remain with copyright holders.

    + + diff --git a/lib/xml-apis-ext.LICENSE.txt b/lib/xml-apis-ext.LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/lib/xml-apis-ext.LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/xml-apis-ext.NOTICE.txt b/lib/xml-apis-ext.NOTICE.txt new file mode 100644 index 000000000..f6d34b5ee --- /dev/null +++ b/lib/xml-apis-ext.NOTICE.txt @@ -0,0 +1,16 @@ + ========================================================================= + == NOTICE file corresponding to section 4(d) of the Apache License, == + == Version 2.0, in this case for the Apache xml-commons xml-apis == + == distribution. == + ========================================================================= + + Apache XML Commons XML APIs + Copyright 2006 The Apache Software Foundation. + + This product includes software developed at + The Apache Software Foundation (http://www.apache.org/). + + Portions of this software were originally based on the following: + - software copyright (c) 1999, IBM Corporation., http://www.ibm.com. + - software copyright (c) 1999, Sun Microsystems., http://www.sun.com. + - software copyright (c) 2000 World Wide Web Consortium, http://www.w3.org diff --git a/lib/xml-apis-ext.README.dom.txt b/lib/xml-apis-ext.README.dom.txt new file mode 100644 index 000000000..bde694497 --- /dev/null +++ b/lib/xml-apis-ext.README.dom.txt @@ -0,0 +1,56 @@ +xml-commons/java/external/README.dom.txt $Id: README.dom.txt 477038 2006-11-20 04:40:36Z mrglavas $ + + +HEAR YE, HEAR YE! + + +All of the .java software and associated documentation about +the DOM in this repository are distributed under the license +from the W3C, which is provided herein. + + +LICENSE.dom-software.txt covers all software from the W3C +including the following items in the xml-commons project: + + xml-commons/java/external/src/org/w3c + and all subdirectories + +(Note: SAC (The Simple API for CSS) has been published under an older +version of the W3C license. The original license file is LICENSE.sac.html.) + +LICENSE.dom-documentation.txt covers all documentation from the W3C +including the following items in the xml-commons project: + + xml-commons/java/external/xdocs/dom + and all subdirectories + +The actual DOM Java Language Binding classes in xml-commons came from: + http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.html + +The specification of DOM Level 3's various parts is at: + http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/ + http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/ + http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226/ + +The specification of DOM Level 2's various parts is at: + http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/ + http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113/ + http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/ + http://www.w3.org/TR/2000/REC-DOM-Level-2-Views-20001113/ + +The specification of DOM Level 1's various parts is at: + http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-html.html + +Links to all available W3C DOM Java Bindings can be found at: + http://www.w3.org/DOM/DOMTR + +The actual classes of The Simple API for CSS (SAC) came from: + http://www.w3.org/Style/CSS/SAC/ + http://www.w3.org/2002/06/sacjava-1.3.zip + +The actual DOM Java Language Binding classes for SMIL came from: + http://dev.w3.org/cvsweb/java/classes/org/w3c/dom/smil/ + (both ElementTimeControl.java and TimeEvent.java were taken at revision 1.1) + +The actual DOM Java Language Binding classes for SVG 1.1 came from: + http://www.w3.org/TR/SVG11/java.html \ No newline at end of file diff --git a/lib/xml-apis-ext.jar b/lib/xml-apis-ext.jar deleted file mode 100644 index a7869d68a..000000000 Binary files a/lib/xml-apis-ext.jar and /dev/null differ diff --git a/src/documentation/content/xdocs/news.xml b/src/documentation/content/xdocs/news.xml index 0a4467e66..1a5c178e2 100644 --- a/src/documentation/content/xdocs/news.xml +++ b/src/documentation/content/xdocs/news.xml @@ -23,6 +23,14 @@ $Revision$ +
    + 26th March 2007 - Apache FOP 0.95beta Released +

    The Apache FOP team is delighted to present you a beta version of the + next production grade release of the new FOP codebase. This release + contains many bug fixes and new features. See the Release Notes for a list of + the most important changes.

    +
    30 October 2007 - New Committer

    Welcome Max Berger!

    diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index f6bb52cb3..1f782b2ea 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/src/java/org/apache/fop/fonts/CustomFont.java @@ -190,12 +190,17 @@ public abstract class CustomFont extends Typeface return fontBBox; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getFlags() { return flags; } + + /** {@inheritDoc} */ + public boolean isSymbolicFont() { + return ((getFlags() & 4) != 0) || "ZapfDingbatsEncoding".equals(getEncodingName()); + //Note: The check for ZapfDingbats is necessary as the PFM does not reliably indicate + //if a font is symbolic. + } /** * Returns the font weight (100, 200...800, 900). This value may be different from the diff --git a/src/java/org/apache/fop/fonts/FontDescriptor.java b/src/java/org/apache/fop/fonts/FontDescriptor.java index 841d99de2..fb9c7d02e 100644 --- a/src/java/org/apache/fop/fonts/FontDescriptor.java +++ b/src/java/org/apache/fop/fonts/FontDescriptor.java @@ -53,7 +53,11 @@ public interface FontDescriptor extends FontMetrics { */ int getFlags(); - + /** + * Indicates whether the font is a symbolic font. + * @return true if the font is a symbolic font (i.e. Symbol or ZapfDingbats) + */ + boolean isSymbolicFont(); /** * Returns the font's bounding box. * @return the bounding box diff --git a/src/java/org/apache/fop/fonts/FontReader.java b/src/java/org/apache/fop/fonts/FontReader.java index 51d90c7e5..6f148f503 100644 --- a/src/java/org/apache/fop/fonts/FontReader.java +++ b/src/java/org/apache/fop/fonts/FontReader.java @@ -27,8 +27,6 @@ import java.util.Set; import javax.xml.parsers.SAXParserFactory; -import org.apache.fop.apps.FOPException; -import org.apache.fop.fonts.apps.TTFReader; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.Locator; @@ -36,6 +34,9 @@ import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; +import org.apache.fop.apps.FOPException; +import org.apache.fop.fonts.apps.TTFReader; + /** * Class for reading a metric.xml file and creating a font object. * Typical usage: @@ -228,11 +229,11 @@ public class FontReader extends DefaultHandler { if ("font-name".equals(localName)) { returnFont.setFontName(content); } else if ("full-name".equals(localName)) { - multiFont.setFullName(content); + returnFont.setFullName(content); } else if ("family-name".equals(localName)) { Set s = new java.util.HashSet(); s.add(content); - multiFont.setFamilyNames(s); + returnFont.setFamilyNames(s); } else if ("ttc-name".equals(localName) && isCID) { multiFont.setTTCName(content); } else if ("encoding".equals(localName)) { diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index b4f7773a3..70b971fff 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -321,14 +321,18 @@ public class LazyFont extends Typeface implements FontDescriptor { return realFontDescriptor.getAscender(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int getFlags() { load(true); return realFontDescriptor.getFlags(); } + /** {@inheritDoc} */ + public boolean isSymbolicFont() { + load(true); + return realFontDescriptor.isSymbolicFont(); + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java b/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java index 55a7ae1c0..d59fd5c7e 100644 --- a/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java @@ -32,6 +32,7 @@ public class UnixFontDirFinder extends NativeFontDirFinder { return new String[] { System.getProperty("user.home") + "/.fonts", // user "/usr/local/fonts", // local + "/usr/local/share/fonts", // local shared "/usr/share/fonts", // system "/usr/X11R6/lib/X11/fonts" // X }; diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index bed9c53ae..d432c7657 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -229,8 +229,12 @@ class RowPainter { // Then add areas for cells finishing on the current row for (int i = 0; i < colCount; i++) { - GridUnit currentGU = currentRow.getGridUnit(i); - if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0 + GridUnit currentGU = currentRow.getGridUnit(i); + if (currentGU.isEmpty()) { + // TODO remove once missing cells are properly implemented (i.e., replaced + // by an fo:table-cell element containing an empty fo:block) + firstCellOnPage[i] = false; + } else if (currentGU.getColSpanIndex() == 0 && (lastInPart || currentGU.isLastGridUnitRowSpan()) && firstCellParts[i] != null) { assert firstCellParts[i].pgu == currentGU.getPrimary(); @@ -260,7 +264,8 @@ class RowPainter { actualRowHeight, borderBeforeWhich, borderAfterWhich, lastOnPage); firstCellParts[i] = null; - firstCellOnPage[i] = false; + Arrays.fill(firstCellOnPage, i, i + currentGU.getCell().getNumberColumnsSpanned(), + false); } } currentRowOffset += actualRowHeight; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 7a2ee171c..9b4a03a67 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.ListIterator; import java.util.Map; import org.apache.commons.logging.Log; @@ -41,6 +42,7 @@ import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; +import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.ListElement; @@ -232,6 +234,17 @@ public class TableContentLayoutManager implements PercentBaseContext { //Get elements for next row group nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); + /* + * The last break element produced by TableStepper (for the previous row + * group) may be used to represent the break between the two row groups. + * Its penalty value and break class must just be overridden by the + * characteristics of the keep or break between the two. + * + * However, we mustn't forget that if the after border of the last row of + * the row group is thicker in the normal case than in the trailing case, + * an additional glue will be appended to the element list. So we may have + * to go two steps backwards in the list. + */ //Determine keep constraints int penaltyStrength = BlockLevelLayoutManager.KEEP_AUTO; @@ -246,24 +259,35 @@ public class TableContentLayoutManager implements PercentBaseContext { 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(); - } + BreakElement breakElement; + ListIterator elemIter = returnList.listIterator(returnList.size()); + ListElement elem = (ListElement) elemIter.previous(); + if (elem instanceof KnuthGlue) { + breakElement = (BreakElement) elemIter.previous(); + } else { + breakElement = (BreakElement) elem; } - returnList.add(new BreakElement(penaltyPos, - penaltyLen, penaltyValue, breakBetween, context)); + breakElement.setPenaltyValue(penaltyValue); + breakElement.setBreakClass(breakBetween); returnList.addAll(nextRowGroupElems); breakBetween = context.getBreakAfter(); } } + /* + * The last break produced for the last row-group of this table part must be + * removed, because the breaking after the table will be handled by TableLM. + * Unless the element list ends with a glue, which must be kept to accurately + * represent the content. In such a case the break is simply disabled by setting + * its penalty to infinite. + */ + ListIterator elemIter = returnList.listIterator(returnList.size()); + ListElement elem = (ListElement) elemIter.previous(); + if (elem instanceof KnuthGlue) { + BreakElement breakElement = (BreakElement) elemIter.previous(); + breakElement.setPenaltyValue(KnuthElement.INFINITE); + } else { + elemIter.remove(); + } context.updateKeepWithPreviousPending(keepWithPrevious); context.setBreakBefore(breakBefore); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 7c963338f..6aa619368 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -282,13 +282,8 @@ public class TableStepper { laststep = step; 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(); - } + assert !returnList.isEmpty(); + lastTCPos.setFlag(TableContentPosition.LAST_IN_ROWGROUP, true); return returnList; } diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index 02f0c2cdb..6211b5da7 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -1203,10 +1203,11 @@ public class PDFFactory { PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor); PDFFont font = null; - font = PDFFont.createFont(fontname, fonttype, basefont, encoding); + font = PDFFont.createFont(fontname, fonttype, basefont, null); getDocument().registerObject(font); if (fonttype == FontType.TYPE0) { + font.setEncoding(encoding); CIDFont cidMetrics; if (metrics instanceof LazyFont) { cidMetrics = (CIDFont)((LazyFont) metrics).getRealFont(); @@ -1252,7 +1253,9 @@ public class PDFFactory { //Handle encoding SingleByteEncoding mapping = singleByteFont.getEncoding(); - if (PDFEncoding.isPredefinedEncoding(mapping.getName())) { + if (singleByteFont.isSymbolicFont()) { + //no encoding, use the font's encoding + } else if (PDFEncoding.isPredefinedEncoding(mapping.getName())) { font.setEncoding(mapping.getName()); } else { Object pdfEncoding = createPDFEncoding(mapping, diff --git a/src/java/org/apache/fop/pdf/PDFFont.java b/src/java/org/apache/fop/pdf/PDFFont.java index 14f1a657c..1f76f1e11 100644 --- a/src/java/org/apache/fop/pdf/PDFFont.java +++ b/src/java/org/apache/fop/pdf/PDFFont.java @@ -62,8 +62,6 @@ public class PDFFont extends PDFDictionary { setEncoding((PDFEncoding)encoding); } else if (encoding instanceof String) { setEncoding((String)encoding); - } else { - throw new IllegalArgumentException("Illegal value for encoding"); } } diff --git a/src/java/org/apache/fop/pdf/PDFResources.java b/src/java/org/apache/fop/pdf/PDFResources.java index b0c0128e1..da213bb87 100644 --- a/src/java/org/apache/fop/pdf/PDFResources.java +++ b/src/java/org/apache/fop/pdf/PDFResources.java @@ -28,6 +28,8 @@ import java.util.Set; import org.apache.fop.fonts.FontDescriptor; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.Typeface; +import org.apache.fop.fonts.base14.Symbol; +import org.apache.fop.fonts.base14.ZapfDingbats; import org.apache.fop.util.ColorProfileUtil; /** @@ -109,8 +111,12 @@ public class PDFResources extends PDFObject { if (font instanceof FontDescriptor) { desc = (FontDescriptor)font; } + String encoding = font.getEncodingName(); + if (font instanceof Symbol || font instanceof ZapfDingbats) { + encoding = null; //Symbolic fonts shouldn't specify an encoding value in PDF + } addFont(doc.getFactory().makeFont( - f, font.getEmbedFontName(), font.getEncodingName(), font, desc)); + f, font.getEmbedFontName(), encoding, font, desc)); } } } diff --git a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java index bc7bb95a1..e91947ba5 100644 --- a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java @@ -32,12 +32,13 @@ import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.WritableRaster; +import java.io.IOException; import org.apache.fop.render.RendererContext.RendererContextWrapper; import org.apache.fop.util.UnitConv; /** - * Graphics2DAdapter implementation for PCL and HP GL/2. + * Abstract base class for Graphics2DAdapter implementations. */ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { @@ -135,4 +136,12 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); } + /** {@inheritDoc} */ + public void paintImage(Graphics2DImagePainter painter, + RendererContext context, + int x, int y, int width, int height) throws IOException { + paintImage((org.apache.xmlgraphics.java2d.Graphics2DImagePainter)painter, + context, x, y, width, height); + } + } diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index b38d973c5..eb0668d8b 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -37,6 +37,7 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.CTM; +import org.apache.fop.area.NormalFlow; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.ForeignObject; @@ -521,6 +522,69 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { } } + /** {@inheritDoc} */ + protected void renderReferenceArea(Block block) { + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + at.translate(block.getXOffset(), block.getYOffset()); + at.translate(0, block.getSpaceBefore()); + + if (!at.isIdentity()) { + saveGraphicsState(); + concatenateTransformationMatrix(mptToPt(at)); + } + + currentIPPosition = 0; + currentBPPosition = 0; + handleBlockTraits(block); + + List children = block.getChildAreas(); + if (children != null) { + renderBlocks(block, children); + } + + if (!at.isIdentity()) { + restoreGraphicsState(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + + /** {@inheritDoc} */ + protected void renderFlow(NormalFlow flow) { + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + + if (!at.isIdentity()) { + saveGraphicsState(); + concatenateTransformationMatrix(mptToPt(at)); + } + + currentIPPosition = 0; + currentBPPosition = 0; + super.renderFlow(flow); + + if (!at.isIdentity()) { + restoreGraphicsState(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + /** * Concatenates the current transformation matrix with the given one, therefore establishing * a new coordinate system. diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 816fa4067..20eceac8c 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -483,6 +483,13 @@ public abstract class AbstractRenderer } } + /** + * Renders a block area that represents a reference area. The reference area establishes + * a new coordinate system. + * @param block the block area + */ + protected abstract void renderReferenceArea(Block block); + /** * Renders a list of block areas. * @@ -551,6 +558,8 @@ public abstract class AbstractRenderer // simply move position currentBPPosition += block.getAllocBPD(); } + } else if (Boolean.TRUE.equals(block.getTrait(Trait.IS_REFERENCE_AREA))) { + renderReferenceArea(block); } else { // save position and offset int saveIP = currentIPPosition; diff --git a/src/java/org/apache/fop/render/Graphics2DAdapter.java b/src/java/org/apache/fop/render/Graphics2DAdapter.java index 0123e04a1..4fbdbe09a 100644 --- a/src/java/org/apache/fop/render/Graphics2DAdapter.java +++ b/src/java/org/apache/fop/render/Graphics2DAdapter.java @@ -47,4 +47,23 @@ public interface Graphics2DAdapter { RendererContext context, int x, int y, int width, int height) throws IOException; + /** + * Paints an arbitrary images on a given Graphics2D instance. The renderer + * providing this functionality must set up a Graphics2D instance so that + * the image with the given extents (in mpt) can be painted by the painter + * passed to this method. The Graphics2DImagePainter is then passed this + * Graphics2D instance so the image can be painted. + * @param painter the painter which will paint the actual image + * @param context the renderer context for the current renderer + * @param x X position of the image + * @param y Y position of the image + * @param width width of the image + * @param height height of the image + * @throws IOException In case of an I/O error while writing the output format + * @deprecated Use the variant with the Graphics2DImagePainter from XML Graphics Commons instead + */ + void paintImage(Graphics2DImagePainter painter, + RendererContext context, + int x, int y, int width, int height) throws IOException; + } diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 045ba9835..5c8e80312 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -59,6 +59,7 @@ import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; import org.apache.fop.area.CTM; +import org.apache.fop.area.NormalFlow; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; @@ -467,9 +468,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void renderBlockViewport(BlockViewport bv, List children) { // clip and position viewport if necessary @@ -590,6 +589,76 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } + /** {@inheritDoc} */ + protected void renderReferenceArea(Block block) { + //TODO Remove this method once concatenateTransformationMatrix() is implemented + + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + at.translate(block.getXOffset(), block.getYOffset()); + at.translate(0, block.getSpaceBefore()); + + if (!at.isIdentity()) { + Rectangle2D contentRect + = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(), + block.getAllocIPD(), block.getAllocBPD()); + pushViewPortPos(new ViewPortPos(contentRect, new CTM(at))); + } + + currentIPPosition = 0; + currentBPPosition = 0; + handleBlockTraits(block); + + List children = block.getChildAreas(); + if (children != null) { + renderBlocks(block, children); + } + + if (!at.isIdentity()) { + popViewPortPos(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + + /** {@inheritDoc} */ + protected void renderFlow(NormalFlow flow) { + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + + if (!at.isIdentity()) { + Rectangle2D contentRect + = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(), + flow.getAllocIPD(), flow.getAllocBPD()); + pushViewPortPos(new ViewPortPos(contentRect, new CTM(at))); + } + + currentIPPosition = 0; + currentBPPosition = 0; + super.renderFlow(flow); + + if (!at.isIdentity()) { + popViewPortPos(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + + /** {@inheritDoc} */ protected void concatenateTransformationMatrix(AffineTransform at) { //Not used here since AFPRenderer defines its own renderBlockViewport() method. @@ -1218,20 +1287,24 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } - /** - * Restores the state stack after a break out. - * @param breakOutList the state stack to restore. - */ - public void restoreStateStackAfterBreakOut(List breakOutList) { - + /** {@inheritDoc} */ + public List breakOutOfStateStack() { + log.debug("Block.FIXED --> break out"); + List breakOutList = new java.util.ArrayList(); + //Don't pop the last ViewPortPos (created by renderPage()) + while (this.viewPortPositions.size() > 1) { + breakOutList.add(0, popViewPortPos()); + } + return breakOutList; } - /** - * Breaks out of the state stack to handle fixed block-containers. - * @return the saved state stack to recreate later - */ - public List breakOutOfStateStack() { - return null; + /** {@inheritDoc} */ + public void restoreStateStackAfterBreakOut(List breakOutList) { + log.debug("Block.FIXED --> restoring context after break-out"); + for (int i = 0, c = breakOutList.size(); i < c; i++) { + ViewPortPos vps = (ViewPortPos)breakOutList.get(i); + pushViewPortPos(vps); + } } /** Saves the graphics state of the rendering engine. */ @@ -1755,12 +1828,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); } - private void popViewPortPos() { - viewPortPositions.remove(viewPortPositions.size() - 1); + private ViewPortPos popViewPortPos() { + ViewPortPos current = (ViewPortPos)viewPortPositions.remove(viewPortPositions.size() - 1); if (viewPortPositions.size() > 0) { ViewPortPos vpp = (ViewPortPos)viewPortPositions.get(viewPortPositions.size() - 1); afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); } + return current; } /** diff --git a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java index 48feba135..b29378a96 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java @@ -28,13 +28,13 @@ import java.io.IOException; import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; -import org.apache.fop.render.Graphics2DAdapter; +import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.RendererContext; /** * Graphics2DAdapter implementation for Java2D. */ -public class Java2DGraphics2DAdapter implements Graphics2DAdapter { +public class Java2DGraphics2DAdapter extends AbstractGraphics2DAdapter { /** {@inheritDoc} */ public void paintImage(Graphics2DImagePainter painter, diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 988517cc7..7ab46c24e 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -66,6 +66,7 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.CTM; +import org.apache.fop.area.NormalFlow; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; @@ -1028,6 +1029,79 @@ public class PCLRenderer extends PrintRenderer { //currentFontName = saveFontName; } + /** {@inheritDoc} */ + protected void renderReferenceArea(Block block) { + //TODO This is the same code as in AbstractPathOrientedRenderer + //So there's some optimization potential but not otherwise PCLRenderer is a little + //difficult to derive from AbstractPathOrientedRenderer. Maybe an additional layer + //between PrintRenderer and AbstractPathOrientedRenderer is necessary. + + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + at.translate(block.getXOffset(), block.getYOffset()); + at.translate(0, block.getSpaceBefore()); + + if (!at.isIdentity()) { + saveGraphicsState(); + concatenateTransformationMatrix(mptToPt(at)); + } + + currentIPPosition = 0; + currentBPPosition = 0; + handleBlockTraits(block); + + List children = block.getChildAreas(); + if (children != null) { + renderBlocks(block, children); + } + + if (!at.isIdentity()) { + restoreGraphicsState(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + + /** {@inheritDoc} */ + protected void renderFlow(NormalFlow flow) { + //TODO This is the same code as in AbstractPathOrientedRenderer + //So there's some optimization potential but not otherwise PCLRenderer is a little + //difficult to derive from AbstractPathOrientedRenderer. Maybe an additional layer + //between PrintRenderer and AbstractPathOrientedRenderer is necessary. + + // save position and offset + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + //Establish a new coordinate system + AffineTransform at = new AffineTransform(); + at.translate(currentIPPosition, currentBPPosition); + + if (!at.isIdentity()) { + saveGraphicsState(); + concatenateTransformationMatrix(mptToPt(at)); + } + + currentIPPosition = 0; + currentBPPosition = 0; + super.renderFlow(flow); + + if (!at.isIdentity()) { + restoreGraphicsState(); + } + + // stacked and relative blocks effect stacking + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } + /** * Concatenates the current transformation matrix with the given one, therefore establishing * a new coordinate system. diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java index a592b4f44..994481d59 100644 --- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java @@ -28,13 +28,13 @@ import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; import org.apache.xmlgraphics.ps.PSGenerator; -import org.apache.fop.render.Graphics2DAdapter; +import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.RendererContext; /** * Graphics2DAdapter implementation for PostScript. */ -public class PSGraphics2DAdapter implements Graphics2DAdapter { +public class PSGraphics2DAdapter extends AbstractGraphics2DAdapter { private PSGenerator gen; private boolean clip = true; diff --git a/src/java/org/apache/fop/render/ps/PSImageUtils.java b/src/java/org/apache/fop/render/ps/PSImageUtils.java new file mode 100644 index 000000000..27eb736d8 --- /dev/null +++ b/src/java/org/apache/fop/render/ps/PSImageUtils.java @@ -0,0 +1,29 @@ +/* + * 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.render.ps; + +/** + * Utility code for rendering images in PostScript. + * @deprecated Kept for compatibility with older FOP extensions (like Barcode4J). Use the + * super-class instead. + */ +public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils { + +} diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index eb3c92e1b..94cd107c7 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -754,9 +754,17 @@ public class XMLRenderer extends PrintRenderer { endElement("flow"); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ + protected void renderReferenceArea(Block block) { + handleBlockTraits(block); + + List children = block.getChildAreas(); + if (children != null) { + renderBlocks(block, children); + } + } + + /** {@inheritDoc} */ protected void renderBlock(Block block) { atts.clear(); addAreaAttributes(block); diff --git a/src/java/org/apache/fop/util/CloseBlockerOutputStream.java b/src/java/org/apache/fop/util/CloseBlockerOutputStream.java index 7192e76d2..c0db8c8b7 100644 --- a/src/java/org/apache/fop/util/CloseBlockerOutputStream.java +++ b/src/java/org/apache/fop/util/CloseBlockerOutputStream.java @@ -19,25 +19,25 @@ package org.apache.fop.util; -import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; +import org.apache.commons.io.output.ProxyOutputStream; + /** * This is a decorator to block calls to close() to the underlying stream. */ -public class CloseBlockerOutputStream extends FilterOutputStream { +public class CloseBlockerOutputStream extends ProxyOutputStream { /** - * @see java.io.FilterOutputStream#FilterOutputStream(OutputStream) + * Main constructor. + * @param out the underlying stream */ public CloseBlockerOutputStream(OutputStream out) { super(out); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void close() throws IOException { try { flush(); diff --git a/status.xml b/status.xml index c82fca331..02786adbc 100644 --- a/status.xml +++ b/status.xml @@ -144,7 +144,28 @@ in the font's primary encoding. - + + + Fixed positioning of absolutely positioned block-containers in multi-column documents. + + + Fixed rendering of fixed block-containers in AFP output. + + + Fixed regression causing bad positioning of block-containers if used as descendant + of a table-cell. + + + Fixed text extraction problem with ZapfDingbats and Symbol font in PDF output. + + + Fixed a performance problem concerning image serialization. + + + Fixed NullPointerException when loading a TrueType font using XML font metric files. + + +
    Notes diff --git a/test/java/org/apache/fop/StandardTestSuite.java b/test/java/org/apache/fop/StandardTestSuite.java index 33e034de0..6399d3b09 100644 --- a/test/java/org/apache/fop/StandardTestSuite.java +++ b/test/java/org/apache/fop/StandardTestSuite.java @@ -22,6 +22,7 @@ package org.apache.fop; import junit.framework.Test; import junit.framework.TestSuite; +import org.apache.fop.fonts.TrueTypeAnsiTestCase; import org.apache.fop.render.pdf.PDFAConformanceTestCase; import org.apache.fop.render.pdf.PDFCMapTestCase; import org.apache.fop.render.pdf.PDFEncodingTestCase; @@ -47,6 +48,7 @@ public class StandardTestSuite { suite.addTest(new TestSuite(PDFEncodingTestCase.class)); suite.addTest(new TestSuite(PDFCMapTestCase.class)); suite.addTest(new TestSuite(PDFsRGBSettingsTestCase.class)); + suite.addTest(new TestSuite(TrueTypeAnsiTestCase.class)); suite.addTest(RichTextFormatTestSuite.suite()); //$JUnit-END$ return suite; diff --git a/test/java/org/apache/fop/fonts/TrueTypeAnsiTestCase.java b/test/java/org/apache/fop/fonts/TrueTypeAnsiTestCase.java new file mode 100644 index 000000000..dc9890167 --- /dev/null +++ b/test/java/org/apache/fop/fonts/TrueTypeAnsiTestCase.java @@ -0,0 +1,107 @@ +/* + * 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.fonts; + +import java.io.File; +import java.io.OutputStream; +import java.io.StringReader; +import java.net.URL; +import java.util.List; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamSource; + +import junit.framework.TestCase; + +import org.apache.commons.io.output.NullOutputStream; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.fonts.apps.TTFReader; +import org.apache.fop.render.pdf.PDFRenderer; + +/** + * Tests XML font metrics file generation and usage for WinAnsi mode. + */ +public class TrueTypeAnsiTestCase extends TestCase { + + /** + * Tests a TrueType font in WinAnsi mode. + * @throws Exception if an error occurs + */ + public void testTrueTypeAnsi() throws Exception { + String fontFamily = "Gladiator Bold"; + File ttfFile = new File("./test/resources/fonts/glb12.ttf"); + File workDir = new File("./build/test-results"); + if (!workDir.isDirectory()) { + assertTrue(workDir.mkdirs()); + } + File metricsFile = new File(workDir, ttfFile.getName() + ".xml"); + if (metricsFile.isFile()) { + assertTrue(metricsFile.delete()); + } + + String[] args = new String[] {"-enc", "ansi", + ttfFile.getCanonicalPath(), metricsFile.getCanonicalPath()}; + TTFReader.main(args); + assertTrue(metricsFile.isFile()); + + FopFactory fopFactory = FopFactory.newInstance(); + FOUserAgent ua = fopFactory.newFOUserAgent(); + PDFRenderer renderer = new PDFRenderer(); + renderer.setUserAgent(ua); + List fontList = new java.util.ArrayList(); + List triplets = new java.util.ArrayList(); + triplets.add(new FontTriplet(fontFamily, "normal", Font.WEIGHT_NORMAL)); + EmbedFontInfo font = new EmbedFontInfo( + metricsFile.toURI().toASCIIString(), + true, triplets, + ttfFile.toURI().toASCIIString(), null); + fontList.add(font); + renderer.addFontList(fontList); + + ua.setRendererOverride(renderer); + OutputStream out = new NullOutputStream(); + + Fop fop = fopFactory.newFop(null, ua, out); + + TransformerFactory tFactory = TransformerFactory.newInstance(); + Source src = new StreamSource(new StringReader( + "Test!")); + Result res = new SAXResult(fop.getDefaultHandler()); + Transformer transformer = tFactory.newTransformer( + getSourceForResource(this, "fonttest.xsl")); + transformer.transform(src, res); + } + + private static Source getSourceForResource(Object reference, String name) { + URL url = reference.getClass().getResource(name); + if (url == null) { + throw new NullPointerException("Resource not found: " + name); + } + return new StreamSource(url.toExternalForm()); + } + +} diff --git a/test/java/org/apache/fop/fonts/fonttest.xsl b/test/java/org/apache/fop/fonts/fonttest.xsl new file mode 100644 index 000000000..26c7d72a5 --- /dev/null +++ b/test/java/org/apache/fop/fonts/fonttest.xsl @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/block-container_absolute-position_multi-column.xml b/test/layoutengine/standard-testcases/block-container_absolute-position_multi-column.xml new file mode 100644 index 000000000..e3b6fb4f8 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_absolute-position_multi-column.xml @@ -0,0 +1,71 @@ + + + + + +

    + This test checks absolutely positioned block-containers in multi-column documents. +

    +
    + + + + + + + + + + + This should not have any line floating over it! This should not have any + line floating over it! This should not have any line floating over it! This + should not have any line floating over it! + + + + This should not have any line floating over it! This should not have any + line floating over it! This should not have any line floating over + it! + + + + This should not have any line floating over it! This should not have any + line floating over it! This should not have any line floating over it! This + should not have any line floating over it! + + + + + +   + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-cell_bc-child.xml b/test/layoutengine/standard-testcases/table-cell_bc-child.xml new file mode 100644 index 000000000..eb199c73b --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_bc-child.xml @@ -0,0 +1,65 @@ + + + + + +

    + This test checks the rendering of block viewports in reference areas generated + by table-cells. This does not test the layout engine, only the renderer. +

    +
    + + + + + + + + + + + + + + + + No red text should be visible! + + No red text should be visible! + + + + + + No red text should be visible! + + No red text should be visible! + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_3.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_3.xml new file mode 100644 index 000000000..8d4f42c16 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_3.xml @@ -0,0 +1,79 @@ + + + + + +

    + This test checks tables with collapsing-border model and complex spanning cells. +

    +
    + + + + + + + + + + + + + + Header 1.1 + + + Header 1.2 + + + + + + Cell 1.1 + + + + + Cell 2.1 + + + Cell 2.2 + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table_bug44621.xml b/test/layoutengine/standard-testcases/table_bug44621.xml index b4b9edbd0..ae04d1903 100644 --- a/test/layoutengine/standard-testcases/table_bug44621.xml +++ b/test/layoutengine/standard-testcases/table_bug44621.xml @@ -66,12 +66,32 @@ + + The after border of cell 1, in the normal + case, is thicker than in the trailing case. + + + + + Cell 1 + + + + + Cell 2 + + + + + + @@ -93,12 +113,27 @@ + + + + + + + + + + 4 - + + 6 + + + + 3 -- cgit v1.2.3 From 64e7cf871471538b8591d6647575d107dd98b3ec Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Mon, 9 Jun 2008 14:15:38 +0000 Subject: Replaced LinkedList with generic List interface git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@665699 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 6 +-- .../org/apache/fop/layoutmgr/AbstractBreaker.java | 10 ++-- .../fop/layoutmgr/AbstractLayoutManager.java | 6 +-- .../fop/layoutmgr/BlockContainerLayoutManager.java | 32 ++++++------ .../apache/fop/layoutmgr/BlockLayoutManager.java | 2 +- .../fop/layoutmgr/BlockStackingLayoutManager.java | 61 ++++++++++++---------- .../org/apache/fop/layoutmgr/ElementListUtils.java | 14 ++--- .../apache/fop/layoutmgr/FlowLayoutManager.java | 17 +++--- .../org/apache/fop/layoutmgr/KnuthBlockBox.java | 17 +++--- .../org/apache/fop/layoutmgr/LayoutManager.java | 5 +- src/java/org/apache/fop/layoutmgr/PageBreaker.java | 6 +-- .../fop/layoutmgr/PageBreakingAlgorithm.java | 6 +-- .../org/apache/fop/layoutmgr/SpaceResolver.java | 2 +- .../fop/layoutmgr/StaticContentLayoutManager.java | 28 +++++----- .../inline/AbstractGraphicsLayoutManager.java | 4 +- .../layoutmgr/inline/CharacterLayoutManager.java | 4 +- .../fop/layoutmgr/inline/ContentLayoutManager.java | 14 +++-- .../layoutmgr/inline/FootnoteLayoutManager.java | 12 ++--- .../fop/layoutmgr/inline/InlineLayoutManager.java | 15 +++--- .../inline/InlineStackingLayoutManager.java | 2 +- .../fop/layoutmgr/inline/LeaderLayoutManager.java | 8 +-- .../layoutmgr/inline/LeafNodeLayoutManager.java | 4 +- .../fop/layoutmgr/inline/LineLayoutManager.java | 24 ++++----- .../fop/layoutmgr/inline/TextLayoutManager.java | 12 ++--- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 6 +-- .../list/ListItemContentLayoutManager.java | 2 +- .../fop/layoutmgr/list/ListItemLayoutManager.java | 23 ++++---- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 6 +-- .../layoutmgr/table/TableCellLayoutManager.java | 23 ++++---- .../fop/layoutmgr/table/TableLayoutManager.java | 8 +-- 30 files changed, 195 insertions(+), 184 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 55bcfa44e..915208e2d 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -38,7 +38,7 @@ public class PrimaryGridUnit extends GridUnit { /** Cell layout manager. */ private TableCellLayoutManager cellLM; /** List of Knuth elements representing the contents of the cell. */ - private LinkedList elements; + private List elements; /** Index of the row where this cell starts. */ private int rowIndex; @@ -106,11 +106,11 @@ public class PrimaryGridUnit extends GridUnit { * * @param elements a list of ListElement (?) */ - public void setElements(LinkedList elements) { + public void setElements(List elements) { this.elements = elements; } - public LinkedList getElements() { + public List getElements() { return this.elements; } diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 4ef0579f2..6f204383d 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -211,7 +211,7 @@ public abstract class AbstractBreaker { * getNextKnuthElements() implementation(s) that are to be called. * @return LinkedList of Knuth elements. */ - protected abstract LinkedList getNextKnuthElements(LayoutContext context, int alignment); + protected abstract List getNextKnuthElements(LayoutContext context, int alignment); /** @return true if there's no content that could be handled. */ public boolean isEmpty() { @@ -549,7 +549,7 @@ public abstract class AbstractBreaker { childLC.signalSpanChange(Constants.NOT_SET); BlockSequence blockList; - LinkedList returnedList = getNextKnuthElements(childLC, alignment); + List returnedList = getNextKnuthElements(childLC, alignment); if (returnedList != null) { if (returnedList.size() == 0) { nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn); @@ -561,8 +561,10 @@ public abstract class AbstractBreaker { nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn); Position breakPosition = null; - if (((KnuthElement) returnedList.getLast()).isForcedBreak()) { - KnuthPenalty breakPenalty = (KnuthPenalty)returnedList.removeLast(); + if (((KnuthElement) returnedList.get(returnedList.size() - 1)) + .isForcedBreak()) { + KnuthPenalty breakPenalty = (KnuthPenalty) returnedList + .remove(returnedList.size() - 1); breakPosition = breakPenalty.getPosition(); switch (breakPenalty.getBreakClass()) { case Constants.EN_PAGE: diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 3f2143bae..13ea66d1f 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -20,14 +20,12 @@ package org.apache.fop.layoutmgr; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.area.Area; import org.apache.fop.area.PageViewport; import org.apache.fop.fo.Constants; @@ -152,7 +150,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, + public List getNextKnuthElements(LayoutContext context, int alignment) { log.warn("null implementation of getNextKnuthElements() called!"); setFinished(true); @@ -160,7 +158,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, int alignment) { log.warn("null implementation of getChangeKnuthElement() called!"); return null; diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 0e6c2cb40..22d5fb941 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -189,7 +189,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { resetSpaces(); if (isAbsoluteOrFixed()) { return getNextKnuthElementsAbsolute(context, alignment); @@ -247,9 +247,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager MinOptMax stackLimit = new MinOptMax(relDims.bpd); - LinkedList returnedList; - LinkedList contentList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList; + List contentList = new LinkedList(); + List returnList = new LinkedList(); if (!breakBeforeServed) { try { @@ -291,7 +291,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager childLC.clearKeepWithPreviousPending(); } if (returnedList.size() == 1 - && ((ListElement)returnedList.getFirst()).isForcedBreak()) { + && ((ListElement)returnedList.get(0)).isForcedBreak()) { // a descendant of this block has break-before /* if (returnList.size() == 0) { @@ -321,7 +321,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager //Avoid NoSuchElementException below (happens with empty blocks) continue; } - if (((ListElement)returnedList.getLast()).isForcedBreak()) { + if (((ListElement) returnedList + .get(returnedList.size() - 1)).isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished()) { // there is no other content in this block; @@ -392,7 +393,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return returnList; } - private LinkedList getNextKnuthElementsAbsolute(LayoutContext context, int alignment) { + private List getNextKnuthElementsAbsolute(LayoutContext context, int alignment) { autoHeight = false; boolean switchedProgressionDirection @@ -515,7 +516,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } updateRelDims(0, 0, false); } - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); if (!breaker.isEmpty()) { Position bcPosition = new BlockContainerPosition(this, breaker); returnList.add(new KnuthBox(0, notifyPos(bcPosition), false)); @@ -622,9 +623,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return lc; } - protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + protected List getNextKnuthElements(LayoutContext context, int alignment) { LayoutManager curLM; // currently active LM - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); @@ -632,7 +633,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); - LinkedList returnedList = null; + List returnedList = null; if (!curLM.isFinished()) { returnedList = curLM.getNextKnuthElements(childLC, alignment); } @@ -723,7 +724,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // "unwrap" the NonLeafPositions stored in parentIter // and put them in a new list; - LinkedList positionList = new LinkedList(); + List positionList = new LinkedList(); Position pos; boolean bSpaceBefore = false; boolean bSpaceAfter = false; @@ -798,10 +799,11 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // // the last item inside positionList is a Position; // // this means that the paragraph has been split // // between consecutive pages - LinkedList splitList = new LinkedList(); + List splitList = new LinkedList(); int splitLength = 0; - int iFirst = ((MappingPosition) positionList.getFirst()).getFirstIndex(); - int iLast = ((MappingPosition) positionList.getLast()).getLastIndex(); + int iFirst = ((MappingPosition) positionList.get(0)).getFirstIndex(); + int iLast = ((MappingPosition) positionList.get(positionList + .size() - 1)).getLastIndex(); // copy from storedList to splitList all the elements from // iFirst to iLast ListIterator storedListIterator = storedList.listIterator(iFirst); diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index c5c7d9445..b6b6f921f 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -113,7 +113,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { resetSpaces(); return super.getNextKnuthElements(context, alignment); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index b208e4e9b..b2fb98ccd 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -63,7 +63,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** space-after value adjusted for block-progression-unit handling */ protected int adjustedSpaceAfter = 0; /** Only used to store the original list when createUnitElements is called */ - protected LinkedList storedList = null; + protected List storedList = null; /** Indicates whether break before has been served or not */ protected boolean breakBeforeServed = false; /** Indicates whether the first visible mark has been returned by this LM, yet */ @@ -235,7 +235,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { //log.debug("BLM.getNextKnuthElements> keep-together = " // + layoutProps.keepTogether.getType()); //log.debug(" keep-with-previous = " + @@ -249,9 +249,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager updateContentAreaIPDwithOverconstrainedAdjust(); - LinkedList returnedList = null; - LinkedList contentList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList = null; + List contentList = new LinkedList(); + List returnList = new LinkedList(); if (!breakBeforeServed) { try { @@ -303,11 +303,11 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } if (returnedList != null && returnedList.size() == 1 - && ((ListElement) returnedList.getFirst()).isForcedBreak()) { + && ((ListElement) returnedList.get(0)).isForcedBreak()) { if (curLM.isFinished() && !hasNextChildLM()) { // a descendant of this block has break-before - forcedBreakAfterLast = (BreakElement) returnedList.getFirst(); + forcedBreakAfterLast = (BreakElement) returnedList.get(0); context.clearPendingMarks(); break; } @@ -344,10 +344,12 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager continue; } contentList.addAll(returnedList); - if (((ListElement) returnedList.getLast()).isForcedBreak()) { + if (((ListElement) returnedList.get(returnedList.size() - 1)) + .isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished() && !hasNextChildLM()) { - forcedBreakAfterLast = (BreakElement)contentList.removeLast(); + forcedBreakAfterLast = (BreakElement) contentList + .remove(contentList.size() - 1); context.clearPendingMarks(); break; } @@ -414,7 +416,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param context the current layout context * @param childLC the currently active child layout context */ - protected void addInBetweenBreak(LinkedList contentList, LayoutContext context, + protected void addInBetweenBreak(List contentList, LayoutContext context, LayoutContext childLC) { if (mustKeepTogether() || context.isKeepWithNextPending() @@ -438,7 +440,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager return; } - ListElement last = (ListElement)contentList.getLast(); + ListElement last = (ListElement) contentList + .get(contentList.size() - 1); if (last.isGlue()) { // the last element in contentList is a glue; // it is a feasible breakpoint, there is no need to add @@ -585,7 +588,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { /*LF*/ //log.debug(""); /*LF*/ //log.debug(" BLM.getChangedKnuthElements> inizio: oldList.size() = " // + oldList.size()); @@ -593,8 +596,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager KnuthElement returnedElement; KnuthElement currElement = null; KnuthElement prevElement = null; - LinkedList returnedList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList = new LinkedList(); + List returnList = new LinkedList(); int fromIndex = 0; // "unwrap" the Positions stored in the elements @@ -691,7 +694,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // add an infinite penalty to forbid a break between blocks returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); - } else if (bSomethingAdded && !((KnuthElement) returnedList.getLast()).isGlue()) { + } else if (bSomethingAdded + && !((KnuthElement) returnedList.get(returnedList + .size() - 1)).isGlue()) { // add a null penalty to allow a break between blocks returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } @@ -711,7 +716,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // there are no more elements to add // remove the last penalty added to returnedList if (returnedList.size() > 0) { - returnedList.removeLast(); + returnedList.remove(returnedList.size() - 1); } //log.debug(" BLM.getChangedKnuthElements> elementi propri, ignorati, da " // + fromIndex + " a " + workList.size()); @@ -943,7 +948,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param isFirst true if this is the first time a layout manager instance needs to generate * border and padding */ - protected void addKnuthElementsForBorderPaddingBefore(LinkedList returnList, boolean isFirst) { + protected void addKnuthElementsForBorderPaddingBefore(List returnList, boolean isFirst) { //Border and Padding (before) CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground(); if (borderAndPadding != null) { @@ -970,7 +975,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param isLast true if this is the last time a layout manager instance needs to generate * border and padding */ - protected void addKnuthElementsForBorderPaddingAfter(LinkedList returnList, boolean isLast) { + protected void addKnuthElementsForBorderPaddingAfter(List returnList, boolean isLast) { //Border and Padding (after) CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground(); if (borderAndPadding != null) { @@ -997,7 +1002,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param context the layout context * @return true if an element has been added due to a break-before. */ - protected boolean addKnuthElementsForBreakBefore(LinkedList returnList, + protected boolean addKnuthElementsForBreakBefore(List returnList, LayoutContext context) { int breakBefore = -1; if (fobj instanceof org.apache.fop.fo.flow.Block) { @@ -1030,7 +1035,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param context the layout context * @return true if an element has been added due to a break-after. */ - protected boolean addKnuthElementsForBreakAfter(LinkedList returnList, + protected boolean addKnuthElementsForBreakAfter(List returnList, LayoutContext context) { int breakAfter = -1; if (fobj instanceof org.apache.fop.fo.flow.Block) { @@ -1062,7 +1067,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param returnList return list to add the additional elements to * @param alignment vertical alignment */ - protected void addKnuthElementsForSpaceBefore(LinkedList returnList/*, + protected void addKnuthElementsForSpaceBefore(List returnList/*, Position returnPosition*/, int alignment) { SpaceProperty spaceBefore = getSpaceBeforeProperty(); // append elements representing space-before @@ -1111,7 +1116,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param returnList return list to add the additional elements to * @param alignment vertical alignment */ - protected void addKnuthElementsForSpaceAfter(LinkedList returnList/*, Position returnPosition*/, + protected void addKnuthElementsForSpaceAfter(List returnList/*, Position returnPosition*/, int alignment) { SpaceProperty spaceAfter = getSpaceAfterProperty(); // append elements representing space-after @@ -1156,22 +1161,22 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager }*/ } - protected LinkedList createUnitElements(LinkedList oldList) { + protected List createUnitElements(List oldList) { //log.debug("Start conversion: " + oldList.size() // + " elements, space-before.min=" + layoutProps.spaceBefore.getSpace().min // + " space-after.min=" + layoutProps.spaceAfter.getSpace().min); // add elements at the beginning and at the end of oldList // representing minimum spaces - LayoutManager lm = ((KnuthElement)oldList.getFirst()).getLayoutManager(); + LayoutManager lm = ((KnuthElement)oldList.get(0)).getLayoutManager(); boolean bAddedBoxBefore = false; boolean bAddedBoxAfter = false; if (adjustedSpaceBefore > 0) { - oldList.addFirst(new KnuthBox(adjustedSpaceBefore, + oldList.add(0, new KnuthBox(adjustedSpaceBefore, new Position(lm), true)); bAddedBoxBefore = true; } if (adjustedSpaceAfter > 0) { - oldList.addLast(new KnuthBox(adjustedSpaceAfter, + oldList.add(new KnuthBox(adjustedSpaceAfter, new Position(lm), true)); bAddedBoxAfter = true; } @@ -1399,10 +1404,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // remove elements at the beginning and at the end of oldList // representing minimum spaces if (adjustedSpaceBefore > 0) { - oldList.removeFirst(); + oldList.remove(0); } if (adjustedSpaceAfter > 0) { - oldList.removeLast(); + oldList.remove(oldList.size() - 1); } // if space-before.conditionality is "discard", correct newList diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java index 9a87e71c4..f3d36276c 100644 --- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java +++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java @@ -38,7 +38,7 @@ public class ElementListUtils { * @param constraint min/opt/max value to restrict the range in which the breaks are removed. * @return true if the opt constraint is bigger than the list contents */ - public static boolean removeLegalBreaks(LinkedList elements, MinOptMax constraint) { + public static boolean removeLegalBreaks(List elements, MinOptMax constraint) { return removeLegalBreaks(elements, constraint.opt); } @@ -50,7 +50,7 @@ public class ElementListUtils { * @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) { + public static boolean removeLegalBreaks(List elements, int constraint) { int len = 0; ListIterator iter = elements.listIterator(); while (iter.hasNext()) { @@ -97,7 +97,7 @@ public class ElementListUtils { * @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) { + public static boolean removeLegalBreaksFromEnd(List elements, int constraint) { int len = 0; ListIterator i = elements.listIterator(elements.size()); while (i.hasPrevious()) { @@ -184,8 +184,8 @@ public class ElementListUtils { * @param elems the element list * @return true if the list ends with a forced break */ - public static boolean endsWithForcedBreak(LinkedList elems) { - ListElement last = (ListElement)elems.getLast(); + public static boolean endsWithForcedBreak(List elems) { + ListElement last = (ListElement) elems.get(elems.size() - 1); return last.isForcedBreak(); } @@ -195,8 +195,8 @@ public class ElementListUtils { * @param elems the element list * @return true if the list ends with a non-infinite penalty */ - public static boolean endsWithNonInfinitePenalty(LinkedList elems) { - ListElement last = (ListElement)elems.getLast(); + public static boolean endsWithNonInfinitePenalty(List elems) { + ListElement last = (ListElement) elems.get(elems.size() - 1); if (last.isPenalty() && ((KnuthPenalty)last).getP() < KnuthElement.INFINITE) { return true; } else if (last instanceof BreakElement diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 9cd5c622d..2410c19cd 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -64,7 +64,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { // set layout dimensions int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth(); @@ -72,8 +72,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager // currently active LM LayoutManager curLM; - LinkedList returnedList; - LinkedList returnList = new LinkedList(); + List returnedList; + List returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { if (!(curLM instanceof WrapperLayoutManager) @@ -114,7 +114,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } // "wrap" the Position inside each element - LinkedList tempList = returnedList; + List tempList = returnedList; returnedList = new LinkedList(); wrapPositionElements(tempList, returnedList); @@ -213,11 +213,11 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, /*int flaggedPenalty,*/ int alignment) { + public List getChangedKnuthElements(List oldList, /*int flaggedPenalty,*/ int alignment) { ListIterator oldListIterator = oldList.listIterator(); KnuthElement returnedElement; - LinkedList returnedList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList = new LinkedList(); + List returnList = new LinkedList(); KnuthElement prevElement = null; KnuthElement currElement = null; int fromIndex = 0; @@ -257,7 +257,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager // add an infinite penalty to forbid a break between blocks returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); - } else if (!((KnuthElement) returnedList.getLast()).isGlue()) { + } else if (!((KnuthElement) returnedList.get(returnedList + .size() - 1)).isGlue()) { // add a null penalty to allow a break between blocks returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } diff --git a/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java b/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java index 53f285377..364c896ad 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java @@ -19,9 +19,10 @@ package org.apache.fop.layoutmgr; -import org.apache.fop.traits.MinOptMax; - import java.util.LinkedList; +import java.util.List; + +import org.apache.fop.traits.MinOptMax; /** * Knuth box used to represent a line in block-progression-dimension (i.e. the width is its height). @@ -34,9 +35,9 @@ public class KnuthBlockBox extends KnuthBox { * it isn't possible to get the opt value stored in a MinOptMax object. */ private int bpd; - private LinkedList footnoteList; + private List footnoteList; /** List of Knuth elements. This is a list of LinkedList elements. */ - private LinkedList elementLists = null; + private List elementLists = null; /** * Creates a new box. @@ -61,7 +62,7 @@ public class KnuthBlockBox extends KnuthBox { * @param pos the Position stored in this box * @param bAux is this box auxiliary? */ - public KnuthBlockBox(int w, LinkedList list, Position pos, boolean bAux) { + public KnuthBlockBox(int w, List list, Position pos, boolean bAux) { super(w, pos, bAux); ipdRange = new MinOptMax(0); bpd = 0; @@ -71,7 +72,7 @@ public class KnuthBlockBox extends KnuthBox { /** * @return the LMs for the footnotes cited in this box. */ - public LinkedList getFootnoteBodyLMs() { + public List getFootnoteBodyLMs() { return footnoteList; } @@ -86,7 +87,7 @@ public class KnuthBlockBox extends KnuthBox { * Adds the given list of Knuth elements to this box' list of elements. * @param list elements corresponding to a footnote body */ - public void addElementList(LinkedList list) { + public void addElementList(List list) { if (elementLists == null) { elementLists = new LinkedList(); } @@ -98,7 +99,7 @@ public class KnuthBlockBox extends KnuthBox { * @return a list of KnuthElement sequences corresponding to footnotes cited in this * box */ - public LinkedList getElementLists() { + public List getElementLists() { return elementLists; } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManager.java b/src/java/org/apache/fop/layoutmgr/LayoutManager.java index 0b17c9a27..0700ea43a 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManager.java @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr; -import java.util.LinkedList; import java.util.List; import org.apache.fop.area.Area; @@ -138,7 +137,7 @@ public interface LayoutManager extends PercentBaseContext { * @param alignment the desired text alignement * @return the list of KnuthElements */ - LinkedList getNextKnuthElements(LayoutContext context, int alignment); + List getNextKnuthElements(LayoutContext context, int alignment); /** * Get a sequence of KnuthElements representing the content @@ -175,7 +174,7 @@ public interface LayoutManager extends PercentBaseContext { * @param alignment the desired text alignment * @return the updated list of KnuthElements */ - LinkedList getChangedKnuthElements(List oldList, int alignment); + List getChangedKnuthElements(List oldList, int alignment); /** * Returns the IPD of the content area diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index d6be75758..b25e4bd4f 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -135,8 +135,8 @@ public class PageBreaker extends AbstractBreaker { } /** {@inheritDoc} */ - protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) { - LinkedList contentList = null; + protected List getNextKnuthElements(LayoutContext context, int alignment) { + List contentList = null; while (!childFLM.isFinished() && contentList == null) { contentList = childFLM.getNextKnuthElements(context, alignment); @@ -156,7 +156,7 @@ public class PageBreaker extends AbstractBreaker { footnoteContext.setStackLimitBP(context.getStackLimitBP()); footnoteContext.setRefIPD(pslm.getCurrentPV() .getRegionReference(Constants.FO_REGION_BODY).getIPD()); - LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs(); + List footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs(); ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator(); // store the lists of elements representing the footnote bodies // in the box representing the line containing their references diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 5e3d0a887..a3155e102 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -21,11 +21,11 @@ package org.apache.fop.layoutmgr; import java.util.ArrayList; import java.util.LinkedList; +import java.util.List; import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition; @@ -230,7 +230,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { * @param elementLists list of KnuthElement sequences corresponding to the footnotes * bodies */ - private void handleFootnotes(LinkedList elementLists) { + private void handleFootnotes(List elementLists) { // initialization if (!footnotesPending) { footnotesPending = true; @@ -286,7 +286,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { return returnValue; } - private void resetFootnotes(LinkedList elementLists) { + private void resetFootnotes(List elementLists) { for (int i = 0; i < elementLists.size(); i++) { /*LinkedList removedList = (LinkedList)*/footnotesList.remove(footnotesList.size() - 1); lengthList.remove(lengthList.size() - 1); diff --git a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java index 58de6a980..051f76d7f 100644 --- a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java +++ b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java @@ -614,7 +614,7 @@ public class SpaceResolver { * Resolves unresolved elements applying the space resolution rules defined in 4.3.1. * @param elems the element list */ - public static void resolveElementList(LinkedList elems) { + public static void resolveElementList(List elems) { if (log.isTraceEnabled()) { log.trace(elems); } diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 8065f9aad..3a8786bd7 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -87,7 +87,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { if (true) { throw new UnsupportedOperationException( "Shouldn't this method be emptied because it's never called at all?"); @@ -102,8 +102,8 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { BlockLevelLayoutManager curLM; BlockLevelLayoutManager prevLM = null; MinOptMax stackSize = new MinOptMax(); - LinkedList returnedList; - LinkedList returnList = new LinkedList(); + List returnedList; + List returnList = new LinkedList(); while ((curLM = ((BlockLevelLayoutManager) getChildLM())) != null) { if (curLM instanceof InlineLevelLayoutManager) { @@ -125,7 +125,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { // + returnedList.size()); // "wrap" the Position inside each element - LinkedList tempList = returnedList; + List tempList = returnedList; KnuthElement tempElement; returnedList = new LinkedList(); ListIterator listIter = tempList.listIterator(); @@ -136,8 +136,8 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } if (returnedList.size() == 1 - && ((KnuthElement)returnedList.getFirst()).isPenalty() - && ((KnuthPenalty)returnedList.getFirst()).getP() == -KnuthElement.INFINITE) { + && ((KnuthElement)returnedList.get(0)).isPenalty() + && ((KnuthPenalty)returnedList.get(0)).getP() == -KnuthElement.INFINITE) { // a descendant of this flow has break-before returnList.addAll(returnedList); return returnList; @@ -150,16 +150,18 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); - } else if (!((KnuthElement) returnList.getLast()).isGlue()) { + } else if (!((KnuthElement) returnList.get(returnList + .size() - 1)).isGlue()) { // add a null penalty to allow a break between blocks returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } } /*LF*/ if (returnedList.size() > 0) { // controllare! returnList.addAll(returnedList); - if (((KnuthElement)returnedList.getLast()).isPenalty() - && ((KnuthPenalty)returnedList.getLast()).getP() - == -KnuthElement.INFINITE) { + final KnuthElement last = (KnuthElement) returnedList + .get(returnedList.size() - 1); + if (last.isPenalty() + && ((KnuthPenalty) last).getP() == -KnuthElement.INFINITE) { // a descendant of this flow has break-after /*LF*/ //log.debug("FLM - break after!!"); return returnList; @@ -325,9 +327,9 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { return lc; } - protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + protected List getNextKnuthElements(LayoutContext context, int alignment) { LayoutManager curLM; // currently active LM - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); @@ -335,7 +337,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(context.getWritingMode()); - LinkedList returnedList = null; + List returnedList = null; //The following is a HACK! Ignore leading and trailing white space boolean ignore = curLM instanceof TextLayoutManager; if (!curLM.isFinished()) { diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index 38e0c35bc..e90927699 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -21,7 +21,7 @@ package org.apache.fop.layoutmgr.inline; import java.awt.Dimension; import java.awt.Rectangle; -import java.util.LinkedList; +import java.util.List; import org.apache.fop.area.Area; import org.apache.fop.area.inline.Viewport; @@ -104,7 +104,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, + public List getNextKnuthElements(LayoutContext context, int alignment) { Viewport areaCurrent = getInlineArea(); setCurrentArea(areaCurrent); diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index a6f9be7af..c81a23a9c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -90,7 +90,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { MinOptMax ipd; curArea = get(context); KnuthSequence seq = new InlineKnuthSequence(); @@ -179,7 +179,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { if (isFinished()) { return null; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index 2af844c5c..b43c4c841 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -27,8 +27,6 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.LineArea; @@ -131,7 +129,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager stackSize = 0; - LinkedList contentList = + List contentList = getNextKnuthElements(childLC, Constants.EN_START); ListIterator contentIter = contentList.listIterator(); while (contentIter.hasNext()) { @@ -254,9 +252,9 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager } } - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { - LinkedList contentList = new LinkedList(); - LinkedList returnedList; + public List getNextKnuthElements(LayoutContext context, int alignment) { + List contentList = new LinkedList(); + List returnedList; childLM.initialize(); while (!childLM.isFinished()) { @@ -267,7 +265,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager // move elements to contentList, and accumulate their size KnuthElement contentElement; while (returnedList.size() > 0) { - Object obj = returnedList.removeFirst(); + Object obj = returnedList.remove(0); if (obj instanceof KnuthSequence) { KnuthSequence ks = (KnuthSequence)obj; for (Iterator it = ks.iterator(); it.hasNext(); ) { @@ -312,7 +310,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager return false; } - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, /*int flaggedPenalty,*/ int alignment) { return null; diff --git a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java index adb0e5a73..a02cfee89 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java @@ -71,7 +71,7 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, + public List getNextKnuthElements(LayoutContext context, int alignment) { // for the moment, this LM is set as the citationLM's parent // later on, when this LM will have nothing more to do, the citationLM's parent @@ -82,9 +82,9 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { bodyLM.initialize(); // get Knuth elements representing the footnote citation - LinkedList returnedList = new LinkedList(); + List returnedList = new LinkedList(); while (!citationLM.isFinished()) { - LinkedList partialList = citationLM.getNextKnuthElements(context, alignment); + List partialList = citationLM.getNextKnuthElements(context, alignment); if (partialList != null) { returnedList.addAll(partialList); } @@ -122,9 +122,9 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, int alignment) { - LinkedList returnedList = super.getChangedKnuthElements(oldList, alignment); + List returnedList = super.getChangedKnuthElements(oldList, alignment); addAnchor(returnedList); return returnedList; } @@ -164,7 +164,7 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { * Find the last box in the sequence, and add a reference to the FootnoteBodyLM * @param citationList the list of elements representing the footnote citation */ - private void addAnchor(LinkedList citationList) { + private void addAnchor(List citationList) { KnuthInlineBox lastBox = null; // the list of elements is searched backwards, until we find a box ListIterator citationIterator = citationList.listIterator(citationList.size()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 7c2e4748a..123259cd4 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -233,14 +233,14 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { LayoutManager curLM; // the list returned by child LM - LinkedList returnedList; + List returnedList; // the list which will be returned to the parent LM - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); KnuthSequence lastSequence = null; SpaceSpecifier leadingSpace = context.getLeadingSpace(); @@ -367,7 +367,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); childLC.clearKeepsPending(); } - lastSequence = (KnuthSequence) returnList.getLast(); + lastSequence = (KnuthSequence) returnList + .get(returnList.size() - 1); lastChildLM = curLM; } @@ -432,7 +433,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // set in the layout context, it must be also set in the // layout context given to lastLM, but must be cleared in the // layout context given to the other LMs. - LinkedList positionList = new LinkedList(); + List positionList = new LinkedList(); NonLeafPosition pos; LayoutManager lastLM = null;// last child LM in this iterator Position lastPos = null; @@ -533,8 +534,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { - LinkedList returnedList = new LinkedList(); + public List getChangedKnuthElements(List oldList, int alignment) { + List returnedList = new LinkedList(); addKnuthElementsForBorderPaddingStart(returnedList); returnedList.addAll(super.getChangedKnuthElements(oldList, alignment)); addKnuthElementsForBorderPaddingEnd(returnedList); diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index bf1538a7c..81fc7901d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -364,7 +364,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { // "unwrap" the Positions stored in the elements ListIterator oldListIterator = oldList.listIterator(); KnuthElement oldElement; diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index 1e7c793df..3bb82aa11 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -52,7 +52,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { private Leader fobj; private Font font = null; - private LinkedList contentList = null; + private List contentList = null; private ContentLayoutManager clm = null; private int contentAreaIPD = 0; @@ -230,7 +230,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, + public List getNextKnuthElements(LayoutContext context, int alignment) { MinOptMax ipd; curArea = get(context); @@ -305,13 +305,13 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, int alignment) { if (isFinished()) { return null; } - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); addKnuthElementsForBorderPaddingStart(returnList); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index fb5e9ee4d..552e74889 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -249,7 +249,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { curArea = get(context); if (curArea == null) { @@ -313,7 +313,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, + public List getChangedKnuthElements(List oldList, int alignment) { if (isFinished()) { return null; diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index c9f72e64f..b77f36f0d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -574,7 +574,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { FontInfo fi = fobj.getFOEventHandler().getFontInfo(); FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); Font fs = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this)); @@ -644,7 +644,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager LayoutContext inlineLC = new LayoutContext(context); InlineLevelLayoutManager curLM; - LinkedList returnedList = null; + List returnedList = null; iLineWidth = context.getStackLimitIP().opt; // convert all the text in a sequence of paragraphs made @@ -666,7 +666,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } if (lastPar != null) { - KnuthSequence firstSeq = (KnuthSequence) returnedList.getFirst(); + KnuthSequence firstSeq = (KnuthSequence) returnedList.get(0); // finish last paragraph before a new block sequence if (!firstSeq.isInlineSequence()) { @@ -901,7 +901,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param context the layout context * @return a list of Knuth elements representing broken lines */ - private LinkedList createLineBreaks(int alignment, LayoutContext context) { + private List createLineBreaks(int alignment, LayoutContext context) { // find the optimal line breaking points for each paragraph ListIterator paragraphsIterator @@ -1048,9 +1048,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param context the layout context * @return the newly built element list */ - private LinkedList postProcessLineBreaks(int alignment, LayoutContext context) { + private List postProcessLineBreaks(int alignment, LayoutContext context) { - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); for (int p = 0; p < knuthParagraphs.size(); p++) { // penalty between paragraphs @@ -1068,7 +1068,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(p); if (!seq.isInlineSequence()) { - LinkedList targetList = new LinkedList(); + List targetList = new LinkedList(); ListIterator listIter = seq.listIterator(); while (listIter.hasNext()) { ListElement tempElement; @@ -1110,7 +1110,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos(); // create a list of the FootnoteBodyLM handling footnotes // whose citations are in this line - LinkedList footnoteList = new LinkedList(); + List footnoteList = new LinkedList(); ListIterator elementIterator = seq.listIterator(startIndex); while (elementIterator.nextIndex() <= endIndex) { KnuthElement element = (KnuthElement) elementIterator.next(); @@ -1334,8 +1334,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { - LinkedList returnList = new LinkedList(); + public List getChangedKnuthElements(List oldList, int alignment) { + List returnList = new LinkedList(); for (int p = 0; p < knuthParagraphs.size(); p++) { LineLayoutPossibilities llPoss; llPoss = (LineLayoutPossibilities)lineLayoutsList.get(p); @@ -1384,7 +1384,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager ListIterator currParIterator = currPar.listIterator(currPar.ignoreAtStart); // list of TLM involved in hyphenation - LinkedList updateList = new LinkedList(); + List updateList = new LinkedList(); KnuthElement firstElement = null; KnuthElement nextElement = null; // current InlineLevelLayoutManager @@ -1497,7 +1497,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager .applyChanges(currPar.subList(fromIndex + iAddedElements, toIndex + iAddedElements))) { // insert the new KnuthElements - LinkedList newElements = null; + List newElements = null; newElements = currUpdate.inlineLM.getChangedKnuthElements (currPar.subList(fromIndex + iAddedElements, diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 903ec84ae..eec2b1e91 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -523,12 +523,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(final LayoutContext context, final int alignment) { + public List getNextKnuthElements(final LayoutContext context, final int alignment) { this.lineStartBAP = context.getLineStartBorderAndPaddingWidth(); this.lineEndBAP = context.getLineEndBorderAndPaddingWidth(); this.alignmentContext = context.getAlignmentContext(); - final LinkedList returnList = new LinkedList(); + final List returnList = new LinkedList(); KnuthSequence sequence = new InlineKnuthSequence(); AreaInfo ai = null; AreaInfo prevAi = null; @@ -624,9 +624,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { sequence = this.processLinebreak(returnList, sequence); } - if (((List)returnList.getLast()).size() == 0) { + if (((List) returnList.get(returnList.size() - 1)).isEmpty()) { //Remove an empty sequence because of a trailing newline - returnList.removeLast(); + returnList.remove(returnList.size() - 1); } this.setFinished(true); @@ -637,7 +637,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - private KnuthSequence processLinebreak(final LinkedList returnList, + private KnuthSequence processLinebreak(final List returnList, KnuthSequence sequence) { if (this.lineEndBAP != 0) { sequence.add( @@ -942,7 +942,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(final List oldList, + public List getChangedKnuthElements(final List oldList, final int alignment) { if (this.isFinished()) { return null; diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index dfffbdd04..11e69970e 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -115,9 +115,9 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { resetSpaces(); - LinkedList returnList = super.getNextKnuthElements(context, alignment); + List returnList = super.getNextKnuthElements(context, alignment); //fox:widow-content-limit int widowRowLimit = getListBlockFO().getWidowContentLimit().getValue(); @@ -135,7 +135,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { //log.debug("LBLM.getChangedKnuthElements>"); return super.getChangedKnuthElements(oldList, alignment); } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 549244267..124827976 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -98,7 +98,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { //log.debug(" ListItemContentLayoutManager.getChanged>"); return super.getChangedKnuthElements(oldList, alignment); } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 9d08415ff..37ec4964d 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -72,8 +72,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager private Block curBlockArea = null; - private LinkedList labelList = null; - private LinkedList bodyList = null; + private List labelList = null; + private List bodyList = null; private boolean discardBorderBefore; private boolean discardBorderAfter; @@ -190,11 +190,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { referenceIPD = context.getRefIPD(); LayoutContext childLC; - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); if (!breakBeforeServed) { try { @@ -243,7 +243,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager this.keepWithNextPendingOnBody = childLC.getKeepWithNextPending(); // create a combined list - LinkedList returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList, context); + List returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList, context); // "wrap" the Position inside each element wrapPositionElements(returnedList, returnList, true); @@ -262,10 +262,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager return returnList; } - private LinkedList getCombinedKnuthElementsForListItem(LinkedList labelElements, - LinkedList bodyElements, - LayoutContext context) { - //Copy elements to array lists to improve element access performance + private List getCombinedKnuthElementsForListItem(List labelElements, + List bodyElements, LayoutContext context) { + // Copy elements to array lists to improve element access performance List[] elementLists = {new ArrayList(labelElements), new ArrayList(bodyElements)}; int[] fullHeights = {ElementListUtils.calcContentLength(elementLists[0]), @@ -429,7 +428,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager /** * {@inheritDoc} */ - public LinkedList getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { //log.debug(" LILM.getChanged> label"); // label labelList = label.getChangedKnuthElements(labelList, alignment); @@ -458,9 +457,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } } - LinkedList returnedList = body.getChangedKnuthElements(oldList, alignment); + List returnedList = body.getChangedKnuthElements(oldList, alignment); // "wrap" the Position inside each element - LinkedList tempList = returnedList; + List tempList = returnedList; KnuthElement tempElement; returnedList = new LinkedList(); ListIterator listIter = tempList.listIterator(); diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 19b97322c..50688dd0e 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -21,10 +21,10 @@ package org.apache.fop.layoutmgr.table; 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.fo.Constants; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; @@ -116,7 +116,7 @@ class RowGroupLayoutManager { childLC.setRefIPD(spanWidth); //Get the element list for the cell contents - LinkedList elems = primary.getCellLM().getNextKnuthElements( + List elems = primary.getCellLM().getNextKnuthElements( childLC, alignment); ElementListObserver.observe(elems, "table-cell", primary.getCell().getId()); primary.setElements(elems); @@ -124,7 +124,7 @@ class RowGroupLayoutManager { } } computeRowHeights(); - LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context, + List elements = tableStepper.getCombinedKnuthElementsForRowGroup(context, rowGroup, bodyType); returnList.addAll(elements); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 6afb57dca..1b402095d 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -20,13 +20,14 @@ package org.apache.fop.layoutmgr.table; 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.area.Trait; +import org.apache.fop.fo.flow.ListItem; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; @@ -126,16 +127,16 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager /** * {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { MinOptMax stackLimit = new MinOptMax(context.getStackLimitBP()); referenceIPD = context.getRefIPD(); cellIPD = referenceIPD; cellIPD -= getIPIndents(); - LinkedList returnedList; - LinkedList contentList = new LinkedList(); - LinkedList returnList = new LinkedList(); + List returnedList; + List contentList = new LinkedList(); + List returnList = new LinkedList(); BlockLevelLayoutManager curLM; // currently active LM BlockLevelLayoutManager prevLM = null; // previously active LM @@ -187,13 +188,15 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } //Space resolution SpaceResolver.resolveElementList(returnList); - if (((KnuthElement) returnList.getFirst()).isForcedBreak()) { - primaryGridUnit.setBreakBefore(((KnuthPenalty) returnList.getFirst()).getBreakClass()); - returnList.removeFirst(); + if (((KnuthElement) returnList.get(0)).isForcedBreak()) { + primaryGridUnit.setBreakBefore(((KnuthPenalty) returnList.get(0)).getBreakClass()); + returnList.remove(0); assert !returnList.isEmpty(); } - if (((KnuthElement) returnList.getLast()).isForcedBreak()) { - KnuthPenalty p = (KnuthPenalty) returnList.getLast(); + final KnuthElement lastItem = (KnuthElement) returnList + .get(returnList.size() - 1); + if (((KnuthElement) lastItem).isForcedBreak()) { + KnuthPenalty p = (KnuthPenalty) lastItem; primaryGridUnit.setBreakAfter(p.getBreakClass()); p.setP(0); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 0fe47d7b4..d370dc37f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -178,9 +178,9 @@ public class TableLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { - LinkedList returnList = new LinkedList(); + List returnList = new LinkedList(); /* * Compute the IPD and adjust it if necessary (overconstrained) @@ -271,8 +271,8 @@ public class TableLayoutManager extends BlockStackingLayoutManager int breakBefore = BreakUtil.compareBreakClasses(getTable().getBreakBefore(), childLC.getBreakBefore()); if (breakBefore != Constants.EN_AUTO) { - returnList.addFirst(new BreakElement(getAuxiliaryPosition(), - 0, -KnuthElement.INFINITE, breakBefore, context)); + returnList.add(0, new BreakElement(getAuxiliaryPosition(), 0, + -KnuthElement.INFINITE, breakBefore, context)); } //addKnuthElementsForBreakAfter(returnList, context); -- cgit v1.2.3 From a435c09dc62eeeba6201c74d1c1f3b2313c4356f Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 9 Jun 2008 17:27:51 +0000 Subject: Some updates (improvements?) in the UAX#14-related files: - LineBreakPairTable.txt: replace tabs with spaces to make the file a bit easier to read (constant column-width, instead of depending on an editor's settings for tabs) - GenerateLineBreakUtils.java: - generate a public final utility class - add some spacing in the generated file, after commas and before/after '=' (same styling as manually created files) - use Java 1.4 String.split() to tokenize lines, instead of StringTokenizer - add javadoc comments for public constants and methods - LineBreakUtils.java: regenerated after the above updates git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@665793 13f79535-47bb-0310-9956-ffa450edef68 --- src/codegen/unicode/data/LineBreakPairTable.txt | 56 +- .../fop/text/linebreak/GenerateLineBreakUtils.java | 160 ++- .../apache/fop/text/linebreak/LineBreakUtils.java | 1278 +++++++++++--------- 3 files changed, 804 insertions(+), 690 deletions(-) (limited to 'src') diff --git a/src/codegen/unicode/data/LineBreakPairTable.txt b/src/codegen/unicode/data/LineBreakPairTable.txt index 93388e1bd..948877d9f 100755 --- a/src/codegen/unicode/data/LineBreakPairTable.txt +++ b/src/codegen/unicode/data/LineBreakPairTable.txt @@ -1,28 +1,28 @@ - OP CL QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT -OP ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ @ ^ ^ ^ ^ ^ ^ -CL _ ^ % % ^ ^ ^ ^ % % % % _ _ % % _ _ ^ # ^ _ _ _ _ _ -QU ^ ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % -GL % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % -NS _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ -EX _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ -SY _ ^ % % % ^ ^ ^ _ _ % _ _ _ % % _ _ ^ # ^ _ _ _ _ _ -IS _ ^ % % % ^ ^ ^ _ _ % % _ _ % % _ _ ^ # ^ _ _ _ _ _ -PR % ^ % % % ^ ^ ^ _ _ % % % _ % % _ _ ^ # ^ % % % % % -PO % ^ % % % ^ ^ ^ _ _ % % _ _ % % _ _ ^ # ^ _ _ _ _ _ -NU % ^ % % % ^ ^ ^ % % % % _ % % % _ _ ^ # ^ _ _ _ _ _ -AL % ^ % % % ^ ^ ^ _ _ % % _ % % % _ _ ^ # ^ _ _ _ _ _ -ID _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ _ -IN _ ^ % % % ^ ^ ^ _ _ _ _ _ % % % _ _ ^ # ^ _ _ _ _ _ -HY _ ^ % % % ^ ^ ^ _ _ % _ _ _ % % _ _ ^ # ^ _ _ _ _ _ -BA _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ -BB % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % -B2 _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ ^ ^ # ^ _ _ _ _ _ -ZW _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ^ _ _ _ _ _ _ _ -CM _ ^ % % % ^ ^ ^ _ _ % % _ % % % _ _ ^ # ^ _ _ _ _ _ -WJ % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % -H2 _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ % % -H3 _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ % -JL _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ % % % % _ -JV _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ % % -JT _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ % - + OP CL QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT +OP ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ @ ^ ^ ^ ^ ^ ^ +CL _ ^ % % ^ ^ ^ ^ % % % % _ _ % % _ _ ^ # ^ _ _ _ _ _ +QU ^ ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % +GL % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % +NS _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +EX _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +SY _ ^ % % % ^ ^ ^ _ _ % _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +IS _ ^ % % % ^ ^ ^ _ _ % % _ _ % % _ _ ^ # ^ _ _ _ _ _ +PR % ^ % % % ^ ^ ^ _ _ % % % _ % % _ _ ^ # ^ % % % % % +PO % ^ % % % ^ ^ ^ _ _ % % _ _ % % _ _ ^ # ^ _ _ _ _ _ +NU % ^ % % % ^ ^ ^ % % % % _ % % % _ _ ^ # ^ _ _ _ _ _ +AL % ^ % % % ^ ^ ^ _ _ % % _ % % % _ _ ^ # ^ _ _ _ _ _ +ID _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ _ +IN _ ^ % % % ^ ^ ^ _ _ _ _ _ % % % _ _ ^ # ^ _ _ _ _ _ +HY _ ^ % % % ^ ^ ^ _ _ % _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +BA _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ +BB % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % +B2 _ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % _ ^ ^ # ^ _ _ _ _ _ +ZW _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ^ _ _ _ _ _ _ _ +CM _ ^ % % % ^ ^ ^ _ _ % % _ % % % _ _ ^ # ^ _ _ _ _ _ +WJ % ^ % % % ^ ^ ^ % % % % % % % % % % ^ # ^ % % % % % +H2 _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ % % +H3 _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ % +JL _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ % % % % _ +JV _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ % % +JT _ ^ % % % ^ ^ ^ _ % _ _ _ % % % _ _ ^ # ^ _ _ _ _ % + diff --git a/src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java b/src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java index 7eba4573a..532e6a44b 100644 --- a/src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java +++ b/src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java @@ -30,7 +30,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.StringTokenizer; /** *

    Utility for generating a Java class representing line break properties @@ -55,6 +54,7 @@ public class GenerateLineBreakUtils { private static final byte COMBINING_PROHIBITED_BREAK = 3; // @ in table private static final byte PROHIBITED_BREAK = 4; // ^ in table private static final byte EXPLICIT_BREAK = 5; // ! in rules + private static final String BREAK_CLASS_TOKENS = "_%#@^!"; private static final String notInPairTable[] = { "AI", "BK", "CB", "CR", "LF", "NL", "SA", "SG", "SP", "XX" }; private static final byte lineBreakProperties[] = new byte[0x10000]; @@ -103,27 +103,32 @@ public class GenerateLineBreakUtils { BufferedReader b = new BufferedReader(new FileReader(breakPairFileName)); String line = b.readLine(); int lineNumber = 1; + String[] lineTokens; + String name; // read header if (line != null) { - StringTokenizer tok = new StringTokenizer(line); + lineTokens = line.split("\\s+"); byte columnNumber = 0; - while (tok.hasMoreTokens()) { - String name = tok.nextToken(); - if (columnNumber >= columnHeader.length) { - throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected column header " + name); - } - if (notInPairTableMap.get(name) != null) { - throw new Exception(breakPairFileName + ':' + lineNumber + ": invalid column header " + name); - } - Byte v = (Byte)lineBreakPropertyValues.get(name); - if (v != null) { - byte vv = v.byteValue(); - columnHeader[columnNumber] = vv; - columnMap[vv] = columnNumber; - } else { - throw new Exception(breakPairFileName + ':' + lineNumber + ": unknown column header " + name); + + for (int i = 0; i < lineTokens.length; ++i) { + name = lineTokens[i]; + if (name.length() > 0) { + if (columnNumber >= columnHeader.length) { + throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected column header " + name); + } + if (notInPairTableMap.get(name) != null) { + throw new Exception(breakPairFileName + ':' + lineNumber + ": invalid column header " + name); + } + Byte v = (Byte)lineBreakPropertyValues.get(name); + if (v != null) { + byte vv = v.byteValue(); + columnHeader[columnNumber] = vv; + columnMap[vv] = columnNumber; + } else { + throw new Exception(breakPairFileName + ':' + lineNumber + ": unknown column header " + name); + } + columnNumber++; } - columnNumber++; } if (columnNumber < columnHeader.length) { StringBuffer missing = new StringBuffer(); @@ -156,9 +161,9 @@ public class GenerateLineBreakUtils { throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected row " + line); } pairTable[rowNumber] = new byte[tableSize]; - StringTokenizer tok = new StringTokenizer(line); - if (tok.hasMoreTokens()) { - String name = tok.nextToken(); + lineTokens = line.split("\\s+"); + if (lineTokens.length > 0) { + name = lineTokens[0]; if (notInPairTableMap.get(name) != null) { throw new Exception(breakPairFileName + ':' + lineNumber + ": invalid row header " + name); } @@ -174,27 +179,15 @@ public class GenerateLineBreakUtils { throw new Exception(breakPairFileName + ':' + lineNumber + ": can't read row header"); } int columnNumber = 0; - while (tok.hasMoreTokens()) { - String token = tok.nextToken(); + String token; + for (int i = 1; i < lineTokens.length; ++i) { + token = lineTokens[i]; if (token.length() == 1) { - switch (token.charAt(0)) { - case '^' : - pairTable[rowNumber][columnNumber] = PROHIBITED_BREAK; - break; - case '%' : - pairTable[rowNumber][columnNumber] = INDIRECT_BREAK; - break; - case '_' : - pairTable[rowNumber][columnNumber] = DIRECT_BREAK; - break; - case '#' : - pairTable[rowNumber][columnNumber] = COMBINING_INDIRECT_BREAK; - break; - case '@' : - pairTable[rowNumber][columnNumber] = COMBINING_PROHIBITED_BREAK; - break; - default : - throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected token: " + token); + byte tokenBreakClass = (byte)BREAK_CLASS_TOKENS.indexOf(token.charAt(0)); + if (tokenBreakClass >= 0) { + pairTable[rowNumber][columnNumber] = tokenBreakClass; + } else { + throw new Exception(breakPairFileName + ':' + lineNumber + ": unexpected token: " + token); } } else { throw new Exception(breakPairFileName + ':' + lineNumber + ": token too long: " + token); @@ -255,23 +248,35 @@ public class GenerateLineBreakUtils { out.println("package org.apache.fop.text.linebreak;"); out.println(); out.println("/* "); - out.println(" * This is a generated file, DO NOT CHANGE!"); + out.println(" * !!! THIS IS A GENERATED FILE !!! "); + out.println(" * If updates to the source are needed, then:"); + out.println(" * - apply the necessary modifications to "); + out.println(" * 'src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java'"); + out.println(" * - run 'ant codegen-unicode', which will generate a new LineBreakUtils.java"); + out.println(" * in 'src/java/org/apache/fop/text/linebreak'"); + out.println(" * - commit BOTH changed files"); out.println(" */"); out.println(); - out.println("class LineBreakUtils {"); + out.println("public final class LineBreakUtils {"); out.println(); + out.println(" /** Break class constant */"); out.println(" public static final byte DIRECT_BREAK = " + DIRECT_BREAK + ';'); + out.println(" /** Break class constant */"); out.println(" public static final byte INDIRECT_BREAK = " + INDIRECT_BREAK + ';'); + out.println(" /** Break class constant */"); out.println(" public static final byte COMBINING_INDIRECT_BREAK = " + COMBINING_INDIRECT_BREAK + ';'); + out.println(" /** Break class constant */"); out.println(" public static final byte COMBINING_PROHIBITED_BREAK = " + COMBINING_PROHIBITED_BREAK + ';'); + out.println(" /** Break class constant */"); out.println(" public static final byte PROHIBITED_BREAK = " + PROHIBITED_BREAK + ';'); + out.println(" /** Break class constant */"); out.println(" public static final byte EXPLICIT_BREAK = " + EXPLICIT_BREAK + ';'); out.println(); out.println(" private static final byte PAIR_TABLE[][] = {"); boolean printComma = false; for (int i = 1; i <= lineBreakPropertyValueCount; i++) { if (printComma) { - out.println(','); + out.println(", "); } else { printComma = true; } @@ -279,7 +284,7 @@ public class GenerateLineBreakUtils { boolean localPrintComma = false; for (int j = 1; j <= lineBreakPropertyValueCount; j++) { if (localPrintComma) { - out.print(','); + out.print(", "); } else { localPrintComma = true; } @@ -313,7 +318,7 @@ public class GenerateLineBreakUtils { found = true; doStaticLinkCode.append(" lineBreakProperties["); doStaticLinkCode.append(i); - doStaticLinkCode.append("]=lineBreakProperties["); + doStaticLinkCode.append("] = lineBreakProperties["); doStaticLinkCode.append(j); doStaticLinkCode.append("];\n"); break; @@ -322,7 +327,7 @@ public class GenerateLineBreakUtils { } if (!found) { if (rowsPrinted >= 64) { - out.println(" };"); + out.println(" }"); out.println(); initSections++; out.println(" private static void init_" + initSections + "() {"); @@ -334,7 +339,7 @@ public class GenerateLineBreakUtils { for (int k = 0; k < blocksize; k++) { row[i][k] = lineBreakProperties[idx + k]; if (printLocalComma) { - out.print(','); + out.print(", "); } else { printLocalComma = true; } @@ -345,20 +350,21 @@ public class GenerateLineBreakUtils { } idx += blocksize; } - out.println(" };"); + out.println(" }"); out.println(); out.println(" static {"); for (int i = 0; i <= initSections; i++) { out.println(" init_" + i + "();"); } out.print(doStaticLinkCode); - out.println(" };"); + out.println(" }"); out.println(); for (int i = 0; i < lineBreakPropertyShortNames.size(); i++) { String shortName = (String)lineBreakPropertyShortNames.get(i); + out.println(" /** Linebreak property constant */"); out.print(" public static final byte LINE_BREAK_PROPERTY_"); out.print(shortName); - out.print('='); + out.print(" = "); out.print(i + 1); out.println(';'); } @@ -368,9 +374,9 @@ public class GenerateLineBreakUtils { int lineLength = shortNamePrefix.length(); printComma = false; for (int i = 0; i < lineBreakPropertyShortNames.size(); i++) { - String name = (String)lineBreakPropertyShortNames.get(i); + name = (String)lineBreakPropertyShortNames.get(i); if (printComma) { - out.print(','); + out.print(", "); lineLength++; } else { printComma = true; @@ -392,7 +398,7 @@ public class GenerateLineBreakUtils { lineLength = longNamePrefix.length(); printComma = false; for (int i = 0; i < lineBreakPropertyLongNames.size(); i++) { - String name = (String)lineBreakPropertyLongNames.get(i); + name = (String)lineBreakPropertyLongNames.get(i); if (printComma) { out.print(','); lineLength++; @@ -411,32 +417,62 @@ public class GenerateLineBreakUtils { } out.println("};"); out.println(); + out.println(" /**"); + out.println(" * Return the short name for the linebreak property corresponding "); + out.println(" * to the given symbolic constant."); + out.println(" *"); + out.println(" * @param i the numeric value of the linebreak property"); + out.println(" * @return the short name of the linebreak property"); + out.println(" */"); out.println(" public static String getLineBreakPropertyShortName(byte i) {"); - out.println(" if (i>0 && i<=lineBreakPropertyShortNames.length) {"); - out.println(" return lineBreakPropertyShortNames[i-1];"); + out.println(" if (i > 0 && i <= lineBreakPropertyShortNames.length) {"); + out.println(" return lineBreakPropertyShortNames[i - 1];"); out.println(" } else {"); out.println(" return null;"); out.println(" }"); out.println(" }"); out.println(); + out.println(" /**"); + out.println(" * Return the long name for the linebreak property corresponding "); + out.println(" * to the given symbolic constant."); + out.println(" *"); + out.println(" * @param i the numeric value of the linebreak property"); + out.println(" * @return the long name of the linebreak property"); + out.println(" */"); out.println(" public static String getLineBreakPropertyLongName(byte i) {"); - out.println(" if (i>0 && i<=lineBreakPropertyLongNames.length) {"); - out.println(" return lineBreakPropertyLongNames[i-1];"); + out.println(" if (i > 0 && i <= lineBreakPropertyLongNames.length) {"); + out.println(" return lineBreakPropertyLongNames[i - 1];"); out.println(" } else {"); out.println(" return null;"); out.println(" }"); out.println(" }"); out.println(); + out.println(" /**"); + out.println(" * Return the linebreak property constant for the given char"); + out.println(" *"); + out.println(" * @param c the char whose linebreak property to return"); + out.println(" * @return the constant representing the linebreak property"); + out.println(" */"); out.println(" public static byte getLineBreakProperty(char c) {"); - out.println(" return lineBreakProperties[c/" + blocksize + "][c%" + blocksize + "];"); + out.println(" return lineBreakProperties[c / " + blocksize + "][c % " + blocksize + "];"); out.println(" }"); out.println(); + out.println(" /**"); + out.println(" * Return the break class constant for the given pair of linebreak "); + out.println(" * property constants."); + out.println(" *"); + out.println(" * @param lineBreakPropertyBefore the linebreak property for the first character"); + out.println(" * in a two-character sequence"); + out.println(" * @param lineBreakPropertyAfter the linebreak property for the second character"); + out.println(" * in a two-character sequence"); + out.println(" * @return the constant representing the break class"); + out.println(" */"); out.println( - " public static byte getLineBreakPairProperty(int lineBreakPropertyBefore,int lineBreakPropertyAfter) {"); - out.println(" return PAIR_TABLE[lineBreakPropertyBefore-1][lineBreakPropertyAfter-1];"); + " public static byte getLineBreakPairProperty(int lineBreakPropertyBefore, int lineBreakPropertyAfter) {"); + out.println(" return PAIR_TABLE[lineBreakPropertyBefore - 1][lineBreakPropertyAfter - 1];"); out.println(" }"); out.println(); - out.println("};"); + out.println("}"); out.flush(); out.close(); } diff --git a/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java b/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java index 30883ffb2..5e84e1004 100644 --- a/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java +++ b/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java @@ -20,621 +20,669 @@ package org.apache.fop.text.linebreak; /* - * This is a generated file, DO NOT CHANGE! + * !!! THIS IS A GENERATED FILE !!! + * If updates to the source are needed, then: + * - apply the necessary modifications to + * 'src/codegen/unicode/java/org/apache/fop/text/linebreak/GenerateLineBreakUtils.java' + * - run 'ant codegen-unicode', which will generate a new LineBreakUtils.java + * in 'src/java/org/apache/fop/text/linebreak' + * - commit BOTH changed files */ -class LineBreakUtils { +public final class LineBreakUtils { + /** Break class constant */ public static final byte DIRECT_BREAK = 0; + /** Break class constant */ public static final byte INDIRECT_BREAK = 1; + /** Break class constant */ public static final byte COMBINING_INDIRECT_BREAK = 2; + /** Break class constant */ public static final byte COMBINING_PROHIBITED_BREAK = 3; + /** Break class constant */ public static final byte PROHIBITED_BREAK = 4; + /** Break class constant */ public static final byte EXPLICIT_BREAK = 5; private static final byte PAIR_TABLE[][] = { - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,1,1,0,0,1,0,0,0,4,4,0,4}, - {0,0,4,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,1,1,1,0,0,4,2,0,4,1,1,1,1,1,1,4,1,1,1,0,0,1,1,1,1,1,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,4,1,0,1,1,1,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,1,0,0,0,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,1,1,1,0,0,4,2,0,4,1,1,1,1,1,1,4,1,1,1,0,0,1,1,1,1,1,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,1,1,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,1,0,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,1,0,0,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,1,0,0,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,1,1,1,0,1,4,1,0,1,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,1,0,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,1,1,0,0,1,0,0,1,0,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,1,4,0,0,0,0,0,1,1,1,1,1,1,0,0,0,4,4,0,4}, - {0,4,4,4,4,0,0,4,3,0,4,4,4,4,4,4,4,4,4,4,4,0,0,4,4,4,4,4,4,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,1,1,0,0,1,0,0,0,4,4,0,4}, - {0,1,0,1,0,0,0,4,2,0,4,1,1,1,1,1,0,4,1,1,1,0,0,1,1,1,0,0,1,0,0,0,4,4,0,4}, - {0,1,1,1,1,0,0,4,2,0,4,1,1,1,1,1,1,4,1,1,1,0,0,1,1,4,1,1,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,1,0,0,0,4,2,0,4,1,0,0,1,0,0,4,0,0,0,0,0,1,1,0,0,0,1,0,0,0,4,4,0,4}, - {0,1,1,1,1,0,0,4,2,0,4,1,1,1,1,1,1,4,1,1,1,0,0,1,1,1,1,1,1,0,0,0,4,4,0,4}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4}}; + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 4, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 1, 1, 1, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 4, 1, 0, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 1, 1, 1, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 0, 1, 4, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 1, 4, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 4, 4, 4, 4, 0, 0, 4, 3, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 0, 4, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 1, 1, 1, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 0, 0, 1, 1, 4, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 4, 2, 0, 4, 1, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 1, 1, 1, 1, 0, 0, 4, 2, 0, 4, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 4, 4, 0, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}}; private static byte lineBreakProperties[][] = new byte[512][]; private static void init_0() { - lineBreakProperties[0] = new byte[] { 9,9,9,9,9,9,9,9,9,4,22,6,6,10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,32,11,29,2,28,27,2,29,26,8,2,28,18,15,18,33,25,25,25,25,25,25,25,25,25,25,18,18,2,2,2,11,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,28,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,4,8,2,9}; - lineBreakProperties[1] = new byte[] { 9,9,9,9,9,23,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,12,1,27,28,28,28,2,1,1,2,1,29,2,4,2,2,27,28,1,1,5,2,1,1,1,1,1,29,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2}; - lineBreakProperties[2] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[5] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,5,1,1,1,5,1,2,2,1,2,2,2,2,2,2,2,1,1,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[6] = new byte[] { 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,12,9,9,9,9,9,9,9,9,9,9,9,9,12,12,12,12,12,12,12,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,2,2,0,0,0,0,2,2,2,2,18,0}; - lineBreakProperties[7] = new byte[] { 0,0,0,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[9] = new byte[] { 2,2,2,9,9,9,9,0,9,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[10] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[11] = new byte[] { 2,2,2,2,2,2,2,2,0,18,4,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,4,9,2,9,9,2,9,9,11,9,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[12] = new byte[] { 2,2,2,2,0,0,0,0,0,0,0,27,11,18,2,2,9,9,9,9,9,9,0,0,0,0,0,11,0,0,11,11,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,25,25,25,25,25,25,25,25,25,25,11,25,25,2,2,2,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[13] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,11,2,9,9,9,9,9,9,9,2,9,9,9,9,9,9,9,2,2,9,9,2,9,9,9,9,2,2,25,25,25,25,25,25,25,25,25,25,2,2,2,2,2,2}; - lineBreakProperties[14] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[15] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,2,2,2,2,18,11,2,0,0,0,0,0}; - lineBreakProperties[16] = new byte[] { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[18] = new byte[] { 0,9,9,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,9,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,2,9,9,9,9,0,0,0,2,2,2,2,2,2,2,2,2,2,9,9,4,4,25,25,25,25,25,25,25,25,25,25,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2}; - lineBreakProperties[19] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,2,2,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,0,0,0,2,2,2,2,0,0,9,2,9,9,9,9,9,9,9,0,0,9,9,0,0,9,9,9,2,0,0,0,0,0,0,0,0,9,0,0,0,0,2,2,0,2,2,2,9,9,0,0,25,25,25,25,25,25,25,25,25,25,2,2,28,28,2,2,2,2,2,2,2,0,0,0,0,0}; - lineBreakProperties[20] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,0,0,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,0,2,2,0,0,9,0,9,9,9,9,9,0,0,0,0,9,9,0,0,9,9,9,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0,2,0,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,9,9,2,2,2,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[21] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,0,0,9,2,9,9,9,9,9,9,9,9,0,9,9,9,0,9,9,9,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,9,9,0,0,25,25,25,25,25,25,25,25,25,25,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[22] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,2,2,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,0,0,9,2,9,9,9,9,9,9,0,0,0,9,9,0,0,9,9,9,0,0,0,0,0,0,0,0,9,9,0,0,0,0,2,2,0,2,2,2,0,0,0,0,25,25,25,25,25,25,25,25,25,25,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[23] = new byte[] { 0,0,9,2,0,2,2,2,2,2,2,0,0,0,2,2,2,0,2,2,2,2,0,0,0,2,2,0,2,0,2,2,0,0,0,2,2,0,0,0,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,9,9,9,9,9,0,0,0,9,9,9,0,9,9,9,9,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,2,2,2,2,2,2,2,2,2,28,2,0,0,0,0,0}; - lineBreakProperties[24] = new byte[] { 0,9,9,9,0,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,0,0,0,9,9,9,9,9,9,9,0,9,9,9,0,9,9,9,9,0,0,0,0,0,0,0,9,9,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[25] = new byte[] { 0,0,9,9,0,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,0,9,2,9,9,9,9,9,9,9,0,9,9,9,0,9,9,9,9,0,0,0,0,0,0,0,9,9,0,0,0,0,0,0,0,2,0,2,2,9,9,0,0,25,25,25,25,25,25,25,25,25,25,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[26] = new byte[] { 0,0,9,9,0,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,9,9,9,9,9,9,0,0,9,9,9,0,9,9,9,9,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,2,2,0,0,0,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[27] = new byte[] { 0,0,9,9,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,0,2,0,0,2,2,2,2,2,2,2,0,0,0,9,0,0,0,0,9,9,9,9,9,9,0,9,0,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,2,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[28] = new byte[] { 0,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,0,0,0,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,2,25,25,25,25,25,25,25,25,25,25,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[29] = new byte[] { 0,30,30,0,30,0,0,30,30,0,30,0,0,30,0,0,0,0,0,0,30,30,30,30,0,30,30,30,30,30,30,30,0,30,30,30,0,30,0,30,0,0,30,30,0,30,30,30,30,30,30,30,30,30,30,30,30,30,0,30,30,30,0,0,30,30,30,30,30,0,30,0,30,30,30,30,30,30,0,0,25,25,25,25,25,25,25,25,25,25,0,0,30,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[30] = new byte[] { 2,5,5,5,5,2,5,5,12,5,5,4,12,11,11,11,11,11,12,2,11,2,2,2,9,9,2,2,2,2,2,2,25,25,25,25,25,25,25,25,25,25,2,2,2,2,2,2,2,2,2,2,4,9,2,9,2,9,26,8,26,8,9,9,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,4}; - lineBreakProperties[31] = new byte[] { 9,9,9,9,9,4,9,9,2,2,2,2,0,0,0,0,9,9,9,9,9,9,9,9,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,4,4,2,2,2,2,2,2,9,2,2,2,2,2,2,0,0,2,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[32] = new byte[] { 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,30,30,30,30,30,0,30,30,0,30,30,30,30,30,30,30,0,0,0,30,30,30,30,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,4,4,2,2,2,2,30,30,30,30,30,30,30,30,30,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[33] = new byte[] { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0}; - lineBreakProperties[34] = new byte[] { 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,0,0,0,0,0,19,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21}; - lineBreakProperties[35] = new byte[] { 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,0,0,0,0,0,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0}; - lineBreakProperties[36] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[37] = new byte[] { 2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[38] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,9,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0}; - lineBreakProperties[39] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[40] = new byte[] { 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[44] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[45] = new byte[] { 4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[46] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,9,9,9,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,4,4,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,0,9,9,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[47] = new byte[] { 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,4,4,24,30,4,2,4,28,30,30,0,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0}; - lineBreakProperties[48] = new byte[] { 2,2,4,4,4,4,5,2,4,4,2,9,9,9,12,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0}; - lineBreakProperties[49] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[50] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,2,0,0,0,11,11,25,25,25,25,25,25,25,25,25,25,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,0,30,30,30,30,30,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[51] = new byte[] { 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,0,0,0,0,0,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,0,0,0,0,0,0,25,25,25,25,25,25,25,25,25,25,0,0,0,0,30,30,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[52] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,0,0,4,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[54] = new byte[] { 9,9,9,9,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,2,2,2,2,2,2,2,0,0,0,0,25,25,25,25,25,25,25,25,25,25,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,2,2,2,2,2,2,2,2,2,0,0,0}; - lineBreakProperties[59] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9}; - lineBreakProperties[61] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0}; - lineBreakProperties[62] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,0,2,0,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0}; - lineBreakProperties[63] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,0,2,2,2,2,2,2,2,2,2,0}; - lineBreakProperties[64] = new byte[] { 4,4,4,4,4,4,4,12,4,4,4,36,9,9,9,9,4,12,4,4,3,1,1,2,29,29,26,29,29,29,26,29,1,1,2,2,17,17,17,4,6,6,9,9,9,9,9,12,27,27,27,27,27,27,27,27,2,29,29,1,24,24,2,2,2,2,2,2,18,26,8,24,24,24,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4,2,4,4,4,34,2,2,2,0,0,0,0,0,0,9,9,9,9,9,9,2,2,0,0,1,2,2,2,2,2,2,2,2,26,8,1}; - lineBreakProperties[65] = new byte[] { 2,1,1,1,1,2,2,2,2,2,2,2,2,26,8,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,28,28,28,28,28,28,28,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[66] = new byte[] { 2,2,2,27,2,1,2,2,2,27,2,2,2,2,2,2,2,2,2,1,2,2,28,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,1,1,2,2,2,2,2,1,2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2}; - lineBreakProperties[67] = new byte[] { 2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[68] = new byte[] { 1,2,1,1,2,2,2,1,1,2,2,1,2,2,2,1,2,1,28,28,2,1,2,2,2,2,1,2,2,1,1,1,1,2,2,1,2,1,2,1,1,1,1,1,1,2,1,2,2,2,2,2,1,1,1,1,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,1,2,2,2,1,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,2,1,1,1,1,2,2,1,1,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[69] = new byte[] { 2,2,1,1,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[70] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[71] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[72] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - lineBreakProperties[73] = new byte[] { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2}; - lineBreakProperties[74] = new byte[] { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[75] = new byte[] { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,1,1,2,2,1,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[76] = new byte[] { 2,2,2,2,2,1,1,2,2,1,2,2,2,2,1,1,2,2,2,2,1,1,1,1,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,1,1,1,2,1,1,1,1,2,1,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - }; + lineBreakProperties[0] = new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 22, 6, 6, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 11, 29, 2, 28, 27, 2, 29, 26, 8, 2, 28, 18, 15, 18, 33, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 28, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 4, 8, 2, 9}; + lineBreakProperties[1] = new byte[] { 9, 9, 9, 9, 9, 23, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 26, 27, 28, 28, 28, 2, 1, 1, 2, 1, 29, 2, 4, 2, 2, 27, 28, 1, 1, 5, 2, 1, 1, 1, 1, 1, 29, 1, 1, 1, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[2] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[5] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 5, 1, 1, 1, 5, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 1, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[6] = new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 12, 12, 12, 12, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 18, 0}; + lineBreakProperties[7] = new byte[] { 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[9] = new byte[] { 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[10] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[11] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 0, 18, 4, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 9, 2, 9, 9, 2, 9, 9, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[12] = new byte[] { 2, 2, 2, 2, 0, 0, 2, 2, 2, 27, 27, 27, 18, 18, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 0, 0, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 27, 25, 25, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[13] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 11, 2, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 2, 9, 9, 9, 9, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[14] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[15] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 18, 11, 2, 0, 0, 0, 0, 0}; + lineBreakProperties[16] = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[18] = new byte[] { 0, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 2, 9, 9, 9, 9, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 4, 4, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2}; + lineBreakProperties[19] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 28, 28, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0}; + lineBreakProperties[20] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 9, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 9, 9, 2, 2, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[21] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[22] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[23] = new byte[] { 0, 0, 9, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0, 2, 0, 2, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 28, 2, 0, 0, 0, 0, 0}; + lineBreakProperties[24] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[25] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[26] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[27] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[28] = new byte[] { 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[29] = new byte[] { 0, 30, 30, 0, 30, 0, 0, 30, 30, 0, 30, 0, 0, 30, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 0, 30, 0, 30, 0, 0, 30, 30, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 30, 30, 30, 0, 0, 30, 30, 30, 30, 30, 0, 30, 0, 30, 30, 30, 30, 30, 30, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[30] = new byte[] { 2, 5, 5, 5, 5, 2, 5, 5, 12, 5, 5, 4, 12, 11, 11, 11, 11, 11, 12, 2, 11, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 9, 2, 9, 2, 9, 26, 8, 26, 8, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4}; + lineBreakProperties[31] = new byte[] { 9, 9, 9, 9, 9, 4, 9, 9, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 4, 4, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 0, 2, 2, 5, 5, 4, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[32] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 4, 4, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}; + lineBreakProperties[33] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 30, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; + lineBreakProperties[34] = new byte[] { 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 19, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}; + lineBreakProperties[35] = new byte[] { 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[36] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[37] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[38] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; + lineBreakProperties[39] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[40] = new byte[] { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[44] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[45] = new byte[] { 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[46] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[47] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 4, 4, 24, 30, 4, 2, 4, 28, 30, 30, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[48] = new byte[] { 2, 2, 11, 11, 4, 4, 5, 2, 11, 11, 2, 9, 9, 9, 12, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[49] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[50] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 2, 0, 0, 0, 11, 11, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[51] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 30, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[52] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[54] = new byte[] { 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; + lineBreakProperties[55] = new byte[] { 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[56] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 4, 4, 4, 4, 4, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4}; + lineBreakProperties[59] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9}; + lineBreakProperties[62] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0}; + lineBreakProperties[63] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 5, 2, 0}; + lineBreakProperties[64] = new byte[] { 4, 4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 36, 9, 9, 9, 9, 4, 12, 4, 4, 3, 1, 1, 2, 29, 29, 26, 29, 29, 29, 26, 29, 1, 1, 2, 2, 17, 17, 17, 4, 6, 6, 9, 9, 9, 9, 9, 12, 27, 27, 27, 27, 27, 27, 27, 27, 2, 29, 29, 1, 24, 24, 2, 2, 2, 2, 2, 2, 18, 26, 8, 24, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 4, 4, 4, 4, 2, 4, 4, 4, 34, 2, 2, 2, 2, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 2, 2, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 1}; + lineBreakProperties[65] = new byte[] { 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 28, 28, 28, 28, 28, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[66] = new byte[] { 2, 2, 2, 27, 2, 1, 2, 2, 2, 27, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[67] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[68] = new byte[] { 1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 28, 28, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[69] = new byte[] { 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[70] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[71] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[72] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + lineBreakProperties[73] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}; + lineBreakProperties[74] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[75] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + } private static void init_1() { - lineBreakProperties[77] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[78] = new byte[] { 0,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,0,2,0,2,2,2,29,29,29,29,0,0,2,11,11,2,2,2,2,26,8,26,8,26,8,26,8,26,8,26,8,26,8,1,1,1,1,1,1,1,1,1,1}; - lineBreakProperties[79] = new byte[] { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,26,8,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,26,8,26,8,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[83] = new byte[] { 2,2,2,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,26,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,2,2}; - lineBreakProperties[86] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[88] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0}; - lineBreakProperties[89] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,2,4,4}; - lineBreakProperties[90] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[91] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[92] = new byte[] { 29,29,29,29,29,29,29,29,29,29,29,29,29,29,4,4,4,4,4,4,4,4,2,4,0,0,0,0,29,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[93] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[94] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[95] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0}; - lineBreakProperties[96] = new byte[] { 16,8,8,16,16,24,16,16,26,8,26,8,26,8,26,8,26,8,16,16,26,8,26,8,26,8,26,8,24,26,8,8,16,16,16,16,16,16,16,16,16,16,9,9,9,9,9,9,16,16,16,16,16,16,16,16,16,16,16,24,24,16,16,16,0,24,16,24,16,24,16,24,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[97] = new byte[] { 16,16,16,24,16,24,16,24,16,16,16,16,16,16,24,16,16,16,16,16,16,24,24,0,0,9,9,24,24,24,24,16,24,24,16,24,16,24,16,24,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,16,24,16,24,16,16,16,16,16,16,24,16,16,16,16,16,16,24,24,16,16,16,16,24,24,24,24,16}; - lineBreakProperties[98] = new byte[] { 0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[99] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24}; - lineBreakProperties[100] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[101] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0}; - lineBreakProperties[155] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[319] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[320] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[329] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[334] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[336] = new byte[] { 2,2,9,2,2,2,9,2,2,2,2,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9,9,9,9,9,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,5,11,11,0,0,0,0,0,0,0,0}; - lineBreakProperties[344] = new byte[] { 13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[345] = new byte[] { 14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14}; - lineBreakProperties[346] = new byte[] { 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[347] = new byte[] { 14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14}; - lineBreakProperties[348] = new byte[] { 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[349] = new byte[] { 14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[350] = new byte[] { 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - lineBreakProperties[431] = new byte[] { 14,14,14,14,14,14,14,14,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[432] = new byte[] { 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31}; - lineBreakProperties[448] = new byte[] { 35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35}; - lineBreakProperties[500] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}; - lineBreakProperties[501] = new byte[] { 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - lineBreakProperties[502] = new byte[] { 2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,2,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,2,0,2,2,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[503] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[506] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,26,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[507] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,27,2,0,0}; - lineBreakProperties[508] = new byte[] { 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,18,8,8,18,18,11,11,26,8,17,0,0,0,0,0,0,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,26,8,26,8,26,8,26,8,26,8,26,8,26,8,26,8,16,16,26,8,16,16,16,16,16,16,16,8,16,8,0,24,24,11,11,16,26,8,26,8,26,8,16,16,16,16,16,16,16,16,0,16,28,27,16,0,0,0,0,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[509] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,34}; - lineBreakProperties[510] = new byte[] { 0,11,16,16,28,27,16,16,26,8,16,16,8,16,8,16,16,16,16,16,16,16,16,16,16,16,24,24,16,16,16,11,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,26,16,8,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,26,16,8,16,26,8,8,26,8,8,24,2,24,24,24,24,24,24,24,24,24,24,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - lineBreakProperties[511] = new byte[] { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,24,24,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,0,0,0,27,28,16,16,16,28,28,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,9,9,9,7,1,0,0}; - }; + lineBreakProperties[76] = new byte[] { 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[77] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[78] = new byte[] { 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 0, 2, 2, 2, 29, 29, 29, 29, 0, 0, 2, 11, 11, 2, 2, 2, 2, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + lineBreakProperties[79] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 26, 8, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[83] = new byte[] { 2, 2, 2, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 26, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 2, 2}; + lineBreakProperties[86] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[88] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0}; + lineBreakProperties[89] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 4, 4, 4, 2, 11, 4}; + lineBreakProperties[90] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[91] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; + lineBreakProperties[92] = new byte[] { 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 26, 4, 2, 2, 29, 29, 2, 2, 29, 29, 26, 8, 26, 8, 26, 8, 26, 8, 4, 4, 4, 4, 11, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[93] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[94] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[95] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0}; + lineBreakProperties[96] = new byte[] { 16, 8, 8, 16, 16, 24, 16, 16, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 16, 16, 26, 8, 26, 8, 26, 8, 26, 8, 24, 26, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 9, 9, 9, 9, 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 16, 16, 16, 0, 24, 16, 24, 16, 24, 16, 24, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[97] = new byte[] { 16, 16, 16, 24, 16, 24, 16, 24, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 24, 24, 0, 0, 9, 9, 24, 24, 24, 24, 16, 24, 24, 16, 24, 16, 24, 16, 24, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 16, 24, 16, 24, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 24, 24, 16, 16, 16, 16, 24, 24, 24, 24, 16}; + lineBreakProperties[98] = new byte[] { 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[99] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24}; + lineBreakProperties[100] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[101] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0}; + lineBreakProperties[155] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[319] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[320] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[329] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[332] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 11, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 2, 2}; + lineBreakProperties[333] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[335] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2}; + lineBreakProperties[336] = new byte[] { 2, 2, 9, 2, 2, 2, 9, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[337] = new byte[] { 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[338] = new byte[] { 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[340] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 2, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[344] = new byte[] { 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[345] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14}; + lineBreakProperties[346] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[347] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[348] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[349] = new byte[] { 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[350] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + lineBreakProperties[431] = new byte[] { 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[432] = new byte[] { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}; + lineBreakProperties[448] = new byte[] { 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35}; + lineBreakProperties[500] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + lineBreakProperties[501] = new byte[] { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[502] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[503] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[506] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[507] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 2, 0, 0}; + lineBreakProperties[508] = new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 8, 8, 18, 18, 11, 11, 26, 8, 17, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 26, 8, 16, 16, 26, 8, 16, 16, 16, 16, 16, 16, 16, 8, 16, 8, 0, 24, 24, 11, 11, 16, 26, 8, 26, 8, 26, 8, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 28, 27, 16, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[509] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 34}; + lineBreakProperties[510] = new byte[] { 0, 11, 16, 16, 28, 27, 16, 16, 26, 8, 16, 16, 8, 16, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 26, 16, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 26, 16, 8, 16, 26, 8, 8, 26, 8, 8, 24, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[511] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 27, 28, 16, 16, 16, 28, 28, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 7, 1, 0, 0}; + } static { init_0(); init_1(); - lineBreakProperties[3]=lineBreakProperties[2]; - lineBreakProperties[4]=lineBreakProperties[2]; - lineBreakProperties[8]=lineBreakProperties[2]; - lineBreakProperties[17]=lineBreakProperties[16]; - lineBreakProperties[41]=lineBreakProperties[2]; - lineBreakProperties[42]=lineBreakProperties[2]; - lineBreakProperties[43]=lineBreakProperties[2]; - lineBreakProperties[53]=lineBreakProperties[16]; - lineBreakProperties[55]=lineBreakProperties[16]; - lineBreakProperties[56]=lineBreakProperties[16]; - lineBreakProperties[57]=lineBreakProperties[16]; - lineBreakProperties[58]=lineBreakProperties[2]; - lineBreakProperties[60]=lineBreakProperties[2]; - lineBreakProperties[80]=lineBreakProperties[2]; - lineBreakProperties[81]=lineBreakProperties[2]; - lineBreakProperties[82]=lineBreakProperties[2]; - lineBreakProperties[84]=lineBreakProperties[2]; - lineBreakProperties[85]=lineBreakProperties[2]; - lineBreakProperties[87]=lineBreakProperties[16]; - lineBreakProperties[102]=lineBreakProperties[94]; - lineBreakProperties[103]=lineBreakProperties[94]; - lineBreakProperties[104]=lineBreakProperties[94]; - lineBreakProperties[105]=lineBreakProperties[94]; - lineBreakProperties[106]=lineBreakProperties[94]; - lineBreakProperties[107]=lineBreakProperties[94]; - lineBreakProperties[108]=lineBreakProperties[94]; - lineBreakProperties[109]=lineBreakProperties[94]; - lineBreakProperties[110]=lineBreakProperties[94]; - lineBreakProperties[111]=lineBreakProperties[94]; - lineBreakProperties[112]=lineBreakProperties[94]; - lineBreakProperties[113]=lineBreakProperties[94]; - lineBreakProperties[114]=lineBreakProperties[94]; - lineBreakProperties[115]=lineBreakProperties[94]; - lineBreakProperties[116]=lineBreakProperties[94]; - lineBreakProperties[117]=lineBreakProperties[94]; - lineBreakProperties[118]=lineBreakProperties[94]; - lineBreakProperties[119]=lineBreakProperties[94]; - lineBreakProperties[120]=lineBreakProperties[94]; - lineBreakProperties[121]=lineBreakProperties[94]; - lineBreakProperties[122]=lineBreakProperties[94]; - lineBreakProperties[123]=lineBreakProperties[94]; - lineBreakProperties[124]=lineBreakProperties[94]; - lineBreakProperties[125]=lineBreakProperties[94]; - lineBreakProperties[126]=lineBreakProperties[94]; - lineBreakProperties[127]=lineBreakProperties[94]; - lineBreakProperties[128]=lineBreakProperties[94]; - lineBreakProperties[129]=lineBreakProperties[94]; - lineBreakProperties[130]=lineBreakProperties[94]; - lineBreakProperties[131]=lineBreakProperties[94]; - lineBreakProperties[132]=lineBreakProperties[94]; - lineBreakProperties[133]=lineBreakProperties[94]; - lineBreakProperties[134]=lineBreakProperties[94]; - lineBreakProperties[135]=lineBreakProperties[94]; - lineBreakProperties[136]=lineBreakProperties[94]; - lineBreakProperties[137]=lineBreakProperties[94]; - lineBreakProperties[138]=lineBreakProperties[94]; - lineBreakProperties[139]=lineBreakProperties[94]; - lineBreakProperties[140]=lineBreakProperties[94]; - lineBreakProperties[141]=lineBreakProperties[94]; - lineBreakProperties[142]=lineBreakProperties[94]; - lineBreakProperties[143]=lineBreakProperties[94]; - lineBreakProperties[144]=lineBreakProperties[94]; - lineBreakProperties[145]=lineBreakProperties[94]; - lineBreakProperties[146]=lineBreakProperties[94]; - lineBreakProperties[147]=lineBreakProperties[94]; - lineBreakProperties[148]=lineBreakProperties[94]; - lineBreakProperties[149]=lineBreakProperties[94]; - lineBreakProperties[150]=lineBreakProperties[94]; - lineBreakProperties[151]=lineBreakProperties[94]; - lineBreakProperties[152]=lineBreakProperties[94]; - lineBreakProperties[153]=lineBreakProperties[94]; - lineBreakProperties[154]=lineBreakProperties[94]; - lineBreakProperties[156]=lineBreakProperties[94]; - lineBreakProperties[157]=lineBreakProperties[94]; - lineBreakProperties[158]=lineBreakProperties[94]; - lineBreakProperties[159]=lineBreakProperties[94]; - lineBreakProperties[160]=lineBreakProperties[94]; - lineBreakProperties[161]=lineBreakProperties[94]; - lineBreakProperties[162]=lineBreakProperties[94]; - lineBreakProperties[163]=lineBreakProperties[94]; - lineBreakProperties[164]=lineBreakProperties[94]; - lineBreakProperties[165]=lineBreakProperties[94]; - lineBreakProperties[166]=lineBreakProperties[94]; - lineBreakProperties[167]=lineBreakProperties[94]; - lineBreakProperties[168]=lineBreakProperties[94]; - lineBreakProperties[169]=lineBreakProperties[94]; - lineBreakProperties[170]=lineBreakProperties[94]; - lineBreakProperties[171]=lineBreakProperties[94]; - lineBreakProperties[172]=lineBreakProperties[94]; - lineBreakProperties[173]=lineBreakProperties[94]; - lineBreakProperties[174]=lineBreakProperties[94]; - lineBreakProperties[175]=lineBreakProperties[94]; - lineBreakProperties[176]=lineBreakProperties[94]; - lineBreakProperties[177]=lineBreakProperties[94]; - lineBreakProperties[178]=lineBreakProperties[94]; - lineBreakProperties[179]=lineBreakProperties[94]; - lineBreakProperties[180]=lineBreakProperties[94]; - lineBreakProperties[181]=lineBreakProperties[94]; - lineBreakProperties[182]=lineBreakProperties[94]; - lineBreakProperties[183]=lineBreakProperties[94]; - lineBreakProperties[184]=lineBreakProperties[94]; - lineBreakProperties[185]=lineBreakProperties[94]; - lineBreakProperties[186]=lineBreakProperties[94]; - lineBreakProperties[187]=lineBreakProperties[94]; - lineBreakProperties[188]=lineBreakProperties[94]; - lineBreakProperties[189]=lineBreakProperties[94]; - lineBreakProperties[190]=lineBreakProperties[94]; - lineBreakProperties[191]=lineBreakProperties[94]; - lineBreakProperties[192]=lineBreakProperties[94]; - lineBreakProperties[193]=lineBreakProperties[94]; - lineBreakProperties[194]=lineBreakProperties[94]; - lineBreakProperties[195]=lineBreakProperties[94]; - lineBreakProperties[196]=lineBreakProperties[94]; - lineBreakProperties[197]=lineBreakProperties[94]; - lineBreakProperties[198]=lineBreakProperties[94]; - lineBreakProperties[199]=lineBreakProperties[94]; - lineBreakProperties[200]=lineBreakProperties[94]; - lineBreakProperties[201]=lineBreakProperties[94]; - lineBreakProperties[202]=lineBreakProperties[94]; - lineBreakProperties[203]=lineBreakProperties[94]; - lineBreakProperties[204]=lineBreakProperties[94]; - lineBreakProperties[205]=lineBreakProperties[94]; - lineBreakProperties[206]=lineBreakProperties[94]; - lineBreakProperties[207]=lineBreakProperties[94]; - lineBreakProperties[208]=lineBreakProperties[94]; - lineBreakProperties[209]=lineBreakProperties[94]; - lineBreakProperties[210]=lineBreakProperties[94]; - lineBreakProperties[211]=lineBreakProperties[94]; - lineBreakProperties[212]=lineBreakProperties[94]; - lineBreakProperties[213]=lineBreakProperties[94]; - lineBreakProperties[214]=lineBreakProperties[94]; - lineBreakProperties[215]=lineBreakProperties[94]; - lineBreakProperties[216]=lineBreakProperties[94]; - lineBreakProperties[217]=lineBreakProperties[94]; - lineBreakProperties[218]=lineBreakProperties[94]; - lineBreakProperties[219]=lineBreakProperties[94]; - lineBreakProperties[220]=lineBreakProperties[94]; - lineBreakProperties[221]=lineBreakProperties[94]; - lineBreakProperties[222]=lineBreakProperties[94]; - lineBreakProperties[223]=lineBreakProperties[94]; - lineBreakProperties[224]=lineBreakProperties[94]; - lineBreakProperties[225]=lineBreakProperties[94]; - lineBreakProperties[226]=lineBreakProperties[94]; - lineBreakProperties[227]=lineBreakProperties[94]; - lineBreakProperties[228]=lineBreakProperties[94]; - lineBreakProperties[229]=lineBreakProperties[94]; - lineBreakProperties[230]=lineBreakProperties[94]; - lineBreakProperties[231]=lineBreakProperties[94]; - lineBreakProperties[232]=lineBreakProperties[94]; - lineBreakProperties[233]=lineBreakProperties[94]; - lineBreakProperties[234]=lineBreakProperties[94]; - lineBreakProperties[235]=lineBreakProperties[94]; - lineBreakProperties[236]=lineBreakProperties[94]; - lineBreakProperties[237]=lineBreakProperties[94]; - lineBreakProperties[238]=lineBreakProperties[94]; - lineBreakProperties[239]=lineBreakProperties[94]; - lineBreakProperties[240]=lineBreakProperties[94]; - lineBreakProperties[241]=lineBreakProperties[94]; - lineBreakProperties[242]=lineBreakProperties[94]; - lineBreakProperties[243]=lineBreakProperties[94]; - lineBreakProperties[244]=lineBreakProperties[94]; - lineBreakProperties[245]=lineBreakProperties[94]; - lineBreakProperties[246]=lineBreakProperties[94]; - lineBreakProperties[247]=lineBreakProperties[94]; - lineBreakProperties[248]=lineBreakProperties[94]; - lineBreakProperties[249]=lineBreakProperties[94]; - lineBreakProperties[250]=lineBreakProperties[94]; - lineBreakProperties[251]=lineBreakProperties[94]; - lineBreakProperties[252]=lineBreakProperties[94]; - lineBreakProperties[253]=lineBreakProperties[94]; - lineBreakProperties[254]=lineBreakProperties[94]; - lineBreakProperties[255]=lineBreakProperties[94]; - lineBreakProperties[256]=lineBreakProperties[94]; - lineBreakProperties[257]=lineBreakProperties[94]; - lineBreakProperties[258]=lineBreakProperties[94]; - lineBreakProperties[259]=lineBreakProperties[94]; - lineBreakProperties[260]=lineBreakProperties[94]; - lineBreakProperties[261]=lineBreakProperties[94]; - lineBreakProperties[262]=lineBreakProperties[94]; - lineBreakProperties[263]=lineBreakProperties[94]; - lineBreakProperties[264]=lineBreakProperties[94]; - lineBreakProperties[265]=lineBreakProperties[94]; - lineBreakProperties[266]=lineBreakProperties[94]; - lineBreakProperties[267]=lineBreakProperties[94]; - lineBreakProperties[268]=lineBreakProperties[94]; - lineBreakProperties[269]=lineBreakProperties[94]; - lineBreakProperties[270]=lineBreakProperties[94]; - lineBreakProperties[271]=lineBreakProperties[94]; - lineBreakProperties[272]=lineBreakProperties[94]; - lineBreakProperties[273]=lineBreakProperties[94]; - lineBreakProperties[274]=lineBreakProperties[94]; - lineBreakProperties[275]=lineBreakProperties[94]; - lineBreakProperties[276]=lineBreakProperties[94]; - lineBreakProperties[277]=lineBreakProperties[94]; - lineBreakProperties[278]=lineBreakProperties[94]; - lineBreakProperties[279]=lineBreakProperties[94]; - lineBreakProperties[280]=lineBreakProperties[94]; - lineBreakProperties[281]=lineBreakProperties[94]; - lineBreakProperties[282]=lineBreakProperties[94]; - lineBreakProperties[283]=lineBreakProperties[94]; - lineBreakProperties[284]=lineBreakProperties[94]; - lineBreakProperties[285]=lineBreakProperties[94]; - lineBreakProperties[286]=lineBreakProperties[94]; - lineBreakProperties[287]=lineBreakProperties[94]; - lineBreakProperties[288]=lineBreakProperties[94]; - lineBreakProperties[289]=lineBreakProperties[94]; - lineBreakProperties[290]=lineBreakProperties[94]; - lineBreakProperties[291]=lineBreakProperties[94]; - lineBreakProperties[292]=lineBreakProperties[94]; - lineBreakProperties[293]=lineBreakProperties[94]; - lineBreakProperties[294]=lineBreakProperties[94]; - lineBreakProperties[295]=lineBreakProperties[94]; - lineBreakProperties[296]=lineBreakProperties[94]; - lineBreakProperties[297]=lineBreakProperties[94]; - lineBreakProperties[298]=lineBreakProperties[94]; - lineBreakProperties[299]=lineBreakProperties[94]; - lineBreakProperties[300]=lineBreakProperties[94]; - lineBreakProperties[301]=lineBreakProperties[94]; - lineBreakProperties[302]=lineBreakProperties[94]; - lineBreakProperties[303]=lineBreakProperties[94]; - lineBreakProperties[304]=lineBreakProperties[94]; - lineBreakProperties[305]=lineBreakProperties[94]; - lineBreakProperties[306]=lineBreakProperties[94]; - lineBreakProperties[307]=lineBreakProperties[94]; - lineBreakProperties[308]=lineBreakProperties[94]; - lineBreakProperties[309]=lineBreakProperties[94]; - lineBreakProperties[310]=lineBreakProperties[94]; - lineBreakProperties[311]=lineBreakProperties[94]; - lineBreakProperties[312]=lineBreakProperties[94]; - lineBreakProperties[313]=lineBreakProperties[94]; - lineBreakProperties[314]=lineBreakProperties[94]; - lineBreakProperties[315]=lineBreakProperties[94]; - lineBreakProperties[316]=lineBreakProperties[94]; - lineBreakProperties[317]=lineBreakProperties[94]; - lineBreakProperties[318]=lineBreakProperties[94]; - lineBreakProperties[321]=lineBreakProperties[94]; - lineBreakProperties[322]=lineBreakProperties[94]; - lineBreakProperties[323]=lineBreakProperties[94]; - lineBreakProperties[324]=lineBreakProperties[94]; - lineBreakProperties[325]=lineBreakProperties[94]; - lineBreakProperties[326]=lineBreakProperties[94]; - lineBreakProperties[327]=lineBreakProperties[94]; - lineBreakProperties[328]=lineBreakProperties[94]; - lineBreakProperties[330]=lineBreakProperties[16]; - lineBreakProperties[331]=lineBreakProperties[16]; - lineBreakProperties[332]=lineBreakProperties[16]; - lineBreakProperties[333]=lineBreakProperties[16]; - lineBreakProperties[335]=lineBreakProperties[16]; - lineBreakProperties[337]=lineBreakProperties[16]; - lineBreakProperties[338]=lineBreakProperties[16]; - lineBreakProperties[339]=lineBreakProperties[16]; - lineBreakProperties[340]=lineBreakProperties[16]; - lineBreakProperties[341]=lineBreakProperties[16]; - lineBreakProperties[342]=lineBreakProperties[16]; - lineBreakProperties[343]=lineBreakProperties[16]; - lineBreakProperties[351]=lineBreakProperties[344]; - lineBreakProperties[352]=lineBreakProperties[345]; - lineBreakProperties[353]=lineBreakProperties[346]; - lineBreakProperties[354]=lineBreakProperties[347]; - lineBreakProperties[355]=lineBreakProperties[348]; - lineBreakProperties[356]=lineBreakProperties[349]; - lineBreakProperties[357]=lineBreakProperties[350]; - lineBreakProperties[358]=lineBreakProperties[344]; - lineBreakProperties[359]=lineBreakProperties[345]; - lineBreakProperties[360]=lineBreakProperties[346]; - lineBreakProperties[361]=lineBreakProperties[347]; - lineBreakProperties[362]=lineBreakProperties[348]; - lineBreakProperties[363]=lineBreakProperties[349]; - lineBreakProperties[364]=lineBreakProperties[350]; - lineBreakProperties[365]=lineBreakProperties[344]; - lineBreakProperties[366]=lineBreakProperties[345]; - lineBreakProperties[367]=lineBreakProperties[346]; - lineBreakProperties[368]=lineBreakProperties[347]; - lineBreakProperties[369]=lineBreakProperties[348]; - lineBreakProperties[370]=lineBreakProperties[349]; - lineBreakProperties[371]=lineBreakProperties[350]; - lineBreakProperties[372]=lineBreakProperties[344]; - lineBreakProperties[373]=lineBreakProperties[345]; - lineBreakProperties[374]=lineBreakProperties[346]; - lineBreakProperties[375]=lineBreakProperties[347]; - lineBreakProperties[376]=lineBreakProperties[348]; - lineBreakProperties[377]=lineBreakProperties[349]; - lineBreakProperties[378]=lineBreakProperties[350]; - lineBreakProperties[379]=lineBreakProperties[344]; - lineBreakProperties[380]=lineBreakProperties[345]; - lineBreakProperties[381]=lineBreakProperties[346]; - lineBreakProperties[382]=lineBreakProperties[347]; - lineBreakProperties[383]=lineBreakProperties[348]; - lineBreakProperties[384]=lineBreakProperties[349]; - lineBreakProperties[385]=lineBreakProperties[350]; - lineBreakProperties[386]=lineBreakProperties[344]; - lineBreakProperties[387]=lineBreakProperties[345]; - lineBreakProperties[388]=lineBreakProperties[346]; - lineBreakProperties[389]=lineBreakProperties[347]; - lineBreakProperties[390]=lineBreakProperties[348]; - lineBreakProperties[391]=lineBreakProperties[349]; - lineBreakProperties[392]=lineBreakProperties[350]; - lineBreakProperties[393]=lineBreakProperties[344]; - lineBreakProperties[394]=lineBreakProperties[345]; - lineBreakProperties[395]=lineBreakProperties[346]; - lineBreakProperties[396]=lineBreakProperties[347]; - lineBreakProperties[397]=lineBreakProperties[348]; - lineBreakProperties[398]=lineBreakProperties[349]; - lineBreakProperties[399]=lineBreakProperties[350]; - lineBreakProperties[400]=lineBreakProperties[344]; - lineBreakProperties[401]=lineBreakProperties[345]; - lineBreakProperties[402]=lineBreakProperties[346]; - lineBreakProperties[403]=lineBreakProperties[347]; - lineBreakProperties[404]=lineBreakProperties[348]; - lineBreakProperties[405]=lineBreakProperties[349]; - lineBreakProperties[406]=lineBreakProperties[350]; - lineBreakProperties[407]=lineBreakProperties[344]; - lineBreakProperties[408]=lineBreakProperties[345]; - lineBreakProperties[409]=lineBreakProperties[346]; - lineBreakProperties[410]=lineBreakProperties[347]; - lineBreakProperties[411]=lineBreakProperties[348]; - lineBreakProperties[412]=lineBreakProperties[349]; - lineBreakProperties[413]=lineBreakProperties[350]; - lineBreakProperties[414]=lineBreakProperties[344]; - lineBreakProperties[415]=lineBreakProperties[345]; - lineBreakProperties[416]=lineBreakProperties[346]; - lineBreakProperties[417]=lineBreakProperties[347]; - lineBreakProperties[418]=lineBreakProperties[348]; - lineBreakProperties[419]=lineBreakProperties[349]; - lineBreakProperties[420]=lineBreakProperties[350]; - lineBreakProperties[421]=lineBreakProperties[344]; - lineBreakProperties[422]=lineBreakProperties[345]; - lineBreakProperties[423]=lineBreakProperties[346]; - lineBreakProperties[424]=lineBreakProperties[347]; - lineBreakProperties[425]=lineBreakProperties[348]; - lineBreakProperties[426]=lineBreakProperties[349]; - lineBreakProperties[427]=lineBreakProperties[350]; - lineBreakProperties[428]=lineBreakProperties[344]; - lineBreakProperties[429]=lineBreakProperties[345]; - lineBreakProperties[430]=lineBreakProperties[346]; - lineBreakProperties[433]=lineBreakProperties[432]; - lineBreakProperties[434]=lineBreakProperties[432]; - lineBreakProperties[435]=lineBreakProperties[432]; - lineBreakProperties[436]=lineBreakProperties[432]; - lineBreakProperties[437]=lineBreakProperties[432]; - lineBreakProperties[438]=lineBreakProperties[432]; - lineBreakProperties[439]=lineBreakProperties[432]; - lineBreakProperties[440]=lineBreakProperties[432]; - lineBreakProperties[441]=lineBreakProperties[432]; - lineBreakProperties[442]=lineBreakProperties[432]; - lineBreakProperties[443]=lineBreakProperties[432]; - lineBreakProperties[444]=lineBreakProperties[432]; - lineBreakProperties[445]=lineBreakProperties[432]; - lineBreakProperties[446]=lineBreakProperties[432]; - lineBreakProperties[447]=lineBreakProperties[432]; - lineBreakProperties[449]=lineBreakProperties[448]; - lineBreakProperties[450]=lineBreakProperties[448]; - lineBreakProperties[451]=lineBreakProperties[448]; - lineBreakProperties[452]=lineBreakProperties[448]; - lineBreakProperties[453]=lineBreakProperties[448]; - lineBreakProperties[454]=lineBreakProperties[448]; - lineBreakProperties[455]=lineBreakProperties[448]; - lineBreakProperties[456]=lineBreakProperties[448]; - lineBreakProperties[457]=lineBreakProperties[448]; - lineBreakProperties[458]=lineBreakProperties[448]; - lineBreakProperties[459]=lineBreakProperties[448]; - lineBreakProperties[460]=lineBreakProperties[448]; - lineBreakProperties[461]=lineBreakProperties[448]; - lineBreakProperties[462]=lineBreakProperties[448]; - lineBreakProperties[463]=lineBreakProperties[448]; - lineBreakProperties[464]=lineBreakProperties[448]; - lineBreakProperties[465]=lineBreakProperties[448]; - lineBreakProperties[466]=lineBreakProperties[448]; - lineBreakProperties[467]=lineBreakProperties[448]; - lineBreakProperties[468]=lineBreakProperties[448]; - lineBreakProperties[469]=lineBreakProperties[448]; - lineBreakProperties[470]=lineBreakProperties[448]; - lineBreakProperties[471]=lineBreakProperties[448]; - lineBreakProperties[472]=lineBreakProperties[448]; - lineBreakProperties[473]=lineBreakProperties[448]; - lineBreakProperties[474]=lineBreakProperties[448]; - lineBreakProperties[475]=lineBreakProperties[448]; - lineBreakProperties[476]=lineBreakProperties[448]; - lineBreakProperties[477]=lineBreakProperties[448]; - lineBreakProperties[478]=lineBreakProperties[448]; - lineBreakProperties[479]=lineBreakProperties[448]; - lineBreakProperties[480]=lineBreakProperties[448]; - lineBreakProperties[481]=lineBreakProperties[448]; - lineBreakProperties[482]=lineBreakProperties[448]; - lineBreakProperties[483]=lineBreakProperties[448]; - lineBreakProperties[484]=lineBreakProperties[448]; - lineBreakProperties[485]=lineBreakProperties[448]; - lineBreakProperties[486]=lineBreakProperties[448]; - lineBreakProperties[487]=lineBreakProperties[448]; - lineBreakProperties[488]=lineBreakProperties[448]; - lineBreakProperties[489]=lineBreakProperties[448]; - lineBreakProperties[490]=lineBreakProperties[448]; - lineBreakProperties[491]=lineBreakProperties[448]; - lineBreakProperties[492]=lineBreakProperties[448]; - lineBreakProperties[493]=lineBreakProperties[448]; - lineBreakProperties[494]=lineBreakProperties[448]; - lineBreakProperties[495]=lineBreakProperties[448]; - lineBreakProperties[496]=lineBreakProperties[448]; - lineBreakProperties[497]=lineBreakProperties[448]; - lineBreakProperties[498]=lineBreakProperties[94]; - lineBreakProperties[499]=lineBreakProperties[94]; - lineBreakProperties[504]=lineBreakProperties[2]; - lineBreakProperties[505]=lineBreakProperties[2]; - }; + lineBreakProperties[3] = lineBreakProperties[2]; + lineBreakProperties[4] = lineBreakProperties[2]; + lineBreakProperties[8] = lineBreakProperties[2]; + lineBreakProperties[17] = lineBreakProperties[16]; + lineBreakProperties[41] = lineBreakProperties[2]; + lineBreakProperties[42] = lineBreakProperties[2]; + lineBreakProperties[43] = lineBreakProperties[2]; + lineBreakProperties[53] = lineBreakProperties[16]; + lineBreakProperties[57] = lineBreakProperties[16]; + lineBreakProperties[58] = lineBreakProperties[2]; + lineBreakProperties[60] = lineBreakProperties[2]; + lineBreakProperties[61] = lineBreakProperties[2]; + lineBreakProperties[80] = lineBreakProperties[2]; + lineBreakProperties[81] = lineBreakProperties[2]; + lineBreakProperties[82] = lineBreakProperties[2]; + lineBreakProperties[84] = lineBreakProperties[2]; + lineBreakProperties[85] = lineBreakProperties[2]; + lineBreakProperties[87] = lineBreakProperties[16]; + lineBreakProperties[102] = lineBreakProperties[94]; + lineBreakProperties[103] = lineBreakProperties[94]; + lineBreakProperties[104] = lineBreakProperties[94]; + lineBreakProperties[105] = lineBreakProperties[94]; + lineBreakProperties[106] = lineBreakProperties[94]; + lineBreakProperties[107] = lineBreakProperties[94]; + lineBreakProperties[108] = lineBreakProperties[94]; + lineBreakProperties[109] = lineBreakProperties[94]; + lineBreakProperties[110] = lineBreakProperties[94]; + lineBreakProperties[111] = lineBreakProperties[94]; + lineBreakProperties[112] = lineBreakProperties[94]; + lineBreakProperties[113] = lineBreakProperties[94]; + lineBreakProperties[114] = lineBreakProperties[94]; + lineBreakProperties[115] = lineBreakProperties[94]; + lineBreakProperties[116] = lineBreakProperties[94]; + lineBreakProperties[117] = lineBreakProperties[94]; + lineBreakProperties[118] = lineBreakProperties[94]; + lineBreakProperties[119] = lineBreakProperties[94]; + lineBreakProperties[120] = lineBreakProperties[94]; + lineBreakProperties[121] = lineBreakProperties[94]; + lineBreakProperties[122] = lineBreakProperties[94]; + lineBreakProperties[123] = lineBreakProperties[94]; + lineBreakProperties[124] = lineBreakProperties[94]; + lineBreakProperties[125] = lineBreakProperties[94]; + lineBreakProperties[126] = lineBreakProperties[94]; + lineBreakProperties[127] = lineBreakProperties[94]; + lineBreakProperties[128] = lineBreakProperties[94]; + lineBreakProperties[129] = lineBreakProperties[94]; + lineBreakProperties[130] = lineBreakProperties[94]; + lineBreakProperties[131] = lineBreakProperties[94]; + lineBreakProperties[132] = lineBreakProperties[94]; + lineBreakProperties[133] = lineBreakProperties[94]; + lineBreakProperties[134] = lineBreakProperties[94]; + lineBreakProperties[135] = lineBreakProperties[94]; + lineBreakProperties[136] = lineBreakProperties[94]; + lineBreakProperties[137] = lineBreakProperties[94]; + lineBreakProperties[138] = lineBreakProperties[94]; + lineBreakProperties[139] = lineBreakProperties[94]; + lineBreakProperties[140] = lineBreakProperties[94]; + lineBreakProperties[141] = lineBreakProperties[94]; + lineBreakProperties[142] = lineBreakProperties[94]; + lineBreakProperties[143] = lineBreakProperties[94]; + lineBreakProperties[144] = lineBreakProperties[94]; + lineBreakProperties[145] = lineBreakProperties[94]; + lineBreakProperties[146] = lineBreakProperties[94]; + lineBreakProperties[147] = lineBreakProperties[94]; + lineBreakProperties[148] = lineBreakProperties[94]; + lineBreakProperties[149] = lineBreakProperties[94]; + lineBreakProperties[150] = lineBreakProperties[94]; + lineBreakProperties[151] = lineBreakProperties[94]; + lineBreakProperties[152] = lineBreakProperties[94]; + lineBreakProperties[153] = lineBreakProperties[94]; + lineBreakProperties[154] = lineBreakProperties[94]; + lineBreakProperties[156] = lineBreakProperties[94]; + lineBreakProperties[157] = lineBreakProperties[94]; + lineBreakProperties[158] = lineBreakProperties[94]; + lineBreakProperties[159] = lineBreakProperties[94]; + lineBreakProperties[160] = lineBreakProperties[94]; + lineBreakProperties[161] = lineBreakProperties[94]; + lineBreakProperties[162] = lineBreakProperties[94]; + lineBreakProperties[163] = lineBreakProperties[94]; + lineBreakProperties[164] = lineBreakProperties[94]; + lineBreakProperties[165] = lineBreakProperties[94]; + lineBreakProperties[166] = lineBreakProperties[94]; + lineBreakProperties[167] = lineBreakProperties[94]; + lineBreakProperties[168] = lineBreakProperties[94]; + lineBreakProperties[169] = lineBreakProperties[94]; + lineBreakProperties[170] = lineBreakProperties[94]; + lineBreakProperties[171] = lineBreakProperties[94]; + lineBreakProperties[172] = lineBreakProperties[94]; + lineBreakProperties[173] = lineBreakProperties[94]; + lineBreakProperties[174] = lineBreakProperties[94]; + lineBreakProperties[175] = lineBreakProperties[94]; + lineBreakProperties[176] = lineBreakProperties[94]; + lineBreakProperties[177] = lineBreakProperties[94]; + lineBreakProperties[178] = lineBreakProperties[94]; + lineBreakProperties[179] = lineBreakProperties[94]; + lineBreakProperties[180] = lineBreakProperties[94]; + lineBreakProperties[181] = lineBreakProperties[94]; + lineBreakProperties[182] = lineBreakProperties[94]; + lineBreakProperties[183] = lineBreakProperties[94]; + lineBreakProperties[184] = lineBreakProperties[94]; + lineBreakProperties[185] = lineBreakProperties[94]; + lineBreakProperties[186] = lineBreakProperties[94]; + lineBreakProperties[187] = lineBreakProperties[94]; + lineBreakProperties[188] = lineBreakProperties[94]; + lineBreakProperties[189] = lineBreakProperties[94]; + lineBreakProperties[190] = lineBreakProperties[94]; + lineBreakProperties[191] = lineBreakProperties[94]; + lineBreakProperties[192] = lineBreakProperties[94]; + lineBreakProperties[193] = lineBreakProperties[94]; + lineBreakProperties[194] = lineBreakProperties[94]; + lineBreakProperties[195] = lineBreakProperties[94]; + lineBreakProperties[196] = lineBreakProperties[94]; + lineBreakProperties[197] = lineBreakProperties[94]; + lineBreakProperties[198] = lineBreakProperties[94]; + lineBreakProperties[199] = lineBreakProperties[94]; + lineBreakProperties[200] = lineBreakProperties[94]; + lineBreakProperties[201] = lineBreakProperties[94]; + lineBreakProperties[202] = lineBreakProperties[94]; + lineBreakProperties[203] = lineBreakProperties[94]; + lineBreakProperties[204] = lineBreakProperties[94]; + lineBreakProperties[205] = lineBreakProperties[94]; + lineBreakProperties[206] = lineBreakProperties[94]; + lineBreakProperties[207] = lineBreakProperties[94]; + lineBreakProperties[208] = lineBreakProperties[94]; + lineBreakProperties[209] = lineBreakProperties[94]; + lineBreakProperties[210] = lineBreakProperties[94]; + lineBreakProperties[211] = lineBreakProperties[94]; + lineBreakProperties[212] = lineBreakProperties[94]; + lineBreakProperties[213] = lineBreakProperties[94]; + lineBreakProperties[214] = lineBreakProperties[94]; + lineBreakProperties[215] = lineBreakProperties[94]; + lineBreakProperties[216] = lineBreakProperties[94]; + lineBreakProperties[217] = lineBreakProperties[94]; + lineBreakProperties[218] = lineBreakProperties[94]; + lineBreakProperties[219] = lineBreakProperties[94]; + lineBreakProperties[220] = lineBreakProperties[94]; + lineBreakProperties[221] = lineBreakProperties[94]; + lineBreakProperties[222] = lineBreakProperties[94]; + lineBreakProperties[223] = lineBreakProperties[94]; + lineBreakProperties[224] = lineBreakProperties[94]; + lineBreakProperties[225] = lineBreakProperties[94]; + lineBreakProperties[226] = lineBreakProperties[94]; + lineBreakProperties[227] = lineBreakProperties[94]; + lineBreakProperties[228] = lineBreakProperties[94]; + lineBreakProperties[229] = lineBreakProperties[94]; + lineBreakProperties[230] = lineBreakProperties[94]; + lineBreakProperties[231] = lineBreakProperties[94]; + lineBreakProperties[232] = lineBreakProperties[94]; + lineBreakProperties[233] = lineBreakProperties[94]; + lineBreakProperties[234] = lineBreakProperties[94]; + lineBreakProperties[235] = lineBreakProperties[94]; + lineBreakProperties[236] = lineBreakProperties[94]; + lineBreakProperties[237] = lineBreakProperties[94]; + lineBreakProperties[238] = lineBreakProperties[94]; + lineBreakProperties[239] = lineBreakProperties[94]; + lineBreakProperties[240] = lineBreakProperties[94]; + lineBreakProperties[241] = lineBreakProperties[94]; + lineBreakProperties[242] = lineBreakProperties[94]; + lineBreakProperties[243] = lineBreakProperties[94]; + lineBreakProperties[244] = lineBreakProperties[94]; + lineBreakProperties[245] = lineBreakProperties[94]; + lineBreakProperties[246] = lineBreakProperties[94]; + lineBreakProperties[247] = lineBreakProperties[94]; + lineBreakProperties[248] = lineBreakProperties[94]; + lineBreakProperties[249] = lineBreakProperties[94]; + lineBreakProperties[250] = lineBreakProperties[94]; + lineBreakProperties[251] = lineBreakProperties[94]; + lineBreakProperties[252] = lineBreakProperties[94]; + lineBreakProperties[253] = lineBreakProperties[94]; + lineBreakProperties[254] = lineBreakProperties[94]; + lineBreakProperties[255] = lineBreakProperties[94]; + lineBreakProperties[256] = lineBreakProperties[94]; + lineBreakProperties[257] = lineBreakProperties[94]; + lineBreakProperties[258] = lineBreakProperties[94]; + lineBreakProperties[259] = lineBreakProperties[94]; + lineBreakProperties[260] = lineBreakProperties[94]; + lineBreakProperties[261] = lineBreakProperties[94]; + lineBreakProperties[262] = lineBreakProperties[94]; + lineBreakProperties[263] = lineBreakProperties[94]; + lineBreakProperties[264] = lineBreakProperties[94]; + lineBreakProperties[265] = lineBreakProperties[94]; + lineBreakProperties[266] = lineBreakProperties[94]; + lineBreakProperties[267] = lineBreakProperties[94]; + lineBreakProperties[268] = lineBreakProperties[94]; + lineBreakProperties[269] = lineBreakProperties[94]; + lineBreakProperties[270] = lineBreakProperties[94]; + lineBreakProperties[271] = lineBreakProperties[94]; + lineBreakProperties[272] = lineBreakProperties[94]; + lineBreakProperties[273] = lineBreakProperties[94]; + lineBreakProperties[274] = lineBreakProperties[94]; + lineBreakProperties[275] = lineBreakProperties[94]; + lineBreakProperties[276] = lineBreakProperties[94]; + lineBreakProperties[277] = lineBreakProperties[94]; + lineBreakProperties[278] = lineBreakProperties[94]; + lineBreakProperties[279] = lineBreakProperties[94]; + lineBreakProperties[280] = lineBreakProperties[94]; + lineBreakProperties[281] = lineBreakProperties[94]; + lineBreakProperties[282] = lineBreakProperties[94]; + lineBreakProperties[283] = lineBreakProperties[94]; + lineBreakProperties[284] = lineBreakProperties[94]; + lineBreakProperties[285] = lineBreakProperties[94]; + lineBreakProperties[286] = lineBreakProperties[94]; + lineBreakProperties[287] = lineBreakProperties[94]; + lineBreakProperties[288] = lineBreakProperties[94]; + lineBreakProperties[289] = lineBreakProperties[94]; + lineBreakProperties[290] = lineBreakProperties[94]; + lineBreakProperties[291] = lineBreakProperties[94]; + lineBreakProperties[292] = lineBreakProperties[94]; + lineBreakProperties[293] = lineBreakProperties[94]; + lineBreakProperties[294] = lineBreakProperties[94]; + lineBreakProperties[295] = lineBreakProperties[94]; + lineBreakProperties[296] = lineBreakProperties[94]; + lineBreakProperties[297] = lineBreakProperties[94]; + lineBreakProperties[298] = lineBreakProperties[94]; + lineBreakProperties[299] = lineBreakProperties[94]; + lineBreakProperties[300] = lineBreakProperties[94]; + lineBreakProperties[301] = lineBreakProperties[94]; + lineBreakProperties[302] = lineBreakProperties[94]; + lineBreakProperties[303] = lineBreakProperties[94]; + lineBreakProperties[304] = lineBreakProperties[94]; + lineBreakProperties[305] = lineBreakProperties[94]; + lineBreakProperties[306] = lineBreakProperties[94]; + lineBreakProperties[307] = lineBreakProperties[94]; + lineBreakProperties[308] = lineBreakProperties[94]; + lineBreakProperties[309] = lineBreakProperties[94]; + lineBreakProperties[310] = lineBreakProperties[94]; + lineBreakProperties[311] = lineBreakProperties[94]; + lineBreakProperties[312] = lineBreakProperties[94]; + lineBreakProperties[313] = lineBreakProperties[94]; + lineBreakProperties[314] = lineBreakProperties[94]; + lineBreakProperties[315] = lineBreakProperties[94]; + lineBreakProperties[316] = lineBreakProperties[94]; + lineBreakProperties[317] = lineBreakProperties[94]; + lineBreakProperties[318] = lineBreakProperties[94]; + lineBreakProperties[321] = lineBreakProperties[94]; + lineBreakProperties[322] = lineBreakProperties[94]; + lineBreakProperties[323] = lineBreakProperties[94]; + lineBreakProperties[324] = lineBreakProperties[94]; + lineBreakProperties[325] = lineBreakProperties[94]; + lineBreakProperties[326] = lineBreakProperties[94]; + lineBreakProperties[327] = lineBreakProperties[94]; + lineBreakProperties[328] = lineBreakProperties[94]; + lineBreakProperties[330] = lineBreakProperties[2]; + lineBreakProperties[331] = lineBreakProperties[2]; + lineBreakProperties[334] = lineBreakProperties[2]; + lineBreakProperties[339] = lineBreakProperties[16]; + lineBreakProperties[341] = lineBreakProperties[16]; + lineBreakProperties[342] = lineBreakProperties[16]; + lineBreakProperties[343] = lineBreakProperties[16]; + lineBreakProperties[351] = lineBreakProperties[344]; + lineBreakProperties[352] = lineBreakProperties[345]; + lineBreakProperties[353] = lineBreakProperties[346]; + lineBreakProperties[354] = lineBreakProperties[347]; + lineBreakProperties[355] = lineBreakProperties[348]; + lineBreakProperties[356] = lineBreakProperties[349]; + lineBreakProperties[357] = lineBreakProperties[350]; + lineBreakProperties[358] = lineBreakProperties[344]; + lineBreakProperties[359] = lineBreakProperties[345]; + lineBreakProperties[360] = lineBreakProperties[346]; + lineBreakProperties[361] = lineBreakProperties[347]; + lineBreakProperties[362] = lineBreakProperties[348]; + lineBreakProperties[363] = lineBreakProperties[349]; + lineBreakProperties[364] = lineBreakProperties[350]; + lineBreakProperties[365] = lineBreakProperties[344]; + lineBreakProperties[366] = lineBreakProperties[345]; + lineBreakProperties[367] = lineBreakProperties[346]; + lineBreakProperties[368] = lineBreakProperties[347]; + lineBreakProperties[369] = lineBreakProperties[348]; + lineBreakProperties[370] = lineBreakProperties[349]; + lineBreakProperties[371] = lineBreakProperties[350]; + lineBreakProperties[372] = lineBreakProperties[344]; + lineBreakProperties[373] = lineBreakProperties[345]; + lineBreakProperties[374] = lineBreakProperties[346]; + lineBreakProperties[375] = lineBreakProperties[347]; + lineBreakProperties[376] = lineBreakProperties[348]; + lineBreakProperties[377] = lineBreakProperties[349]; + lineBreakProperties[378] = lineBreakProperties[350]; + lineBreakProperties[379] = lineBreakProperties[344]; + lineBreakProperties[380] = lineBreakProperties[345]; + lineBreakProperties[381] = lineBreakProperties[346]; + lineBreakProperties[382] = lineBreakProperties[347]; + lineBreakProperties[383] = lineBreakProperties[348]; + lineBreakProperties[384] = lineBreakProperties[349]; + lineBreakProperties[385] = lineBreakProperties[350]; + lineBreakProperties[386] = lineBreakProperties[344]; + lineBreakProperties[387] = lineBreakProperties[345]; + lineBreakProperties[388] = lineBreakProperties[346]; + lineBreakProperties[389] = lineBreakProperties[347]; + lineBreakProperties[390] = lineBreakProperties[348]; + lineBreakProperties[391] = lineBreakProperties[349]; + lineBreakProperties[392] = lineBreakProperties[350]; + lineBreakProperties[393] = lineBreakProperties[344]; + lineBreakProperties[394] = lineBreakProperties[345]; + lineBreakProperties[395] = lineBreakProperties[346]; + lineBreakProperties[396] = lineBreakProperties[347]; + lineBreakProperties[397] = lineBreakProperties[348]; + lineBreakProperties[398] = lineBreakProperties[349]; + lineBreakProperties[399] = lineBreakProperties[350]; + lineBreakProperties[400] = lineBreakProperties[344]; + lineBreakProperties[401] = lineBreakProperties[345]; + lineBreakProperties[402] = lineBreakProperties[346]; + lineBreakProperties[403] = lineBreakProperties[347]; + lineBreakProperties[404] = lineBreakProperties[348]; + lineBreakProperties[405] = lineBreakProperties[349]; + lineBreakProperties[406] = lineBreakProperties[350]; + lineBreakProperties[407] = lineBreakProperties[344]; + lineBreakProperties[408] = lineBreakProperties[345]; + lineBreakProperties[409] = lineBreakProperties[346]; + lineBreakProperties[410] = lineBreakProperties[347]; + lineBreakProperties[411] = lineBreakProperties[348]; + lineBreakProperties[412] = lineBreakProperties[349]; + lineBreakProperties[413] = lineBreakProperties[350]; + lineBreakProperties[414] = lineBreakProperties[344]; + lineBreakProperties[415] = lineBreakProperties[345]; + lineBreakProperties[416] = lineBreakProperties[346]; + lineBreakProperties[417] = lineBreakProperties[347]; + lineBreakProperties[418] = lineBreakProperties[348]; + lineBreakProperties[419] = lineBreakProperties[349]; + lineBreakProperties[420] = lineBreakProperties[350]; + lineBreakProperties[421] = lineBreakProperties[344]; + lineBreakProperties[422] = lineBreakProperties[345]; + lineBreakProperties[423] = lineBreakProperties[346]; + lineBreakProperties[424] = lineBreakProperties[347]; + lineBreakProperties[425] = lineBreakProperties[348]; + lineBreakProperties[426] = lineBreakProperties[349]; + lineBreakProperties[427] = lineBreakProperties[350]; + lineBreakProperties[428] = lineBreakProperties[344]; + lineBreakProperties[429] = lineBreakProperties[345]; + lineBreakProperties[430] = lineBreakProperties[346]; + lineBreakProperties[433] = lineBreakProperties[432]; + lineBreakProperties[434] = lineBreakProperties[432]; + lineBreakProperties[435] = lineBreakProperties[432]; + lineBreakProperties[436] = lineBreakProperties[432]; + lineBreakProperties[437] = lineBreakProperties[432]; + lineBreakProperties[438] = lineBreakProperties[432]; + lineBreakProperties[439] = lineBreakProperties[432]; + lineBreakProperties[440] = lineBreakProperties[432]; + lineBreakProperties[441] = lineBreakProperties[432]; + lineBreakProperties[442] = lineBreakProperties[432]; + lineBreakProperties[443] = lineBreakProperties[432]; + lineBreakProperties[444] = lineBreakProperties[432]; + lineBreakProperties[445] = lineBreakProperties[432]; + lineBreakProperties[446] = lineBreakProperties[432]; + lineBreakProperties[447] = lineBreakProperties[432]; + lineBreakProperties[449] = lineBreakProperties[448]; + lineBreakProperties[450] = lineBreakProperties[448]; + lineBreakProperties[451] = lineBreakProperties[448]; + lineBreakProperties[452] = lineBreakProperties[448]; + lineBreakProperties[453] = lineBreakProperties[448]; + lineBreakProperties[454] = lineBreakProperties[448]; + lineBreakProperties[455] = lineBreakProperties[448]; + lineBreakProperties[456] = lineBreakProperties[448]; + lineBreakProperties[457] = lineBreakProperties[448]; + lineBreakProperties[458] = lineBreakProperties[448]; + lineBreakProperties[459] = lineBreakProperties[448]; + lineBreakProperties[460] = lineBreakProperties[448]; + lineBreakProperties[461] = lineBreakProperties[448]; + lineBreakProperties[462] = lineBreakProperties[448]; + lineBreakProperties[463] = lineBreakProperties[448]; + lineBreakProperties[464] = lineBreakProperties[448]; + lineBreakProperties[465] = lineBreakProperties[448]; + lineBreakProperties[466] = lineBreakProperties[448]; + lineBreakProperties[467] = lineBreakProperties[448]; + lineBreakProperties[468] = lineBreakProperties[448]; + lineBreakProperties[469] = lineBreakProperties[448]; + lineBreakProperties[470] = lineBreakProperties[448]; + lineBreakProperties[471] = lineBreakProperties[448]; + lineBreakProperties[472] = lineBreakProperties[448]; + lineBreakProperties[473] = lineBreakProperties[448]; + lineBreakProperties[474] = lineBreakProperties[448]; + lineBreakProperties[475] = lineBreakProperties[448]; + lineBreakProperties[476] = lineBreakProperties[448]; + lineBreakProperties[477] = lineBreakProperties[448]; + lineBreakProperties[478] = lineBreakProperties[448]; + lineBreakProperties[479] = lineBreakProperties[448]; + lineBreakProperties[480] = lineBreakProperties[448]; + lineBreakProperties[481] = lineBreakProperties[448]; + lineBreakProperties[482] = lineBreakProperties[448]; + lineBreakProperties[483] = lineBreakProperties[448]; + lineBreakProperties[484] = lineBreakProperties[448]; + lineBreakProperties[485] = lineBreakProperties[448]; + lineBreakProperties[486] = lineBreakProperties[448]; + lineBreakProperties[487] = lineBreakProperties[448]; + lineBreakProperties[488] = lineBreakProperties[448]; + lineBreakProperties[489] = lineBreakProperties[448]; + lineBreakProperties[490] = lineBreakProperties[448]; + lineBreakProperties[491] = lineBreakProperties[448]; + lineBreakProperties[492] = lineBreakProperties[448]; + lineBreakProperties[493] = lineBreakProperties[448]; + lineBreakProperties[494] = lineBreakProperties[448]; + lineBreakProperties[495] = lineBreakProperties[448]; + lineBreakProperties[496] = lineBreakProperties[448]; + lineBreakProperties[497] = lineBreakProperties[448]; + lineBreakProperties[498] = lineBreakProperties[94]; + lineBreakProperties[499] = lineBreakProperties[94]; + lineBreakProperties[504] = lineBreakProperties[2]; + lineBreakProperties[505] = lineBreakProperties[2]; + } - public static final byte LINE_BREAK_PROPERTY_AI=1; - public static final byte LINE_BREAK_PROPERTY_AL=2; - public static final byte LINE_BREAK_PROPERTY_B2=3; - public static final byte LINE_BREAK_PROPERTY_BA=4; - public static final byte LINE_BREAK_PROPERTY_BB=5; - public static final byte LINE_BREAK_PROPERTY_BK=6; - public static final byte LINE_BREAK_PROPERTY_CB=7; - public static final byte LINE_BREAK_PROPERTY_CL=8; - public static final byte LINE_BREAK_PROPERTY_CM=9; - public static final byte LINE_BREAK_PROPERTY_CR=10; - public static final byte LINE_BREAK_PROPERTY_EX=11; - public static final byte LINE_BREAK_PROPERTY_GL=12; - public static final byte LINE_BREAK_PROPERTY_H2=13; - public static final byte LINE_BREAK_PROPERTY_H3=14; - public static final byte LINE_BREAK_PROPERTY_HY=15; - public static final byte LINE_BREAK_PROPERTY_ID=16; - public static final byte LINE_BREAK_PROPERTY_IN=17; - public static final byte LINE_BREAK_PROPERTY_IS=18; - public static final byte LINE_BREAK_PROPERTY_JL=19; - public static final byte LINE_BREAK_PROPERTY_JT=20; - public static final byte LINE_BREAK_PROPERTY_JV=21; - public static final byte LINE_BREAK_PROPERTY_LF=22; - public static final byte LINE_BREAK_PROPERTY_NL=23; - public static final byte LINE_BREAK_PROPERTY_NS=24; - public static final byte LINE_BREAK_PROPERTY_NU=25; - public static final byte LINE_BREAK_PROPERTY_OP=26; - public static final byte LINE_BREAK_PROPERTY_PO=27; - public static final byte LINE_BREAK_PROPERTY_PR=28; - public static final byte LINE_BREAK_PROPERTY_QU=29; - public static final byte LINE_BREAK_PROPERTY_SA=30; - public static final byte LINE_BREAK_PROPERTY_SG=31; - public static final byte LINE_BREAK_PROPERTY_SP=32; - public static final byte LINE_BREAK_PROPERTY_SY=33; - public static final byte LINE_BREAK_PROPERTY_WJ=34; - public static final byte LINE_BREAK_PROPERTY_XX=35; - public static final byte LINE_BREAK_PROPERTY_ZW=36; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_AI = 1; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_AL = 2; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_B2 = 3; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_BA = 4; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_BB = 5; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_BK = 6; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_CB = 7; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_CL = 8; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_CM = 9; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_CR = 10; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_EX = 11; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_GL = 12; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_H2 = 13; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_H3 = 14; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_HY = 15; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_ID = 16; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_IN = 17; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_IS = 18; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_JL = 19; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_JT = 20; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_JV = 21; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_LF = 22; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_NL = 23; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_NS = 24; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_NU = 25; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_OP = 26; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_PO = 27; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_PR = 28; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_QU = 29; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_SA = 30; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_SG = 31; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_SP = 32; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_SY = 33; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_WJ = 34; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_XX = 35; + /** Linebreak property constant */ + public static final byte LINE_BREAK_PROPERTY_ZW = 36; - private static String lineBreakPropertyShortNames[] = {"AI","AL","B2","BA","BB","BK","CB","CL","CM","CR","EX", - "GL","H2","H3","HY","ID","IN","IS","JL","JT","JV","LF","NL","NS","NU","OP","PO","PR","QU","SA","SG","SP", - "SY","WJ","XX","ZW"}; + private static String lineBreakPropertyShortNames[] = {"AI", "AL", "B2", "BA", "BB", "BK", "CB", "CL", "CM", "CR", "EX", + "GL", "H2", "H3", "HY", "ID", "IN", "IS", "JL", "JT", "JV", "LF", "NL", "NS", "NU", "OP", "PO", "PR", "QU", "SA", "SG", "SP", + "SY", "WJ", "XX", "ZW"}; private static String lineBreakPropertyLongNames[] = {"Ambiguous","Alphabetic","Break_Both","Break_After","Break_Before", "Mandatory_Break","Contingent_Break","Close_Punctuation","Combining_Mark","Carriage_Return","Exclamation", @@ -642,28 +690,58 @@ class LineBreakUtils { "Nonstarter","Numeric","Open_Punctuation","Postfix_Numeric","Prefix_Numeric","Quotation","Complex_Context", "Surrogate","Space","Break_Symbols","Word_Joiner","Unknown","ZWSpace"}; + /** + * Return the short name for the linebreak property corresponding + * to the given symbolic constant. + * + * @param i the numeric value of the linebreak property + * @return the short name of the linebreak property + */ public static String getLineBreakPropertyShortName(byte i) { - if (i>0 && i<=lineBreakPropertyShortNames.length) { - return lineBreakPropertyShortNames[i-1]; + if (i > 0 && i <= lineBreakPropertyShortNames.length) { + return lineBreakPropertyShortNames[i - 1]; } else { return null; } } + /** + * Return the long name for the linebreak property corresponding + * to the given symbolic constant. + * + * @param i the numeric value of the linebreak property + * @return the long name of the linebreak property + */ public static String getLineBreakPropertyLongName(byte i) { - if (i>0 && i<=lineBreakPropertyLongNames.length) { - return lineBreakPropertyLongNames[i-1]; + if (i > 0 && i <= lineBreakPropertyLongNames.length) { + return lineBreakPropertyLongNames[i - 1]; } else { return null; } } + /** + * Return the linebreak property constant for the given char + * + * @param c the char whose linebreak property to return + * @return the constant representing the linebreak property + */ public static byte getLineBreakProperty(char c) { - return lineBreakProperties[c/128][c%128]; + return lineBreakProperties[c / 128][c % 128]; } - public static byte getLineBreakPairProperty(int lineBreakPropertyBefore,int lineBreakPropertyAfter) { - return PAIR_TABLE[lineBreakPropertyBefore-1][lineBreakPropertyAfter-1]; + /** + * Return the break class constant for the given pair of linebreak + * property constants. + * + * @param lineBreakPropertyBefore the linebreak property for the first character + * in a two-character sequence + * @param lineBreakPropertyAfter the linebreak property for the second character + * in a two-character sequence + * @return the constant representing the break class + */ + public static byte getLineBreakPairProperty(int lineBreakPropertyBefore, int lineBreakPropertyAfter) { + return PAIR_TABLE[lineBreakPropertyBefore - 1][lineBreakPropertyAfter - 1]; } -}; +} -- cgit v1.2.3 From 802e3087140006e4b59eaef052949ab4ddd28338 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Tue, 10 Jun 2008 07:52:36 +0000 Subject: Replaced getLast() calls with calls to listUtil git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@665995 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/AbstractBreaker.java | 28 +++++------ .../fop/layoutmgr/BlockContainerLayoutManager.java | 18 +++---- .../fop/layoutmgr/BlockStackingLayoutManager.java | 30 ++++++------ .../org/apache/fop/layoutmgr/ElementListUtils.java | 12 +++-- .../fop/layoutmgr/StaticContentLayoutManager.java | 19 ++++---- .../fop/layoutmgr/inline/InlineLayoutManager.java | 14 +++--- .../fop/layoutmgr/inline/TextLayoutManager.java | 5 +- .../layoutmgr/table/TableCellLayoutManager.java | 12 ++--- src/java/org/apache/fop/util/ListUtil.java | 55 ++++++++++++++++++++++ 9 files changed, 128 insertions(+), 65 deletions(-) create mode 100644 src/java/org/apache/fop/util/ListUtil.java (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 6f204383d..c830220e7 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -28,6 +28,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.Constants; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * Abstract base class for breakers (page breakers, static region handlers etc.). @@ -116,8 +117,8 @@ public abstract class AbstractBreaker { public KnuthSequence endSequence(Position breakPosition) { // remove glue and penalty item at the end of the paragraph while (this.size() > ignoreAtStart - && !((KnuthElement)this.get(this.size() - 1)).isBox()) { - this.remove(this.size() - 1); + && !((KnuthElement) ListUtil.getLast(this)).isBox()) { + ListUtil.removeLast(this); } if (this.size() > ignoreAtStart) { // add the elements representing the space at the end of the last line @@ -215,7 +216,7 @@ public abstract class AbstractBreaker { /** @return true if there's no content that could be handled. */ public boolean isEmpty() { - return (this.blockLists.size() == 0); + return (this.blockLists.isEmpty()); } protected void startPart(BlockSequence list, int breakClass) { @@ -551,7 +552,7 @@ public abstract class AbstractBreaker { BlockSequence blockList; List returnedList = getNextKnuthElements(childLC, alignment); if (returnedList != null) { - if (returnedList.size() == 0) { + if (returnedList.isEmpty()) { nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn); return nextSequenceStartsOn; } @@ -561,10 +562,9 @@ public abstract class AbstractBreaker { nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn); Position breakPosition = null; - if (((KnuthElement) returnedList.get(returnedList.size() - 1)) - .isForcedBreak()) { - KnuthPenalty breakPenalty = (KnuthPenalty) returnedList - .remove(returnedList.size() - 1); + if (((KnuthElement) ListUtil.getLast(returnedList)).isForcedBreak()) { + KnuthPenalty breakPenalty = (KnuthPenalty) ListUtil + .removeLast(returnedList); breakPosition = breakPenalty.getPosition(); switch (breakPenalty.getBreakClass()) { case Constants.EN_PAGE: @@ -745,12 +745,12 @@ public abstract class AbstractBreaker { if (!bBoxSeen) { // this is the first box met in this page bBoxSeen = true; - } else if (unconfirmedList.size() > 0) { - // glue items in unconfirmedList were not after - // the last box - // in this page; they must be added to - // blockSpaceList - while (unconfirmedList.size() > 0) { + } else { + while (!unconfirmedList.isEmpty()) { + // glue items in unconfirmedList were not after + // the last box + // in this page; they must be added to + // blockSpaceList KnuthGlue blockSpace = (KnuthGlue) unconfirmedList .removeFirst(); spaceMaxAdjustment.max += ((KnuthGlue) blockSpace) diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 22d5fb941..732cb1ae7 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -39,6 +39,7 @@ import org.apache.fop.fo.flow.BlockContainer; import org.apache.fop.fo.properties.CommonAbsolutePosition; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; +import org.apache.fop.util.ListUtil; /** * LayoutManager for a block-container FO. @@ -285,7 +286,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // get elements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); - if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { + if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { //Propagate keep-with-previous up from the first child context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); childLC.clearKeepWithPreviousPending(); @@ -317,12 +318,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager addInBetweenBreak(contentList, context, childLC); } contentList.addAll(returnedList); - if (returnedList.size() == 0) { + if (returnedList.isEmpty()) { //Avoid NoSuchElementException below (happens with empty blocks) continue; } - if (((ListElement) returnedList - .get(returnedList.size() - 1)).isForcedBreak()) { + if (((ListElement) ListUtil.getLast(returnedList)) + .isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished()) { // there is no other content in this block; @@ -754,7 +755,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // pos was created by this BCLM and was inside an element // representing space before or after // this means the space was not discarded - if (positionList.size() == 0 && bcpos == null) { + if (positionList.isEmpty() && bcpos == null) { // pos was in the element representing space-before bSpaceBefore = true; } else { @@ -801,9 +802,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // // between consecutive pages List splitList = new LinkedList(); int splitLength = 0; - int iFirst = ((MappingPosition) positionList.get(0)).getFirstIndex(); - int iLast = ((MappingPosition) positionList.get(positionList - .size() - 1)).getLastIndex(); + int iFirst = ((MappingPosition) positionList.get(0)) + .getFirstIndex(); + int iLast = ((MappingPosition) ListUtil.getLast(positionList)) + .getLastIndex(); // copy from storedList to splitList all the elements from // iFirst to iLast ListIterator storedListIterator = storedList.listIterator(iFirst); diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index b2fb98ccd..4360f62e9 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -36,6 +36,7 @@ import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.layoutmgr.inline.LineLayoutManager; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * Base LayoutManager class for all areas which stack their child @@ -296,7 +297,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // get elements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); - if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { + if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { //Propagate keep-with-previous up from the first child context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); childLC.clearKeepWithPreviousPending(); @@ -312,7 +313,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager break; } - if (contentList.size() == 0) { + if (contentList.isEmpty()) { // Empty fo:block, zero-length box makes sure the IDs and/or markers // are registered and borders/padding are painted. returnList.add(new KnuthBox(0, notifyPos(new Position(this)), false)); @@ -339,17 +340,17 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // before the one handled by curLM addInBetweenBreak(contentList, context, childLC); } - if (returnedList == null || returnedList.size() == 0) { + if (returnedList == null || returnedList.isEmpty()) { //Avoid NoSuchElementException below (happens with empty blocks) continue; } contentList.addAll(returnedList); - if (((ListElement) returnedList.get(returnedList.size() - 1)) + if (((ListElement) ListUtil.getLast(returnedList)) .isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished() && !hasNextChildLM()) { - forcedBreakAfterLast = (BreakElement) contentList - .remove(contentList.size() - 1); + forcedBreakAfterLast = (BreakElement) ListUtil + .removeLast(contentList); context.clearPendingMarks(); break; } @@ -381,7 +382,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /* end of extension */ returnedList = new LinkedList(); - if (contentList.size() > 0) { + if (!contentList.isEmpty()) { wrapPositionElements(contentList, returnList); } else if (forcedBreakAfterLast == null) { // Empty fo:block, zero-length box makes sure the IDs and/or markers @@ -440,8 +441,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager return; } - ListElement last = (ListElement) contentList - .get(contentList.size() - 1); + ListElement last = (ListElement) ListUtil.getLast(contentList); if (last.isGlue()) { // the last element in contentList is a glue; // it is a feasible breakpoint, there is no need to add @@ -695,8 +695,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); } else if (bSomethingAdded - && !((KnuthElement) returnedList.get(returnedList - .size() - 1)).isGlue()) { + && !((KnuthElement) ListUtil.getLast(returnedList)) + .isGlue()) { // add a null penalty to allow a break between blocks returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } @@ -715,8 +715,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // currLM == this // there are no more elements to add // remove the last penalty added to returnedList - if (returnedList.size() > 0) { - returnedList.remove(returnedList.size() - 1); + if (!returnedList.isEmpty()) { + ListUtil.removeLast(returnedList); } //log.debug(" BLM.getChangedKnuthElements> elementi propri, ignorati, da " // + fromIndex + " a " + workList.size()); @@ -1407,7 +1407,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager oldList.remove(0); } if (adjustedSpaceAfter > 0) { - oldList.remove(oldList.size() - 1); + ListUtil.removeLast(oldList); } // if space-before.conditionality is "discard", correct newList @@ -1464,7 +1464,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager newList.addLast(new KnuthBox(wrongBox.getW() - decreasedLength, wrongBox.getPosition(), false)); // add preserved elements - if (preserveList.size() > 0) { + if (!preserveList.isEmpty()) { newList.addAll(preserveList); } // insert the correct glue diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java index f3d36276c..c04d197e4 100644 --- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java +++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java @@ -19,16 +19,20 @@ package org.apache.fop.layoutmgr; -import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * Utilities for Knuth element lists. */ -public class ElementListUtils { +public final class ElementListUtils { + + private ElementListUtils() { + // Utility class. + } /** * Removes legal breaks in an element list. A constraint can be specified to limit the @@ -185,7 +189,7 @@ public class ElementListUtils { * @return true if the list ends with a forced break */ public static boolean endsWithForcedBreak(List elems) { - ListElement last = (ListElement) elems.get(elems.size() - 1); + ListElement last = (ListElement) ListUtil.getLast(elems); return last.isForcedBreak(); } @@ -196,7 +200,7 @@ public class ElementListUtils { * @return true if the list ends with a non-infinite penalty */ public static boolean endsWithNonInfinitePenalty(List elems) { - ListElement last = (ListElement) elems.get(elems.size() - 1); + ListElement last = (ListElement) ListUtil.getLast(elems); if (last.isPenalty() && ((KnuthPenalty)last).getP() < KnuthElement.INFINITE) { return true; } else if (last instanceof BreakElement diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 3a8786bd7..44e0cc476 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -38,6 +38,7 @@ import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; import org.apache.fop.layoutmgr.inline.TextLayoutManager; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * LayoutManager for an fo:flow object. @@ -142,7 +143,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { returnList.addAll(returnedList); return returnList; } else { - if (returnList.size() > 0) { + if (!returnList.isEmpty()) { // there is a block before this one if (prevLM.mustKeepWithNext() || curLM.mustKeepWithPrevious()) { @@ -150,16 +151,16 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); - } else if (!((KnuthElement) returnList.get(returnList - .size() - 1)).isGlue()) { + } else if (!((KnuthElement) ListUtil.getLast(returnList)) + .isGlue()) { // add a null penalty to allow a break between blocks returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } } -/*LF*/ if (returnedList.size() > 0) { // controllare! +/*LF*/ if (!returnedList.isEmpty()) { // controllare! returnList.addAll(returnedList); - final KnuthElement last = (KnuthElement) returnedList - .get(returnedList.size() - 1); + final KnuthElement last = (KnuthElement) ListUtil + .getLast(returnedList); if (last.isPenalty() && ((KnuthPenalty) last).getP() == -KnuthElement.INFINITE) { // a descendant of this flow has break-after @@ -173,10 +174,10 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { setFinished(true); - if (returnList.size() > 0) { - return returnList; - } else { + if (returnList.isEmpty()) { return null; + } else { + return returnList; } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 123259cd4..d0874d626 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -56,6 +56,7 @@ import org.apache.fop.layoutmgr.SpaceSpecifier; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; +import org.apache.fop.util.ListUtil; /** * LayoutManager for objects which stack children in the inline direction, @@ -312,11 +313,11 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // get KnuthElements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); - if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) { + if (returnList.isEmpty() && childLC.isKeepWithPreviousPending()) { childLC.clearKeepWithPreviousPending(); } if (returnedList == null - || returnedList.size() == 0) { + || returnedList.isEmpty()) { // curLM returned null or an empty list, because it finished; // just iterate once more to see if there is another child continue; @@ -335,7 +336,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { returnedList.remove(0); } // add border and padding to the first complete sequence of this LM - if (!borderAdded && returnedList.size() != 0) { + if (!borderAdded && !returnedList.isEmpty()) { addKnuthElementsForBorderPaddingStart((KnuthSequence) returnedList.get(0)); borderAdded = true; } @@ -367,8 +368,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); childLC.clearKeepsPending(); } - lastSequence = (KnuthSequence) returnList - .get(returnList.size() - 1); + lastSequence = (KnuthSequence) ListUtil.getLast(returnList); lastChildLM = curLM; } @@ -379,7 +379,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { setFinished(true); log.trace(trace); - if (returnList.size() == 0) { + if (returnList.isEmpty()) { /* * if the FO itself is empty, but has an id specified * or associated fo:markers, then we still need a dummy @@ -396,7 +396,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } } - return returnList.size() == 0 ? null : returnList; + return returnList.isEmpty() ? null : returnList; } /** diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index eec2b1e91..575728f0d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -46,6 +46,7 @@ import org.apache.fop.text.linebreak.LineBreakStatus; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; import org.apache.fop.util.CharUtilities; +import org.apache.fop.util.ListUtil; /** * LayoutManager for text (a sequence of characters) which generates one @@ -624,9 +625,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { sequence = this.processLinebreak(returnList, sequence); } - if (((List) returnList.get(returnList.size() - 1)).isEmpty()) { + if (((List) ListUtil.getLast(returnList)).isEmpty()) { //Remove an empty sequence because of a trailing newline - returnList.remove(returnList.size() - 1); + ListUtil.removeLast(returnList); } this.setFinished(true); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 1b402095d..43b34e4b7 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -27,7 +27,6 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.Trait; -import org.apache.fop.fo.flow.ListItem; import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; @@ -53,6 +52,7 @@ import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * LayoutManager for a table-cell FO. @@ -152,7 +152,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager if (childLC.isKeepWithNextPending()) { log.debug("child LM signals pending keep with next"); } - if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) { + if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { primaryGridUnit.setKeepWithPreviousStrength(childLC.getKeepWithPreviousPending()); childLC.clearKeepWithPreviousPending(); } @@ -163,7 +163,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager addInBetweenBreak(contentList, context, childLC); } contentList.addAll(returnedList); - if (returnedList.size() == 0) { + if (returnedList.isEmpty()) { //Avoid NoSuchElementException below (happens with empty blocks) continue; } @@ -177,7 +177,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager primaryGridUnit.setKeepWithNextStrength(context.getKeepWithNextPending()); returnedList = new LinkedList(); - if (contentList.size() > 0) { + if (!contentList.isEmpty()) { wrapPositionElements(contentList, returnList); } else { // In relaxed validation mode, table-cells having no children are authorised. @@ -193,8 +193,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager returnList.remove(0); assert !returnList.isEmpty(); } - final KnuthElement lastItem = (KnuthElement) returnList - .get(returnList.size() - 1); + final KnuthElement lastItem = (KnuthElement) ListUtil + .getLast(returnList); if (((KnuthElement) lastItem).isForcedBreak()) { KnuthPenalty p = (KnuthPenalty) lastItem; primaryGridUnit.setBreakAfter(p.getBreakClass()); diff --git a/src/java/org/apache/fop/util/ListUtil.java b/src/java/org/apache/fop/util/ListUtil.java new file mode 100644 index 000000000..a6b8d490c --- /dev/null +++ b/src/java/org/apache/fop/util/ListUtil.java @@ -0,0 +1,55 @@ +/* + * 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.List; + +/** + * Provides helper functions for {@link java.util.List}. + * + */ +public final class ListUtil { + + private ListUtil() { + // Utility class. + } + + /** + * Retrieve the last element from a list. + * + * @param list + * The list to work on + * @return last element + */ + public static Object getLast(List list) { + return list.get(list.size() - 1); + } + + /** + * Retrieve and remove the last element from a list. + * + * @param list + * The list to work on + * @return previous last element + */ + public static Object removeLast(List list) { + return list.remove(list.size() - 1); + } +} -- cgit v1.2.3 From 2bffd1862a284e46ca89e3a596a09d8ee0e9a06b Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sat, 14 Jun 2008 16:21:15 +0000 Subject: minor spelling fixes git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@667831 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/LayoutManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManager.java b/src/java/org/apache/fop/layoutmgr/LayoutManager.java index 0700ea43a..ad0d9f69c 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManager.java @@ -134,7 +134,7 @@ public interface LayoutManager extends PercentBaseContext { * of the node assigned to the LM * * @param context the LayoutContext used to store layout information - * @param alignment the desired text alignement + * @param alignment the desired text alignment * @return the list of KnuthElements */ List getNextKnuthElements(LayoutContext context, int alignment); @@ -145,7 +145,7 @@ public interface LayoutManager extends PercentBaseContext { * * In the context of line breaking, this method is called after hyphenation has * been performed, in order to receive the sequence of elements representing the - * text together with all possibile hyphenation points. + * text together with all possible hyphenation points. * For example, if the text "representation" originates a single box element * when getNextKnuthElements() is called, it will be now split in syllables * (rep-re-sen-ta-tion) each one originating a box and divided by additional -- cgit v1.2.3 From 2c2280fc7310566da8465db351c7bd94b9eceae5 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sat, 14 Jun 2008 18:18:14 +0000 Subject: minor spelling fixes git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@667862 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index 552e74889..19a8cdf2d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -91,7 +91,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager /** - * Create a Leaf node layout mananger. + * Create a Leaf node layout manager. * @param node the FObj to attach to this LM. */ public LeafNodeLayoutManager(FObj node) { @@ -99,7 +99,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** - * Create a Leaf node layout mananger. + * Create a Leaf node layout manager. */ public LeafNodeLayoutManager() { } -- cgit v1.2.3 From caab9b0408a6ad1734f1996673fad20caf53423f Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sat, 14 Jun 2008 18:23:28 +0000 Subject: minor spelling & checkstyle fixes git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@667864 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/AbstractBaseLayoutManager.java | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java index 7fd289c05..27189bf86 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java @@ -34,17 +34,17 @@ import org.apache.fop.fo.FObj; public abstract class AbstractBaseLayoutManager implements LayoutManager, PercentBaseContext { - /** Indicator if this LM generates reference areas */ + /** Indicator if this LM generates reference areas. */ protected boolean generatesReferenceArea = false; - /** Indicator if this LM generates block areas */ + /** Indicator if this LM generates block areas. */ protected boolean generatesBlockArea = false; - /** The formatting object for this LM */ + /** The formatting object for this LM. */ protected final FObj fobj; /** * logging instance */ - private static Log log = LogFactory.getLog(AbstractBaseLayoutManager.class); + private static final Log LOG = LogFactory.getLog(AbstractBaseLayoutManager.class); /** * Abstract base layout manager. @@ -69,8 +69,8 @@ public abstract class AbstractBaseLayoutManager // --------- Property Resolution related functions --------- // /** {@inheritDoc} */ - public int getBaseLength(int lengthBase, FObj fobj) { - if (fobj == this.fobj) { + public int getBaseLength(int lengthBase, FObj fobjx) { + if (fobjx == this.fobj) { switch (lengthBase) { case LengthBase.CONTAINING_BLOCK_WIDTH: return getAncestorBlockAreaIPD(); @@ -81,20 +81,20 @@ public abstract class AbstractBaseLayoutManager case LengthBase.CONTAINING_REFAREA_WIDTH: return getReferenceAreaIPD(); default: - log.error("Unknown base type for LengthBase:" + lengthBase); + LOG.error("Unknown base type for LengthBase:" + lengthBase); return 0; } } else { LayoutManager lm = getParent(); - while (lm != null && fobj != lm.getFObj()) { + while (lm != null && fobjx != lm.getFObj()) { lm = lm.getParent(); } if (lm != null) { - return lm.getBaseLength(lengthBase, fobj); + return lm.getBaseLength(lengthBase, fobjx); } } - log.error("Cannot find LM to handle given FO for LengthBase. (" - + fobj.getContextInfo() + ")"); + LOG.error("Cannot find LM to handle given FO for LengthBase. (" + + fobjx.getContextInfo() + ")"); return 0; } @@ -111,7 +111,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -128,7 +128,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -141,7 +141,7 @@ public abstract class AbstractBaseLayoutManager if (lm != null) { return lm.getContentAreaIPD(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -154,7 +154,7 @@ public abstract class AbstractBaseLayoutManager if (lm != null) { return lm.getContentAreaBPD(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -171,7 +171,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } @@ -188,7 +188,7 @@ public abstract class AbstractBaseLayoutManager } lm = lm.getParent(); } - log.error("No parent LM found"); + LOG.error("No parent LM found"); return 0; } -- cgit v1.2.3 From 2ad567b2f6e4f9f5db847c11742ddf8ca331db83 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sat, 14 Jun 2008 22:20:42 +0000 Subject: removed double storage of 'fobj' git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@667893 13f79535-47bb-0310-9956-ffa450edef68 --- .../inline/AbstractGraphicsLayoutManager.java | 35 ++++++---------------- .../inline/ExternalGraphicLayoutManager.java | 12 ++++---- .../layoutmgr/inline/InstreamForeignObjectLM.java | 11 ++++--- 3 files changed, 20 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index e90927699..76002da2f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -39,16 +39,14 @@ import org.apache.fop.layoutmgr.TraitSetter; */ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManager { - /** The graphics object this LM deals with */ - protected AbstractGraphics fobj; - /** - * Constructor - * @param node the formatting object that creates this area + * Constructor. + * + * @param node + * the formatting object that creates this area */ public AbstractGraphicsLayoutManager(AbstractGraphics node) { super(node); - fobj = node; } /** @@ -57,6 +55,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage * @return the viewport inline area */ private Viewport getInlineArea() { + final AbstractGraphics fobj = (AbstractGraphics)this.fobj; Dimension intrinsicSize = new Dimension( fobj.getIntrinsicWidth(), fobj.getIntrinsicHeight()); @@ -113,6 +112,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage /** {@inheritDoc} */ protected AlignmentContext makeAlignmentContext(LayoutContext context) { + final AbstractGraphics fobj = (AbstractGraphics)this.fobj; return new AlignmentContext( get(context).getAllocBPD() , fobj.getAlignmentAdjust() @@ -128,7 +128,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage * the viewport. * @return the appropriate area */ - abstract Area getChildArea(); + protected abstract Area getChildArea(); // --------- Property Resolution related functions --------- // @@ -138,31 +138,14 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage public int getBaseLength(int lengthBase, FObj fobj) { switch (lengthBase) { case LengthBase.IMAGE_INTRINSIC_WIDTH: - return getIntrinsicWidth(); + return ((AbstractGraphics)fobj).getIntrinsicWidth(); case LengthBase.IMAGE_INTRINSIC_HEIGHT: - return getIntrinsicHeight(); + return ((AbstractGraphics)fobj).getIntrinsicHeight(); case LengthBase.ALIGNMENT_ADJUST: return get(null).getBPD(); default: // Delegate to super class return super.getBaseLength(lengthBase, fobj); } } - - /** - * Returns the intrinsic width of the e-g. - * @return the width of the element - */ - protected int getIntrinsicWidth() { - return fobj.getIntrinsicWidth(); - } - - /** - * Returns the intrinsic height of the e-g. - * @return the height of the element - */ - protected int getIntrinsicHeight() { - return fobj.getIntrinsicHeight(); - } - } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java index ab05d60c3..d7bff5a5c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java @@ -29,20 +29,20 @@ import org.apache.fop.fo.flow.ExternalGraphic; */ public class ExternalGraphicLayoutManager extends AbstractGraphicsLayoutManager { - private ExternalGraphic fobj; - /** - * Constructor - * @param node the fo:external-graphic formatting object that creates the area + * Constructor. + * + * @param node + * the fo:external-graphic formatting object that creates the + * area */ public ExternalGraphicLayoutManager(ExternalGraphic node) { super(node); - fobj = node; } /** {@inheritDoc} */ protected Area getChildArea() { - return new Image(fobj.getSrc()); + return new Image(((ExternalGraphic) fobj).getSrc()); } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java b/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java index e7da50a9a..5f9365f83 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java @@ -29,20 +29,19 @@ import org.apache.fop.fo.flow.InstreamForeignObject; */ public class InstreamForeignObjectLM extends AbstractGraphicsLayoutManager { - private InstreamForeignObject fobj; - /** - * Constructor - * @param node the formatting object that creates this area + * Constructor. + * + * @param node + * the formatting object that creates this area */ public InstreamForeignObjectLM(InstreamForeignObject node) { super(node); - fobj = node; } /** {@inheritDoc} */ protected Area getChildArea() { - XMLObj child = (XMLObj) fobj.getChildXMLObj(); + XMLObj child = ((InstreamForeignObject) fobj).getChildXMLObj(); org.w3c.dom.Document doc = child.getDOMDocument(); String ns = child.getNamespaceURI(); -- cgit v1.2.3 From 7535be8128645c85c982b21817704aaa994465d8 Mon Sep 17 00:00:00 2001 From: Luca Furini Date: Mon, 16 Jun 2008 14:52:14 +0000 Subject: Fixing the PageBreakingAlgorithm, replacing calls to getLineWidth() with getLineWidth(int) so as to take into account each page's real height. This fixes the positioning of footnotes when the page bpd is not the same for all pages. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@668177 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/PageBreakingAlgorithm.java | 8 +- status.xml | 5 + .../footnote_changing-page-bpd.xml | 97 ++++++++++++++++++++ .../footnote_changing-page-bpd_2.xml | 102 +++++++++++++++++++++ 4 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 test/layoutengine/standard-testcases/footnote_changing-page-bpd.xml create mode 100644 test/layoutengine/standard-testcases/footnote_changing-page-bpd_2.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index a3155e102..9e0b42ecb 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -325,7 +325,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // this page contains some footnote citations // add the footnote separator width actualWidth += footnoteSeparatorLength.opt; - if (actualWidth + allFootnotes <= getLineWidth()) { + if (actualWidth + allFootnotes <= getLineWidth(activeNode.line)) { // there is enough space to insert all footnotes: // add the whole allFootnotes length actualWidth += allFootnotes; @@ -337,7 +337,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { = checkCanDeferOldFootnotes(pageNode, elementIndex)) || newFootnotes) && (footnoteSplit = getFootnoteSplit(pageNode, - getLineWidth() - actualWidth, canDeferOldFootnotes)) > 0) { + getLineWidth(activeNode.line) - actualWidth, canDeferOldFootnotes)) > 0) { // it is allowed to break or even defer footnotes if either: // - there are new footnotes in the last piece of content, and // there is space to add at least a piece of the first one @@ -683,7 +683,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { insertedFootnotesLength = lastNode.totalFootnotes; footnoteListIndex = lastNode.footnoteListIndex; footnoteElementIndex = lastNode.footnoteElementIndex; - int availableBPD = getLineWidth(); + int availableBPD = getLineWidth(lastNode.line); int split = 0; KnuthPageNode prevNode = lastNode; @@ -718,7 +718,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { removeNode(prevNode.line, prevNode); prevNode = node; - availableBPD = getLineWidth(); + availableBPD = getLineWidth(node.line); } } // create the last node diff --git a/status.xml b/status.xml index 02786adbc..cc345117f 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,11 @@ + + Fixed an inconsistency in footnote handling that led to unnecessary + empty areas in pages whose last normal line contains footnotes + when the page bpd is not the same for all pages. + + + + +

    + This test checks the positioning of footnotes when the body bpd changes + from page to page. +

    + + + + + + + + + + + + + + + + + + line 1. + line 2. + line 3. + line 4. + line 5. + line 6. + line 7. + line 8. + line 9. + line 10. + line 11. + line 12. + line 13. + line 14. + line 15. + line 16. + line 17. + + 1 + + 1 ftnt line 1/3. + ftnt line 2/3. + ftnt line 3/3. + + + + line 18. + line 19. + line 20. + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/footnote_changing-page-bpd_2.xml b/test/layoutengine/standard-testcases/footnote_changing-page-bpd_2.xml new file mode 100644 index 000000000..635cb171b --- /dev/null +++ b/test/layoutengine/standard-testcases/footnote_changing-page-bpd_2.xml @@ -0,0 +1,102 @@ + + + + + +

    + This test checks the positioning of footnotes when the body bpd changes + from page to page, in particular when footnote pages are created. +

    +
    + + + + + + + + + + + + + + + + + + + + + line 1. + line 2. + line 3. + line 4. + + 1 + + 1 ftnt line 1. + ftnt line 2. + ftnt line 3. + ftnt line 4. + ftnt line 5. + ftnt line 6. + ftnt line 7. + ftnt line 8. + ftnt line 9. + ftnt line 10. + ftnt line 11. + ftnt line 12. + ftnt line 13. + ftnt line 14. + ftnt line 15. + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -- cgit v1.2.3 From b74b9b4a0f90016f6a950cc92dd5fbab8a0f6dbb Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 17 Jun 2008 09:04:05 +0000 Subject: Wrong line number reported in the case of a line overflow. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@668576 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index b77f36f0d..87077ee77 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -387,9 +387,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager InlineLevelEventProducer eventProducer = InlineLevelEventProducer.Provider.get( getFObj().getUserAgent().getEventBroadcaster()); - eventProducer.lineOverflows(this, addedPositions + 1, + eventProducer.lineOverflows(this, bestActiveNode.line, -lack, getFObj().getLocator()); - String textDiff = (lack < -50000 ? "more than 50 points" : (-lack) + "mpt"); } } -- cgit v1.2.3 From 73d57c82452bac39a3b1fb19e8092f80dc254f94 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 19 Jun 2008 08:25:46 +0000 Subject: Simplifications and a Checkstyle fix. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@669423 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOEventHandler.java | 2 +- src/java/org/apache/fop/fo/FOTreeBuilder.java | 7 +++---- src/java/org/apache/fop/fo/properties/PageDimensionMaker.java | 5 ++--- 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 7521d398c..7aa6e8eeb 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -566,7 +566,7 @@ public abstract class FOEventHandler { * @param start Offset for characters to process. * @param length Portion of array to process. */ - public void characters(char data[], int start, int length) { + public void characters(char[] data, int start, int length) { } /** diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index 84abc4b8b..b1a0467b1 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -150,8 +150,7 @@ public class FOTreeBuilder extends DefaultHandler { this.delegate.endDocument(); if (this.rootFObj == null && empty) { FOValidationEventProducer eventProducer - = FOValidationEventProducer.Provider.get( - foEventHandler.getUserAgent().getEventBroadcaster()); + = FOValidationEventProducer.Provider.get(userAgent.getEventBroadcaster()); eventProducer.emptyDocument(this); } rootFObj = null; @@ -254,7 +253,7 @@ public class FOTreeBuilder extends DefaultHandler { || !localName.equals("root")) { FOValidationEventProducer eventProducer = FOValidationEventProducer.Provider.get( - foEventHandler.getUserAgent().getEventBroadcaster()); + userAgent.getEventBroadcaster()); eventProducer.invalidFORoot(this, FONode.getNodeString(namespaceURI, localName), getEffectiveLocator()); } @@ -379,7 +378,7 @@ public class FOTreeBuilder extends DefaultHandler { if (maker instanceof UnknownXMLObj.Maker) { FOValidationEventProducer eventProducer = FOValidationEventProducer.Provider.get( - foEventHandler.getUserAgent().getEventBroadcaster()); + userAgent.getEventBroadcaster()); eventProducer.unknownFormattingObject(this, currentFObj.getName(), new QName(namespaceURI, localName), getEffectiveLocator()); diff --git a/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java b/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java index 839ac7022..542dcac32 100644 --- a/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java +++ b/src/java/org/apache/fop/fo/properties/PageDimensionMaker.java @@ -23,7 +23,6 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; -import org.apache.fop.fo.properties.LengthProperty; /** * Custom Maker for page-height / page-width @@ -54,8 +53,8 @@ public class PageDimensionMaker extends LengthProperty.Maker { Property p = super.get(0, propertyList, tryInherit, tryDefault); FObj fo = propertyList.getFObj(); String fallbackValue = (propId == Constants.PR_PAGE_HEIGHT) - ? fo.getFOEventHandler().getUserAgent().getPageHeight() - : fo.getFOEventHandler().getUserAgent().getPageWidth(); + ? fo.getUserAgent().getPageHeight() + : fo.getUserAgent().getPageWidth(); if (p.getEnum() == Constants.EN_INDEFINITE) { int otherId = (propId == Constants.PR_PAGE_HEIGHT) -- cgit v1.2.3 From 9e3c365a2ccea075659a0c6ec18f3186b379afc1 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 19 Jun 2008 09:46:12 +0000 Subject: Separation of concerns: Split FOEventHandler into FOEventHandler and FOTreeBuilderContext. The latter contains stuff only used at tree-building stage. FOEventHandler is oriented towards output. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@669436 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOEventHandler.java | 80 --------------- src/java/org/apache/fop/fo/FONode.java | 11 ++- src/java/org/apache/fop/fo/FOText.java | 2 +- src/java/org/apache/fop/fo/FOTreeBuilder.java | 17 ++-- .../org/apache/fop/fo/FOTreeBuilderContext.java | 107 +++++++++++++++++++++ src/java/org/apache/fop/fo/FObj.java | 4 +- src/java/org/apache/fop/fo/FObjMixed.java | 6 +- .../apache/fop/fo/flow/AbstractRetrieveMarker.java | 14 +-- src/java/org/apache/fop/fo/flow/Marker.java | 10 +- src/java/org/apache/fop/fo/pagination/Root.java | 25 ++++- 10 files changed, 168 insertions(+), 108 deletions(-) create mode 100644 src/java/org/apache/fop/fo/FOTreeBuilderContext.java (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 7aa6e8eeb..880dd7868 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -19,9 +19,6 @@ package org.apache.fop.fo; -import java.util.HashSet; -import java.util.Set; - import org.xml.sax.SAXException; import org.apache.fop.apps.FOUserAgent; @@ -74,27 +71,6 @@ public abstract class FOEventHandler { */ protected FontInfo fontInfo; - /** - * The current set of id's in the FO tree. - * This is used so we know if the FO tree contains duplicates. - */ - private Set idReferences = new HashSet(); - - /** - * The property list maker. - */ - protected PropertyListMaker propertyListMaker; - - /** - * The XMLWhitespaceHandler for this tree - */ - protected XMLWhiteSpaceHandler whiteSpaceHandler = new XMLWhiteSpaceHandler(); - - /** - * Indicates whether processing descendants of a marker - */ - private boolean inMarker = false; - /** * Main constructor * @param foUserAgent the apps.FOUserAgent instance for this process @@ -105,14 +81,6 @@ public abstract class FOEventHandler { this.fontInfo.setEventListener(new FontEventAdapter(foUserAgent.getEventBroadcaster())); } - /** - * Retuns the set of ID references. - * @return the ID references - */ - public Set getIDReferences() { - return idReferences; - } - /** * Returns the User Agent object associated with this FOEventHandler. * @return the User Agent object @@ -129,54 +97,6 @@ public abstract class FOEventHandler { return this.fontInfo; } - /** - * Return the propertyListMaker. - * - * @return the currently active {@link PropertyListMaker} - */ - public PropertyListMaker getPropertyListMaker() { - return propertyListMaker; - } - - /** - * Set a new propertyListMaker. - * - * @param propertyListMaker the new {@link PropertyListMaker} to use - */ - public void setPropertyListMaker(PropertyListMaker propertyListMaker) { - this.propertyListMaker = propertyListMaker; - } - - /** - * Return the XMLWhiteSpaceHandler - * @return the whiteSpaceHandler - */ - public XMLWhiteSpaceHandler getXMLWhiteSpaceHandler() { - return whiteSpaceHandler; - } - - /** - * Switch to or from marker context - * (used by FOTreeBuilder when processing - * a marker) - * - * @param inMarker true if a marker is being processed; - * false otherwise - * - */ - protected void switchMarkerContext(boolean inMarker) { - this.inMarker = inMarker; - } - - /** - * Check whether in marker context - * - * @return true if a marker is being processed - */ - protected boolean inMarker() { - return this.inMarker; - } - /** * This method is called to indicate the start of a new document run. * @throws SAXException In case of a problem diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index 951e4c430..8ce570056 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -22,7 +22,6 @@ package org.apache.fop.fo; // Java import java.util.ListIterator; import java.util.Map; -import java.util.NoSuchElementException; import org.xml.sax.Attributes; import org.xml.sax.Locator; @@ -157,12 +156,20 @@ public abstract class FONode implements Cloneable { return parent.getFOEventHandler(); } + /** + * Returns the context class providing information used during FO tree building. + * @return the builder context + */ + public FOTreeBuilderContext getBuilderContext() { + return parent.getBuilderContext(); + } + /** * Indicates whether this node is a child of an fo:marker. * @return true if this node is a child of an fo:marker */ protected boolean inMarker() { - return getFOEventHandler().inMarker(); + return getBuilderContext().inMarker(); } /** diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index f21386075..c53937bb1 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -245,7 +245,7 @@ public class FOText extends FONode { * text-transform property. */ private void textTransform() { - if (getFOEventHandler().inMarker() + if (getBuilderContext().inMarker() || textTransform == Constants.EN_NONE) { return; } diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index b1a0467b1..264ef986d 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -66,6 +66,9 @@ public class FOTreeBuilder extends DefaultHandler { /** Current delegate ContentHandler to receive the SAX events */ protected ContentHandler delegate; + + /** Provides information used during tree building stage. */ + private FOTreeBuilderContext builderContext; /** The object that handles formatting and rendering to a stream */ private FOEventHandler foEventHandler; @@ -101,7 +104,8 @@ public class FOTreeBuilder extends DefaultHandler { //one of the RTF-, MIF- etc. Handlers. foEventHandler = foUserAgent.getRendererFactory().createFOEventHandler( foUserAgent, outputFormat, stream); - foEventHandler.setPropertyListMaker(new PropertyListMaker() { + builderContext = new FOTreeBuilderContext(); + builderContext.setPropertyListMaker(new PropertyListMaker() { public PropertyList make(FObj fobj, PropertyList parentPropertyList) { return new StaticPropertyList(fobj, parentPropertyList); } @@ -270,6 +274,7 @@ public class FOTreeBuilder extends DefaultHandler { foNode = fobjMaker.make(currentFObj); if (rootFObj == null) { rootFObj = (Root) foNode; + rootFObj.setBuilderContext(builderContext); rootFObj.setFOEventHandler(foEventHandler); } propertyList = foNode.createPropertyList( @@ -277,10 +282,10 @@ public class FOTreeBuilder extends DefaultHandler { foNode.processNode(localName, getEffectiveLocator(), attlist, propertyList); if (foNode.getNameId() == Constants.FO_MARKER) { - if (foEventHandler.inMarker()) { + if (builderContext.inMarker()) { nestedMarkerDepth++; } else { - foEventHandler.switchMarkerContext(true); + builderContext.switchMarkerContext(true); } } foNode.startOfNode(); @@ -309,7 +314,7 @@ public class FOTreeBuilder extends DefaultHandler { } currentFObj = foNode; - if (propertyList != null && !foEventHandler.inMarker()) { + if (propertyList != null && !builderContext.inMarker()) { currentPropertyList = propertyList; } } @@ -332,13 +337,13 @@ public class FOTreeBuilder extends DefaultHandler { if (currentPropertyList != null && currentPropertyList.getFObj() == currentFObj - && !foEventHandler.inMarker()) { + && !builderContext.inMarker()) { currentPropertyList = currentPropertyList.getParentPropertyList(); } if (currentFObj.getNameId() == Constants.FO_MARKER) { if (nestedMarkerDepth == 0) { - foEventHandler.switchMarkerContext(false); + builderContext.switchMarkerContext(false); } else { nestedMarkerDepth--; } diff --git a/src/java/org/apache/fop/fo/FOTreeBuilderContext.java b/src/java/org/apache/fop/fo/FOTreeBuilderContext.java new file mode 100644 index 000000000..0cbdd7797 --- /dev/null +++ b/src/java/org/apache/fop/fo/FOTreeBuilderContext.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo; + +import java.util.HashSet; +import java.util.Set; + +/** + * Context class providing information needed while building the FO tree. + */ +public class FOTreeBuilderContext { + + /** + * The current set of id's in the FO tree. + * This is used so we know if the FO tree contains duplicates. + */ + private Set idReferences = new HashSet(); + + /** + * The property list maker. + */ + protected PropertyListMaker propertyListMaker; + + /** + * The XMLWhitespaceHandler for this tree + */ + protected XMLWhiteSpaceHandler whiteSpaceHandler = new XMLWhiteSpaceHandler(); + + /** + * Indicates whether processing descendants of a marker + */ + private boolean inMarker = false; + + /** + * Returns the set of ID references. + * @return the ID references + */ + public Set getIDReferences() { + return idReferences; + } + + /** + * Return the propertyListMaker. + * + * @return the currently active {@link PropertyListMaker} + */ + public PropertyListMaker getPropertyListMaker() { + return propertyListMaker; + } + + /** + * Set a new propertyListMaker. + * + * @param propertyListMaker the new {@link PropertyListMaker} to use + */ + public void setPropertyListMaker(PropertyListMaker propertyListMaker) { + this.propertyListMaker = propertyListMaker; + } + + /** + * Return the XMLWhiteSpaceHandler + * @return the whiteSpaceHandler + */ + public XMLWhiteSpaceHandler getXMLWhiteSpaceHandler() { + return whiteSpaceHandler; + } + + /** + * Switch to or from marker context + * (used by FOTreeBuilder when processing + * a marker) + * + * @param inMarker true if a marker is being processed; + * false otherwise + * + */ + protected void switchMarkerContext(boolean inMarker) { + this.inMarker = inMarker; + } + + /** + * Check whether in marker context + * + * @return true if a marker is being processed + */ + protected boolean inMarker() { + return this.inMarker; + } + +} diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index 0bbec4d47..45b89dc8a 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -130,7 +130,7 @@ public abstract class FObj extends FONode implements Constants { */ protected PropertyList createPropertyList(PropertyList parent, FOEventHandler foEventHandler) throws FOPException { - return foEventHandler.getPropertyListMaker().make(this, parent); + return getBuilderContext().getPropertyListMaker().make(this, parent); } /** @@ -165,7 +165,7 @@ public abstract class FObj extends FONode implements Constants { */ private void checkId(String id) throws ValidationException { if (!inMarker() && !id.equals("")) { - Set idrefs = getFOEventHandler().getIDReferences(); + Set idrefs = getBuilderContext().getIDReferences(); if (!idrefs.contains(id)) { idrefs.add(id); } else { diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java index bf7383398..b0b9cd04b 100644 --- a/src/java/org/apache/fop/fo/FObjMixed.java +++ b/src/java/org/apache/fop/fo/FObjMixed.java @@ -68,7 +68,7 @@ public abstract class FObjMixed extends FObj { flushText(); if (!inMarker() || getNameId() == FO_MARKER) { - getFOEventHandler().whiteSpaceHandler + getBuilderContext().whiteSpaceHandler .handleWhiteSpace(this, currentTextNode); } super.endOfNode(); @@ -83,7 +83,7 @@ public abstract class FObjMixed extends FObj { * @param fobj the node for which to handle white-space */ protected static void handleWhiteSpaceFor(FObjMixed fobj) { - fobj.getFOEventHandler().getXMLWhiteSpaceHandler() + fobj.getBuilderContext().getXMLWhiteSpaceHandler() .handleWhiteSpace(fobj, fobj.currentTextNode); } @@ -159,7 +159,7 @@ public abstract class FObjMixed extends FObj { } } else { // handle white-space for all text up to here - getFOEventHandler().whiteSpaceHandler + getBuilderContext().whiteSpaceHandler .handleWhiteSpace(this, currentTextNode, child); currentTextNode = null; } diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index 83a0ddbdc..a276e4214 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -16,20 +16,22 @@ */ /* $Id$ */ + package org.apache.fop.fo.flow; +import java.util.Iterator; + +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FOText; import org.apache.fop.fo.FObj; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.flow.table.TableFObj; import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.apps.FOPException; -import org.xml.sax.Locator; - -import java.util.Iterator; +import org.apache.fop.fo.flow.table.TableFObj; /** * Abstract base class for the @@ -80,7 +82,7 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { } private PropertyList createPropertyListFor(FObj fo, PropertyList parent) { - return getFOEventHandler().getPropertyListMaker().make(fo, parent); + return getBuilderContext().getPropertyListMaker().make(fo, parent); } private void cloneSingleNode(FONode child, FONode newParent, diff --git a/src/java/org/apache/fop/fo/flow/Marker.java b/src/java/org/apache/fop/fo/flow/Marker.java index 7eda2101e..ea6721686 100644 --- a/src/java/org/apache/fop/fo/flow/Marker.java +++ b/src/java/org/apache/fop/fo/flow/Marker.java @@ -26,8 +26,8 @@ import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOTreeBuilderContext; import org.apache.fop.fo.FObj; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; @@ -84,10 +84,10 @@ public class Marker extends FObjMixed { /** {@inheritDoc} */ protected void startOfNode() { - FOEventHandler foEventHandler = getFOEventHandler(); + FOTreeBuilderContext builderContext = getBuilderContext(); // Push a new property list maker which will make MarkerPropertyLists. - savePropertyListMaker = foEventHandler.getPropertyListMaker(); - foEventHandler.setPropertyListMaker(new PropertyListMaker() { + savePropertyListMaker = builderContext.getPropertyListMaker(); + builderContext.setPropertyListMaker(new PropertyListMaker() { public PropertyList make(FObj fobj, PropertyList parentPropertyList) { PropertyList pList = new MarkerPropertyList(fobj, parentPropertyList); descendantPropertyLists.put(fobj, pList); @@ -100,7 +100,7 @@ public class Marker extends FObjMixed { protected void endOfNode() throws FOPException { super.endOfNode(); // Pop the MarkerPropertyList maker. - getFOEventHandler().setPropertyListMaker(savePropertyListMaker); + getBuilderContext().setPropertyListMaker(savePropertyListMaker); savePropertyListMaker = null; } diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java index 04014f6fc..c6346e9fb 100644 --- a/src/java/org/apache/fop/fo/pagination/Root.java +++ b/src/java/org/apache/fop/fo/pagination/Root.java @@ -27,6 +27,7 @@ import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOTreeBuilderContext; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; @@ -58,6 +59,11 @@ public class Root extends FObj { private int endingPageNumberOfPreviousSequence = 0; private int totalPagesGenerated = 0; + /** + * Context class used while building the FO tree. + */ + private FOTreeBuilderContext builderContext; + /** * FOEventHandler object for this FO Tree */ @@ -164,10 +170,23 @@ public class Root extends FObj { return foEventHandler; } - /** - * Gets the last page number generated by the previous page-sequence - * @return the last page number, 0 if no page sequences yet generated + /** + * Sets the builder context for this FO tree. + * @param context the builder context to be used */ + public void setBuilderContext(FOTreeBuilderContext context) { + this.builderContext = context; + } + + /** {@inheritDoc} */ + public FOTreeBuilderContext getBuilderContext() { + return this.builderContext; + } + + /** + * Gets the last page number generated by the previous page-sequence + * @return the last page number, 0 if no page sequences yet generated + */ public int getEndingPageNumberOfPreviousSequence() { return endingPageNumberOfPreviousSequence; } -- cgit v1.2.3 From 4ae76120cfae1310834b6a7a4e50fac833eb81d8 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 20 Jun 2008 09:18:56 +0000 Subject: Strict/loose validation of ordering somehow got lost in processing feedback branch merge. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@669835 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/Table.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index 5b96a668e..5f998b956 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -200,7 +200,9 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } else { tableFooterFound = true; if (tableBodyFound) { - nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)", true); + if (getUserAgent().validateStrictly()) { + nodesOutOfOrderError(loc, "fo:table-footer", "(table-body+)", true); + } if (!isSeparateBorderModel()) { TableEventProducer eventProducer = TableEventProducer.Provider.get( getUserAgent().getEventBroadcaster()); -- cgit v1.2.3 From 30d0f7a3e83bf0e2d7866ea623f64d6f8204a13e Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Sat, 21 Jun 2008 16:10:03 +0000 Subject: Moved the contents of TableBody into a new abstract base class TablePart, which is now subclassed by TableBody, TableHeader and TableFooter. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670217 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOEventHandler.java | 27 +- .../apache/fop/fo/flow/table/BorderResolver.java | 2 +- .../fo/flow/table/CollapsingBorderResolver.java | 10 +- .../fop/fo/flow/table/FixedColRowGroupBuilder.java | 6 +- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 4 +- .../apache/fop/fo/flow/table/RowGroupBuilder.java | 8 +- .../fop/fo/flow/table/SeparateBorderResolver.java | 2 +- src/java/org/apache/fop/fo/flow/table/Table.java | 12 +- .../org/apache/fop/fo/flow/table/TableBody.java | 236 +----------------- .../org/apache/fop/fo/flow/table/TableCell.java | 2 +- .../fop/fo/flow/table/TableCellContainer.java | 4 +- .../org/apache/fop/fo/flow/table/TableFooter.java | 6 +- .../org/apache/fop/fo/flow/table/TableHeader.java | 6 +- .../org/apache/fop/fo/flow/table/TablePart.java | 274 +++++++++++++++++++++ .../org/apache/fop/fo/flow/table/TableRow.java | 14 +- .../fo/flow/table/VariableColRowGroupBuilder.java | 4 +- .../org/apache/fop/layoutmgr/table/RowPainter.java | 4 +- .../layoutmgr/table/TableCellLayoutManager.java | 4 +- .../layoutmgr/table/TableContentLayoutManager.java | 23 +- .../fop/layoutmgr/table/TableContentPosition.java | 6 +- .../fop/layoutmgr/table/TableRowIterator.java | 6 +- src/java/org/apache/fop/render/rtf/RTFHandler.java | 62 +++-- .../fop/render/rtf/TableAttributesConverter.java | 5 +- 23 files changed, 397 insertions(+), 330 deletions(-) create mode 100644 src/java/org/apache/fop/fo/flow/table/TablePart.java (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 880dd7868..90856d57a 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -40,6 +40,9 @@ import org.apache.fop.fo.flow.PageNumberCitation; import org.apache.fop.fo.flow.PageNumberCitationLast; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableFooter; +import org.apache.fop.fo.flow.table.TableHeader; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableRow; @@ -257,44 +260,44 @@ public abstract class FOEventHandler { /** * - * @param th TableBody that is starting; + * @param header TableHeader that is starting; */ - public void startHeader(TableBody th) { + public void startHeader(TableHeader header) { } /** * - * @param th TableBody that is ending. + * @param header TableHeader that is ending. */ - public void endHeader(TableBody th) { + public void endHeader(TableHeader header) { } /** * - * @param tf TableFooter that is starting. + * @param footer TableFooter that is starting. */ - public void startFooter(TableBody tf) { + public void startFooter(TableFooter footer) { } /** * - * @param tf TableFooter that is ending. + * @param footer TableFooter that is ending. */ - public void endFooter(TableBody tf) { + public void endFooter(TableFooter footer) { } /** * - * @param tb TableBody that is starting. + * @param body TableBody that is starting. */ - public void startBody(TableBody tb) { + public void startBody(TableBody body) { } /** * - * @param tb TableBody that is ending. + * @param body TableBody that is ending. */ - public void endBody(TableBody tb) { + public void endBody(TableBody body) { } /** diff --git a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java index 5322b08d3..82bdac845 100644 --- a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java @@ -40,7 +40,7 @@ interface BorderResolver { * * @param part the part that has started */ - void startPart(TableBody part); + void startPart(TablePart part); /** * Receives notification of the end of a table-header/footer/body. diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java index 2d48380ee..3a887166a 100644 --- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java @@ -73,7 +73,7 @@ class CollapsingBorderResolver implements BorderResolver { */ private abstract class Resolver { - protected TableBody tablePart; + protected TablePart tablePart; protected boolean firstInPart; @@ -177,7 +177,7 @@ class CollapsingBorderResolver implements BorderResolver { } } - void startPart(TableBody part) { + void startPart(TablePart part) { tablePart = part; firstInPart = true; borderStartTableAndBody = collapsingBorderModel.determineWinner(table.borderStart, @@ -415,8 +415,8 @@ class CollapsingBorderResolver implements BorderResolver { } /** {@inheritDoc} */ - public void startPart(TableBody part) { - if (part.isTableHeader()) { + public void startPart(TablePart part) { + if (part instanceof TableHeader) { delegate = new ResolverInHeader(); } else { if (leadingBorders == null || table.omitHeaderAtBreak()) { @@ -427,7 +427,7 @@ class CollapsingBorderResolver implements BorderResolver { leadingBorders.add(border); } } - if (part.isTableFooter()) { + if (part instanceof TableFooter) { resolverInFooter = new ResolverInFooter(); delegate = resolverInFooter; } else { diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java index 0d24491d9..a7719528a 100644 --- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java @@ -143,8 +143,8 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void endRow(TableBody body) { - handleRowEnd(body); + void endRow(TablePart part) { + handleRowEnd(part); } private void handleRowEnd(TableCellContainer container) { @@ -172,7 +172,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void startTablePart(TableBody part) { + void startTablePart(TablePart part) { firstInPart = true; borderResolver.startPart(part); } diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 915208e2d..a4b064a53 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -78,12 +78,12 @@ public class PrimaryGridUnit extends GridUnit { * * @return the enclosing table part */ - public TableBody getTableBody() { + public TablePart getTablePart() { FONode node = cell.getParent(); if (node instanceof TableRow) { node = node.getParent(); } - return (TableBody) node; + return (TablePart) node; } public TableCellLayoutManager getCellLM() { diff --git a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java index c954be711..9748a77aa 100644 --- a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java @@ -57,7 +57,7 @@ abstract class RowGroupBuilder { /** * Receives notification of the end of the current row. If the current row finishes - * the row group, the {@link TableBody#addRowGroup(List)} method of the parent table + * the row group, the {@link TablePart#addRowGroup(List)} method of the parent table * part will be called. */ abstract void endTableRow(); @@ -65,21 +65,21 @@ abstract class RowGroupBuilder { /** * Receives notification of the end of the current row, when the source contains no * fo:table-row element. If the current row finishes the row group, the - * {@link TableBody#addRowGroup(List)} method of the given table part will be called. + * {@link TablePart#addRowGroup(List)} method of the given table part will be called. * *

    If the source does contain explicit fo:table-row elements, then the * {@link #endTableRow()} method will be called instead.

    * * @param part the part containing the current row */ - abstract void endRow(TableBody part); + abstract void endRow(TablePart part); /** * Receives notification of the start of a table-header/footer/body. * * @param part the part being started */ - abstract void startTablePart(TableBody part); + abstract void startTablePart(TablePart part); /** * Receives notification of the end of a table-header/footer/body. The current diff --git a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java index c6d46ecf5..afd05823b 100644 --- a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java +++ b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java @@ -31,7 +31,7 @@ class SeparateBorderResolver implements BorderResolver { } /** {@inheritDoc} */ - public void startPart(TableBody part) { + public void startPart(TablePart part) { } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index 5f998b956..771ec0c64 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -76,8 +76,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { private ColumnNumberManager columnNumberManager = new ColumnNumberManager(); /** the table-header and -footer */ - private TableBody tableHeader = null; - private TableBody tableFooter = null; + private TableHeader tableHeader = null; + private TableFooter tableFooter = null; /** used for validation */ private boolean tableColumnFound = false; @@ -279,10 +279,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } switch (childId) { case FO_TABLE_FOOTER: - tableFooter = (TableBody) child; + tableFooter = (TableFooter) child; break; case FO_TABLE_HEADER: - tableHeader = (TableBody) child; + tableHeader = (TableHeader) child; break; default: super.addChildNode(child); @@ -404,12 +404,12 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } /** @return the body for the table-header. */ - public TableBody getTableHeader() { + public TableHeader getTableHeader() { return tableHeader; } /** @return the body for the table-footer. */ - public TableBody getTableFooter() { + public TableFooter getTableFooter() { return tableFooter; } diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index b4e48d2e6..ee5024240 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -15,53 +15,17 @@ * limitations under the License. */ -/* $Id$ */ +/* $Id: $ */ package org.apache.fop.fo.flow.table; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import org.xml.sax.Attributes; -import org.xml.sax.Locator; - -import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.properties.CommonBorderPaddingBackground; /** * Class modelling the
    * fo:table-body object. */ -public class TableBody extends TableCellContainer { - // The value of properties relevant for fo:table-body. - private CommonBorderPaddingBackground commonBorderPaddingBackground; - // Unused but valid items, commented out for performance: - // private CommonAccessibility commonAccessibility; - // private CommonAural commonAural; - // private CommonRelativePosition commonRelativePosition; - // private int visibility; - // End of property values - - /** - * used for validation - */ - protected boolean tableRowsFound = false; - protected boolean tableCellsFound = false; - - private boolean firstRow = true; - - private boolean rowsStarted = false; - - private boolean lastCellEndsRow = true; - - /** The last encountered table-row. */ - private TableRow lastRow; - - private List rowGroups = new LinkedList(); +public class TableBody extends TablePart { /** * Create a TableBody instance with the given {@link FONode} @@ -72,200 +36,4 @@ public class TableBody extends TableCellContainer { super(parent); } - /** {@inheritDoc} */ - public void bind(PropertyList pList) throws FOPException { - commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); - super.bind(pList); - } - - /** {@inheritDoc} */ - public void processNode(String elementName, Locator locator, - Attributes attlist, PropertyList pList) - throws FOPException { - if (!inMarker()) { - Table t = getTable(); - if (t.hasExplicitColumns()) { - int size = t.getNumberOfColumns(); - pendingSpans = new ArrayList(size); - for (int i = 0; i < size; i++) { - pendingSpans.add(null); - } - } else { - pendingSpans = new ArrayList(); - } - columnNumberManager = new ColumnNumberManager(); - } - super.processNode(elementName, locator, attlist, pList); - } - - /** {@inheritDoc} */ - public void startOfNode() throws FOPException { - super.startOfNode(); - getFOEventHandler().startBody(this); - } - - /** {@inheritDoc} */ - public void endOfNode() throws FOPException { - - if (!inMarker()) { - pendingSpans = null; - columnNumberManager = null; - } - - getFOEventHandler().endBody(this); - - if (!(tableRowsFound || tableCellsFound)) { - missingChildElementError("marker* (table-row+|table-cell+)", true); - getParent().removeChild(this); - } else { - finishLastRowGroup(); - } - } - - /** {@inheritDoc} */ - TableBody getTablePart() { - return this; - } - - protected void finishLastRowGroup() throws ValidationException { - if (!inMarker()) { - RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder(); - if (tableRowsFound) { - rowGroupBuilder.endTableRow(); - } else if (!lastCellEndsRow) { - rowGroupBuilder.endRow(this); - } - try { - rowGroupBuilder.endTablePart(); - } catch (ValidationException e) { - e.setLocator(locator); - throw e; - } - } - } - - /** - * {@inheritDoc} - *
    XSL Content Model: marker* (table-row+|table-cell+) - */ - protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI)) { - if (localName.equals("marker")) { - if (tableRowsFound || tableCellsFound) { - nodesOutOfOrderError(loc, "fo:marker", "(table-row+|table-cell+)"); - } - } else if (localName.equals("table-row")) { - tableRowsFound = true; - if (tableCellsFound) { - TableEventProducer eventProducer = TableEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.noMixRowsAndCells(this, getName(), getLocator()); - } - } else if (localName.equals("table-cell")) { - tableCellsFound = true; - if (tableRowsFound) { - TableEventProducer eventProducer = TableEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.noMixRowsAndCells(this, getName(), getLocator()); - } - } else { - invalidChildError(loc, nsURI, localName); - } - } - } - - /** {@inheritDoc} */ - protected void addChildNode(FONode child) throws FOPException { - if (!inMarker()) { - switch (child.getNameId()) { - case FO_TABLE_ROW: - if (!rowsStarted) { - getTable().getRowGroupBuilder().startTablePart(this); - } else { - columnNumberManager.prepareForNextRow(pendingSpans); - getTable().getRowGroupBuilder().endTableRow(); - } - rowsStarted = true; - lastRow = (TableRow) child; - getTable().getRowGroupBuilder().startTableRow(lastRow); - break; - case FO_TABLE_CELL: - if (!rowsStarted) { - getTable().getRowGroupBuilder().startTablePart(this); - } - rowsStarted = true; - TableCell cell = (TableCell) child; - addTableCellChild(cell, firstRow); - lastCellEndsRow = cell.endsRow(); - if (lastCellEndsRow) { - firstRow = false; - columnNumberManager.prepareForNextRow(pendingSpans); - getTable().getRowGroupBuilder().endRow(this); - } - break; - default: - //nop - } - } - super.addChildNode(child); - } - - void addRowGroup(List rowGroup) { - rowGroups.add(rowGroup); - } - - public List getRowGroups() { - return rowGroups; - } - - /** - * Get the {@link CommonBorderPaddingBackground} instance attached - * to this TableBody. - * @return the {@link CommonBorderPaddingBackground} instance. - */ - public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { - return commonBorderPaddingBackground; - } - - /** {@inheritDoc} */ - public String getLocalName() { - return "table-body"; - } - - /** - * {@inheritDoc} - * @return {@link org.apache.fop.fo.Constants#FO_TABLE_BODY} - */ - public int getNameId() { - return FO_TABLE_BODY; - } - - protected boolean isTableHeader() { - return false; - } - - protected boolean isTableFooter() { - return false; - } - - /** - * @param obj table row in question - * @return true if the given table row is the first row of this body. - */ - public boolean isFirst(TableRow obj) { - return (firstChild == null - || firstChild == obj); - } - - void signalNewRow() { - if (rowsStarted) { - firstRow = false; - if (!lastCellEndsRow) { - columnNumberManager.prepareForNextRow(pendingSpans); - getTable().getRowGroupBuilder().endRow(this); - } - } - } - } diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java index 2781bf082..2603ba8b4 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCell.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java @@ -81,7 +81,7 @@ public class TableCell extends TableFObj { startsRow = pList.get(PR_STARTS_ROW).getEnum(); // For properly computing columnNumber if (startsRow() && getParent().getNameId() != FO_TABLE_ROW) { - ((TableBody) getParent()).signalNewRow(); + ((TablePart) getParent()).signalNewRow(); } endsRow = pList.get(PR_ENDS_ROW).getEnum(); columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue(); diff --git a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java index de9f271b5..1d1a29b35 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java @@ -95,9 +95,9 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb /** * Returns the enclosing table-header/footer/body of this container. * - * @return this for TableBody, or the parent element for TableRow + * @return this for TablePart, or the parent element for TableRow */ - abstract TableBody getTablePart(); + abstract TablePart getTablePart(); /** {@inheritDoc} */ public ColumnNumberManager getColumnNumberManager() { diff --git a/src/java/org/apache/fop/fo/flow/table/TableFooter.java b/src/java/org/apache/fop/fo/flow/table/TableFooter.java index d05824e95..8f166b321 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFooter.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFooter.java @@ -28,7 +28,7 @@ import org.apache.fop.fo.FONode; * Class modelling the * fo:table-footer object. */ -public class TableFooter extends TableBody { +public class TableFooter extends TablePart { /** * Create a TableFooter instance with the given {@link FONode} @@ -67,8 +67,4 @@ public class TableFooter extends TableBody { return FO_TABLE_FOOTER; } - /** {@inheritDoc} */ - protected boolean isTableFooter() { - return true; - } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java index 252ba1b8b..5939fba73 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java +++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java @@ -28,7 +28,7 @@ import org.apache.fop.fo.FONode; * Class modelling the * fo:table-header object. */ -public class TableHeader extends TableBody { +public class TableHeader extends TablePart { /** * Create a TableHeader instance with the given {@link FONode} @@ -66,8 +66,4 @@ public class TableHeader extends TableBody { return FO_TABLE_HEADER; } - /** {@inheritDoc} */ - protected boolean isTableHeader() { - return true; - } } diff --git a/src/java/org/apache/fop/fo/flow/table/TablePart.java b/src/java/org/apache/fop/fo/flow/table/TablePart.java new file mode 100644 index 000000000..677a7a17c --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/table/TablePart.java @@ -0,0 +1,274 @@ +/* + * 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: TableBody.java 655614 2008-05-12 19:37:39Z vhennebert $ */ + +package org.apache.fop.fo.flow.table; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.properties.CommonBorderPaddingBackground; + +/** + * An abstract base class modelling a TablePart + * (i.e. fo:table-header, fo:table-footer and fo:table-body). + */ +public abstract class TablePart extends TableCellContainer { + // The value of properties relevant for fo:table-body. + private CommonBorderPaddingBackground commonBorderPaddingBackground; + // Unused but valid items, commented out for performance: + // private CommonAccessibility commonAccessibility; + // private CommonAural commonAural; + // private CommonRelativePosition commonRelativePosition; + // private int visibility; + // End of property values + + /** + * used for validation + */ + protected boolean tableRowsFound = false; + protected boolean tableCellsFound = false; + + private boolean firstRow = true; + + private boolean rowsStarted = false; + + private boolean lastCellEndsRow = true; + + /** The last encountered table-row. */ + private TableRow lastRow; + + private List rowGroups = new LinkedList(); + + /** + * Create a TablePart instance with the given {@link FONode} + * as parent. + * @param parent FONode that is the parent of the object + */ + public TablePart(FONode parent) { + super(parent); + } + + /** {@inheritDoc} */ + public void bind(PropertyList pList) throws FOPException { + commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); + super.bind(pList); + } + + /** {@inheritDoc} */ + public void processNode(String elementName, Locator locator, + Attributes attlist, PropertyList pList) + throws FOPException { + if (!inMarker()) { + Table t = getTable(); + if (t.hasExplicitColumns()) { + int size = t.getNumberOfColumns(); + pendingSpans = new ArrayList(size); + for (int i = 0; i < size; i++) { + pendingSpans.add(null); + } + } else { + pendingSpans = new ArrayList(); + } + columnNumberManager = new ColumnNumberManager(); + } + super.processNode(elementName, locator, attlist, pList); + } + + /** {@inheritDoc} */ + public void startOfNode() throws FOPException { + super.startOfNode(); + if (this instanceof TableHeader) { + getFOEventHandler().startHeader((TableHeader)this); + } else if (this instanceof TableFooter) { + getFOEventHandler().startFooter((TableFooter)this); + } else { + getFOEventHandler().startBody((TableBody)this); + } + } + + /** {@inheritDoc} */ + public void endOfNode() throws FOPException { + if (!inMarker()) { + pendingSpans = null; + columnNumberManager = null; + } + + if (this instanceof TableHeader) { + getFOEventHandler().endHeader((TableHeader)this); + } else if (this instanceof TableFooter) { + getFOEventHandler().endFooter((TableFooter)this); + } else { + getFOEventHandler().endBody((TableBody)this); + } + + if (!(tableRowsFound || tableCellsFound)) { + missingChildElementError("marker* (table-row+|table-cell+)", true); + getParent().removeChild(this); + } else { + finishLastRowGroup(); + } + } + + /** {@inheritDoc} */ + TablePart getTablePart() { + return this; + } + + protected void finishLastRowGroup() throws ValidationException { + if (!inMarker()) { + RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder(); + if (tableRowsFound) { + rowGroupBuilder.endTableRow(); + } else if (!lastCellEndsRow) { + rowGroupBuilder.endRow(this); + } + try { + rowGroupBuilder.endTablePart(); + } catch (ValidationException e) { + e.setLocator(locator); + throw e; + } + } + } + + /** + * {@inheritDoc} + *
    XSL Content Model: marker* (table-row+|table-cell+) + */ + protected void validateChildNode(Locator loc, String nsURI, String localName) + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if (localName.equals("marker")) { + if (tableRowsFound || tableCellsFound) { + nodesOutOfOrderError(loc, "fo:marker", "(table-row+|table-cell+)"); + } + } else if (localName.equals("table-row")) { + tableRowsFound = true; + if (tableCellsFound) { + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noMixRowsAndCells(this, getName(), getLocator()); + } + } else if (localName.equals("table-cell")) { + tableCellsFound = true; + if (tableRowsFound) { + TableEventProducer eventProducer = TableEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.noMixRowsAndCells(this, getName(), getLocator()); + } + } else { + invalidChildError(loc, nsURI, localName); + } + } + } + + /** {@inheritDoc} */ + protected void addChildNode(FONode child) throws FOPException { + if (!inMarker()) { + switch (child.getNameId()) { + case FO_TABLE_ROW: + if (!rowsStarted) { + getTable().getRowGroupBuilder().startTablePart(this); + } else { + columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().endTableRow(); + } + rowsStarted = true; + lastRow = (TableRow) child; + getTable().getRowGroupBuilder().startTableRow(lastRow); + break; + case FO_TABLE_CELL: + if (!rowsStarted) { + getTable().getRowGroupBuilder().startTablePart(this); + } + rowsStarted = true; + TableCell cell = (TableCell) child; + addTableCellChild(cell, firstRow); + lastCellEndsRow = cell.endsRow(); + if (lastCellEndsRow) { + firstRow = false; + columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().endRow(this); + } + break; + default: + //nop + } + } + super.addChildNode(child); + } + + void addRowGroup(List rowGroup) { + rowGroups.add(rowGroup); + } + + public List getRowGroups() { + return rowGroups; + } + + /** + * Get the {@link CommonBorderPaddingBackground} instance attached + * to this TableBody. + * @return the {@link CommonBorderPaddingBackground} instance. + */ + public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { + return commonBorderPaddingBackground; + } + + /** {@inheritDoc} */ + public String getLocalName() { + return "table-body"; + } + + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_BODY} + */ + public int getNameId() { + return FO_TABLE_BODY; + } + + /** + * @param obj table row in question + * @return true if the given table row is the first row of this body. + */ + public boolean isFirst(TableRow obj) { + return (firstChild == null + || firstChild == obj); + } + + void signalNewRow() { + if (rowsStarted) { + firstRow = false; + if (!lastCellEndsRow) { + columnNumberManager.prepareForNextRow(pendingSpans); + getTable().getRowGroupBuilder().endRow(this); + } + } + } + +} diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java index 3be794fbd..8b5fc6bd4 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableRow.java +++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java @@ -79,9 +79,9 @@ public class TableRow extends TableCellContainer { public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { if (!inMarker()) { - TableBody body = (TableBody) parent; - pendingSpans = body.pendingSpans; - columnNumberManager = body.columnNumberManager; + TablePart part = (TablePart) parent; + pendingSpans = part.pendingSpans; + columnNumberManager = part.columnNumberManager; } super.processNode(elementName, locator, attlist, pList); } @@ -90,8 +90,8 @@ public class TableRow extends TableCellContainer { protected void addChildNode(FONode child) throws FOPException { if (!inMarker()) { TableCell cell = (TableCell) child; - TableBody body = (TableBody) getParent(); - addTableCellChild(cell, body.isFirst(this)); + TablePart part = (TablePart) getParent(); + addTableCellChild(cell, part.isFirst(this)); } super.addChildNode(child); } @@ -129,8 +129,8 @@ public class TableRow extends TableCellContainer { } /** {@inheritDoc} */ - TableBody getTablePart() { - return (TableBody) parent; + TablePart getTablePart() { + return (TablePart) parent; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java index d59870f0a..23c16d1f2 100644 --- a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java +++ b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java @@ -82,7 +82,7 @@ class VariableColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void endRow(final TableBody part) { + void endRow(final TablePart part) { events.add(new Event() { public void play(RowGroupBuilder rowGroupBuilder) { rowGroupBuilder.endRow(part); @@ -91,7 +91,7 @@ class VariableColRowGroupBuilder extends RowGroupBuilder { } /** {@inheritDoc} */ - void startTablePart(final TableBody part) { + void startTablePart(final TablePart part) { events.add(new Event() { public void play(RowGroupBuilder rowGroupBuilder) { rowGroupBuilder.startTablePart(part); diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index d432c7657..38f1a7b30 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -32,7 +32,7 @@ import org.apache.fop.fo.flow.table.ConditionalBorder; 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.TableBody; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthElement; @@ -94,7 +94,7 @@ class RowPainter { this.firstRowOnPageIndex = -1; } - void startTablePart(TableBody tablePart) { + void startTablePart(TablePart tablePart) { CommonBorderPaddingBackground background = tablePart.getCommonBorderPaddingBackground(); if (background.hasBackground()) { tablePartBackground = background; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 43b34e4b7..52915c008 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -31,7 +31,7 @@ import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; 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.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableRow; @@ -439,7 +439,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager -startIndent); } - TableBody body = primaryGridUnit.getTableBody(); + TablePart body = primaryGridUnit.getTablePart(); if (body.getCommonBorderPaddingBackground().hasBackground()) { painter.registerPartBackgroundArea( getBackgroundArea(paddingRectBPD, borderBeforeWidth)); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 9b4a03a67..80e904f8f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr.table; -import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -35,7 +34,7 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.flow.table.EffRow; 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.TablePart; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListUtils; @@ -324,7 +323,7 @@ public class TableContentLayoutManager implements PercentBaseContext { this.usedBPD = 0; RowPainter painter = new RowPainter(this, layoutContext); - List tablePositions = new ArrayList(); + List tablePositions = new java.util.ArrayList(); List headerElements = null; List footerElements = null; Position firstPos = null; @@ -417,9 +416,9 @@ public class TableContentLayoutManager implements PercentBaseContext { } } - private void addHeaderFooterAreas(List elements, TableBody part, RowPainter painter, + private void addHeaderFooterAreas(List elements, TablePart part, RowPainter painter, boolean lastOnPage) { - List lst = new ArrayList(elements.size()); + List lst = new java.util.ArrayList(elements.size()); for (Iterator iter = new KnuthPossPosIter(elements); iter.hasNext();) { Position pos = (Position) iter.next(); /* @@ -446,32 +445,32 @@ public class TableContentLayoutManager implements PercentBaseContext { private void addBodyAreas(Iterator iterator, RowPainter painter, boolean lastOnPage) { painter.startBody(); - List lst = new ArrayList(); + List lst = new java.util.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(); + TablePart part = pos.getTablePart(); lst.add(pos); while (iterator.hasNext()) { pos = (TableContentPosition) iterator.next(); - if (pos.getTableBody() != body) { - addTablePartAreas(lst, painter, body, isFirstPos, true, false, false); + if (pos.getTablePart() != part) { + addTablePartAreas(lst, painter, part, isFirstPos, true, false, false); isFirstPos = true; lst.clear(); - body = pos.getTableBody(); + part = pos.getTablePart(); } 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); + addTablePartAreas(lst, painter, part, isFirstPos, isLastPos, true, lastOnPage); painter.endBody(); } /** * Adds the areas corresponding to a single fo:table-header/footer/body element. */ - private void addTablePartAreas(List positions, RowPainter painter, TableBody body, + private void addTablePartAreas(List positions, RowPainter painter, TablePart body, boolean isFirstPos, boolean isLastPos, boolean lastInBody, boolean lastOnPage) { getTableLM().getCurrentPV().addMarkers(body.getMarkers(), true, isFirstPos, isLastPos); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java index 260b8cfdf..62d25fcb1 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java @@ -22,7 +22,7 @@ package org.apache.fop.layoutmgr.table; import java.util.List; import org.apache.fop.fo.flow.table.EffRow; -import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.Position; @@ -80,8 +80,8 @@ class TableContentPosition extends Position { return row; } - TableBody getTableBody() { - return ((CellPart) cellParts.get(0)).pgu.getTableBody(); + TablePart getTablePart() { + return ((CellPart) cellParts.get(0)).pgu.getTablePart(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java index 62e308c13..282cd0fd5 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java @@ -28,6 +28,7 @@ import org.apache.fop.fo.FONode.FONodeIterator; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; /** @@ -69,7 +70,7 @@ public class TableRowIterator { case FOOTER: rowGroupsIter = table.getTableFooter().getRowGroups().iterator(); break; - default: + case BODY: List rowGroupsList = new LinkedList(); // TODO this is ugly for (FONodeIterator iter = table.getChildNodes(); iter.hasNext();) { @@ -79,6 +80,9 @@ public class TableRowIterator { } } rowGroupsIter = rowGroupsList.iterator(); + break; + default: + throw new IllegalArgumentException("Unrecognised TablePart: " + tablePart); } } diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 05aade551..75f524f72 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -76,6 +76,8 @@ import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fo.flow.PageNumber; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TableFooter; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.flow.table.TableHeader; @@ -611,25 +613,29 @@ public class RTFHandler extends FOEventHandler { /** * {@inheritDoc} */ - public void startHeader(TableBody th) { + public void startHeader(TableHeader header) { + startPart(header); } /** * {@inheritDoc} */ - public void endHeader(TableBody th) { + public void endHeader(TableHeader header) { + endPart(header); } /** * {@inheritDoc} */ - public void startFooter(TableBody tf) { + public void startFooter(TableFooter footer) { + startPart(footer); } /** * {@inheritDoc} */ - public void endFooter(TableBody tf) { + public void endFooter(TableFooter footer) { + endPart(footer); } /** @@ -687,31 +693,25 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ - public void startBody(TableBody tb) { + private void startPart(TablePart part) { if (bDefer) { return; } try { - RtfAttributes atts = TableAttributesConverter.convertTableBodyAttributes(tb); + RtfAttributes atts = TableAttributesConverter.convertTablePartAttributes(part); RtfTable tbl = (RtfTable)builderContext.getContainer(RtfTable.class, true, this); tbl.setHeaderAttribs(atts); } catch (IOException ioe) { handleIOTrouble(ioe); } catch (Exception e) { - log.error("startBody: " + e.getMessage()); + log.error("startPart: " + e.getMessage()); throw new RuntimeException(e.getMessage()); - } + } } - /** - * {@inheritDoc} - */ - public void endBody(TableBody tb) { + private void endPart(TablePart tb) { if (bDefer) { return; } @@ -722,9 +722,25 @@ public class RTFHandler extends FOEventHandler { } catch (IOException ioe) { handleIOTrouble(ioe); } catch (Exception e) { - log.error("endBody: " + e.getMessage()); + log.error("endPart: " + e.getMessage()); throw new RuntimeException(e.getMessage()); - } + } + } + + + /** + * {@inheritDoc} + */ + public void startBody(TableBody body) { + startPart(body); + } + + + /** + * {@inheritDoc} + */ + public void endBody(TableBody body) { + endPart(body); } /** @@ -1607,6 +1623,18 @@ public class RTFHandler extends FOEventHandler { } else { endTable( (Table) foNode); } + } else if (foNode instanceof TableHeader) { + if (bStart) { + startHeader( (TableHeader) foNode); + } else { + endHeader( (TableHeader) foNode); + } + } else if (foNode instanceof TableFooter) { + if (bStart) { + startFooter( (TableFooter) foNode); + } else { + endFooter( (TableFooter) foNode); + } } else if (foNode instanceof TableBody) { if (bStart) { startBody( (TableBody) foNode); diff --git a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java index 677832418..a28d91d36 100644 --- a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java +++ b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java @@ -24,12 +24,11 @@ import java.awt.Color; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.fo.flow.table.TableBody; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableHeader; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; -import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes; @@ -91,7 +90,7 @@ public final class TableAttributesConverter { * * @throws ConverterException On convertion error */ - static RtfAttributes convertTableBodyAttributes(TableBody fobj) + static RtfAttributes convertTablePartAttributes(TablePart part) throws FOPException { FOPRtfAttributes attrib = new FOPRtfAttributes(); return attrib; -- cgit v1.2.3 From 72c8655231d048d4c01ea77ca3277d1334e839db Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 09:07:47 +0000 Subject: Addition to r670217 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670323 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/table/TableBody.java | 25 ++++++++++++++ .../org/apache/fop/fo/flow/table/TableFooter.java | 8 ++--- .../org/apache/fop/fo/flow/table/TableHeader.java | 8 ++--- .../org/apache/fop/fo/flow/table/TablePart.java | 40 ++-------------------- 4 files changed, 34 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index ee5024240..c3cf772ac 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -20,6 +20,7 @@ package org.apache.fop.fo.flow.table; import org.apache.fop.fo.FONode; +import org.apache.fop.apps.FOPException; /** * Class modelling the @@ -36,4 +37,28 @@ public class TableBody extends TablePart { super(parent); } + /** {@inheritDoc} */ + public void startOfNode() throws FOPException { + super.startOfNode(); + getFOEventHandler().startBody(this); + } + + /** {@inheritDoc} */ + public void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endBody(this); + } + + /** {@inheritDoc} */ + public String getLocalName() { + return "table-body"; + } + + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_TABLE_BODY} + */ + public int getNameId() { + return FO_TABLE_BODY; + } } diff --git a/src/java/org/apache/fop/fo/flow/table/TableFooter.java b/src/java/org/apache/fop/fo/flow/table/TableFooter.java index 8f166b321..886001e76 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFooter.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFooter.java @@ -43,15 +43,13 @@ public class TableFooter extends TablePart { /** {@inheritDoc} */ public void startOfNode() throws FOPException { super.startOfNode(); + getFOEventHandler().startFooter(this); } /** {@inheritDoc} */ public void endOfNode() throws FOPException { - if (!(tableRowsFound || tableCellsFound)) { - missingChildElementError("marker* (table-row+|table-cell+)"); - } else { - finishLastRowGroup(); - } + super.endOfNode(); + getFOEventHandler().endFooter(this); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java index 5939fba73..c42d79b46 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java +++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java @@ -42,15 +42,13 @@ public class TableHeader extends TablePart { /** {@inheritDoc} */ public void startOfNode() throws FOPException { super.startOfNode(); + getFOEventHandler().startHeader(this); } /** {@inheritDoc} */ public void endOfNode() throws FOPException { - if (!(tableRowsFound || tableCellsFound)) { - missingChildElementError("marker* (table-row+|table-cell+)"); - } else { - finishLastRowGroup(); - } + super.endOfNode(); + getFOEventHandler().endHeader(this); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/table/TablePart.java b/src/java/org/apache/fop/fo/flow/table/TablePart.java index 677a7a17c..67af69e03 100644 --- a/src/java/org/apache/fop/fo/flow/table/TablePart.java +++ b/src/java/org/apache/fop/fo/flow/table/TablePart.java @@ -58,9 +58,6 @@ public abstract class TablePart extends TableCellContainer { private boolean lastCellEndsRow = true; - /** The last encountered table-row. */ - private TableRow lastRow; - private List rowGroups = new LinkedList(); /** @@ -82,6 +79,7 @@ public abstract class TablePart extends TableCellContainer { public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + if (!inMarker()) { Table t = getTable(); if (t.hasExplicitColumns()) { @@ -96,35 +94,17 @@ public abstract class TablePart extends TableCellContainer { columnNumberManager = new ColumnNumberManager(); } super.processNode(elementName, locator, attlist, pList); - } - /** {@inheritDoc} */ - public void startOfNode() throws FOPException { - super.startOfNode(); - if (this instanceof TableHeader) { - getFOEventHandler().startHeader((TableHeader)this); - } else if (this instanceof TableFooter) { - getFOEventHandler().startFooter((TableFooter)this); - } else { - getFOEventHandler().startBody((TableBody)this); - } } /** {@inheritDoc} */ public void endOfNode() throws FOPException { + super.endOfNode(); if (!inMarker()) { pendingSpans = null; columnNumberManager = null; } - if (this instanceof TableHeader) { - getFOEventHandler().endHeader((TableHeader)this); - } else if (this instanceof TableFooter) { - getFOEventHandler().endFooter((TableFooter)this); - } else { - getFOEventHandler().endBody((TableBody)this); - } - if (!(tableRowsFound || tableCellsFound)) { missingChildElementError("marker* (table-row+|table-cell+)", true); getParent().removeChild(this); @@ -198,8 +178,7 @@ public abstract class TablePart extends TableCellContainer { getTable().getRowGroupBuilder().endTableRow(); } rowsStarted = true; - lastRow = (TableRow) child; - getTable().getRowGroupBuilder().startTableRow(lastRow); + getTable().getRowGroupBuilder().startTableRow((TableRow)child); break; case FO_TABLE_CELL: if (!rowsStarted) { @@ -239,19 +218,6 @@ public abstract class TablePart extends TableCellContainer { return commonBorderPaddingBackground; } - /** {@inheritDoc} */ - public String getLocalName() { - return "table-body"; - } - - /** - * {@inheritDoc} - * @return {@link org.apache.fop.fo.Constants#FO_TABLE_BODY} - */ - public int getNameId() { - return FO_TABLE_BODY; - } - /** * @param obj table row in question * @return true if the given table row is the first row of this body. -- cgit v1.2.3 From fca3dcefc389f5c96faf7d032f98909e5484df37 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 09:28:56 +0000 Subject: Minor javadoc correction git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670325 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/expr/PropertyException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/expr/PropertyException.java b/src/java/org/apache/fop/fo/expr/PropertyException.java index 16055a738..d16d1c8ff 100644 --- a/src/java/org/apache/fop/fo/expr/PropertyException.java +++ b/src/java/org/apache/fop/fo/expr/PropertyException.java @@ -37,7 +37,7 @@ public class PropertyException extends FOPException { /** * Constructor - * @param the Exception causing this PropertyException + * @param cause the Exception causing this PropertyException */ public PropertyException(Exception cause) { super(cause); -- cgit v1.2.3 From 1dcb12e27c42ada6068d65dcb84f0e2901bc19c2 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 10:53:51 +0000 Subject: Avoid StackOverflow on TableColumn.toString() during debugging. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670335 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/table/TableColumn.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java index 6916e090b..025f5a74f 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java +++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java @@ -239,7 +239,7 @@ public class TableColumn extends TableFObj { sb.append(" number-columns-spanned=") .append(getNumberColumnsSpanned()); } - sb.append(" column-width=").append(getColumnWidth()); + sb.append(" column-width=").append(((Property)getColumnWidth()).getString()); return sb.toString(); } -- cgit v1.2.3 From cebba418a9d2acb940cb30e3cab714e3e6dc2767 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 11:01:27 +0000 Subject: Minor tweak: use XG Commons version of the interface git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670336 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java index f08b1f433..bdfd1fc29 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java @@ -22,7 +22,7 @@ package org.apache.fop.fo.extensions.xmp; import java.io.Serializable; import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.apache.fop.util.XMLizable; +import org.apache.xmlgraphics.util.XMLizable; import org.apache.xmlgraphics.xmp.Metadata; import org.apache.xmlgraphics.xmp.XMPConstants; import org.xml.sax.ContentHandler; -- cgit v1.2.3 From 79fbd6dfcc97b2b0e5c5b82cd2fae1057a0f331a Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 11:18:03 +0000 Subject: Changed FONode.addCharacters() signature to match the characters() event (use 'length' as a parameter instead of 'end') git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670341 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FONode.java | 4 ++-- src/java/org/apache/fop/fo/FOText.java | 3 +-- src/java/org/apache/fop/fo/FOTreeBuilder.java | 2 +- src/java/org/apache/fop/fo/FObjMixed.java | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index 8ce570056..4f84dd717 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -274,12 +274,12 @@ public abstract class FONode implements Cloneable { * * @param data array of characters containing text to be added * @param start starting array element to add - * @param end ending array element to add + * @param length number of elements to add * @param pList currently applicable PropertyList * @param locator location in the XSL-FO source file. * @throws FOPException if there's a problem during processing */ - protected void addCharacters(char[] data, int start, int end, + protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) throws FOPException { // ignore diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index c53937bb1..ac3babb42 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -123,10 +123,9 @@ public class FOText extends FONode { } /** {@inheritDoc} */ - protected void addCharacters(char[] data, int start, int end, + protected void addCharacters(char[] data, int start, int length, PropertyList list, Locator locator) throws FOPException { - int length = end - start; int calength = 0; char[] nca; if (ca != null) { diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index 264ef986d..574e5eb79 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -360,7 +360,7 @@ public class FOTreeBuilder extends DefaultHandler { public void characters(char[] data, int start, int length) throws FOPException { if (currentFObj != null) { - currentFObj.addCharacters(data, start, start + length, + currentFObj.addCharacters(data, start, length, currentPropertyList, getEffectiveLocator()); } } diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java index b0b9cd04b..4b8bdde73 100644 --- a/src/java/org/apache/fop/fo/FObjMixed.java +++ b/src/java/org/apache/fop/fo/FObjMixed.java @@ -50,7 +50,7 @@ public abstract class FObjMixed extends FObj { } /** {@inheritDoc} */ - protected void addCharacters(char[] data, int start, int end, + protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) throws FOPException { if (ft == null) { @@ -60,7 +60,7 @@ public abstract class FObjMixed extends FObj { ft.bind(pList); } } - ft.addCharacters(data, start, end, null, null); + ft.addCharacters(data, start, length, null, null); } /** {@inheritDoc} */ -- cgit v1.2.3 From ebee3981d4f0356d283bb25f2541b1e8a4129f1e Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 11:28:06 +0000 Subject: Changed signature for static handleWhiteSpaceFor(), and used internally to make the code a bit more compact git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670344 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FObjMixed.java | 11 +++++------ src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java | 7 ++++--- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java index 4b8bdde73..c1fcfe4ff 100644 --- a/src/java/org/apache/fop/fo/FObjMixed.java +++ b/src/java/org/apache/fop/fo/FObjMixed.java @@ -68,8 +68,7 @@ public abstract class FObjMixed extends FObj { flushText(); if (!inMarker() || getNameId() == FO_MARKER) { - getBuilderContext().whiteSpaceHandler - .handleWhiteSpace(this, currentTextNode); + handleWhiteSpaceFor(this, null); } super.endOfNode(); } @@ -81,10 +80,11 @@ public abstract class FObjMixed extends FObj { * to trigger 'end-of-node' white-space handling) * * @param fobj the node for which to handle white-space + * @param nextChild the next child to be added */ - protected static void handleWhiteSpaceFor(FObjMixed fobj) { + protected static void handleWhiteSpaceFor(FObjMixed fobj, FONode nextChild) { fobj.getBuilderContext().getXMLWhiteSpaceHandler() - .handleWhiteSpace(fobj, fobj.currentTextNode); + .handleWhiteSpace(fobj, fobj.currentTextNode, nextChild); } /** @@ -159,8 +159,7 @@ public abstract class FObjMixed extends FObj { } } else { // handle white-space for all text up to here - getBuilderContext().whiteSpaceHandler - .handleWhiteSpace(this, currentTextNode, child); + handleWhiteSpaceFor(this, child); currentTextNode = null; } } diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index a276e4214..ae06d8399 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -111,7 +111,7 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { addChildTo(newChild, (FObj) newParent); if (newChild.getNameId() == FO_TABLE) { Table t = (Table) child; - cloneSubtree(t.getColumns().listIterator(), + cloneSubtree(t.getColumns().iterator(), newChild, marker, newPropertyList); cloneSingleNode(t.getTableHeader(), newChild, marker, newPropertyList); @@ -129,8 +129,9 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { ft.bind(parentPropertyList); addChildTo(newChild, (FObj) newParent); } + // trigger 'end-of-node' white-space handling if (newChild instanceof FObjMixed) { - handleWhiteSpaceFor((FObjMixed) newChild); + handleWhiteSpaceFor((FObjMixed) newChild, null); } } } @@ -169,7 +170,7 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { } cloneSubtree(marker.getChildNodes(), this, marker, propertyList); - handleWhiteSpaceFor(this); + handleWhiteSpaceFor(this, null); } /** -- cgit v1.2.3 From cd2b9b2a43f6e199da46cbf98faadb17f0939307 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 19:19:17 +0000 Subject: Correction: characters() expects a 'length' not an 'endIndex' git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670401 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOText.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index ac3babb42..7ae73d7e0 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -183,7 +183,7 @@ public class FOText extends FONode { /** {@inheritDoc} */ protected void endOfNode() throws FOPException { textTransform(); - getFOEventHandler().characters(ca, startIndex, endIndex); + getFOEventHandler().characters(ca, startIndex, endIndex - startIndex); } /** -- cgit v1.2.3 From d93f3a8b778d818ac56f5e378d3d58755ebf25da Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 20:18:27 +0000 Subject: Very minor tweak: simplify conditional git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670409 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/RecursiveCharIterator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/RecursiveCharIterator.java b/src/java/org/apache/fop/fo/RecursiveCharIterator.java index 22ece76f3..a4aa28e37 100644 --- a/src/java/org/apache/fop/fo/RecursiveCharIterator.java +++ b/src/java/org/apache/fop/fo/RecursiveCharIterator.java @@ -113,7 +113,7 @@ public class RecursiveCharIterator extends CharIterator { */ public boolean hasNext() { while (curCharIter != null) { - if (curCharIter.hasNext() == false) { + if (!curCharIter.hasNext()) { getNextCharIter(); } else { return true; -- cgit v1.2.3 From e04c31d665be016ffe9e36efb9e5f41917e30069 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 20:38:28 +0000 Subject: Deleted deprecated interface; unused after r670336 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670411 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/util/XMLizable.java | 35 ----------------------------- 1 file changed, 35 deletions(-) delete mode 100644 src/java/org/apache/fop/util/XMLizable.java (limited to 'src') diff --git a/src/java/org/apache/fop/util/XMLizable.java b/src/java/org/apache/fop/util/XMLizable.java deleted file mode 100644 index a16131989..000000000 --- a/src/java/org/apache/fop/util/XMLizable.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.util; - -/* - * Copied from Apache Excalibur: - * https://svn.apache.org/repos/asf/excalibur/trunk/components/xmlutil/ - * src/java/org/apache/excalibur/xml/sax/XMLizable.java - */ - -/** - * This interface can be implemented by classes willing to provide an XML representation - * of their current state as SAX events. - * @deprecated Use the interface in Apache XML Graphics Commons instead. - */ -public interface XMLizable extends org.apache.xmlgraphics.util.XMLizable { - -} -- cgit v1.2.3 From d02d89fc246b1ba9ee398f69ac15664656420cb2 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 20:57:43 +0000 Subject: Partial fix of FOEventHandler call sequence (see also Bugzilla #45237): call startOfNode() after addChildNode() moved initialization for tableFOs to processNode() moved finishing code to a finalizeNode() method (which is now also used by AbstractRetrieveMarker) restored protected status of startOfNode()/endOfNode() in fo.flow.table package git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670412 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FONode.java | 21 ++++++++++++- src/java/org/apache/fop/fo/FOTreeBuilder.java | 2 +- .../apache/fop/fo/flow/AbstractRetrieveMarker.java | 12 ++------ src/java/org/apache/fop/fo/flow/table/Table.java | 35 +++++++++++----------- .../org/apache/fop/fo/flow/table/TableBody.java | 4 +-- .../org/apache/fop/fo/flow/table/TableCell.java | 17 +++++++---- .../org/apache/fop/fo/flow/table/TableFObj.java | 16 ++++------ .../org/apache/fop/fo/flow/table/TableFooter.java | 4 +-- .../org/apache/fop/fo/flow/table/TableHeader.java | 4 +-- .../org/apache/fop/fo/flow/table/TablePart.java | 9 +++--- .../org/apache/fop/fo/flow/table/TableRow.java | 15 ++++++---- 11 files changed, 77 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index 4f84dd717..87d3bfa3c 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -298,11 +298,16 @@ public abstract class FONode implements Cloneable { * Primarily used for making final content model validation checks * and/or informing the {@link FOEventHandler} that the end of this FO * has been reached. + * The default implementation simply calls {@link #finalizeNode()}, without + * sending any event to the {@link FOEventHandler}. + *
    Note: the recommended way to override this method in subclasses is + *

    super.endOfNode(); // invoke finalizeNode() + *
    getFOEventHandler().endXXX(); // send endOfNode() notification
    * * @throws FOPException if there's a problem during processing */ protected void endOfNode() throws FOPException { - // do nothing by default + this.finalizeNode(); } /** @@ -326,6 +331,20 @@ public abstract class FONode implements Cloneable { //nop } + /** + * Finalize this node. + * This method can be overridden by subclasses to perform finishing + * tasks (cleanup, validation checks, ...) without triggering + * endXXX() events in the {@link FOEventHandler}. + * The method is called by the default {@link #endOfNode()} + * implementation. + * + * @throws FOPException in case there was an error + */ + public void finalizeNode() throws FOPException { + // do nothing by default + } + /** * Return the parent node of this node * diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index 574e5eb79..d8f712212 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -288,7 +288,6 @@ public class FOTreeBuilder extends DefaultHandler { builderContext.switchMarkerContext(true); } } - foNode.startOfNode(); } catch (IllegalArgumentException e) { throw new SAXException(e); } @@ -317,6 +316,7 @@ public class FOTreeBuilder extends DefaultHandler { if (propertyList != null && !builderContext.inMarker()) { currentPropertyList = propertyList; } + currentFObj.startOfNode(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index ae06d8399..0ce648c3a 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -102,12 +102,6 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { getLocator(), pList, newPropertyList); - if (newChild instanceof TableFObj) { - // TODO calling startOfNode (and endOfNode, below) on other fobjs may - // have undesirable side-effects. This is really ugly and will need to - // be addressed sooner or later - ((TableFObj) newChild).startOfNode(); - } addChildTo(newChild, (FObj) newParent); if (newChild.getNameId() == FO_TABLE) { Table t = (Table) child; @@ -120,15 +114,13 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { } cloneSubtree(child.getChildNodes(), newChild, marker, newPropertyList); - if (newChild instanceof TableFObj) { - // TODO this is ugly - ((TableFObj) newChild).endOfNode(); - } } else if (child instanceof FOText) { FOText ft = (FOText) newChild; ft.bind(parentPropertyList); addChildTo(newChild, (FObj) newParent); } + + newChild.finalizeNode(); // trigger 'end-of-node' white-space handling if (newChild instanceof FObjMixed) { handleWhiteSpaceFor((FObjMixed) newChild, null); diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index 771ec0c64..9feb77c9c 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -157,10 +157,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { this.propList = pList; } - /** - * {@inheritDoc} - */ - public void startOfNode() throws FOPException { + /** {@inheritDoc} */ + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startTable(this); } @@ -218,11 +216,15 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { } } - /** - * {@inheritDoc} - */ - public void endOfNode() throws FOPException { + /** {@inheritDoc} */ + protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endTable(this); + } + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { + if (!tableBodyFound) { missingChildElementError( "(marker*,table-column*,table-header?,table-footer?" @@ -244,13 +246,10 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { this.propList = null; rowGroupBuilder = null; } - getFOEventHandler().endTable(this); - + } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { int childId = child.getNameId(); @@ -523,17 +522,17 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder { return FO_TABLE; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public FONode clone(FONode parent, boolean removeChildren) throws FOPException { Table clone = (Table) super.clone(parent, removeChildren); - clone.columnsFinalized = false; if (removeChildren) { clone.columns = new ArrayList(); + clone.columnsFinalized = false; + clone.columnNumberManager = new ColumnNumberManager(); clone.tableHeader = null; clone.tableFooter = null; + clone.rowGroupBuilder = null; } return clone; } diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index c3cf772ac..b4071e255 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -38,13 +38,13 @@ public class TableBody extends TablePart { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startBody(this); } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { + protected void endOfNode() throws FOPException { super.endOfNode(); getFOEventHandler().endBody(this); } diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java index 2603ba8b4..21da54128 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableCell.java +++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java @@ -91,17 +91,24 @@ public class TableCell extends TableFObj { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startCell(this); } /** * Make sure content model satisfied, if so then tell the - * FOEventHandler that we are at the end of the flow. + * FOEventHandler that we are at the end of the table-cell. * {@inheritDoc} */ - public void endOfNode() throws FOPException { + protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endCell(this); + } + + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { + if (!blockItemFound) { missingChildElementError("marker* (%block;)+", true); } @@ -111,9 +118,9 @@ public class TableCell extends TableFObj { getUserAgent().getEventBroadcaster()); eventProducer.startEndRowUnderTableRowWarning(this, getLocator()); } - getFOEventHandler().endCell(this); + } - + /** * {@inheritDoc} *
    XSL Content Model: marker* (%block;)+ diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 016046ae2..370bb9de4 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -34,6 +34,8 @@ import org.apache.fop.fo.properties.NumberProperty; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.PropertyMaker; import org.apache.fop.layoutmgr.table.CollapsingBorderModel; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; /** * Common base class for table-related FOs @@ -207,8 +209,8 @@ public abstract class TableFObj extends FObj { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { - super.startOfNode(); + public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); Table table = getTable(); if (!inMarker() && !table.isSeparateBorderModel()) { collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table @@ -216,15 +218,7 @@ public abstract class TableFObj extends FObj { setCollapsedBorders(); } } - - /* - * TODO made public so that RetrieveMarker can access it. - */ - /** {@inheritDoc} */ - public void endOfNode() throws FOPException { - super.endOfNode(); - } - + /** * Prepares the borders of this element if the collapsing-border model is in use. * Conflict resolution with parent elements is done where applicable. diff --git a/src/java/org/apache/fop/fo/flow/table/TableFooter.java b/src/java/org/apache/fop/fo/flow/table/TableFooter.java index 886001e76..a89a2e431 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFooter.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFooter.java @@ -41,13 +41,13 @@ public class TableFooter extends TablePart { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startFooter(this); } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { + protected void endOfNode() throws FOPException { super.endOfNode(); getFOEventHandler().endFooter(this); } diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java index c42d79b46..7f4173754 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java +++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java @@ -40,13 +40,13 @@ public class TableHeader extends TablePart { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startHeader(this); } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { + protected void endOfNode() throws FOPException { super.endOfNode(); getFOEventHandler().endHeader(this); } diff --git a/src/java/org/apache/fop/fo/flow/table/TablePart.java b/src/java/org/apache/fop/fo/flow/table/TablePart.java index 67af69e03..4d20db8c4 100644 --- a/src/java/org/apache/fop/fo/flow/table/TablePart.java +++ b/src/java/org/apache/fop/fo/flow/table/TablePart.java @@ -79,7 +79,8 @@ public abstract class TablePart extends TableCellContainer { public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { - + + super.processNode(elementName, locator, attlist, pList); if (!inMarker()) { Table t = getTable(); if (t.hasExplicitColumns()) { @@ -93,13 +94,11 @@ public abstract class TablePart extends TableCellContainer { } columnNumberManager = new ColumnNumberManager(); } - super.processNode(elementName, locator, attlist, pList); - + } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { - super.endOfNode(); + public void finalizeNode() throws FOPException { if (!inMarker()) { pendingSpans = null; columnNumberManager = null; diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java index 8b5fc6bd4..ac6eafc2f 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableRow.java +++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java @@ -78,12 +78,12 @@ public class TableRow extends TableCellContainer { /** {@inheritDoc} */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); if (!inMarker()) { TablePart part = (TablePart) parent; pendingSpans = part.pendingSpans; columnNumberManager = part.columnNumberManager; } - super.processNode(elementName, locator, attlist, pList); } /** {@inheritDoc} */ @@ -97,13 +97,19 @@ public class TableRow extends TableCellContainer { } /** {@inheritDoc} */ - public void startOfNode() throws FOPException { + protected void startOfNode() throws FOPException { super.startOfNode(); getFOEventHandler().startRow(this); } /** {@inheritDoc} */ - public void endOfNode() throws FOPException { + protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().endRow(this); + } + + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { if (firstChild == null) { missingChildElementError("(table-cell+)"); } @@ -111,9 +117,8 @@ public class TableRow extends TableCellContainer { pendingSpans = null; columnNumberManager = null; } - getFOEventHandler().endRow(this); } - + /** * {@inheritDoc} String, String) *
    XSL Content Model: (table-cell+) -- cgit v1.2.3 From 07c5dcf7162f75c1c176d67df52bf0c50f462f78 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 22:10:55 +0000 Subject: Switch FOText to use a java.nio.CharBuffer, and implement the CharSequence interface. TextLayoutManager no longer duplicates the char array, operates on the FOText (charAt(i)) Additionally: endOfNode() for FOText and Character deferred until after white-space handling. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670422 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOText.java | 442 +++++++++++---------- src/java/org/apache/fop/fo/FOTreeBuilder.java | 19 +- src/java/org/apache/fop/fo/FObjMixed.java | 154 +++---- .../apache/fop/fo/flow/AbstractRetrieveMarker.java | 8 +- .../apache/fop/layoutmgr/LayoutManagerMapping.java | 4 +- .../fop/layoutmgr/inline/TextLayoutManager.java | 124 +++--- src/java/org/apache/fop/render/rtf/RTFHandler.java | 2 +- 7 files changed, 406 insertions(+), 347 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index 7ae73d7e0..217997ace 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -20,6 +20,7 @@ package org.apache.fop.fo; import java.awt.Color; +import java.nio.CharBuffer; import java.util.NoSuchElementException; import org.xml.sax.Locator; @@ -33,48 +34,17 @@ import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.SpaceProperty; +import org.apache.fop.util.CharUtilities; /** * A text node (PCDATA) in the formatting object tree. - * - * Unfortunately the BufferManager implementation holds - * onto references to the character data in this object - * longer than the lifetime of the object itself, causing - * excessive memory consumption and OOM errors. */ -public class FOText extends FONode { +public class FOText extends FONode implements CharSequence { - /** - * the character array containing the text - */ - public char[] ca; - - /** - * The starting valid index of the ca array - * to be processed. - * - * This value is originally equal to 0, but becomes - * incremented during leading whitespace removal by the flow.Block class, - * via the TextCharIterator.remove() method below. - */ - public int startIndex = 0; + /** the CharBuffer containing the text */ + private CharBuffer charBuffer; - /** - * The ending valid index of the ca array - * to be processed. - * - * This value is originally equal to ca.length, but becomes - * decremented during between-word whitespace removal by the - * XMLWhiteSpaceHandler via the TextCharIterator.remove() - * method below. - */ - public int endIndex = 0; - - /** properties relevant for PCDATA */ - /* TODO: these are basically always the same as the parent FObj or FObjMixed - * so maybe those can be removed, and the accessors could - * dispatch the call to the parent? - */ + /** properties relevant for #PCDATA */ private CommonFont commonFont; private CommonHyphenation commonHyphenation; private Color color; @@ -105,10 +75,10 @@ public class FOText extends FONode { * which FOText nodes are descendants of the same block. */ private Block ancestorBlock = null; - + /** Holds the text decoration values. May be null */ private CommonTextDecoration textDecoration; - + private static final int IS_WORD_CHAR_FALSE = 0; private static final int IS_WORD_CHAR_TRUE = 1; private static final int IS_WORD_CHAR_MAYBE = 2; @@ -126,33 +96,58 @@ public class FOText extends FONode { protected void addCharacters(char[] data, int start, int length, PropertyList list, Locator locator) throws FOPException { - int calength = 0; - char[] nca; - if (ca != null) { - calength = ca.length; - nca = new char[calength + length]; - System.arraycopy(ca, 0, nca, 0, calength); + if (this.charBuffer == null) { + // buffer not yet initialized, do so now + this.charBuffer = CharBuffer.allocate(length); } else { - nca = new char[length]; + // allocate a larger buffer, and transfer contents + int newLength = this.charBuffer.limit() + length; + CharBuffer newBuffer = CharBuffer.allocate(newLength); + this.charBuffer.rewind(); + newBuffer.put(this.charBuffer); + this.charBuffer = newBuffer; } - System.arraycopy(data, start, nca, calength, length); - endIndex = nca.length; - this.ca = nca; - } + // append characters + this.charBuffer.put(data, start, length); + + } /** - * {@inheritDoc} + * Return the array of characters for this instance. + * + * @return a char array containing the text */ + public char[] getCharArray() { + + if (this.charBuffer == null) { + return null; + } + + if (this.charBuffer.hasArray()) { + return this.charBuffer.array(); + } + + // only if the buffer implementation has + // no accessible backing array, return a new one + char[] ca = new char[this.charBuffer.limit()]; + this.charBuffer.rewind(); + this.charBuffer.get(ca); + return ca; + + } + + /** {@inheritDoc} */ public FONode clone(FONode parent, boolean removeChildren) throws FOPException { FOText ft = (FOText) super.clone(parent, removeChildren); if (removeChildren) { - //not really removing, but just make sure the char array - //pointed to is really a different one, and reset any - //possible whitespace-handling effects - if (ca != null) { - ft.ca = new char[ca.length]; - System.arraycopy(ca, 0, ft.ca, 0, ca.length); + // not really removing, just make sure the char buffer + // pointed to is really a different one + if (this.charBuffer != null) { + ft.charBuffer = CharBuffer.allocate(this.charBuffer.limit()); + this.charBuffer.rewind(); + ft.charBuffer.put(this.charBuffer); + ft.charBuffer.rewind(); } } ft.prevFOTextThisBlock = null; @@ -161,29 +156,33 @@ public class FOText extends FONode { return ft; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { - commonFont = pList.getFontProps(); - commonHyphenation = pList.getHyphenationProps(); - color = pList.get(Constants.PR_COLOR).getColor(getUserAgent()); - keepTogether = pList.get(Constants.PR_KEEP_TOGETHER).getKeep(); - lineHeight = pList.get(Constants.PR_LINE_HEIGHT).getSpace(); - letterSpacing = pList.get(Constants.PR_LETTER_SPACING); - whiteSpaceCollapse = pList.get(Constants.PR_WHITE_SPACE_COLLAPSE).getEnum(); - whiteSpaceTreatment = pList.get(Constants.PR_WHITE_SPACE_TREATMENT).getEnum(); - textTransform = pList.get(Constants.PR_TEXT_TRANSFORM).getEnum(); - wordSpacing = pList.get(Constants.PR_WORD_SPACING); - wrapOption = pList.get(Constants.PR_WRAP_OPTION).getEnum(); - textDecoration = pList.getTextDecorationProps(); - baselineShift = pList.get(Constants.PR_BASELINE_SHIFT).getLength(); + this.commonFont = pList.getFontProps(); + this.commonHyphenation = pList.getHyphenationProps(); + this.color = pList.get(Constants.PR_COLOR).getColor(getUserAgent()); + this.keepTogether = pList.get(Constants.PR_KEEP_TOGETHER).getKeep(); + this.lineHeight = pList.get(Constants.PR_LINE_HEIGHT).getSpace(); + this.letterSpacing = pList.get(Constants.PR_LETTER_SPACING); + this.whiteSpaceCollapse = pList.get(Constants.PR_WHITE_SPACE_COLLAPSE).getEnum(); + this.whiteSpaceTreatment = pList.get(Constants.PR_WHITE_SPACE_TREATMENT).getEnum(); + this.textTransform = pList.get(Constants.PR_TEXT_TRANSFORM).getEnum(); + this.wordSpacing = pList.get(Constants.PR_WORD_SPACING); + this.wrapOption = pList.get(Constants.PR_WRAP_OPTION).getEnum(); + this.textDecoration = pList.getTextDecorationProps(); + this.baselineShift = pList.get(Constants.PR_BASELINE_SHIFT).getLength(); } /** {@inheritDoc} */ protected void endOfNode() throws FOPException { + super.endOfNode(); + getFOEventHandler().characters( + this.getCharArray(), 0, this.charBuffer.limit()); + } + + /** {@inheritDoc} */ + public void finalizeNode() { textTransform(); - getFOEventHandler().characters(ca, startIndex, endIndex - startIndex); } /** @@ -197,16 +196,20 @@ public class FOText extends FONode { */ public boolean willCreateArea() { if (whiteSpaceCollapse == Constants.EN_FALSE - && endIndex - startIndex > 0) { + && this.charBuffer.limit() > 0) { return true; } - for (int i = startIndex; i < endIndex; i++) { - char ch = ca[i]; - if (!((ch == ' ') - || (ch == '\n') - || (ch == '\r') - || (ch == '\t'))) { // whitespace + char ch; + this.charBuffer.rewind(); + while (this.charBuffer.hasRemaining()) { + ch = this.charBuffer.get(); + if (!((ch == CharUtilities.SPACE) + || (ch == CharUtilities.LINEFEED_CHAR) + || (ch == CharUtilities.CARRIAGE_RETURN) + || (ch == CharUtilities.TAB))) { + // not whitespace + this.charBuffer.rewind(); return true; } } @@ -221,7 +224,7 @@ public class FOText extends FONode { } /** - * This method is run as part of the ancestor Block's flushText(), to + * This method is run as part of the ancestor Block's flushText(), to * create xref pointers to the previous FOText objects within the same Block * @param ancestorBlock the ancestor fo:block */ @@ -229,7 +232,7 @@ public class FOText extends FONode { this.ancestorBlock = ancestorBlock; // if the last FOText is a sibling, point to it, and have it point here if (ancestorBlock.lastFOTextProcessed != null) { - if (ancestorBlock.lastFOTextProcessed.ancestorBlock + if (ancestorBlock.lastFOTextProcessed.ancestorBlock == this.ancestorBlock) { prevFOTextThisBlock = ancestorBlock.lastFOTextProcessed; prevFOTextThisBlock.nextFOTextThisBlock = this; @@ -240,16 +243,47 @@ public class FOText extends FONode { } /** - * This method is run as part of the Constructor, to handle the - * text-transform property. + * This method is run as part of endOfNode(), to handle the + * text-transform property for accumulated FOText */ private void textTransform() { - if (getBuilderContext().inMarker() + if (getBuilderContext().inMarker() || textTransform == Constants.EN_NONE) { return; } - for (int i = 0; i < endIndex; i++) { - ca[i] = charTransform(i); + + this.charBuffer.rewind(); + CharBuffer tmp = this.charBuffer.slice(); + char c; + int lim = this.charBuffer.limit(); + int pos = -1; + while (++pos < lim) { + c = this.charBuffer.get(); + switch (textTransform) { + case Constants.EN_UPPERCASE: + tmp.put(Character.toUpperCase(c)); + break; + case Constants.EN_LOWERCASE: + tmp.put(Character.toLowerCase(c)); + break; + case Constants.EN_CAPITALIZE: + if (isStartOfWord(pos)) { + /* + Use toTitleCase here. Apparently, some languages use + a different character to represent a letter when using + initial caps than when all of the letters in the word + are capitalized. We will try to let Java handle this. + */ + tmp.put(Character.toTitleCase(c)); + } else { + tmp.put(c); + } + break; + default: + //should never happen as the property subsystem catches that case + assert false; + //nop + } } } @@ -260,7 +294,7 @@ public class FOText extends FONode { * well, such as word-spacing. The definition of "word" is somewhat ambiguous * and appears to be definable by the user agent. * - * @param i index into ca[] + * @param i index into charBuffer * * @return True if the character at this location is the start of a new * word. @@ -268,33 +302,33 @@ public class FOText extends FONode { private boolean isStartOfWord(int i) { char prevChar = getRelativeCharInBlock(i, -1); /* All we are really concerned about here is of what type prevChar - is. If inputChar is not part of a word, then the Java - conversions will (we hope) simply return inputChar. - */ - switch (isWordChar(prevChar)) { - case IS_WORD_CHAR_TRUE: - return false; - case IS_WORD_CHAR_FALSE: - return true; - /* "MAYBE" implies that additional context is needed. An example is a - * single-quote, either straight or closing, which might be interpreted - * as a possessive or a contraction, or might be a closing quote. + * is. If inputChar is not part of a word, then the Java + * conversions will (we hope) simply return inputChar. */ - case IS_WORD_CHAR_MAYBE: - char prevPrevChar = getRelativeCharInBlock(i, -2); - switch (isWordChar(prevPrevChar)) { + switch (isWordChar(prevChar)) { case IS_WORD_CHAR_TRUE: return false; case IS_WORD_CHAR_FALSE: return true; + /* "MAYBE" implies that additional context is needed. An example is a + * single-quote, either straight or closing, which might be interpreted + * as a possessive or a contraction, or might be a closing quote. + */ case IS_WORD_CHAR_MAYBE: - return true; + char prevPrevChar = getRelativeCharInBlock(i, -2); + switch (isWordChar(prevPrevChar)) { + case IS_WORD_CHAR_TRUE: + return false; + case IS_WORD_CHAR_FALSE: + return true; + case IS_WORD_CHAR_MAYBE: + return true; + default: + return false; + } default: return false; } - default: - return false; - } } /** @@ -303,7 +337,7 @@ public class FOText extends FONode { * block as one unit, allowing text in adjoining FOText objects to be * returned if the parameters are outside of the current object. * - * @param i index into ca[] + * @param i index into the CharBuffer * @param offset signed integer with relative position within the * block of the character to return. To return the character immediately * preceding i, pass -1. To return the character immediately after i, @@ -312,30 +346,34 @@ public class FOText extends FONode { * the offset points to an area outside of the block. */ private char getRelativeCharInBlock(int i, int offset) { + + int charIndex = i + offset; // The easy case is where the desired character is in the same FOText - if (((i + offset) >= 0) && ((i + offset) <= this.endIndex)) { - return ca[i + offset]; + if (charIndex >= 0 && charIndex < this.length()) { + return this.charAt(i + offset); } + // For now, we can't look at following FOText nodes if (offset > 0) { - return '\u0000'; - } + return CharUtilities.NULL_CHAR; + } + // Remaining case has the text in some previous FOText node boolean foundChar = false; - char charToReturn = '\u0000'; + char charToReturn = CharUtilities.NULL_CHAR; FOText nodeToTest = this; int remainingOffset = offset + i; while (!foundChar) { if (nodeToTest.prevFOTextThisBlock == null) { - foundChar = true; break; } nodeToTest = nodeToTest.prevFOTextThisBlock; - if ((nodeToTest.endIndex + remainingOffset) >= 0) { - charToReturn = nodeToTest.ca[nodeToTest.endIndex + remainingOffset]; + int diff = nodeToTest.length() + remainingOffset - 1; + if (diff >= 0) { + charToReturn = nodeToTest.charAt(diff); foundChar = true; } else { - remainingOffset = remainingOffset + nodeToTest.endIndex; + remainingOffset += diff; } } return charToReturn; @@ -365,39 +403,6 @@ public class FOText extends FONode { return ancestorBlock; } - /** - * Transforms one character in ca[] using the text-transform property. - * - * @param i the index into ca[] - * @return char with transformed value - */ - private char charTransform(int i) { - switch (textTransform) { - /* put NONE first, as this is probably the common case */ - case Constants.EN_NONE: - return ca[i]; - case Constants.EN_UPPERCASE: - return Character.toUpperCase(ca[i]); - case Constants.EN_LOWERCASE: - return Character.toLowerCase(ca[i]); - case Constants.EN_CAPITALIZE: - if (isStartOfWord(i)) { - /* - Use toTitleCase here. Apparently, some languages use - a different character to represent a letter when using - initial caps than when all of the letters in the word - are capitalized. We will try to let Java handle this. - */ - return Character.toTitleCase(ca[i]); - } else { - return ca[i]; - } - default: - assert false; //should never happen as the property subsystem catches that case - return ca[i]; - } - } - /** * Determines whether the input char should be considered part of a * "word". This is used primarily to determine whether the character @@ -483,57 +488,64 @@ public class FOText extends FONode { } private class TextCharIterator extends CharIterator { - private int curIndex = 0; - - /* Current space removal process: just increment the startIndex - to "remove" leading spaces from ca, until an unremoved character - is found. Then perform arraycopy's to remove extra spaces - between words. nextCharCalled is used to determine if an - unremoved character has already been found--if its value > 2 - than it means that has occurred (it is reset to zero each time we - remove a space via incrementing the startIndex.) */ - private int nextCharCalled = 0; - + + int currentPosition = 0; + + boolean canRemove = false; + boolean canReplace = false; + + /** {@inheritDoc} */ public boolean hasNext() { - if (curIndex == 0) { -// log.debug("->" + new String(ca) + "<-"); - } - return (curIndex < endIndex); + return (this.currentPosition < charBuffer.limit()); } + /** {@inheritDoc} */ public char nextChar() { - if (curIndex < endIndex) { - nextCharCalled++; - // Just a char class? Don't actually care about the value! - return ca[curIndex++]; + + if (this.currentPosition < charBuffer.limit()) { + this.canRemove = true; + this.canReplace = true; + return charBuffer.get(currentPosition++); } else { throw new NoSuchElementException(); } + } + /** {@inheritDoc} */ public void remove() { - if (curIndex < endIndex && nextCharCalled < 2) { - startIndex++; - nextCharCalled = 0; -// log.debug("removeA: " + new String(ca, startIndex, endIndex - startIndex)); - } else if (curIndex < endIndex) { - // copy from curIndex to end to curIndex-1 - System.arraycopy(ca, curIndex, ca, curIndex - 1, - endIndex - curIndex); - endIndex--; - curIndex--; -// log.debug("removeB: " + new String(ca, startIndex, endIndex - startIndex)); - } else if (curIndex == endIndex) { -// log.debug("removeC: " + new String(ca, startIndex, endIndex - startIndex)); - endIndex--; - curIndex--; + + if (this.canRemove) { + charBuffer.position(currentPosition); + // Slice the buffer at the current position + CharBuffer tmp = charBuffer.slice(); + // Reset position to before current character + charBuffer.position(--currentPosition); + if (tmp.hasRemaining()) { + // Transfer any remaining characters + charBuffer.mark(); + charBuffer.put(tmp); + charBuffer.reset(); + } + // Decrease limit + charBuffer.limit(charBuffer.limit() - 1); + // Make sure following calls fail, unless nextChar() was called + this.canRemove = false; + } else { + throw new IllegalStateException(); } + } + /** {@inheritDoc} */ public void replaceChar(char c) { - if (curIndex > 0 && curIndex <= endIndex) { - ca[curIndex - 1] = c; + + if (this.canReplace) { + charBuffer.put(currentPosition - 1, c); + } else { + throw new IllegalStateException(); } + } } @@ -559,7 +571,7 @@ public class FOText extends FONode { return color; } - /** + /** * @return the "keep-together" property. */ public KeepProperty getKeepTogether() { @@ -570,40 +582,40 @@ public class FOText extends FONode { * @return the "letter-spacing" property. */ public Property getLetterSpacing() { - return letterSpacing; + return letterSpacing; } - + /** * @return the "line-height" property. */ public SpaceProperty getLineHeight() { return lineHeight; } - + /** * @return the "white-space-treatment" property */ public int getWhitespaceTreatment() { return whiteSpaceTreatment; } - + /** * @return the "word-spacing" property. */ public Property getWordSpacing() { - return wordSpacing; + return wordSpacing; } - + /** * @return the "wrap-option" property. */ public int getWrapOption() { - return wrapOption; + return wrapOption; } - + /** @return the "text-decoration" property. */ public CommonTextDecoration getTextDecoration() { - return textDecoration; + return textDecoration; } /** @return the baseline-shift property */ @@ -613,14 +625,12 @@ public class FOText extends FONode { /** {@inheritDoc} */ public String toString() { - StringBuffer sb = new StringBuffer(super.toString()); - sb.append(" (").append(ca).append(")"); - return sb.toString(); + return (this.charBuffer == null) ? "" : this.charBuffer.toString(); } - + /** {@inheritDoc} */ public String getLocalName() { - return null; + return "#PCDATA"; } /** {@inheritDoc} */ @@ -630,10 +640,34 @@ public class FOText extends FONode { /** {@inheritDoc} */ protected String gatherContextInfo() { - if (getLocator() != null) { + if (this.locator != null) { return super.gatherContextInfo(); } else { - return new String(ca).trim(); + return this.toString(); + } + } + + /** {@inheritDoc} */ + public char charAt(int position) { + return this.charBuffer.get(position); + } + + /** {@inheritDoc} */ + public CharSequence subSequence(int start, int end) { + return this.charBuffer.subSequence(start, end); + } + + /** {@inheritDoc} */ + public int length() { + return this.charBuffer.limit(); + } + + /** + * Resets the backing java.nio.CharBuffer + */ + public void resetBuffer() { + if (this.charBuffer != null) { + this.charBuffer.rewind(); } - } -} \ No newline at end of file + } +} diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index d8f712212..6682ff703 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -144,7 +144,7 @@ public class FOTreeBuilder extends DefaultHandler { log.debug("Building formatting object tree"); } foEventHandler.startDocument(); - this.mainFOHandler = new MainFOHandler(); + this.mainFOHandler = new MainFOHandler(); this.mainFOHandler.startDocument(); this.delegate = this.mainFOHandler; } @@ -224,7 +224,7 @@ public class FOTreeBuilder extends DefaultHandler { } else { //No formatting results available for output formats no //involving the layout engine. - return null; + return null; } } @@ -316,7 +316,13 @@ public class FOTreeBuilder extends DefaultHandler { if (propertyList != null && !builderContext.inMarker()) { currentPropertyList = propertyList; } - currentFObj.startOfNode(); + + // fo:characters can potentially be removed during + // white-space handling. + // Do not notify the FOEventHandler. + if (currentFObj.getNameId() != Constants.FO_CHARACTER) { + currentFObj.startOfNode(); + } } /** {@inheritDoc} */ @@ -333,7 +339,12 @@ public class FOTreeBuilder extends DefaultHandler { + ") vs. " + localName + " (" + uri + ")"); } - currentFObj.endOfNode(); + // fo:characters can potentially be removed during + // white-space handling. + // Do not notify the FOEventHandler. + if (currentFObj.getNameId() != Constants.FO_CHARACTER) { + currentFObj.endOfNode(); + } if (currentPropertyList != null && currentPropertyList.getFObj() == currentFObj diff --git a/src/java/org/apache/fop/fo/FObjMixed.java b/src/java/org/apache/fop/fo/FObjMixed.java index c1fcfe4ff..068c2d635 100644 --- a/src/java/org/apache/fop/fo/FObjMixed.java +++ b/src/java/org/apache/fop/fo/FObjMixed.java @@ -28,27 +28,27 @@ import org.apache.fop.apps.FOPException; * (= those that can contain both child {@link FONode}s and #PCDATA). */ public abstract class FObjMixed extends FObj { - + /** Represents accumulated, pending FO text. See {@link #flushText()}. */ - protected FOText ft = null; - + private FOText ft = null; + /** Used for white-space handling; start CharIterator at node ... */ protected FONode currentTextNode; - + /** Used in creating pointers between subsequent {@link FOText} nodes - * in the same {@link org.apache.fop.fo.flow.Block} + * in the same {@link org.apache.fop.fo.flow.Block} * (for handling text-transform) */ protected FOText lastFOTextProcessed = null; - + /** * Base constructor - * + * * @param parent FONode that is the parent of this object */ protected FObjMixed(FONode parent) { super(parent); } - + /** {@inheritDoc} */ protected void addCharacters(char[] data, int start, int length, PropertyList pList, @@ -65,20 +65,21 @@ public abstract class FObjMixed extends FObj { /** {@inheritDoc} */ protected void endOfNode() throws FOPException { - flushText(); - if (!inMarker() - || getNameId() == FO_MARKER) { - handleWhiteSpaceFor(this, null); - } + super.endOfNode(); + if (!inMarker() || getNameId() == FO_MARKER) { + // send character[s]() events to the FOEventHandler + sendCharacters(); + } + } /** - * Handles white-space for the node that is passed in, + * Handles white-space for the node that is passed in, * starting at its current text-node - * (used by {@link org.apache.fop.fo.flow.RetrieveMarker} + * (used by {@link org.apache.fop.fo.flow.RetrieveMarker} * to trigger 'end-of-node' white-space handling) - * + * * @param fobj the node for which to handle white-space * @param nextChild the next child to be added */ @@ -86,86 +87,97 @@ public abstract class FObjMixed extends FObj { fobj.getBuilderContext().getXMLWhiteSpaceHandler() .handleWhiteSpace(fobj, fobj.currentTextNode, nextChild); } - + /** - * Adds accumulated text as one FOText instance, unless - * the one instance's char array contains more than - * Short.MAX_VALUE characters. In the latter case the - * instance is split up into more manageable chunks. - * + * Creates block-pointers between subsequent FOText nodes + * in the same Block. (used for handling text-transform) + * + * TODO: !! Revisit: does not take into account fo:characters !! + * * @throws FOPException if there is a problem during processing */ - protected void flushText() throws FOPException { + private void flushText() throws FOPException { if (ft != null) { FOText lft = ft; /* make sure nested calls to itself have no effect */ ft = null; - FOText tmpText; - int indexStart = 0; - int indexEnd = (lft.ca.length > Short.MAX_VALUE - ? Short.MAX_VALUE : lft.ca.length) - 1; - int charCount = 0; - short tmpSize; - while (charCount < lft.ca.length) { - tmpSize = (short) (indexEnd - indexStart + 1); - charCount += tmpSize; - tmpText = (FOText) lft.clone(this, false); - tmpText.ca = new char[tmpSize]; - tmpText.startIndex = 0; - tmpText.endIndex = tmpSize; - System.arraycopy(lft.ca, indexStart, - tmpText.ca, 0, indexEnd - indexStart + 1); - if (getNameId() == FO_BLOCK) { - tmpText.createBlockPointers((org.apache.fop.fo.flow.Block) this); - this.lastFOTextProcessed = tmpText; - } else if (getNameId() != FO_MARKER - && getNameId() != FO_TITLE - && getNameId() != FO_BOOKMARK_TITLE) { - FONode fo = parent; - int foNameId = fo.getNameId(); - while (foNameId != FO_BLOCK - && foNameId != FO_MARKER - && foNameId != FO_TITLE - && foNameId != FO_BOOKMARK_TITLE - && foNameId != FO_PAGE_SEQUENCE) { - fo = fo.getParent(); - foNameId = fo.getNameId(); - } - if (foNameId == FO_BLOCK) { - tmpText.createBlockPointers((org.apache.fop.fo.flow.Block) fo); - ((FObjMixed) fo).lastFOTextProcessed = tmpText; - } else if (foNameId == FO_PAGE_SEQUENCE - && tmpText.willCreateArea()) { - log.error("Could not create block pointers." - + " FOText w/o Block ancestor."); - } + if (getNameId() == FO_BLOCK) { + lft.createBlockPointers((org.apache.fop.fo.flow.Block) this); + this.lastFOTextProcessed = lft; + } else if (getNameId() != FO_MARKER + && getNameId() != FO_TITLE + && getNameId() != FO_BOOKMARK_TITLE) { + FONode fo = parent; + int foNameId = fo.getNameId(); + while (foNameId != FO_BLOCK + && foNameId != FO_MARKER + && foNameId != FO_TITLE + && foNameId != FO_BOOKMARK_TITLE + && foNameId != FO_PAGE_SEQUENCE) { + fo = fo.getParent(); + foNameId = fo.getNameId(); + } + if (foNameId == FO_BLOCK) { + lft.createBlockPointers((org.apache.fop.fo.flow.Block) fo); + ((FObjMixed) fo).lastFOTextProcessed = lft; + } else if (foNameId == FO_PAGE_SEQUENCE + && lft.willCreateArea()) { + log.error("Could not create block pointers." + + " FOText w/o Block ancestor."); + } + } + this.addChildNode(lft); + } + } + + private void sendCharacters() throws FOPException { + + if (this.currentTextNode != null) { + FONodeIterator nodeIter + = this.getChildNodes(this.currentTextNode); + FONode node; + while (nodeIter.hasNext()) { + node = nodeIter.nextNode(); + assert (node instanceof FOText + || node.getNameId() == FO_CHARACTER); + if (node.getNameId() == FO_CHARACTER) { + node.startOfNode(); } - tmpText.endOfNode(); - addChildNode(tmpText); - indexStart = indexEnd + 1; - indexEnd = (((lft.ca.length - charCount) < Short.MAX_VALUE) - ? lft.ca.length : charCount + Short.MAX_VALUE) - 1; + node.endOfNode(); } } + this.currentTextNode = null; } /** {@inheritDoc} */ protected void addChildNode(FONode child) throws FOPException { + flushText(); if (!inMarker()) { if (child instanceof FOText || child.getNameId() == FO_CHARACTER) { - if (currentTextNode == null) { - currentTextNode = child; + if (this.currentTextNode == null) { + this.currentTextNode = child; } } else { // handle white-space for all text up to here handleWhiteSpaceFor(this, child); - currentTextNode = null; + // send character[s]() events to the FOEventHandler + sendCharacters(); } } super.addChildNode(child); } - + + /** {@inheritDoc} */ + public void finalizeNode() throws FOPException { + + flushText(); + if (!inMarker() || getNameId() == FO_MARKER) { + handleWhiteSpaceFor(this, null); + } + + } + /** * Returns a {@link CharIterator} over this FO's character content * diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index 0ce648c3a..c88147350 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -119,12 +119,10 @@ public abstract class AbstractRetrieveMarker extends FObjMixed { ft.bind(parentPropertyList); addChildTo(newChild, (FObj) newParent); } - + + // trigger end-of-node white-space handling + // and finalization for table-FOs newChild.finalizeNode(); - // trigger 'end-of-node' white-space handling - if (newChild instanceof FObjMixed) { - handleWhiteSpaceFor((FObjMixed) newChild, null); - } } } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java index 087963013..862c0a4be 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java @@ -41,8 +41,8 @@ import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.flow.ExternalGraphic; import org.apache.fop.fo.flow.Footnote; import org.apache.fop.fo.flow.Inline; -import org.apache.fop.fo.flow.InlineLevel; import org.apache.fop.fo.flow.InlineContainer; +import org.apache.fop.fo.flow.InlineLevel; import org.apache.fop.fo.flow.InstreamForeignObject; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.ListBlock; @@ -224,7 +224,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { public static class FOTextLayoutManagerMaker extends Maker { public void make(FONode node, List lms) { FOText foText = (FOText) node; - if (foText.endIndex - foText.startIndex > 0) { + if (foText.length() > 0) { lms.add(new TextLayoutManager(foText)); } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 575728f0d..c6210edce 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -61,20 +61,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * Number of word-spaces? */ private class AreaInfo { - private final short startIndex; - private final short breakIndex; - private final short wordSpaceCount; - private short letterSpaceCount; + private final int startIndex; + private final int breakIndex; + private final int wordSpaceCount; + private int letterSpaceCount; private final MinOptMax areaIPD; private final boolean isHyphenated; private final boolean isSpace; private boolean breakOppAfter; private final Font font; - AreaInfo(final short startIndex, - final short breakIndex, - final short wordSpaceCount, - final short letterSpaceCount, + AreaInfo(final int startIndex, + final int breakIndex, + final int wordSpaceCount, + final int letterSpaceCount, final MinOptMax areaIPD, final boolean isHyphenated, final boolean isSpace, @@ -132,7 +132,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private static final MinOptMax ZERO_MINOPTMAX = new MinOptMax(0); private final FOText foText; - private final char[] textArray; + /** * Contains an array of widths to adjust for kerning. The first entry can * be used to influence the start position of the first letter. The entry i+1 defines the @@ -143,7 +143,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** Font used for the space between words. */ private Font spaceFont = null; /** Start index of next TextArea */ - private short nextStart = 0; + private int nextStart = 0; /** size of a space character (U+0020) glyph in current font */ private int spaceCharIPD; private MinOptMax wordSpaceIPD; @@ -155,8 +155,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private boolean hasChanged = false; private int returnedIndex = 0; - private short thisStart = 0; - private short tempStart = 0; + private int thisStart = 0; + private int tempStart = 0; private List changeList = null; private AlignmentContext alignmentContext = null; @@ -177,10 +177,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { super(); this.foText = node; - this.textArray = new char[node.endIndex - node.startIndex]; - System.arraycopy(node.ca, node.startIndex, this.textArray, 0, - node.endIndex - node.startIndex); - this.letterAdjustArray = new MinOptMax[this.textArray.length + 1]; + this.letterAdjustArray = new MinOptMax[node.length() + 1]; this.vecAreaInfo = new java.util.ArrayList(); } @@ -205,6 +202,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public void initialize() { + this.foText.resetBuffer(); + this.spaceFont = FontSelector.selectFontForCharacterInText(' ', this.foText, this); // With CID fonts, space isn't neccesary currentFontState.width(32) @@ -296,7 +295,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { int letterSpaceCount, final int firstAreaInfoIndex, final int lastAreaInfoIndex, final MinOptMax realWidth, final LayoutContext context) { - // TODO: These two statements (if, for) where like this before my recent + // TODO: These two statements (if, for) were like this before my recent // changes. However, it seems as if they should use the AreaInfo from // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last ai. // This needs to be checked. @@ -441,7 +440,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // areaInfo stores information about spaces // add the spaces - except zero-width spaces - to the TextArea for (int j = areaInfo.startIndex; j < areaInfo.breakIndex; j++) { - final char spaceChar = this.textArray[j]; + final char spaceChar = this.foText.charAt(j); if (!CharUtilities.isZeroWidthSpace(spaceChar)) { textArea.addSpace(spaceChar, 0, CharUtilities.isAdjustableSpace(spaceChar)); @@ -469,8 +468,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { for (int j = wordStartIndex; j <= i; j++) { final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(j); int lsCount = ai.letterSpaceCount; - wordChars.append(this.textArray, ai.startIndex, - ai.breakIndex - ai.startIndex); + /* TODO: in Java 5, StringBuffer has an append() variant + * for CharSequence, so the below iteration can be replaced + * by: + * wordChars.append(this.foText, ai.startIndex, + * ai.breakIndex - ai.startIndex); + */ + for (int ci = ai.startIndex; ci < ai.breakIndex; ci++) { + wordChars.append(this.foText.charAt(ci)); + } for (int k = 0; k < ai.breakIndex - ai.startIndex; k++) { final MinOptMax adj = this.letterAdjustArray[ai.startIndex + k]; if (letter > 0) { @@ -522,7 +528,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { || CharUtilities.isNonBreakableSpace(ch) || CharUtilities.isFixedWidthSpace(ch); } - + /** {@inheritDoc} */ public List getNextKnuthElements(final LayoutContext context, final int alignment) { this.lineStartBAP = context.getLineStartBorderAndPaddingWidth(); @@ -540,8 +546,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { boolean inWord = false; boolean inWhitespace = false; char ch = 0; - while (this.nextStart < this.textArray.length) { - ch = this.textArray[this.nextStart]; + while (this.nextStart < this.foText.length()) { + ch = this.foText.charAt(this.nextStart); boolean breakOpportunity = false; final byte breakAction = this.keepTogether ? LineBreakStatus.PROHIBITED_BREAK : lbs.nextChar(ch); @@ -560,10 +566,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { TextLayoutManager.LOG.error("Unexpected breakAction: " + breakAction); } if (inWord) { - if (breakOpportunity + if (breakOpportunity || TextLayoutManager.isSpace(ch) || CharUtilities.isExplicitBreak(ch)) { - // this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN + // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN prevAi = this.processWord(alignment, sequence, prevAi, ch, breakOpportunity, true); } @@ -588,24 +594,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { || ch == CharUtilities.NBSPACE) { // preserved space or non-breaking space: // create the AreaInfo object - ai = new AreaInfo(this.nextStart, (short) (this.nextStart + 1), - (short) 1, (short) 0, this.wordSpaceIPD, false, true, + ai = new AreaInfo(this.nextStart, this.nextStart + 1, + 1, 0, this.wordSpaceIPD, false, true, breakOpportunity, this.spaceFont); - this.thisStart = (short) (this.nextStart + 1); + this.thisStart = this.nextStart + 1; } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) { // create the AreaInfo object final Font font = FontSelector.selectFontForCharacterInText(ch, this.foText, this); final MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); - ai = new AreaInfo(this.nextStart, (short) (this.nextStart + 1), - (short) 0, (short) 0, ipd, false, true, + ai = new AreaInfo(this.nextStart, this.nextStart + 1, + 0, 0, ipd, false, true, breakOpportunity, font); - this.thisStart = (short) (this.nextStart + 1); + this.thisStart = this.nextStart + 1; } else if (CharUtilities.isExplicitBreak(ch)) { //mandatory break-character: only advance index - this.thisStart = (short) (this.nextStart + 1); + this.thisStart = this.nextStart + 1; } - + inWord = !TextLayoutManager.isSpace(ch) && !CharUtilities.isExplicitBreak(ch); inWhitespace = ch == CharUtilities.SPACE @@ -619,17 +625,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } else if (inWhitespace) { this.processWhitespace(alignment, sequence, true); } else if (ai != null) { - ai = this.processLeftoverAi(alignment, sequence, ai, ch, + this.processLeftoverAi(alignment, sequence, ai, ch, ch == CharUtilities.ZERO_WIDTH_SPACE); } else if (CharUtilities.isExplicitBreak(ch)) { - sequence = this.processLinebreak(returnList, sequence); + this.processLinebreak(returnList, sequence); } if (((List) ListUtil.getLast(returnList)).isEmpty()) { //Remove an empty sequence because of a trailing newline ListUtil.removeLast(returnList); } - + this.setFinished(true); if (returnList.isEmpty()) { return null; @@ -663,24 +669,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private AreaInfo processWhitespace(final int alignment, final KnuthSequence sequence, final boolean breakOpportunity) { - AreaInfo ai; - AreaInfo prevAi; // End of whitespace // create the AreaInfo object - ai = new AreaInfo(this.thisStart, this.nextStart, - (short) (this.nextStart - this.thisStart), (short) 0, + AreaInfo ai = new AreaInfo(this.thisStart, this.nextStart, + this.nextStart - this.thisStart, 0, MinOptMax.multiply(this.wordSpaceIPD, this.nextStart - this.thisStart), false, true, breakOpportunity, this.spaceFont); this.vecAreaInfo.add(ai); - prevAi = ai; // create the elements this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); - ai = null; this.thisStart = this.nextStart; - return prevAi; + return ai; } private AreaInfo processWord(final int alignment, final KnuthSequence sequence, @@ -688,21 +690,21 @@ public class TextLayoutManager extends LeafNodeLayoutManager { final boolean checkEndsWithHyphen) { AreaInfo ai; //Word boundary found, process widths and kerning - short lastIndex = this.nextStart; + int lastIndex = this.nextStart; while (lastIndex > 0 - && this.textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { + && this.foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { lastIndex--; } final boolean endsWithHyphen = checkEndsWithHyphen - && this.textArray[lastIndex] == CharUtilities.SOFT_HYPHEN; + && this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; final Font font = FontSelector - .selectFontForCharactersInText(this.textArray, + .selectFontForCharactersInText(this.foText, this.thisStart, lastIndex, this.foText, this); final int wordLength = lastIndex - this.thisStart; final boolean kerning = font.hasKerning(); final MinOptMax wordIPD = new MinOptMax(0); for (int i = this.thisStart; i < lastIndex; i++) { - final char c = this.textArray[i]; + final char c = this.foText.charAt(i); //character width final int charWidth = font.getCharWidth(c); @@ -712,10 +714,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (kerning) { int kern = 0; if (i > this.thisStart) { - final char previous = this.textArray[i - 1]; + final char previous = this.foText.charAt(i - 1); kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { - final char previous = this.textArray[prevAi.breakIndex - 1]; + final char previous = this.foText.charAt(prevAi.breakIndex - 1); kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; } if (kern != 0) { @@ -730,7 +732,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { && lastIndex > 0 && endsWithHyphen) { final int kern = font.getKernValue( - this.textArray[lastIndex - 1], ch) + this.foText.charAt(lastIndex - 1), ch) * font.getFontSize() / 1000; if (kern != 0) { this.addToLetterAdjust(lastIndex, kern); @@ -746,8 +748,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); // create the AreaInfo object - ai = new AreaInfo(this.thisStart, lastIndex, (short) 0, - (short) iLetterSpaces, wordIPD, + ai = new AreaInfo(this.thisStart, lastIndex, 0, + iLetterSpaces, wordIPD, endsWithHyphen, false, breakOpportunity, font); prevAi = ai; @@ -776,7 +778,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(idx); ai.letterSpaceCount++; ai.areaIPD.add(this.letterSpaceIPD); - if (TextLayoutManager.BREAK_CHARS.indexOf(this.textArray[this.tempStart - 1]) >= 0) { + if (TextLayoutManager.BREAK_CHARS.indexOf(this.foText.charAt(this.tempStart - 1)) >= 0) { // the last character could be used as a line break // append new elements to oldList oldListIterator = oldList.listIterator(oldList.size()); @@ -867,7 +869,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //log.info("Word: " + new String(textArray, startIndex, stopIndex - startIndex)); for (int i = startIndex; i < stopIndex; i++) { - final char c = this.textArray[i]; + final char c = this.foText.charAt(i); newIPD.add(new MinOptMax(font.getCharWidth(c))); //if (i > startIndex) { if (i < stopIndex) { @@ -899,8 +901,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.changeList = new LinkedList(); } this.changeList.add(new PendingChange(new AreaInfo( - (short) startIndex, (short) stopIndex, (short) 0, - (short) (isWordEnd ? stopIndex - startIndex - 1 + startIndex, stopIndex, 0, + (isWordEnd ? stopIndex - startIndex - 1 : stopIndex - startIndex), newIPD, hyphenFollows, false, false, font), ((LeafPosition) pos).getLeafPos())); @@ -973,7 +975,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { final int leafValue = ((LeafPosition) pos).getLeafPos(); if (leafValue != -1) { final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(leafValue); - sbChars.append(this.textArray, ai.startIndex, ai.breakIndex - ai.startIndex); + for (int i = ai.startIndex; i < ai.breakIndex; ++i) { + sbChars.append(this.foText.charAt(i)); + } } } @@ -999,7 +1003,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { mainPosition, true)); } } else { - if (this.textArray[ai.startIndex] != CharUtilities.SPACE + if (this.foText.charAt(ai.startIndex) != CharUtilities.SPACE || this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved this.addElementsForBreakingSpace(baseList, alignment, ai, @@ -1153,7 +1157,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // or it ends with a character that can be used as a line break if (ai.isHyphenated) { MinOptMax widthIfNoBreakOccurs = null; - if (ai.breakIndex < this.textArray.length) { + if (ai.breakIndex < this.foText.length()) { //Add in kerning in no-break condition widthIfNoBreakOccurs = this.letterAdjustArray[ai.breakIndex]; } diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 75f524f72..6171e68b4 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -1568,7 +1568,7 @@ public class RTFHandler extends FOEventHandler { } else if (foNode instanceof FOText) { if (bStart) { FOText text = (FOText) foNode; - text(text, text.ca, text.startIndex, text.endIndex); + text(text, text.getCharArray(), 0, text.length()); } } else if (foNode instanceof Character) { if (bStart) { -- cgit v1.2.3 From d617099c1d581634a9e8bd4bc4ab27ae4b1f6ace Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 22:17:00 +0000 Subject: Added missing file from r670422 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670423 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/util/CharUtilities.java | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/util/CharUtilities.java b/src/java/org/apache/fop/util/CharUtilities.java index 6baa5c0fd..eb56cd331 100644 --- a/src/java/org/apache/fop/util/CharUtilities.java +++ b/src/java/org/apache/fop/util/CharUtilities.java @@ -54,10 +54,14 @@ public class CharUtilities { public static final int XMLWHITESPACE = 4; + /** null char */ + public static final char NULL_CHAR = '\u0000'; /** linefeed character */ public static final char LINEFEED_CHAR = '\n'; /** carriage return */ public static final char CARRIAGE_RETURN = '\r'; + /** normal tab */ + public static final char TAB = '\t'; /** normal space */ public static final char SPACE = '\u0020'; /** non-breaking space */ @@ -80,9 +84,12 @@ public class CharUtilities { public static final char PARAGRAPH_SEPARATOR = '\u2029'; /** missing ideograph */ public static final char MISSING_IDEOGRAPH = '\u25A1'; + /** Ideogreaphic space */ + public static final char IDEOGRAPHIC_SPACE = '\u3000'; /** Unicode value indicating the the character is "not a character". */ public static final char NOT_A_CHARACTER = '\uFFFF'; + /** * Utility class: Constructor prevents instantiating when subclassed. */ @@ -97,11 +104,18 @@ public class CharUtilities { * @return the determined character class */ public static int classOf(char c) { - if (c == CODE_EOT) { return EOT; } - if (c == '\n') { return LINEFEED; } - if (c == ' ' || c == '\r' || c == '\t') { return XMLWHITESPACE; } - if (isAnySpace(c)) { return UCWHITESPACE; } - return NONWHITESPACE; + switch (c) { + case CODE_EOT: + return EOT; + case LINEFEED_CHAR: + return LINEFEED; + case SPACE: + case CARRIAGE_RETURN: + case TAB: + return XMLWHITESPACE; + default: + return isAnySpace(c) ? UCWHITESPACE : NONWHITESPACE; + } } -- cgit v1.2.3 From 9c1e622432f126a45cb2d0971029364eaa63d60e Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 22 Jun 2008 22:18:53 +0000 Subject: Another missing file... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670424 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontSelector.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/FontSelector.java b/src/java/org/apache/fop/fonts/FontSelector.java index ec5ea26bf..5e3ed816e 100644 --- a/src/java/org/apache/fop/fonts/FontSelector.java +++ b/src/java/org/apache/fop/fonts/FontSelector.java @@ -88,7 +88,7 @@ public final class FontSelector { /** * Selects a font which is able to display the most of the given characters. * - * @param textArray + * @param charSeq * Text to go through * @param firstIndex * first index within text. @@ -100,9 +100,10 @@ public final class FontSelector { * the Percent-based context needed for creating the actual font. * @return a Font object. */ - public static Font selectFontForCharactersInText(char[] textArray, + public static Font selectFontForCharactersInText(CharSequence charSeq, int firstIndex, int breakIndex, FOText text, PercentBaseContext context) { + final FontInfo fi = text.getFOEventHandler().getFontInfo(); final CommonFont commonFont = text.getCommonFont(); final FontTriplet[] fontkeys = commonFont.getFontState(fi); @@ -115,7 +116,7 @@ public final class FontSelector { commonFont.fontSize.getValue(context)); fonts[fontnum] = font; for (int pos = firstIndex; pos < breakIndex; pos++) { - if (font.hasChar(textArray[pos])) { + if (font.hasChar(charSeq.charAt(pos))) { fontCount[fontnum]++; } } -- cgit v1.2.3 From 770ac265542a8fd68033ece8457108ef0ec59046 Mon Sep 17 00:00:00 2001 From: Luca Furini Date: Mon, 23 Jun 2008 09:24:14 +0000 Subject: Added support for non-zero borders and padding on page regions. Testcase included, now disabled because it is supposed to run with relaxed validation switched on. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670492 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/Page.java | 5 + src/java/org/apache/fop/area/RegionReference.java | 14 ++- .../fop/render/AbstractPathOrientedRenderer.java | 86 +++++++++++-- status.xml | 4 + test/layoutengine/disabled-testcases.xml | 7 ++ .../simple-page-master_borders_padding.xml | 136 +++++++++++++++++++++ 6 files changed, 239 insertions(+), 13 deletions(-) create mode 100644 test/layoutengine/standard-testcases/simple-page-master_borders_padding.xml (limited to 'src') diff --git a/src/java/org/apache/fop/area/Page.java b/src/java/org/apache/fop/area/Page.java index 64a6db576..94a394014 100644 --- a/src/java/org/apache/fop/area/Page.java +++ b/src/java/org/apache/fop/area/Page.java @@ -126,6 +126,10 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable { } else { rr = new RegionReference(r, rvp); } + // set borders and padding traits + // (a little extensions wrt what prescribed by the specs at 6.4.14) + TraitSetter.addBorders(rr, r.getCommonBorderPaddingBackground(), false, false, false, false, null); + TraitSetter.addPadding(rr, r.getCommonBorderPaddingBackground(), false, false, false, false, null); setRegionReferencePosition(rr, r, rvp.getViewArea()); rvp.setRegionReference(rr); setRegionViewport(r.getNameId(), rvp); @@ -289,3 +293,4 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable { } + diff --git a/src/java/org/apache/fop/area/RegionReference.java b/src/java/org/apache/fop/area/RegionReference.java index c41de7c7a..467aadd85 100644 --- a/src/java/org/apache/fop/area/RegionReference.java +++ b/src/java/org/apache/fop/area/RegionReference.java @@ -73,6 +73,18 @@ public class RegionReference extends Area implements Cloneable { blocks.add(child); } + /** {@inheritDoc} */ + public int getBPD() { + // subtract bpd of borders and padding before / after + return super.getBPD() - getBorderAndPaddingWidthBefore() - getBorderAndPaddingWidthAfter(); + } + + /** {@inheritDoc} */ + public int getIPD() { + // subtract ipd of borders and padding start / end + return super.getIPD() - getBorderAndPaddingWidthStart() - getBorderAndPaddingWidthEnd(); + } + /** * Set the Coordinate Transformation Matrix which transforms content * coordinates in this region reference area which are specified in @@ -133,7 +145,7 @@ public class RegionReference extends Area implements Cloneable { public void addBlock(Block block) { addChildArea(block); } - + /** * Clone this region. * This is used when cloning the page by the page master. diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index eb0668d8b..a6c08747f 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -38,6 +38,7 @@ import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.CTM; import org.apache.fop.area.NormalFlow; +import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.ForeignObject; @@ -96,19 +97,20 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { */ protected void handleRegionTraits(RegionViewport region) { Rectangle2D viewArea = region.getViewArea(); + RegionReference referenceArea = region.getRegionReference(); float startx = (float)(viewArea.getX() / 1000f); float starty = (float)(viewArea.getY() / 1000f); float width = (float)(viewArea.getWidth() / 1000f); float height = (float)(viewArea.getHeight() / 1000f); - if (region.getRegionReference().getRegionClass() == FO_REGION_BODY) { - currentBPPosition = region.getBorderAndPaddingWidthBefore(); - currentIPPosition = region.getBorderAndPaddingWidthStart(); - } - drawBackAndBorders(region, startx, starty, width, height); + // adjust the current position according to region borders and padding + currentBPPosition = referenceArea.getBorderAndPaddingWidthBefore(); + currentIPPosition = referenceArea.getBorderAndPaddingWidthStart(); + // draw background (traits are in the RegionViewport) + // and borders (traits are in the RegionReference) + drawBackAndBorders(region, referenceArea, startx, starty, width, height); } - /** * Draw the background and borders. * This draws the background and border traits for an area given @@ -123,15 +125,57 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { protected void drawBackAndBorders(Area area, float startx, float starty, float width, float height) { + drawBackAndBorders(area, area, startx, starty, width, height); + } + + /** + * Draw the background and borders. + * This draws the background and border traits for an area given + * the position. + * + * @param backgroundArea the area to get the background traits from + * @param borderArea the area to get the border traits from + * @param startx the start x position + * @param starty the start y position + * @param width the width of the area + * @param height the height of the area + */ + protected void drawBackAndBorders(Area backgroundArea, Area borderArea, + float startx, float starty, + float width, float height) { // draw background then border - BorderProps bpsBefore = (BorderProps)area.getTrait(Trait.BORDER_BEFORE); - BorderProps bpsAfter = (BorderProps)area.getTrait(Trait.BORDER_AFTER); - BorderProps bpsStart = (BorderProps)area.getTrait(Trait.BORDER_START); - BorderProps bpsEnd = (BorderProps)area.getTrait(Trait.BORDER_END); + BorderProps bpsBefore = (BorderProps)borderArea.getTrait(Trait.BORDER_BEFORE); + BorderProps bpsAfter = (BorderProps)borderArea.getTrait(Trait.BORDER_AFTER); + BorderProps bpsStart = (BorderProps)borderArea.getTrait(Trait.BORDER_START); + BorderProps bpsEnd = (BorderProps)borderArea.getTrait(Trait.BORDER_END); - Trait.Background back; - back = (Trait.Background)area.getTrait(Trait.BACKGROUND); + drawBackground(startx, starty, width, height, + (Trait.Background) backgroundArea.getTrait(Trait.BACKGROUND), + bpsBefore, bpsAfter, bpsStart, bpsEnd); + drawBorders(startx, starty, width, height, + bpsBefore, bpsAfter, bpsStart, bpsEnd); + } + + /** + * Draw the background. + * This draws the background given the position and the traits. + * + * @param startx the start x position + * @param starty the start y position + * @param width the width of the area + * @param height the height of the area + * @param back the background traits + * @param bpsBefore the border-before traits + * @param bpsAfter the border-after traits + * @param bpsStart the border-start traits + * @param bpsEnd the border-end traits + */ + protected void drawBackground(float startx, float starty, + float width, float height, + Trait.Background back, + BorderProps bpsBefore, BorderProps bpsAfter, + BorderProps bpsStart, BorderProps bpsEnd) { if (back != null) { endTextObject(); @@ -202,7 +246,25 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { restoreGraphicsState(); } } + } + /** + * Draw the borders. + * This draws the border traits given the position and the traits. + * + * @param startx the start x position + * @param starty the start y position + * @param width the width of the area + * @param height the height of the area + * @param bpsBefore the border-before traits + * @param bpsAfter the border-after traits + * @param bpsStart the border-start traits + * @param bpsEnd the border-end traits + */ + protected void drawBorders(float startx, float starty, + float width, float height, + BorderProps bpsBefore, BorderProps bpsAfter, + BorderProps bpsStart, BorderProps bpsEnd) { Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height); drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd); } diff --git a/status.xml b/status.xml index cc345117f..20caa0e1a 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,10 @@ + + Allowing non-zero borders and padding on page regions when + relaxed validation is turned on. + Fixed an inconsistency in footnote handling that led to unnecessary empty areas in pages whose last normal line contains footnotes diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index ba985bf8d..ca05b156b 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -216,4 +216,11 @@ A soft hyphen should be a preferred as break compared to a normal hyphenation point but is not. + + Borders and padding on page regions + simple-page-master_borders_padding.xml + Borders and padding on regions are now implemented but + relaxed validation must be switched on, otherwise there is a validation + exception. + diff --git a/test/layoutengine/standard-testcases/simple-page-master_borders_padding.xml b/test/layoutengine/standard-testcases/simple-page-master_borders_padding.xml new file mode 100644 index 000000000..8ce6101a3 --- /dev/null +++ b/test/layoutengine/standard-testcases/simple-page-master_borders_padding.xml @@ -0,0 +1,136 @@ + + + + + +

    + This test checks page-masters (all regions). The empty block-containers are used to check that all the base widths are set correctly so + length evaluation using percentages is possible. +

    +
    + + + + + + + + + + + + + + + + + region-before1 + + + + + + region-after1 with precedence and display-align="after" + + + + + + region-start1 + + + + + + region-end1 + + + + + + testing all-regions1 + testing all-regions2 + testing all-regions3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -- cgit v1.2.3 From c9f1206db80c4210a42b0eb81dec8cd2202f0558 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 18:01:25 +0000 Subject: Fix XMLObj.addCharacters(): incorrect after r670341 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670689 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/XMLObj.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/XMLObj.java b/src/java/org/apache/fop/fo/XMLObj.java index da610f0e3..683ca5a03 100644 --- a/src/java/org/apache/fop/fo/XMLObj.java +++ b/src/java/org/apache/fop/fo/XMLObj.java @@ -214,7 +214,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { */ protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) { - String str = new String(data, start, length - start); + String str = new String(data, start, length); org.w3c.dom.Text text = doc.createTextNode(str); element.appendChild(text); } -- cgit v1.2.3 From 400e1f2b50c9ae9930e421d248aa21d138144219 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 19:56:51 +0000 Subject: Javadoc modification + addition of clarifying comments git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670723 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/text/linebreak/LineBreakStatus.java | 79 ++++++++++++++++------ 1 file changed, 60 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java b/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java index 44b27889a..94e018c75 100644 --- a/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java +++ b/src/java/org/apache/fop/text/linebreak/LineBreakStatus.java @@ -61,52 +61,90 @@ public class LineBreakStatus { } /** - * Check whether a line break may happen. - * The function returns the line breaking status of the point before the given character. - * The algorithm is the table driven algorithm described in the Unicode - *
    technical report #14. - * The pair table is taken from @see LineBreakUtils + * Check whether a line break may happen according to the rules described in + * the Unicode Line Breaking Algorithm. + * The function returns the line breaking status of the point before the given character. + * The algorithm is the table-driven algorithm, as described in + * + * Unicode Technical Report #14. + * The pair table is taken from {@link LineBreakUtils}. * - * TODO: Better handling for AI, SA, CB and other line break classes. + * TODO: Better handling for AI, SA, SG and XX line break classes. * - * @param c The character. + * @param c the character to check * @return the break action to be taken + * one of: {@link #DIRECT_BREAK}, + * {@link #INDIRECT_BREAK}, + * {@link #COMBINING_INDIRECT_BREAK}, + * {@link #COMBINING_PROHIBITED_BREAK}, + * {@link #PROHIBITED_BREAK}, + * {@link #EXPLICIT_BREAK} */ public byte nextChar(char c) { byte currentClass = LineBreakUtils.getLineBreakProperty(c); - if (currentClass == LineBreakUtils.LINE_BREAK_PROPERTY_AI - || leftClass == LineBreakUtils.LINE_BREAK_PROPERTY_XX) { - //current "Ambiguous" or previous "Unknown": - // assume current "Alphabetic" - currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; + /* Initial conversions */ + switch (currentClass) { + case LineBreakUtils.LINE_BREAK_PROPERTY_AI: + case LineBreakUtils.LINE_BREAK_PROPERTY_SG: + case LineBreakUtils.LINE_BREAK_PROPERTY_XX: + // LB 1: Resolve AI, ... SG and XX into other line breaking classes + // depending on criteria outside the scope of this algorithm. + // In the absence of such criteria, it is recommended that + // classes AI, ... SG and XX be resolved to AL + currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; + break; + + case LineBreakUtils.LINE_BREAK_PROPERTY_SA: + // LB 1: Resolve ... SA ... into other line breaking classes + // depending on criteria outside the scope of this algorithm. + // In the absence of such criteria, it is recommended that + // ... SA be resolved to AL, except that characters of + // class SA that have General_Category Mn or Mc be resolved to CM + switch (Character.getType(c)) { + case Character.COMBINING_SPACING_MARK: //General_Category "Mc" + case Character.NON_SPACING_MARK: //General_Category "Mn" + currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_CM; + break; + default: + currentClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; + } + + default: + //nop } - /** Check 1: initial character after a reset/mandatory break? */ + /* Check 1: First character or initial character after a reset/mandatory break? */ switch (leftClass) { case -1: - //first character after a reset() + //first character or initial character after a reset() leftClass = currentClass; if (leftClass == LineBreakUtils.LINE_BREAK_PROPERTY_CM) { - leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_ID; + // LB 10: Treat any remaining combining marks as AL + leftClass = LineBreakUtils.LINE_BREAK_PROPERTY_AL; } - // LB 2a + // LB 2: Never break at the start of text return PROHIBITED_BREAK; case LineBreakUtils.LINE_BREAK_PROPERTY_BK: case LineBreakUtils.LINE_BREAK_PROPERTY_LF: case LineBreakUtils.LINE_BREAK_PROPERTY_NL: //first character after mandatory break + // LB 4: Always break after hard line breaks + // LB 5: Treat ... LF and NL has hard line breaks reset(); leftClass = currentClass; return EXPLICIT_BREAK; case LineBreakUtils.LINE_BREAK_PROPERTY_CR: //first character after a carriage return: - // explicit break if it is not a linefeed + // LB 5: Treat CR followed by LF, as well as CR ... as hard line breaks + // If current is LF, then fall through to Check 2 (see below), + // and the hard break will be signaled for the character after LF (see above) if (currentClass != LineBreakUtils.LINE_BREAK_PROPERTY_LF) { reset(); + leftClass = currentClass; return EXPLICIT_BREAK; } @@ -114,16 +152,19 @@ public class LineBreakStatus { //nop } - /** Check 2: current is a mandatory break or space? */ + /* Check 2: current is a mandatory break or space? */ switch (currentClass) { case LineBreakUtils.LINE_BREAK_PROPERTY_BK: case LineBreakUtils.LINE_BREAK_PROPERTY_LF: case LineBreakUtils.LINE_BREAK_PROPERTY_NL: case LineBreakUtils.LINE_BREAK_PROPERTY_CR: + // LB 6: Do not break before a hard break leftClass = currentClass; return PROHIBITED_BREAK; case LineBreakUtils.LINE_BREAK_PROPERTY_SP: + // LB 7: Do not break before spaces ... + // Zero-width spaces are in the pair-table (see below) hadSpace = true; return PROHIBITED_BREAK; @@ -131,7 +172,7 @@ public class LineBreakStatus { //nop } - /** Normal treatment, if the first two checks did not return */ + /* Normal treatment, if the first two checks did not return */ boolean savedHadSpace = hadSpace; hadSpace = false; byte breakAction = LineBreakUtils.getLineBreakPairProperty(leftClass, currentClass); -- cgit v1.2.3 From a69b3658ec0f6769b95ab8c3e5cac3976f811c69 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:18:45 +0000 Subject: Javadoc fixup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670760 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java index 3fccf4f67..9da2b0911 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java @@ -78,7 +78,7 @@ public abstract class PSExtensionAttachment implements ExtensionAttachment, XMLi * * @param handler ContentHandler instance to send the SAX events to * @throws SAXException if there's a problem generating the SAX events - * @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler) + * @see org.apache.xmlgraphics.util.XMLizable#toSAX(org.xml.sax.ContentHandler) */ public void toSAX(ContentHandler handler) throws SAXException { AttributesImpl atts = new AttributesImpl(); -- cgit v1.2.3 From 4796fd3e354a8ee284576bc9f402ed365c052dbb Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:21:09 +0000 Subject: Minor cleanup: remove unused parameter from method signature git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670761 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java index 4f5c78540..8e6633ab8 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java @@ -44,7 +44,7 @@ public class PageNumberCitationLayoutManager extends AbstractPageNumberCitationL /** {@inheritDoc} */ public InlineArea get(LayoutContext context) { - curArea = getPageNumberCitationInlineArea(parentLM); + curArea = getPageNumberCitationInlineArea(); return curArea; } @@ -52,7 +52,7 @@ public class PageNumberCitationLayoutManager extends AbstractPageNumberCitationL * if id can be resolved then simply return a word, otherwise * return a resolvable area */ - private InlineArea getPageNumberCitationInlineArea(LayoutManager parentLM) { + private InlineArea getPageNumberCitationInlineArea() { PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId()); TextArea text = null; if (page != null) { -- cgit v1.2.3 From 35ca6c79d80e155e5dc1257c478c6d41947c49e5 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:22:48 +0000 Subject: Minor cleanup: remove double storage of the FObj git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670763 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/layoutmgr/inline/WrapperLayoutManager.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index a5bbdb33c..3ce4a6f9c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -24,26 +24,21 @@ import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.Block; import org.apache.fop.area.LineArea; import org.apache.fop.fo.flow.Wrapper; -import org.apache.fop.layoutmgr.BlockLayoutManager; -import org.apache.fop.layoutmgr.BlockStackingLayoutManager; -import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.TraitSetter; +import org.apache.fop.layoutmgr.*; + +import java.util.LinkedList; /** * This is the layout manager for the fo:wrapper formatting object. */ public class WrapperLayoutManager extends LeafNodeLayoutManager { - private Wrapper fobj; - /** * Creates a new LM for fo:wrapper. * @param node the fo:wrapper */ public WrapperLayoutManager(Wrapper node) { super(node); - fobj = node; } /** {@inheritDoc} */ @@ -70,13 +65,13 @@ public class WrapperLayoutManager extends LeafNodeLayoutManager { public void addAreas(PositionIterator posIter, LayoutContext context) { if (fobj.hasId()) { addId(); - InlineArea area = getEffectiveArea(); if (parentLM instanceof BlockStackingLayoutManager && !(parentLM instanceof BlockLayoutManager)) { Block helperBlock = new Block(); TraitSetter.setProducerID(helperBlock, fobj.getId()); parentLM.addChildArea(helperBlock); } else { + InlineArea area = getEffectiveArea(); parentLM.addChildArea(area); } } -- cgit v1.2.3 From c6791839596bc7998246fb169777fa2b54e3be99 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:24:46 +0000 Subject: Minor cleanup: remove redundant cast git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670765 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/PageSequenceLayoutManager.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java index 5816fe482..c5a3bdeec 100644 --- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java @@ -102,18 +102,17 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager curPage = makeNewPage(false, false); PageBreaker breaker = new PageBreaker(this); - int flowBPD = (int)getCurrentPV().getBodyRegion().getRemainingBPD(); + int flowBPD = getCurrentPV().getBodyRegion().getRemainingBPD(); breaker.doLayout(flowBPD); finishPage(); } - + /** {@inheritDoc} */ public void finishPageSequence() { if (pageSeq.hasId()) { idTracker.signalIDProcessed(pageSeq.getId()); } - pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum, (currentPageNum - startPageNum) + 1); areaTreeHandler.notifyPageSequenceFinished(pageSeq, @@ -150,9 +149,9 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager return; } - StaticContentLayoutManager lm = (StaticContentLayoutManager) - getLayoutManagerMaker().makeStaticContentLayoutManager( - this, sc, reg); + StaticContentLayoutManager lm = getLayoutManagerMaker() + .makeStaticContentLayoutManager( + this, sc, reg); lm.doLayout(); } @@ -166,5 +165,5 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager super.finishPage(); } - + } -- cgit v1.2.3 From 9963937e2913d25207a9d464d48fb3248427aca0 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:25:30 +0000 Subject: Minor cleanup: remove redundant cast git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670766 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 2410c19cd..1c8fb679f 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -68,7 +68,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager // set layout dimensions int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth(); - int flowBPD = (int) getCurrentPV().getBodyRegion().getBPD(); + int flowBPD = getCurrentPV().getBodyRegion().getBPD(); // currently active LM LayoutManager curLM; -- cgit v1.2.3 From 4d7ed2afb16138a9d73596e5063dcea8be4b1482 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:26:56 +0000 Subject: Javadoc fixup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670767 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 50688dd0e..7f91808d0 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -88,7 +88,6 @@ class RowGroupLayoutManager { * @param alignment alignment indicator * @param bodyType Indicates what kind of body is being processed (BODY, HEADER or FOOTER) * @param returnList List to received the generated elements - * @param rowGroup row group to process */ private void createElementsForRowGroup(LayoutContext context, int alignment, int bodyType, LinkedList returnList) { -- cgit v1.2.3 From 05f5dd475ba2e556d86197479393b36029470f31 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:29:53 +0000 Subject: Minor cleanup: simplified conditional git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670770 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/SingleByteFont.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index f1b7b1b48..bdf0acc32 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -50,8 +50,8 @@ public class SingleByteFont extends CustomFont { /** {@inheritDoc} */ public boolean isEmbeddable() { - return (getEmbedFileName() == null && getEmbedResourceName() == null) ? false - : true; + return (!(getEmbedFileName() == null + && getEmbedResourceName() == null)); } /** {@inheritDoc} */ -- cgit v1.2.3 From ea18f526fd30002a348b1fad297815db638ae757 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:32:31 +0000 Subject: A nit... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670773 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/apps/MimeConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/apps/MimeConstants.java b/src/java/org/apache/fop/apps/MimeConstants.java index 31bdaaab1..cdd30c0e1 100644 --- a/src/java/org/apache/fop/apps/MimeConstants.java +++ b/src/java/org/apache/fop/apps/MimeConstants.java @@ -55,7 +55,7 @@ public interface MimeConstants { /** FrameMaker's MIF */ String MIME_MIF = "application/mif"; - /** Structured Vector Graphics */ + /** Scalable Vector Graphics */ String MIME_SVG = "image/svg+xml"; /** GIF images */ -- cgit v1.2.3 From 5578f06aa15fe6d41d81363c1d99db370b350f87 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 23 Jun 2008 21:39:19 +0000 Subject: Fix imports... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@670777 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index 3ce4a6f9c..342e0a6f1 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -20,11 +20,13 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.area.inline.InlineArea; -import org.apache.fop.area.inline.InlineParent; import org.apache.fop.area.Block; -import org.apache.fop.area.LineArea; import org.apache.fop.fo.flow.Wrapper; -import org.apache.fop.layoutmgr.*; +import org.apache.fop.layoutmgr.BlockLayoutManager; +import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.layoutmgr.TraitSetter; import java.util.LinkedList; -- cgit v1.2.3 From dc3032f675f4e6f56f8512e988ae3b82785ac390 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Tue, 24 Jun 2008 11:59:33 +0000 Subject: Another character handling problem, replaced end-start by length git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@671145 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java index c4cc73efc..6cee46752 100644 --- a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java +++ b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java @@ -51,13 +51,13 @@ public class BookmarkTitle extends FObj { * * @param data the character data * @param start the start position in the data array - * @param end the end position in the character array + * @param length the length of the character array * @param locator location in fo source file. */ - protected void addCharacters(char[] data, int start, int end, + protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) { - title += new String(data, start, end - start); + title += new String(data, start, length); } /** -- cgit v1.2.3 From d9ccf5f4edf32a42fa2e8eb285b7133fc6191239 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Thu, 26 Jun 2008 19:44:20 +0000 Subject: Fixed a possible NullPointerException: if the citation appears in a fo:marker, the property will only be parsed if the marker is retrieved... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@672010 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/AbstractPageNumberCitation.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java index b45f21348..58c0f4547 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java +++ b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java @@ -22,6 +22,7 @@ package org.apache.fop.fo.flow; import java.awt.Color; import org.xml.sax.Locator; +import org.xml.sax.Attributes; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; @@ -104,13 +105,18 @@ public abstract class AbstractPageNumberCitation extends FObj { } /** {@inheritDoc} */ - protected void startOfNode() throws FOPException { - super.startOfNode(); - if (refId.equals("")) { + public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + super.processNode(elementName, locator, attlist, pList); + if (!inMarker() && (refId == null || "".equals(refId))) { missingPropertyError("ref-id"); } } + /** {@inheritDoc} */ + protected void startOfNode() throws FOPException { + super.startOfNode(); + } + /** * {@inheritDoc} *
    XSL Content Model: empty -- cgit v1.2.3 From a76d8b110d7736afec93a6fbc2096ddbe332f1c6 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 26 Jun 2008 20:49:11 +0000 Subject: Some basic cleanup. * Duplicated/redundant PSDictionary, PSPageDeviceDictionary and PSDictionaryFormatException removed and now referenced from xmlgraphics commons. * Updated xmlgraphics commons jar containing migrated PSPageDeviceDictionary class. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@672026 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.4svn.jar | Bin 512165 -> 518201 bytes .../apache/fop/render/ps/ImageEncoderCCITTFax.java | 1 + .../org/apache/fop/render/ps/PSDictionary.java | 312 --------------------- .../fop/render/ps/PSDictionaryFormatException.java | 37 --- .../fop/render/ps/PSPageDeviceDictionary.java | 110 -------- src/java/org/apache/fop/render/ps/PSRenderer.java | 3 + 6 files changed, 4 insertions(+), 459 deletions(-) delete mode 100644 src/java/org/apache/fop/render/ps/PSDictionary.java delete mode 100644 src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java delete mode 100644 src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java (limited to 'src') diff --git a/lib/xmlgraphics-commons-1.4svn.jar b/lib/xmlgraphics-commons-1.4svn.jar index d7f9092ea..6c836d46c 100644 Binary files a/lib/xmlgraphics-commons-1.4svn.jar and b/lib/xmlgraphics-commons-1.4svn.jar differ diff --git a/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java b/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java index ab39966d4..d5b2d2a23 100644 --- a/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java +++ b/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java @@ -25,6 +25,7 @@ import java.io.OutputStream; import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; import org.apache.xmlgraphics.ps.ImageEncoder; +import org.apache.xmlgraphics.ps.PSDictionary; /** * ImageEncoder implementation for CCITT encoded images. diff --git a/src/java/org/apache/fop/render/ps/PSDictionary.java b/src/java/org/apache/fop/render/ps/PSDictionary.java deleted file mode 100644 index 5a8f1ea14..000000000 --- a/src/java/org/apache/fop/render/ps/PSDictionary.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.ps; - -import java.util.Iterator; -import java.util.List; -import java.util.StringTokenizer; - -/** - * This class is used to encapsulate postscript dictionary objects. - */ -public class PSDictionary extends java.util.HashMap { - - private static final long serialVersionUID = 815367222496219197L; - - /** - * This class is used to parse dictionary strings. - */ - private static class Maker { - - /** - * Simple token holding class - */ - private class Token { - /** - * start index in string - */ - private int startIndex = -1; - - /** - * end index in string - */ - private int endIndex = -1; - - /** - * token string value - */ - private String value; - } - - private static final String[][] BRACES = { - {"<<", ">>"}, - {"[", "]"}, - {"{", "}"} - }; - - private static final int OPENING = 0; - private static final int CLOSING = 1; - private static final int DICTIONARY = 0; - private static final int ARRAY = 1; - private static final int PROCEDURE = 2; - - /** - * Returns a Token containing the start, end index and value of the next token - * found in a given string - * - * @param str - * string to search - * @param fromIndex - * search from index - * @return Token containing the start, end index and value of the next token - */ - protected Token nextToken(String str, int fromIndex) { - Token t = null; - for (int i = fromIndex; i < str.length(); i++) { - boolean isWhitespace = Character.isWhitespace(str.charAt(i)); - // start index found - if (t == null && !isWhitespace) { - t = new Token(); - t.startIndex = i; - // end index found - } else if (t != null && isWhitespace) { - t.endIndex = i; - break; - } - } - // start index found - if (t != null) { - // end index not found so take end of string - if (t.endIndex == -1) { - t.endIndex = str.length(); - } - t.value = str.substring(t.startIndex, t.endIndex); - } - return t; - } - - /** - * Returns the closing brace index from a given string searches from a - * given index - * - * @param str - * string to search - * @param braces - * string array of opening and closing brace - * @param fromIndex - * searches from index - * @return matching brace index - * @throws org.apache.fop.render.ps.PSDictionaryFormatException - * thrown in the event that a parsing error occurred - */ - private int indexOfMatchingBrace(String str, String[] braces, - int fromIndex) throws PSDictionaryFormatException { - final int len = str.length(); - if (braces.length != 2) { - throw new PSDictionaryFormatException("Wrong number of braces"); - } - for (int openCnt = 0, closeCnt = 0; fromIndex < len; fromIndex++) { - if (str.startsWith(braces[OPENING], fromIndex)) { - openCnt++; - } else if (str.startsWith(braces[CLOSING], fromIndex)) { - closeCnt++; - if (openCnt > 0 && openCnt == closeCnt) { - return fromIndex; // found - } - } - } - return -1; // not found - } - - /** - * Strips braces from complex object string - * - * @param str - * String to parse - * @param braces - * String array containing opening and closing braces - * @return String with braces stripped - * @throws - * org.apache.fop.render.ps.PSDictionaryFormatException object format exception - */ - private String stripBraces(String str, String[] braces) throws PSDictionaryFormatException { - // find first opening brace - int firstIndex = str.indexOf(braces[OPENING]); - if (firstIndex == -1) { - throw new PSDictionaryFormatException( - "Failed to find opening parameter '" + braces[OPENING] - + ""); - } - - // find last matching brace - int lastIndex = indexOfMatchingBrace(str, braces, firstIndex); - if (lastIndex == -1) { - throw new PSDictionaryFormatException( - "Failed to find matching closing parameter '" - + braces[CLOSING] + "'"); - } - - // strip brace and trim - int braceLen = braces[OPENING].length(); - str = str.substring(firstIndex + braceLen, lastIndex).trim(); - return str; - } - - /** - * Parses a dictionary string and provides a dictionary object - * - * @param str a dictionary string - * @return A postscript dictionary object - * @throws - * PSDictionaryFormatException thrown if a dictionary format exception occurs - */ - public PSDictionary parseDictionary(String str) throws PSDictionaryFormatException { - PSDictionary dictionary = new PSDictionary(); - str = stripBraces(str.trim(), BRACES[DICTIONARY]); - // length of dictionary string - final int len = str.length(); - - Token keyToken; - for (int currIndex = 0; (keyToken = nextToken(str, currIndex)) != null - && currIndex <= len;) { - if (keyToken.value == null) { - throw new PSDictionaryFormatException("Failed to parse object key"); - } - Token valueToken = nextToken(str, keyToken.endIndex + 1); - String[] braces = null; - for (int i = 0; i < BRACES.length; i++) { - if (valueToken.value.startsWith(BRACES[i][OPENING])) { - braces = BRACES[i]; - break; - } - } - Object obj = null; - if (braces != null) { - // find closing brace - valueToken.endIndex = indexOfMatchingBrace(str, braces, - valueToken.startIndex) - + braces[OPENING].length(); - if (valueToken.endIndex < 0) { - throw new PSDictionaryFormatException("Closing value brace '" - + braces[CLOSING] + "' not found for key '" - + keyToken.value + "'"); - } - valueToken.value = str.substring(valueToken.startIndex, valueToken.endIndex); - } - if (braces == null || braces == BRACES[PROCEDURE]) { - obj = valueToken.value; - } else if (BRACES[ARRAY] == braces) { - List objList = new java.util.ArrayList(); - String objString = stripBraces(valueToken.value, braces); - StringTokenizer tokenizer = new StringTokenizer(objString, ","); - while (tokenizer.hasMoreTokens()) { - objList.add(tokenizer.nextToken()); - } - obj = objList; - } else if (BRACES[DICTIONARY] == braces) { - obj = parseDictionary(valueToken.value); - } - dictionary.put(keyToken.value, obj); - currIndex = valueToken.endIndex + 1; - } - return dictionary; - } - } - - /** - * Parses a given a dictionary string and returns an object - * - * @param str dictionary string - * @return dictionary object - * @throws PSDictionaryFormatException object format exception - */ - public static PSDictionary valueOf(String str) throws PSDictionaryFormatException { - return (new Maker()).parseDictionary(str); - } - - /** - * @param obj object to test equality against - * @return whether a given object is equal to this dictionary object - * @see java.lang.Object#equals(Object) - */ - public boolean equals(Object obj) { - if (!(obj instanceof PSPageDeviceDictionary)) { - return false; - } - PSDictionary dictionaryObj = (PSDictionary) obj; - if (dictionaryObj.size() != size()) { - return false; - } - for (Iterator it = keySet().iterator(); it.hasNext();) { - String key = (String) it.next(); - if (!dictionaryObj.containsKey(key)) { - return false; - } - if (!dictionaryObj.get(key).equals(get(key))) { - return false; - } - } - return true; - } - - /** - * @return a hash code value for this object. - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - int hashCode = 7; - for (Iterator it = values().iterator(); it.hasNext();) { - Object value = it.next(); - hashCode += value.hashCode(); - } - return hashCode; - } - - /** - * @return a string representation of this dictionary - * @see java.lang.String#toString() - */ - public String toString() { - if (isEmpty()) { - return ""; - } - StringBuffer sb = new StringBuffer("<<\n"); - for (Iterator it = super.keySet().iterator(); it.hasNext();) { - String key = (String) it.next(); - sb.append(" " + key + " "); - Object obj = super.get(key); - if (obj instanceof java.util.ArrayList) { - List array = (List)obj; - String str = "["; - for (int i = 0; i < array.size(); i++) { - Object element = array.get(i); - str += element + " "; - } - str = str.trim(); - str += "]"; - sb.append(str + "\n"); - } else { - sb.append(obj.toString() + "\n"); - } - } - sb.append(">>"); - return sb.toString(); - } -} diff --git a/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java b/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java deleted file mode 100644 index 1a0171d68..000000000 --- a/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.ps; - -/** - * Thrown to indicate that a formatting error has occured when - * trying to parse a postscript dictionary object - */ -public class PSDictionaryFormatException extends Exception { - - private static final long serialVersionUID = 6492321557297860931L; - - /** - * Default constructor - * @param string error message - */ - public PSDictionaryFormatException(String string) { - super(string); - } -} diff --git a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java b/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java deleted file mode 100644 index 88667c24d..000000000 --- a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.ps; - -/** - * Postscript page device dictionary object - * - * This object is used by the postscript renderer to hold postscript page device - * values. It can also be used to minimize the number of setpagedevice calls when - * DSC compliance is false. - */ -public class PSPageDeviceDictionary extends PSDictionary { - - private static final long serialVersionUID = 845943256485806509L; - - /** - * Whether or not the contents of the dictionary are flushed on retrieval - */ - private boolean flushOnRetrieval = false; - - /** - * Dictionary content that has not been output/written yet - */ - private PSDictionary unRetrievedContentDictionary; - - /** - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. - * @return the previous value associated with the key or null - * @see java.util.Map#put(Object, Object) - */ - public Object put(Object key, Object value) { - Object previousValue = super.put(key, value); - if (flushOnRetrieval) { - if (previousValue == null || !previousValue.equals(value)) { - unRetrievedContentDictionary.put(key, value); - } - } - return previousValue; - } - - /** - * @see java.util.Map#clear() - */ - public void clear() { - super.clear(); - if (unRetrievedContentDictionary != null) { - unRetrievedContentDictionary.clear(); - } - } - - /** - * Returns true if this map contains no key-value mappings. - * - * @return true if this map contains no key-value mappings. - */ - public boolean isEmpty() { - if (flushOnRetrieval) { - return unRetrievedContentDictionary.isEmpty(); - } - return super.isEmpty(); - } - - /** - * The contents of the dictionary are flushed when written - * @param flushOnRetrieval boolean value - */ - public void setFlushOnRetrieval(boolean flushOnRetrieval) { - this.flushOnRetrieval = flushOnRetrieval; - if (flushOnRetrieval) { - unRetrievedContentDictionary = new PSDictionary(); - } - } - - /** - * Returns a dictionary string with containing all unwritten content note: - * unnecessary writes are important as there is a device specific - * initgraphics call by the underlying postscript interpreter on every - * setpagedevice call which can result in blank pages etc. - * - * @return unwritten content dictionary string - */ - public String getContent() { - String content; - if (flushOnRetrieval) { - content = unRetrievedContentDictionary.toString(); - unRetrievedContentDictionary.clear(); - } else { - content = super.toString(); - } - return content; - } -} diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index a94c8b0aa..3f1769295 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -57,6 +57,9 @@ import org.apache.xmlgraphics.image.loader.pipeline.ImageProviderPipeline; import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.ps.DSCConstants; import org.apache.xmlgraphics.ps.ImageEncoder; +import org.apache.xmlgraphics.ps.PSDictionary; +import org.apache.xmlgraphics.ps.PSPageDeviceDictionary; +import org.apache.xmlgraphics.ps.PSDictionaryFormatException; import org.apache.xmlgraphics.ps.PSGenerator; import org.apache.xmlgraphics.ps.PSImageUtils; import org.apache.xmlgraphics.ps.PSProcSets; -- cgit v1.2.3 From 1a0a279d3ba3f36ff3f993b05a5a123c367d433b Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 28 Jun 2008 11:22:58 +0000 Subject: Removed unnecessary override git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@672495 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java index 58c0f4547..8849d4d1c 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java +++ b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java @@ -112,11 +112,6 @@ public abstract class AbstractPageNumberCitation extends FObj { } } - /** {@inheritDoc} */ - protected void startOfNode() throws FOPException { - super.startOfNode(); - } - /** * {@inheritDoc} *
    XSL Content Model: empty -- cgit v1.2.3 From 87899794427d024c581b89eb679e4656e912a889 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Sat, 28 Jun 2008 16:05:08 +0000 Subject: Corrected minor spelling mistake in javadoc git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@672537 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/EventListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/EventListener.java b/src/java/org/apache/fop/events/EventListener.java index f8293aed9..cb2d8b965 100644 --- a/src/java/org/apache/fop/events/EventListener.java +++ b/src/java/org/apache/fop/events/EventListener.java @@ -28,7 +28,7 @@ public interface EventListener extends java.util.EventListener { * This method is called for each event that is generated. With the event's ID it is possible * to react to certain events. Events can also simply be recorded and presented to a user. * It is possible to throw an (unchecked) exception if the processing needs to be aborted - * because some special event occured. This way the client can configure the behaviour of + * because some special event occurred. This way the client can configure the behaviour of * the observed application. * @param event the event */ -- cgit v1.2.3 From a9e8348fc754589b9fab0177f36d79e61012dd8a Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Sat, 28 Jun 2008 16:08:13 +0000 Subject: Corrected minor spelling mistake in javadoc git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@672539 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/EventExceptionManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/EventExceptionManager.java b/src/java/org/apache/fop/events/EventExceptionManager.java index 093ae7010..44b1ef7b1 100644 --- a/src/java/org/apache/fop/events/EventExceptionManager.java +++ b/src/java/org/apache/fop/events/EventExceptionManager.java @@ -25,7 +25,7 @@ import java.util.Map; import org.apache.xmlgraphics.util.Service; /** - * This class is reponsible for converting events into exceptions. + * This class is responsible for converting events into exceptions. */ public class EventExceptionManager { -- cgit v1.2.3 From 00f13c2f082ef7f75a12138fe3cac462322b47b7 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 29 Jun 2008 19:53:17 +0000 Subject: Cleanup/re-ordering, and addition of XSL 1.1 FO_ and PR_ constants git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@672670 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/Constants.java | 616 +++++++++++++++++------------- 1 file changed, 349 insertions(+), 267 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java index 2a7f7e0c9..ae4c11229 100644 --- a/src/java/org/apache/fop/fo/Constants.java +++ b/src/java/org/apache/fop/fo/Constants.java @@ -24,9 +24,9 @@ package org.apache.fop.fo; * There are sets of constants describing: *
      *
    • Input and output formats
    • - *
    • Formatting objects
    • - *
    • Formatting properties
    • - *
    • Enumerated values used in formatting properties
    • + *
    • Formatting objects (FO_XXX)
    • + *
    • Formatting properties (PR_XXX)
    • + *
    • Enumerated values used in formatting properties (EN_XXX)
    • *
    */ public interface Constants { @@ -45,124 +45,162 @@ public interface Constants { int FO_BLOCK = 3; /** FO element constant */ int FO_BLOCK_CONTAINER = 4; + /** FO element constant - XSL 1.1 */ + int FO_BOOKMARK_TREE = 5; + /** FO element constant - XSL 1.1 */ + int FO_BOOKMARK = 6; + /** FO element constant - XSL 1.1 */ + int FO_BOOKMARK_TITLE = 7; + /** FO element constant - XSL 1.1 */ + int FO_CHANGE_BAR_BEGIN = 8; + /** FO element constant - XSL 1.1 */ + int FO_CHANGE_BAR_END = 9; /** FO element constant */ - int FO_CHARACTER = 5; + int FO_CHARACTER = 10; /** FO element constant */ - int FO_COLOR_PROFILE = 6; + int FO_COLOR_PROFILE = 11; /** FO element constant */ - int FO_CONDITIONAL_PAGE_MASTER_REFERENCE = 7; + int FO_CONDITIONAL_PAGE_MASTER_REFERENCE = 12; /** FO element constant */ - int FO_DECLARATIONS = 8; + int FO_DECLARATIONS = 13; /** FO element constant */ - int FO_EXTERNAL_GRAPHIC = 9; + int FO_EXTERNAL_GRAPHIC = 14; /** FO element constant */ - int FO_FLOAT = 10; + int FO_FLOAT = 15; /** FO element constant */ - int FO_FLOW = 11; + int FO_FLOW = 16; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_ASSIGNMENT = 17; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_MAP = 18; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_NAME_SPECIFIER = 19; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_SOURCE_LIST = 20; + /** FO element constant - XSL 1.1 */ + int FO_FLOW_TARGET_LIST = 21; + /** FO element constant - XSL 1.1 */ + int FO_FOLIO_PREFIX = 22; + /** FO element constant - XSL 1.1 */ + int FO_FOLIO_SUFFIX = 23; /** FO element constant */ - int FO_FOOTNOTE = 12; + int FO_FOOTNOTE = 24; /** FO element constant */ - int FO_FOOTNOTE_BODY = 13; + int FO_FOOTNOTE_BODY = 25; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_KEY_REFERENCE = 26; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_NUMBER_PREFIX = 27; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_NUMBER_SUFFIX = 28; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_CITATION_LIST = 29; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_CITATION_LIST_SEPARATOR = 30; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_PAGE_CITATION_RANGE_SEPARATOR = 31; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_RANGE_BEGIN = 32; + /** FO element constant - XSL 1.1 */ + int FO_INDEX_RANGE_END = 33; /** FO element constant */ - int FO_INITIAL_PROPERTY_SET = 14; + int FO_INITIAL_PROPERTY_SET = 34; /** FO element constant */ - int FO_INLINE = 15; + int FO_INLINE = 35; /** FO element constant */ - int FO_INLINE_CONTAINER = 16; + int FO_INLINE_CONTAINER = 36; /** FO element constant */ - int FO_INSTREAM_FOREIGN_OBJECT = 17; + int FO_INSTREAM_FOREIGN_OBJECT = 37; /** FO element constant */ - int FO_LAYOUT_MASTER_SET = 18; + int FO_LAYOUT_MASTER_SET = 38; /** FO element constant */ - int FO_LEADER = 19; + int FO_LEADER = 39; /** FO element constant */ - int FO_LIST_BLOCK = 20; + int FO_LIST_BLOCK = 40; /** FO element constant */ - int FO_LIST_ITEM = 21; + int FO_LIST_ITEM = 41; /** FO element constant */ - int FO_LIST_ITEM_BODY = 22; + int FO_LIST_ITEM_BODY = 42; /** FO element constant */ - int FO_LIST_ITEM_LABEL = 23; + int FO_LIST_ITEM_LABEL = 43; /** FO element constant */ - int FO_MARKER = 24; + int FO_MARKER = 44; /** FO element constant */ - int FO_MULTI_CASE = 25; + int FO_MULTI_CASE = 45; /** FO element constant */ - int FO_MULTI_PROPERTIES = 26; + int FO_MULTI_PROPERTIES = 46; /** FO element constant */ - int FO_MULTI_PROPERTY_SET = 27; + int FO_MULTI_PROPERTY_SET = 47; /** FO element constant */ - int FO_MULTI_SWITCH = 28; + int FO_MULTI_SWITCH = 48; /** FO element constant */ - int FO_MULTI_TOGGLE = 29; + int FO_MULTI_TOGGLE = 49; /** FO element constant */ - int FO_PAGE_NUMBER = 30; + int FO_PAGE_NUMBER = 50; /** FO element constant */ - int FO_PAGE_NUMBER_CITATION = 31; + int FO_PAGE_NUMBER_CITATION = 51; + /** FO element constant - XSL 1.1 */ + int FO_PAGE_NUMBER_CITATION_LAST = 52; /** FO element constant */ - int FO_PAGE_SEQUENCE = 32; + int FO_PAGE_SEQUENCE = 53; /** FO element constant */ - int FO_PAGE_SEQUENCE_MASTER = 33; + int FO_PAGE_SEQUENCE_MASTER = 54; + /** FO element constant - XSL 1.1 */ + int FO_PAGE_SEQUENCE_WRAPPER = 55; /** FO element constant */ - int FO_REGION_AFTER = 34; + int FO_REGION_AFTER = 56; /** FO element constant */ - int FO_REGION_BEFORE = 35; + int FO_REGION_BEFORE = 57; /** FO element constant */ - int FO_REGION_BODY = 36; + int FO_REGION_BODY = 58; /** FO element constant */ - int FO_REGION_END = 37; + int FO_REGION_END = 59; + /** FO element constant - XSL 1.1 */ + int FO_REGION_NAME_SPECIFIER = 60; /** FO element constant */ - int FO_REGION_START = 38; + int FO_REGION_START = 61; /** FO element constant */ - int FO_REPEATABLE_PAGE_MASTER_ALTERNATIVES = 39; + int FO_REPEATABLE_PAGE_MASTER_ALTERNATIVES = 62; /** FO element constant */ - int FO_REPEATABLE_PAGE_MASTER_REFERENCE = 40; + int FO_REPEATABLE_PAGE_MASTER_REFERENCE = 63; /** FO element constant */ - int FO_RETRIEVE_MARKER = 41; + int FO_RETRIEVE_MARKER = 64; + /** FO element constant - XSL 1.1 */ + int FO_RETRIEVE_TABLE_MARKER = 65; /** FO element constant */ - int FO_ROOT = 42; + int FO_ROOT = 66; + /** FO element constant - XSL 1.1 */ + int FO_SCALING_VALUE_CITATION = 67; /** FO element constant */ - int FO_SIMPLE_PAGE_MASTER = 43; + int FO_SIMPLE_PAGE_MASTER = 68; /** FO element constant */ - int FO_SINGLE_PAGE_MASTER_REFERENCE = 44; + int FO_SINGLE_PAGE_MASTER_REFERENCE = 69; /** FO element constant */ - int FO_STATIC_CONTENT = 45; + int FO_STATIC_CONTENT = 70; /** FO element constant */ - int FO_TABLE = 46; + int FO_TABLE = 71; /** FO element constant */ - int FO_TABLE_AND_CAPTION = 47; + int FO_TABLE_AND_CAPTION = 72; /** FO element constant */ - int FO_TABLE_BODY = 48; + int FO_TABLE_BODY = 73; /** FO element constant */ - int FO_TABLE_CAPTION = 49; + int FO_TABLE_CAPTION = 74; /** FO element constant */ - int FO_TABLE_CELL = 50; + int FO_TABLE_CELL = 75; /** FO element constant */ - int FO_TABLE_COLUMN = 51; + int FO_TABLE_COLUMN = 76; /** FO element constant */ - int FO_TABLE_FOOTER = 52; + int FO_TABLE_FOOTER = 77; /** FO element constant */ - int FO_TABLE_HEADER = 53; + int FO_TABLE_HEADER = 78; /** FO element constant */ - int FO_TABLE_ROW = 54; + int FO_TABLE_ROW = 79; /** FO element constant */ - int FO_TITLE = 55; + int FO_TITLE = 80; /** FO element constant */ - int FO_WRAPPER = 56; - /** FO element constant - XSL 1.1 */ - int FO_BOOKMARK_TREE = 57; - /** FO element constant - XSL 1.1 */ - int FO_BOOKMARK = 58; - /** FO element constant - XSL 1.1 */ - int FO_BOOKMARK_TITLE = 59; - /** FO element constant - XSL 1.1 */ - int FO_PAGE_SEQUENCE_WRAPPER = 60; - /** FO element constant - XSL 1.1 */ - int FO_PAGE_NUMBER_CITATION_LAST = 61; - /** FO element constant - XSL 1.1 */ - int FO_RETRIEVE_TABLE_MARKER = 62; + int FO_WRAPPER = 81; /** Number of FO element constants defined */ - int FRM_OBJ_COUNT = 62; + int FRM_OBJ_COUNT = 81; // Masks /** @@ -308,394 +346,428 @@ public interface Constants { int PR_CASE_NAME = 61; /** Property constant */ int PR_CASE_TITLE = 62; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_CLASS = 63; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_COLOR = 64; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_OFFSET = 65; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_PLACEMENT = 66; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_STYLE = 67; + /** Property constant - XSL 1.1 */ + int PR_CHANGE_BAR_WIDTH = 68; /** Property constant */ - int PR_CHARACTER = 63; + int PR_CHARACTER = 69; /** Property constant */ - int PR_CLEAR = 64; + int PR_CLEAR = 70; /** Property constant */ - int PR_CLIP = 65; + int PR_CLIP = 71; /** Property constant */ - int PR_COLOR = 66; + int PR_COLOR = 72; /** Property constant */ - int PR_COLOR_PROFILE_NAME = 67; + int PR_COLOR_PROFILE_NAME = 73; /** Property constant */ - int PR_COLUMN_COUNT = 68; + int PR_COLUMN_COUNT = 74; /** Property constant */ - int PR_COLUMN_GAP = 69; + int PR_COLUMN_GAP = 75; /** Property constant */ - int PR_COLUMN_NUMBER = 70; + int PR_COLUMN_NUMBER = 76; /** Property constant */ - int PR_COLUMN_WIDTH = 71; + int PR_COLUMN_WIDTH = 77; /** Property constant */ - int PR_CONTENT_HEIGHT = 72; + int PR_CONTENT_HEIGHT = 78; /** Property constant */ - int PR_CONTENT_TYPE = 73; + int PR_CONTENT_TYPE = 79; /** Property constant */ - int PR_CONTENT_WIDTH = 74; + int PR_CONTENT_WIDTH = 80; /** Property constant */ - int PR_COUNTRY = 75; + int PR_COUNTRY = 81; /** Property constant */ - int PR_CUE = 76; + int PR_CUE = 82; /** Property constant */ - int PR_CUE_AFTER = 77; + int PR_CUE_AFTER = 83; /** Property constant */ - int PR_CUE_BEFORE = 78; + int PR_CUE_BEFORE = 84; /** Property constant */ - int PR_DESTINATION_PLACEMENT_OFFSET = 79; + int PR_DESTINATION_PLACEMENT_OFFSET = 85; /** Property constant */ - int PR_DIRECTION = 80; + int PR_DIRECTION = 86; /** Property constant */ - int PR_DISPLAY_ALIGN = 81; + int PR_DISPLAY_ALIGN = 87; /** Property constant */ - int PR_DOMINANT_BASELINE = 82; + int PR_DOMINANT_BASELINE = 88; /** Property constant */ - int PR_ELEVATION = 83; + int PR_ELEVATION = 89; /** Property constant */ - int PR_EMPTY_CELLS = 84; + int PR_EMPTY_CELLS = 90; /** Property constant */ - int PR_END_INDENT = 85; + int PR_END_INDENT = 91; /** Property constant */ - int PR_ENDS_ROW = 86; + int PR_ENDS_ROW = 92; /** Property constant */ - int PR_EXTENT = 87; + int PR_EXTENT = 93; /** Property constant */ - int PR_EXTERNAL_DESTINATION = 88; + int PR_EXTERNAL_DESTINATION = 94; /** Property constant */ - int PR_FLOAT = 89; + int PR_FLOAT = 95; + /** Property constant -- XSL 1.1 */ + int PR_FLOW_MAP_NAME = 96; + /** Property constant -- XSL 1.1 */ + int PR_FLOW_MAP_REFERENCE = 97; /** Property constant */ - int PR_FLOW_NAME = 90; + int PR_FLOW_NAME = 98; + /** Property constant -- XSL 1.1 */ + int PR_FLOW_NAME_REFERENCE = 99; /** Property constant */ - int PR_FONT = 91; + int PR_FONT = 100; /** Property constant */ - int PR_FONT_FAMILY = 92; + int PR_FONT_FAMILY = 101; /** Property constant */ - int PR_FONT_SELECTION_STRATEGY = 93; + int PR_FONT_SELECTION_STRATEGY = 102; /** Property constant */ - int PR_FONT_SIZE = 94; + int PR_FONT_SIZE = 103; /** Property constant */ - int PR_FONT_SIZE_ADJUST = 95; + int PR_FONT_SIZE_ADJUST = 104; /** Property constant */ - int PR_FONT_STRETCH = 96; + int PR_FONT_STRETCH = 105; /** Property constant */ - int PR_FONT_STYLE = 97; + int PR_FONT_STYLE = 106; /** Property constant */ - int PR_FONT_VARIANT = 98; + int PR_FONT_VARIANT = 107; /** Property constant */ - int PR_FONT_WEIGHT = 99; + int PR_FONT_WEIGHT = 108; /** Property constant */ - int PR_FORCE_PAGE_COUNT = 100; + int PR_FORCE_PAGE_COUNT = 109; /** Property constant */ - int PR_FORMAT = 101; + int PR_FORMAT = 110; /** Property constant */ - int PR_GLYPH_ORIENTATION_HORIZONTAL = 102; + int PR_GLYPH_ORIENTATION_HORIZONTAL = 111; /** Property constant */ - int PR_GLYPH_ORIENTATION_VERTICAL = 103; + int PR_GLYPH_ORIENTATION_VERTICAL = 112; /** Property constant */ - int PR_GROUPING_SEPARATOR = 104; + int PR_GROUPING_SEPARATOR = 113; /** Property constant */ - int PR_GROUPING_SIZE = 105; + int PR_GROUPING_SIZE = 114; /** Property constant */ - int PR_HEIGHT = 106; + int PR_HEIGHT = 115; /** Property constant */ - int PR_HYPHENATE = 107; + int PR_HYPHENATE = 116; /** Property constant */ - int PR_HYPHENATION_CHARACTER = 108; + int PR_HYPHENATION_CHARACTER = 117; /** Property constant */ - int PR_HYPHENATION_KEEP = 109; + int PR_HYPHENATION_KEEP = 118; /** Property constant */ - int PR_HYPHENATION_LADDER_COUNT = 110; + int PR_HYPHENATION_LADDER_COUNT = 119; /** Property constant */ - int PR_HYPHENATION_PUSH_CHARACTER_COUNT = 111; + int PR_HYPHENATION_PUSH_CHARACTER_COUNT = 120; /** Property constant */ - int PR_HYPHENATION_REMAIN_CHARACTER_COUNT = 112; + int PR_HYPHENATION_REMAIN_CHARACTER_COUNT = 121; /** Property constant */ - int PR_ID = 113; + int PR_ID = 122; /** Property constant */ - int PR_INDICATE_DESTINATION = 114; + int PR_INDICATE_DESTINATION = 123; + /** Property constant - XSL 1.1 */ + int PR_INDEX_CLASS = 124; + /** Property constant - XSL 1.1 */ + int PR_INDEX_KEY = 125; /** Property constant */ - int PR_INITIAL_PAGE_NUMBER = 115; + int PR_INITIAL_PAGE_NUMBER = 126; /** Property constant */ - int PR_INLINE_PROGRESSION_DIMENSION = 116; + int PR_INLINE_PROGRESSION_DIMENSION = 127; /** Property constant */ - int PR_INTERNAL_DESTINATION = 117; + int PR_INTERNAL_DESTINATION = 128; + /** Property constant - XSL 1.1 */ + int PR_INTRINSIC_SCALE_VALUE = 129; /** Property constant */ - int PR_KEEP_TOGETHER = 118; + int PR_INTRUSION_DISPLACE = 130; /** Property constant */ - int PR_KEEP_WITH_NEXT = 119; + int PR_KEEP_TOGETHER = 131; /** Property constant */ - int PR_KEEP_WITH_PREVIOUS = 120; + int PR_KEEP_WITH_NEXT = 132; /** Property constant */ - int PR_LANGUAGE = 121; + int PR_KEEP_WITH_PREVIOUS = 133; /** Property constant */ - int PR_LAST_LINE_END_INDENT = 122; + int PR_LANGUAGE = 134; /** Property constant */ - int PR_LEADER_ALIGNMENT = 123; + int PR_LAST_LINE_END_INDENT = 135; /** Property constant */ - int PR_LEADER_LENGTH = 124; + int PR_LEADER_ALIGNMENT = 136; /** Property constant */ - int PR_LEADER_PATTERN = 125; + int PR_LEADER_LENGTH = 137; /** Property constant */ - int PR_LEADER_PATTERN_WIDTH = 126; + int PR_LEADER_PATTERN = 138; /** Property constant */ - int PR_LEFT = 127; + int PR_LEADER_PATTERN_WIDTH = 139; /** Property constant */ - int PR_LETTER_SPACING = 128; + int PR_LEFT = 140; /** Property constant */ - int PR_LETTER_VALUE = 129; + int PR_LETTER_SPACING = 141; /** Property constant */ - int PR_LINEFEED_TREATMENT = 130; + int PR_LETTER_VALUE = 142; /** Property constant */ - int PR_LINE_HEIGHT = 131; + int PR_LINEFEED_TREATMENT = 143; /** Property constant */ - int PR_LINE_HEIGHT_SHIFT_ADJUSTMENT = 132; + int PR_LINE_HEIGHT = 144; /** Property constant */ - int PR_LINE_STACKING_STRATEGY = 133; + int PR_LINE_HEIGHT_SHIFT_ADJUSTMENT = 145; /** Property constant */ - int PR_MARGIN = 134; + int PR_LINE_STACKING_STRATEGY = 146; /** Property constant */ - int PR_MARGIN_BOTTOM = 135; + int PR_MARGIN = 147; /** Property constant */ - int PR_MARGIN_LEFT = 136; + int PR_MARGIN_BOTTOM = 148; /** Property constant */ - int PR_MARGIN_RIGHT = 137; + int PR_MARGIN_LEFT = 149; /** Property constant */ - int PR_MARGIN_TOP = 138; + int PR_MARGIN_RIGHT = 150; /** Property constant */ - int PR_MARKER_CLASS_NAME = 139; + int PR_MARGIN_TOP = 151; /** Property constant */ - int PR_MASTER_NAME = 140; + int PR_MARKER_CLASS_NAME = 152; /** Property constant */ - int PR_MASTER_REFERENCE = 141; + int PR_MASTER_NAME = 153; /** Property constant */ - int PR_MAX_HEIGHT = 142; + int PR_MASTER_REFERENCE = 154; /** Property constant */ - int PR_MAXIMUM_REPEATS = 143; + int PR_MAX_HEIGHT = 155; /** Property constant */ - int PR_MAX_WIDTH = 144; + int PR_MAXIMUM_REPEATS = 156; /** Property constant */ - int PR_MEDIA_USAGE = 145; + int PR_MAX_WIDTH = 157; + /** Property constant - XSL 1.1 */ + int PR_MERGE_PAGES_ACROSS_INDEX_KEY_REFERENCES = 158; + /** Property constant - XSL 1.1 */ + int PR_MERGE_RANGES_ACROSS_INDEX_KEY_REFERENCES = 159; + /** Property constant - XSL 1.1 */ + int PR_MERGE_SEQUENTIAL_PAGE_NUMBERS = 160; /** Property constant */ - int PR_MIN_HEIGHT = 146; + int PR_MEDIA_USAGE = 161; /** Property constant */ - int PR_MIN_WIDTH = 147; + int PR_MIN_HEIGHT = 162; /** Property constant */ - int PR_NUMBER_COLUMNS_REPEATED = 148; + int PR_MIN_WIDTH = 163; /** Property constant */ - int PR_NUMBER_COLUMNS_SPANNED = 149; + int PR_NUMBER_COLUMNS_REPEATED = 164; /** Property constant */ - int PR_NUMBER_ROWS_SPANNED = 150; + int PR_NUMBER_COLUMNS_SPANNED = 165; /** Property constant */ - int PR_ODD_OR_EVEN = 151; + int PR_NUMBER_ROWS_SPANNED = 166; /** Property constant */ - int PR_ORPHANS = 152; + int PR_ODD_OR_EVEN = 167; /** Property constant */ - int PR_OVERFLOW = 153; + int PR_ORPHANS = 168; /** Property constant */ - int PR_PADDING = 154; + int PR_OVERFLOW = 169; /** Property constant */ - int PR_PADDING_AFTER = 155; + int PR_PADDING = 170; /** Property constant */ - int PR_PADDING_BEFORE = 156; + int PR_PADDING_AFTER = 171; /** Property constant */ - int PR_PADDING_BOTTOM = 157; + int PR_PADDING_BEFORE = 172; /** Property constant */ - int PR_PADDING_END = 158; + int PR_PADDING_BOTTOM = 173; /** Property constant */ - int PR_PADDING_LEFT = 159; + int PR_PADDING_END = 174; /** Property constant */ - int PR_PADDING_RIGHT = 160; + int PR_PADDING_LEFT = 175; /** Property constant */ - int PR_PADDING_START = 161; + int PR_PADDING_RIGHT = 176; /** Property constant */ - int PR_PADDING_TOP = 162; + int PR_PADDING_START = 177; /** Property constant */ - int PR_PAGE_BREAK_AFTER = 163; + int PR_PADDING_TOP = 178; /** Property constant */ - int PR_PAGE_BREAK_BEFORE = 164; + int PR_PAGE_BREAK_AFTER = 179; /** Property constant */ - int PR_PAGE_BREAK_INSIDE = 165; + int PR_PAGE_BREAK_BEFORE = 180; /** Property constant */ - int PR_PAGE_HEIGHT = 166; + int PR_PAGE_BREAK_INSIDE = 181; + /** Property constant - XSL 1.1 */ + int PR_PAGE_CITATION_STRATEGY = 182; /** Property constant */ - int PR_PAGE_POSITION = 167; + int PR_PAGE_HEIGHT = 183; + /** Property constant - XSL 1.1 */ + int PR_PAGE_NUMBER_TREATMENT = 184; /** Property constant */ - int PR_PAGE_WIDTH = 168; + int PR_PAGE_POSITION = 185; /** Property constant */ - int PR_PAUSE = 169; + int PR_PAGE_WIDTH = 186; /** Property constant */ - int PR_PAUSE_AFTER = 170; + int PR_PAUSE = 187; /** Property constant */ - int PR_PAUSE_BEFORE = 171; + int PR_PAUSE_AFTER = 188; /** Property constant */ - int PR_PITCH = 172; + int PR_PAUSE_BEFORE = 189; /** Property constant */ - int PR_PITCH_RANGE = 173; + int PR_PITCH = 190; /** Property constant */ - int PR_PLAY_DURING = 174; + int PR_PITCH_RANGE = 191; /** Property constant */ - int PR_POSITION = 175; + int PR_PLAY_DURING = 192; /** Property constant */ - int PR_PRECEDENCE = 176; + int PR_POSITION = 193; /** Property constant */ - int PR_PROVISIONAL_DISTANCE_BETWEEN_STARTS = 177; + int PR_PRECEDENCE = 194; /** Property constant */ - int PR_PROVISIONAL_LABEL_SEPARATION = 178; + int PR_PROVISIONAL_DISTANCE_BETWEEN_STARTS = 195; /** Property constant */ - int PR_REFERENCE_ORIENTATION = 179; + int PR_PROVISIONAL_LABEL_SEPARATION = 196; /** Property constant */ - int PR_REF_ID = 180; + int PR_REFERENCE_ORIENTATION = 197; /** Property constant */ - int PR_REGION_NAME = 181; + int PR_REF_ID = 198; /** Property constant */ - int PR_RELATIVE_ALIGN = 182; + int PR_REGION_NAME = 199; + /** Property constant - XSL 1.1 */ + int PR_REGION_NAME_REFERENCE = 200; + /** Property constant - XSL 1.1 */ + int PR_REF_INDEX_KEY = 201; /** Property constant */ - int PR_RELATIVE_POSITION = 183; + int PR_RELATIVE_ALIGN = 202; /** Property constant */ - int PR_RENDERING_INTENT = 184; + int PR_RELATIVE_POSITION = 203; /** Property constant */ - int PR_RETRIEVE_BOUNDARY = 185; + int PR_RENDERING_INTENT = 204; /** Property constant */ - int PR_RETRIEVE_CLASS_NAME = 186; + int PR_RETRIEVE_BOUNDARY = 205; + /** Property constant - XSL 1.1 */ + int PR_RETRIEVE_BOUNDARY_WITHIN_TABLE = 206; /** Property constant */ - int PR_RETRIEVE_POSITION = 187; + int PR_RETRIEVE_CLASS_NAME = 207; /** Property constant */ - int PR_RICHNESS = 188; + int PR_RETRIEVE_POSITION = 208; + /** Property constant - XSL 1.1 */ + int PR_RETRIEVE_POSITION_WITHIN_TABLE = 209; /** Property constant */ - int PR_RIGHT = 189; + int PR_RICHNESS = 210; /** Property constant */ - int PR_ROLE = 190; + int PR_RIGHT = 211; /** Property constant */ - int PR_RULE_STYLE = 191; + int PR_ROLE = 212; /** Property constant */ - int PR_RULE_THICKNESS = 192; + int PR_RULE_STYLE = 213; /** Property constant */ - int PR_SCALING = 193; + int PR_RULE_THICKNESS = 214; /** Property constant */ - int PR_SCALING_METHOD = 194; + int PR_SCALING = 215; /** Property constant */ - int PR_SCORE_SPACES = 195; + int PR_SCALING_METHOD = 216; /** Property constant */ - int PR_SCRIPT = 196; + int PR_SCORE_SPACES = 217; /** Property constant */ - int PR_SHOW_DESTINATION = 197; + int PR_SCRIPT = 218; /** Property constant */ - int PR_SIZE = 198; + int PR_SHOW_DESTINATION = 219; /** Property constant */ - int PR_SOURCE_DOCUMENT = 199; + int PR_SIZE = 220; /** Property constant */ - int PR_SPACE_AFTER = 200; + int PR_SOURCE_DOCUMENT = 221; /** Property constant */ - int PR_SPACE_BEFORE = 201; + int PR_SPACE_AFTER = 222; /** Property constant */ - int PR_SPACE_END = 202; + int PR_SPACE_BEFORE = 223; /** Property constant */ - int PR_SPACE_START = 203; + int PR_SPACE_END = 224; /** Property constant */ - int PR_SPAN = 204; + int PR_SPACE_START = 225; /** Property constant */ - int PR_SPEAK = 205; + int PR_SPAN = 226; /** Property constant */ - int PR_SPEAK_HEADER = 206; + int PR_SPEAK = 227; /** Property constant */ - int PR_SPEAK_NUMERAL = 207; + int PR_SPEAK_HEADER = 228; /** Property constant */ - int PR_SPEAK_PUNCTUATION = 208; + int PR_SPEAK_NUMERAL = 229; /** Property constant */ - int PR_SPEECH_RATE = 209; + int PR_SPEAK_PUNCTUATION = 230; /** Property constant */ - int PR_SRC = 210; + int PR_SPEECH_RATE = 231; /** Property constant */ - int PR_START_INDENT = 211; + int PR_SRC = 232; /** Property constant */ - int PR_STARTING_STATE = 212; + int PR_START_INDENT = 233; /** Property constant */ - int PR_STARTS_ROW = 213; + int PR_STARTING_STATE = 234; /** Property constant */ - int PR_STRESS = 214; + int PR_STARTS_ROW = 235; /** Property constant */ - int PR_SUPPRESS_AT_LINE_BREAK = 215; + int PR_STRESS = 236; /** Property constant */ - int PR_SWITCH_TO = 216; + int PR_SUPPRESS_AT_LINE_BREAK = 237; /** Property constant */ - int PR_TABLE_LAYOUT = 217; + int PR_SWITCH_TO = 238; /** Property constant */ - int PR_TABLE_OMIT_FOOTER_AT_BREAK = 218; + int PR_TABLE_LAYOUT = 239; /** Property constant */ - int PR_TABLE_OMIT_HEADER_AT_BREAK = 219; + int PR_TABLE_OMIT_FOOTER_AT_BREAK = 240; /** Property constant */ - int PR_TARGET_PRESENTATION_CONTEXT = 220; + int PR_TABLE_OMIT_HEADER_AT_BREAK = 241; /** Property constant */ - int PR_TARGET_PROCESSING_CONTEXT = 221; + int PR_TARGET_PRESENTATION_CONTEXT = 242; /** Property constant */ - int PR_TARGET_STYLESHEET = 222; + int PR_TARGET_PROCESSING_CONTEXT = 243; /** Property constant */ - int PR_TEXT_ALIGN = 223; + int PR_TARGET_STYLESHEET = 244; /** Property constant */ - int PR_TEXT_ALIGN_LAST = 224; + int PR_TEXT_ALIGN = 245; /** Property constant */ - int PR_TEXT_ALTITUDE = 225; + int PR_TEXT_ALIGN_LAST = 246; /** Property constant */ - int PR_TEXT_DECORATION = 226; + int PR_TEXT_ALTITUDE = 247; /** Property constant */ - int PR_TEXT_DEPTH = 227; + int PR_TEXT_DECORATION = 248; /** Property constant */ - int PR_TEXT_INDENT = 228; + int PR_TEXT_DEPTH = 249; /** Property constant */ - int PR_TEXT_SHADOW = 229; + int PR_TEXT_INDENT = 250; /** Property constant */ - int PR_TEXT_TRANSFORM = 230; + int PR_TEXT_SHADOW = 251; /** Property constant */ - int PR_TOP = 231; + int PR_TEXT_TRANSFORM = 252; /** Property constant */ - int PR_TREAT_AS_WORD_SPACE = 232; + int PR_TOP = 253; /** Property constant */ - int PR_UNICODE_BIDI = 233; + int PR_TREAT_AS_WORD_SPACE = 254; /** Property constant */ - int PR_VERTICAL_ALIGN = 234; + int PR_UNICODE_BIDI = 255; /** Property constant */ - int PR_VISIBILITY = 235; + int PR_VERTICAL_ALIGN = 256; /** Property constant */ - int PR_VOICE_FAMILY = 236; + int PR_VISIBILITY = 257; /** Property constant */ - int PR_VOLUME = 237; + int PR_VOICE_FAMILY = 258; /** Property constant */ - int PR_WHITE_SPACE = 238; + int PR_VOLUME = 259; /** Property constant */ - int PR_WHITE_SPACE_COLLAPSE = 239; + int PR_WHITE_SPACE = 260; /** Property constant */ - int PR_WHITE_SPACE_TREATMENT = 240; + int PR_WHITE_SPACE_COLLAPSE = 261; /** Property constant */ - int PR_WIDOWS = 241; + int PR_WHITE_SPACE_TREATMENT = 262; /** Property constant */ - int PR_WIDTH = 242; + int PR_WIDOWS = 263; /** Property constant */ - int PR_WORD_SPACING = 243; + int PR_WIDTH = 264; /** Property constant */ - int PR_WRAP_OPTION = 244; + int PR_WORD_SPACING = 265; /** Property constant */ - int PR_WRITING_MODE = 245; + int PR_WRAP_OPTION = 266; /** Property constant */ - int PR_XML_LANG = 246; + int PR_WRITING_MODE = 267; /** Property constant */ - int PR_Z_INDEX = 247; + int PR_XML_LANG = 268; /** Property constant */ - int PR_INTRUSION_DISPLACE = 248; - /** Property constant - XSL 1.1 */ - int PR_INDEX_CLASS = 249; - /** Property constant - XSL 1.1 */ - int PR_INDEX_KEY = 250; + int PR_Z_INDEX = 269; /** Property constant - FOP proprietary: Custom extension for line alignment */ - int PR_X_BLOCK_PROGRESSION_UNIT = 251; + int PR_X_BLOCK_PROGRESSION_UNIT = 270; /** Property constant - FOP proprietary: limit for widow content in lists and tables */ - int PR_X_WIDOW_CONTENT_LIMIT = 252; + int PR_X_WIDOW_CONTENT_LIMIT = 271; /** Property constant - FOP proprietary: limit for orphan content in lists and tables */ - int PR_X_ORPHAN_CONTENT_LIMIT = 253; - /** Property constant */ - int PR_RETRIEVE_POSITION_WITHIN_TABLE = 254; - /** Property constant */ - int PR_RETRIEVE_BOUNDARY_WITHIN_TABLE = 255; + int PR_X_ORPHAN_CONTENT_LIMIT = 272; /** Number of property constants defined */ - int PROPERTY_COUNT = 255; + int PROPERTY_COUNT = 272; // compound property constants @@ -1113,6 +1185,16 @@ public interface Constants { int EN_TABLE = 194; /** Enumeration constant -- for fo:retrieve-table-marker */ int EN_TABLE_FRAGMENT = 195; + /** Enumeration constant -- XSL 1.1 */ + int EN_MERGE = 196; + /** Enumeration constant -- XSL 1.1 */ + int EN_LEAVE_SEPARATE = 197; + /** Enumeration constant -- XSL 1.1 */ + int EN_LINK = 198; + /** Enumeration constant -- XSL 1.1 */ + int EN_NO_LINK = 199; + /** Enumeration constant -- XSL 1.1 */ + int EN_ALTERNATE = 200; /** Number of enumeration constants defined */ - int ENUM_COUNT = 195; + int ENUM_COUNT = 200; } -- cgit v1.2.3 From 2851b9c98ae24bf423b9ad8451cadaef919e8ac7 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 4 Jul 2008 13:13:29 +0000 Subject: Minor readability improvement. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674039 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/java2d/Java2DRenderer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index e39ae5831..5996c5d0c 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -539,7 +539,9 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem protected void drawBorderLine(float x1, float y1, float x2, float y2, boolean horz, boolean startOrBefore, int style, Color col) { Graphics2D g2d = state.getGraph(); - drawBorderLine(new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1), + float width = x2 - x1; + float height = y2 - y1; + drawBorderLine(new Rectangle2D.Float(x1, y1, width, height), horz, startOrBefore, style, col, g2d); } -- cgit v1.2.3 From f46fc609adc8313f01288205330c9a9e53e75a14 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 4 Jul 2008 13:17:06 +0000 Subject: The pdf StringBuffer is only used on these two lines and doesn't seem to do anything... Very strange... :-S git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674043 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/pdf/PDFRenderer.java | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 06f5921cc..c4f045786 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -1415,7 +1415,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { updateColor(ct, true); beginTextObject(); - StringBuffer pdf = new StringBuffer(); String fontName = getInternalFontNameForArea(text); int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); @@ -1434,8 +1433,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, rx / 1000f, bl / 1000f)); - currentStream.add(pdf.toString()); - super.renderText(text); textutil.writeTJ(); -- cgit v1.2.3 From 204ed6d4a33e1d3bf1f515c70dc2bd06e9898027 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 4 Jul 2008 13:57:57 +0000 Subject: * Some minor optimizations in AbstractRenderer. * Renamed getBooleanTrait() to getTraitAsBoolean() in Area. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674056 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/Area.java | 3 +- .../org/apache/fop/area/inline/InlineArea.java | 8 +-- .../org/apache/fop/render/AbstractRenderer.java | 66 ++++++++++++---------- 3 files changed, 43 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index ff9f5c7d0..d656b7b7d 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -415,10 +415,11 @@ public class Area extends AreaTreeObject implements Serializable { /** * Get a boolean trait from this area. + * * @param oTraitCode the trait key * @return the trait value */ - public boolean getBooleanTrait(Object oTraitCode) { + public boolean getTraitAsBoolean(Object oTraitCode) { final Object obj = getTrait(oTraitCode); if (obj instanceof Boolean) { return ((Boolean)obj).booleanValue(); diff --git a/src/java/org/apache/fop/area/inline/InlineArea.java b/src/java/org/apache/fop/area/inline/InlineArea.java index 0655cabe4..10ea4e304 100644 --- a/src/java/org/apache/fop/area/inline/InlineArea.java +++ b/src/java/org/apache/fop/area/inline/InlineArea.java @@ -182,22 +182,22 @@ public class InlineArea extends Area { *@return true if the inline area is underlined. */ public boolean hasUnderline() { - return getBooleanTrait(Trait.UNDERLINE); + return getTraitAsBoolean(Trait.UNDERLINE); } /** @return true if the inline area is overlined. */ public boolean hasOverline() { - return getBooleanTrait(Trait.OVERLINE); + return getTraitAsBoolean(Trait.OVERLINE); } /** @return true if the inline area has a line through. */ public boolean hasLineThrough() { - return getBooleanTrait(Trait.LINETHROUGH); + return getTraitAsBoolean(Trait.LINETHROUGH); } /** @return true if the inline area is blinking. */ public boolean isBlinking() { - return getBooleanTrait(Trait.BLINK); + return getTraitAsBoolean(Trait.BLINK); } /** diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 20eceac8c..5c3e73ee0 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -246,15 +246,25 @@ public abstract class AbstractRenderer last here. */ RegionViewport viewport; viewport = page.getRegionViewport(FO_REGION_BEFORE); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_START); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_END); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_AFTER); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_BODY); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } } /** @@ -266,27 +276,25 @@ public abstract class AbstractRenderer * @param port The region viewport to be rendered */ protected void renderRegionViewport(RegionViewport port) { - if (port != null) { - Rectangle2D view = port.getViewArea(); - // The CTM will transform coordinates relative to - // this region-reference area into page coords, so - // set origin for the region to 0,0. - currentBPPosition = 0; - currentIPPosition = 0; - - RegionReference regionReference = port.getRegionReference(); - handleRegionTraits(port); - - // shouldn't the viewport have the CTM - startVParea(regionReference.getCTM(), port.isClip() ? view : null); - // do after starting viewport area - if (regionReference.getRegionClass() == FO_REGION_BODY) { - renderBodyRegion((BodyRegion) regionReference); - } else { - renderRegion(regionReference); - } - endVParea(); + Rectangle2D view = port.getViewArea(); + // The CTM will transform coordinates relative to + // this region-reference area into page coords, so + // set origin for the region to 0,0. + currentBPPosition = 0; + currentIPPosition = 0; + + RegionReference regionReference = port.getRegionReference(); + handleRegionTraits(port); + + // shouldn't the viewport have the CTM + startVParea(regionReference.getCTM(), port.isClip() ? view : null); + // do after starting viewport area + if (regionReference.getRegionClass() == FO_REGION_BODY) { + renderBodyRegion((BodyRegion) regionReference); + } else { + renderRegion(regionReference); } + endVParea(); } /** @@ -320,8 +328,7 @@ public abstract class AbstractRenderer * @param region The region reference area */ protected void renderRegion(RegionReference region) { - List blocks = region.getBlocks(); - renderBlocks(null, blocks); + renderBlocks(null, region.getBlocks()); } /** @@ -502,7 +509,7 @@ public abstract class AbstractRenderer int saveBP = currentBPPosition; // Calculate the position of the content rectangle. - if (parent != null && !Boolean.TRUE.equals(parent.getTrait(Trait.IS_VIEWPORT_AREA))) { + if (parent != null && !parent.getTraitAsBoolean(Trait.IS_VIEWPORT_AREA)) { currentBPPosition += parent.getBorderAndPaddingWidthBefore(); /* This is unnecessary now as we're going to use the *-indent traits currentIPPosition += parent.getBorderAndPaddingWidthStart(); @@ -558,7 +565,7 @@ public abstract class AbstractRenderer // simply move position currentBPPosition += block.getAllocBPD(); } - } else if (Boolean.TRUE.equals(block.getTrait(Trait.IS_REFERENCE_AREA))) { + } else if (block.getTraitAsBoolean(Trait.IS_REFERENCE_AREA)) { renderReferenceArea(block); } else { // save position and offset @@ -864,4 +871,5 @@ public abstract class AbstractRenderer matrix[5] = matrix[5] * 1000; return new AffineTransform(matrix); } + } -- cgit v1.2.3 From 95bec3df3e7037eb6fc59270fed288bad8ff73d1 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 4 Jul 2008 14:12:37 +0000 Subject: Replaced conditional with a switch and capitalized method javadoc description. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674065 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/Page.java | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/area/Page.java b/src/java/org/apache/fop/area/Page.java index 94a394014..ddc2a95ab 100644 --- a/src/java/org/apache/fop/area/Page.java +++ b/src/java/org/apache/fop/area/Page.java @@ -209,27 +209,28 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable { /** * Get the region from this page. * - * @param areaclass the region area class + * @param areaClass the region area class * @return the region viewport or null if none */ - public RegionViewport getRegionViewport(int areaclass) { - if (areaclass == Constants.FO_REGION_BEFORE) { + public RegionViewport getRegionViewport(int areaClass) { + switch (areaClass) { + case Constants.FO_REGION_BEFORE: return regionBefore; - } else if (areaclass == Constants.FO_REGION_START) { + case Constants.FO_REGION_START: return regionStart; - } else if (areaclass == Constants.FO_REGION_BODY) { - return regionBody; - } else if (areaclass == Constants.FO_REGION_END) { + case Constants.FO_REGION_BODY: + return regionBody; + case Constants.FO_REGION_END: return regionEnd; - } else if (areaclass == Constants.FO_REGION_AFTER) { + case Constants.FO_REGION_AFTER: return regionAfter; + default: + throw new IllegalArgumentException("No such area class with ID = " + areaClass); } - throw new IllegalArgumentException("No such area class with ID = " - + areaclass); } /** - * indicates whether any FOs have been added to the body region + * Indicates whether any FOs have been added to the body region * * @return whether any FOs have been added to the body region */ -- cgit v1.2.3 From 5d7e72e0c585e43896d239a89bb7fe454220106a Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sat, 5 Jul 2008 22:53:58 +0000 Subject: Fixed ClassCastException when specifying column-number on something other than a fo:table-column or fo:table-cell... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674245 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/table/TableFObj.java | 114 ++++++++++++--------- 1 file changed, 65 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 370bb9de4..faf1f7aba 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -55,9 +55,10 @@ public abstract class TableFObj extends FObj { CollapsingBorderModel collapsingBorderModel; /** - * Main constructor + * Create a TableFObj instance that is a child + * of the given {@link FONode} * - * @param parent the parent node + * @param parent the parent {@link FONode} */ public TableFObj(FONode parent) { super(parent); @@ -81,6 +82,8 @@ public abstract class TableFObj extends FObj { } /** + * Return the value for the "border-precedence" property + * for the given side. * * @param side the side for which to return the border precedence * @return the "border-precedence" value for the given side @@ -102,13 +105,13 @@ public abstract class TableFObj extends FObj { /** * Convenience method to returns a reference - * to the base Table instance + * to the base {@link Table} instance. * * @return the base table instance * */ public Table getTable() { - // Will be overridden in Table; for any other Table-node, recursive call to + // Overridden in Table; for any other Table-node, recursive call to // parent.getTable() return ((TableFObj) parent).getTable(); } @@ -119,13 +122,13 @@ public abstract class TableFObj extends FObj { public abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground(); /** - * PropertyMaker subclass for the column-number property - * + * {@link PropertyMaker} subclass for the column-number property */ public static class ColumnNumberPropertyMaker extends PropertyMaker { /** * Constructor + * * @param propId the id of the property for which the maker should * be created */ @@ -144,46 +147,50 @@ public abstract class TableFObj extends FObj { /** + * {@inheritDoc} * Check the value of the column-number property. - * Return the parent's column index (initial value) in case - * of a negative or zero value - * - * @see org.apache.fop.fo.properties.PropertyMaker#make(PropertyList, String, FObj) */ public Property make(PropertyList propertyList, String value, FObj fo) throws PropertyException { + Property p = super.make(propertyList, value, fo); - ColumnNumberManagerHolder parent - = (ColumnNumberManagerHolder) propertyList.getParentFObj(); - ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); int columnIndex = p.getNumeric().getValue(); int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED) .getNumeric().getValue(); - - int lastIndex = columnIndex - 1 + colSpan; - for (int i = columnIndex; i <= lastIndex; ++i) { - if (columnIndexManager.isColumnNumberUsed(i)) { - /* if column-number is already in use by another - * cell/column => error! - */ - TableEventProducer eventProducer = TableEventProducer.Provider.get( - fo.getUserAgent().getEventBroadcaster()); - eventProducer.cellOverlap(this, propertyList.getFObj().getName(), - i, fo.getLocator()); + + // only check whether the column-number is occupied in case it was + // specified on a fo:table-cell or fo:table-column + int foId = propertyList.getFObj().getNameId(); + if (foId == FO_TABLE_COLUMN || foId == FO_TABLE_CELL) { + ColumnNumberManagerHolder parent + = (ColumnNumberManagerHolder) propertyList.getParentFObj(); + ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); + int lastIndex = columnIndex - 1 + colSpan; + for (int i = columnIndex; i <= lastIndex; ++i) { + if (columnIndexManager.isColumnNumberUsed(i)) { + /* if column-number is already in use by another + * cell/column => error! + */ + TableEventProducer eventProducer + = TableEventProducer.Provider.get( + fo.getUserAgent().getEventBroadcaster()); + eventProducer.cellOverlap( + this, propertyList.getFObj().getName(), + i, propertyList.getFObj().getLocator()); + } } } - return p; } - + /** - * If the value is not positive, return a property whose value is the next column number - * * {@inheritDoc} + * If the value is not positive, return a property whose value + * is the next column number. */ - public Property convertProperty(Property p, - PropertyList propertyList, FObj fo) + public Property convertProperty(Property p, + PropertyList propertyList, FObj fo) throws PropertyException { if (p instanceof EnumProperty) { return EnumNumber.getInstance(p); @@ -191,15 +198,24 @@ public abstract class TableFObj extends FObj { Number val = p.getNumber(); if (val != null) { int i = Math.round(val.floatValue()); + int foId = propertyList.getFObj().getNameId(); if (i <= 0) { - ColumnNumberManagerHolder parent = - (ColumnNumberManagerHolder) propertyList.getParentFObj(); - ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); - i = columnIndexManager.getCurrentColumnNumber(); + if (foId == FO_TABLE_CELL || foId == FO_TABLE_COLUMN) { + ColumnNumberManagerHolder parent = + (ColumnNumberManagerHolder) propertyList.getParentFObj(); + ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); + i = columnIndexManager.getCurrentColumnNumber(); + } else { + /* very exceptional case: + * negative column-number specified on + * a FO that is not a fo:table-cell or fo:table-column + */ + i = 1; + } TableEventProducer eventProducer = TableEventProducer.Provider.get(fo.getUserAgent().getEventBroadcaster()); eventProducer.forceNextColumnNumber(this, propertyList.getFObj().getName(), - val, i, fo.getLocator()); + val, i, propertyList.getFObj().getLocator()); } return NumberProperty.getInstance(i); } @@ -233,26 +249,26 @@ public abstract class TableFObj extends FObj { /** * Creates a BorderSpecification from the border set on the given side. If no border * is set, a BorderSpecification with border-style none is created. - * + * * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END */ private void createBorder(int side) { BorderSpecification borderSpec = new BorderSpecification( getCommonBorderPaddingBackground().getBorderInfo(side), getNameId()); switch (side) { - case CommonBorderPaddingBackground.BEFORE: - borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); - break; - case CommonBorderPaddingBackground.AFTER: - borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); - break; - case CommonBorderPaddingBackground.START: - borderStart = borderSpec; - break; - case CommonBorderPaddingBackground.END: - borderEnd = borderSpec; - break; - default: assert false; + case CommonBorderPaddingBackground.BEFORE: + borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.START: + borderStart = borderSpec; + break; + case CommonBorderPaddingBackground.END: + borderEnd = borderSpec; + break; + default: assert false; } } } -- cgit v1.2.3 From 40d9afc4de1a3ace08cd228e651d8f5b40e001e7 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 6 Jul 2008 07:50:23 +0000 Subject: Switch AreaTreeParser to use a java.nio.CharBuffer, and ignore characters events for all elements other than , or git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674267 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/AreaTreeParser.java | 93 ++++++++++++++++-------- 1 file changed, 64 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index d48221c0a..169593072 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.StringTokenizer; +import java.nio.CharBuffer; import javax.xml.transform.Source; import javax.xml.transform.Transformer; @@ -132,8 +133,10 @@ public class AreaTreeParser { private ElementMappingRegistry elementMappingRegistry; private Attributes lastAttributes; - private StringBuffer content = new StringBuffer(); + private CharBuffer content = CharBuffer.allocate(64); + private boolean ignoreCharacters = true; + private PageViewport currentPageViewport; private Map pageViewportsByKey = new java.util.HashMap(); // set of "ID firsts" that have already been assigned to a PV: @@ -261,7 +264,10 @@ public class AreaTreeParser { boolean handled = true; if ("".equals(uri)) { Maker maker = (Maker)makers.get(localName); + content.clear(); + ignoreCharacters = true; if (maker != null) { + ignoreCharacters = maker.ignoreCharacters(); maker.startElement(attributes); } else if ("extension-attachments".equals(localName)) { //TODO implement me @@ -311,11 +317,12 @@ public class AreaTreeParser { Maker maker = (Maker)makers.get(localName); if (maker != null) { maker.endElement(); + content.clear(); } + ignoreCharacters = true; } else { //log.debug("Ignoring " + localName + " in namespace: " + uri); } - content.setLength(0); //Reset text buffer (see characters()) } } @@ -324,6 +331,7 @@ public class AreaTreeParser { private static interface Maker { void startElement(Attributes attributes) throws SAXException; void endElement(); + boolean ignoreCharacters(); } private abstract class AbstractMaker implements Maker { @@ -335,6 +343,10 @@ public class AreaTreeParser { public void endElement() { //nop } + + public boolean ignoreCharacters() { + return true; + } } private class AreaTreeMaker extends AbstractMaker { @@ -444,7 +456,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionAfterMaker extends AbstractMaker { @@ -455,7 +467,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionStartMaker extends AbstractMaker { @@ -466,7 +478,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionEndMaker extends AbstractMaker { @@ -477,7 +489,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionBodyMaker extends AbstractMaker { @@ -575,7 +587,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), BeforeFloat.class); - } + } } private class BlockMaker extends AbstractMaker { @@ -627,7 +639,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), Block.class); - } + } } private class LineAreaMaker extends AbstractMaker { @@ -735,7 +747,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), TextArea.class); - } + } } private class WordMaker extends AbstractMaker { @@ -759,23 +771,27 @@ public class AreaTreeParser { public void endElement() { int offset = getAttributeAsInteger(lastAttributes, "offset", 0); int[] letterAdjust = toIntArray(lastAttributes.getValue("letter-adjust")); - String txt = content.toString(); - WordArea word = new WordArea(txt, offset, letterAdjust); + content.flip(); + WordArea word = new WordArea(content.toString().trim(), offset, letterAdjust); AbstractTextArea text = getCurrentText(); word.setParentArea(text); text.addChildArea(word); - } + } + + public boolean ignoreCharacters() { + return false; + } } private class SpaceMaker extends AbstractMaker { - + public void endElement() { int offset = getAttributeAsInteger(lastAttributes, "offset", 0); - String txt = content.toString(); //TODO the isAdjustable parameter is currently not used/implemented - if (txt.length() > 0) { + if (content.position() > 0) { + content.flip(); boolean adjustable = getAttributeAsBoolean(lastAttributes, "adj", true); - SpaceArea space = new SpaceArea(txt.charAt(0), offset, adjustable); + SpaceArea space = new SpaceArea(content.charAt(0), offset, adjustable); AbstractTextArea text = getCurrentText(); space.setParentArea(text); text.addChildArea(space); @@ -789,14 +805,18 @@ public class AreaTreeParser { Area parent = (Area)areaStack.peek(); parent.addChildArea(space); } - } + } + + public boolean ignoreCharacters() { + return false; + } } private class CharMaker extends AbstractMaker { - + public void endElement() { - String txt = content.toString(); - Character ch = new Character(txt.charAt(0)); + content.flip(); + Character ch = new Character(content.charAt(0)); transferForeignObjects(lastAttributes, ch); setAreaAttributes(lastAttributes, ch); setTraits(lastAttributes, ch, SUBSET_COMMON); @@ -807,7 +827,11 @@ public class AreaTreeParser { ch.setBaselineOffset(getAttributeAsInteger(lastAttributes, "baseline", 0)); Area parent = (Area)areaStack.peek(); parent.addChildArea(ch); - } + } + + public boolean ignoreCharacters() { + return false; + } } private class LeaderMaker extends AbstractMaker { @@ -830,9 +854,6 @@ public class AreaTreeParser { Area parent = (Area)areaStack.peek(); parent.addChildArea(leader); } - - public void endElement() { - } } private class ViewportMaker extends AbstractMaker { @@ -854,7 +875,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), Viewport.class); - } + } } private class ImageMaker extends AbstractMaker { @@ -1163,11 +1184,25 @@ public class AreaTreeParser { public void characters(char[] ch, int start, int length) throws SAXException { if (delegate != null) { delegate.characters(ch, start, length); - } else { - content.append(ch, start, length); + } else if (!ignoreCharacters) { + int maxLength = this.content.capacity() - this.content.position(); + if (maxLength < length) { + // allocate a larger buffer and transfer content + CharBuffer newContent + = CharBuffer.allocate(this.content.position() + length); + this.content.flip(); + newContent.put(this.content); + this.content = newContent; + } + // make sure the full capacity is used + this.content.limit(this.content.capacity()); + // add characters to the buffer + this.content.put(ch, start, length); + // decrease the limit, if necessary + if (this.content.position() < this.content.limit()) { + this.content.limit(this.content.position()); + } } } - } - } -- cgit v1.2.3 From 8db6a0a344042cb203e0ab6dcece2f1236f2aca9 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 6 Jul 2008 08:15:50 +0000 Subject: Remove deprecated Character area class git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674269 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/AreaTreeParser.java | 24 ------- src/java/org/apache/fop/area/inline/Character.java | 62 ---------------- .../org/apache/fop/render/AbstractRenderer.java | 84 +++++++++------------- 3 files changed, 34 insertions(+), 136 deletions(-) delete mode 100644 src/java/org/apache/fop/area/inline/Character.java (limited to 'src') diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index 169593072..68ad6eb6d 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -57,7 +57,6 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Trait.Background; import org.apache.fop.area.Trait.InternalLink; import org.apache.fop.area.inline.AbstractTextArea; -import org.apache.fop.area.inline.Character; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; @@ -179,7 +178,6 @@ public class AreaTreeParser { makers.put("text", new TextMaker()); makers.put("word", new WordMaker()); makers.put("space", new SpaceMaker()); - makers.put("char", new CharMaker()); makers.put("leader", new LeaderMaker()); makers.put("viewport", new ViewportMaker()); makers.put("image", new ImageMaker()); @@ -812,28 +810,6 @@ public class AreaTreeParser { } } - private class CharMaker extends AbstractMaker { - - public void endElement() { - content.flip(); - Character ch = new Character(content.charAt(0)); - transferForeignObjects(lastAttributes, ch); - setAreaAttributes(lastAttributes, ch); - setTraits(lastAttributes, ch, SUBSET_COMMON); - setTraits(lastAttributes, ch, SUBSET_BOX); - setTraits(lastAttributes, ch, SUBSET_COLOR); - setTraits(lastAttributes, ch, SUBSET_FONT); - ch.setOffset(getAttributeAsInteger(lastAttributes, "offset", 0)); - ch.setBaselineOffset(getAttributeAsInteger(lastAttributes, "baseline", 0)); - Area parent = (Area)areaStack.peek(); - parent.addChildArea(ch); - } - - public boolean ignoreCharacters() { - return false; - } - } - private class LeaderMaker extends AbstractMaker { public void startElement(Attributes attributes) { diff --git a/src/java/org/apache/fop/area/inline/Character.java b/src/java/org/apache/fop/area/inline/Character.java deleted file mode 100644 index 6b6f9744f..000000000 --- a/src/java/org/apache/fop/area/inline/Character.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.area.inline; - -/** - * Single character inline area. - * This inline area holds a single character. - * @deprecated A TextArea with a single WordArea as its child should be used instead. - */ -public class Character extends AbstractTextArea { - // use a String instead of a character because if this character - // ends a syllable the hyphenation character must be added - private String character; - - /** - * Create a new character inline area with the given character. - * - * @param ch the character for this inline area - */ - public Character(char ch) { - character = new String() + ch; - } - - /** - * Get the character for this inline character area. - * - * @return the character - */ - public String getChar() { - return character; - } - - /** - * Add the hyphenation character and its length. - * - * @param hyphChar the hyphenation character - * @param hyphSize the size of the hyphenation character - */ - public void addHyphen(char hyphChar, int hyphSize) { - character += hyphChar; - this.setIPD(this.getIPD() + hyphSize); - } - -} - diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 5c3e73ee0..cfadc3e98 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -54,7 +54,6 @@ import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Span; import org.apache.fop.area.Trait; -import org.apache.fop.area.inline.Character; import org.apache.fop.area.inline.Container; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; @@ -246,25 +245,15 @@ public abstract class AbstractRenderer last here. */ RegionViewport viewport; viewport = page.getRegionViewport(FO_REGION_BEFORE); - if (viewport != null) { - renderRegionViewport(viewport); - } + renderRegionViewport(viewport); viewport = page.getRegionViewport(FO_REGION_START); - if (viewport != null) { - renderRegionViewport(viewport); - } + renderRegionViewport(viewport); viewport = page.getRegionViewport(FO_REGION_END); - if (viewport != null) { - renderRegionViewport(viewport); - } + renderRegionViewport(viewport); viewport = page.getRegionViewport(FO_REGION_AFTER); - if (viewport != null) { - renderRegionViewport(viewport); - } + renderRegionViewport(viewport); viewport = page.getRegionViewport(FO_REGION_BODY); - if (viewport != null) { - renderRegionViewport(viewport); - } + renderRegionViewport(viewport); } /** @@ -276,25 +265,27 @@ public abstract class AbstractRenderer * @param port The region viewport to be rendered */ protected void renderRegionViewport(RegionViewport port) { - Rectangle2D view = port.getViewArea(); - // The CTM will transform coordinates relative to - // this region-reference area into page coords, so - // set origin for the region to 0,0. - currentBPPosition = 0; - currentIPPosition = 0; - - RegionReference regionReference = port.getRegionReference(); - handleRegionTraits(port); - - // shouldn't the viewport have the CTM - startVParea(regionReference.getCTM(), port.isClip() ? view : null); - // do after starting viewport area - if (regionReference.getRegionClass() == FO_REGION_BODY) { - renderBodyRegion((BodyRegion) regionReference); - } else { - renderRegion(regionReference); + if (port != null) { + Rectangle2D view = port.getViewArea(); + // The CTM will transform coordinates relative to + // this region-reference area into page coords, so + // set origin for the region to 0,0. + currentBPPosition = 0; + currentIPPosition = 0; + + RegionReference regionReference = port.getRegionReference(); + handleRegionTraits(port); + + // shouldn't the viewport have the CTM + startVParea(regionReference.getCTM(), port.isClip() ? view : null); + // do after starting viewport area + if (regionReference.getRegionClass() == FO_REGION_BODY) { + renderBodyRegion((BodyRegion) regionReference); + } else { + renderRegion(regionReference); + } + endVParea(); } - endVParea(); } /** @@ -405,7 +396,7 @@ public abstract class AbstractRenderer for (int count = 0; count < spans.size(); count++) { span = (Span) spans.get(count); for (int c = 0; c < span.getColumnCount(); c++) { - NormalFlow flow = (NormalFlow) span.getNormalFlow(c); + NormalFlow flow = span.getNormalFlow(c); if (flow != null) { currentBPPosition = saveSpanBPPos; @@ -509,7 +500,7 @@ public abstract class AbstractRenderer int saveBP = currentBPPosition; // Calculate the position of the content rectangle. - if (parent != null && !parent.getTraitAsBoolean(Trait.IS_VIEWPORT_AREA)) { + if (parent != null && !Boolean.TRUE.equals(parent.getTrait(Trait.IS_VIEWPORT_AREA))) { currentBPPosition += parent.getBorderAndPaddingWidthBefore(); /* This is unnecessary now as we're going to use the *-indent traits currentIPPosition += parent.getBorderAndPaddingWidthStart(); @@ -565,7 +556,7 @@ public abstract class AbstractRenderer // simply move position currentBPPosition += block.getAllocBPD(); } - } else if (block.getTraitAsBoolean(Trait.IS_REFERENCE_AREA)) { + } else if (Boolean.TRUE.equals(block.getTrait(Trait.IS_REFERENCE_AREA))) { renderReferenceArea(block); } else { // save position and offset @@ -638,15 +629,6 @@ public abstract class AbstractRenderer } } - /** - * Render the given Character. - * @param ch the character to render - * @deprecated Only TextArea should be used. This method will be removed eventually. - */ - protected void renderCharacter(Character ch) { - currentIPPosition += ch.getAllocIPD(); - } - /** * Common method to render the background and borders for any inline area. * The all borders and padding are drawn outside the specified area. @@ -754,6 +736,8 @@ public abstract class AbstractRenderer renderContainer((Container) content); } else if (content instanceof ForeignObject) { renderForeignObject((ForeignObject) content, contpos); + } else if (content instanceof InlineBlockParent) { + renderInlineBlockParent((InlineBlockParent) content); } currentIPPosition += viewport.getAllocIPD(); currentBPPosition = saveBP; @@ -792,7 +776,7 @@ public abstract class AbstractRenderer * @param pos The target position of the foreign object * (todo) Make renderForeignObject() protected */ - public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { + protected void renderForeignObject(ForeignObject fo, Rectangle2D pos) { // Default: do nothing. // Some renderers (ex. Text) don't support foreign objects. } @@ -817,8 +801,9 @@ public abstract class AbstractRenderer handler.handleXML(ctx, doc, namespace); } catch (Exception e) { // could not handle document - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - ctx.getUserAgent().getEventBroadcaster()); + ResourceEventProducer eventProducer + = ResourceEventProducer.Provider.get( + ctx.getUserAgent().getEventBroadcaster()); eventProducer.foreignXMLProcessingError(this, doc, namespace, e); } } else { @@ -871,5 +856,4 @@ public abstract class AbstractRenderer matrix[5] = matrix[5] * 1000; return new AffineTransform(matrix); } - } -- cgit v1.2.3 From fac88f32acd0fc24def2b1cef9bcb07c149b4756 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 6 Jul 2008 08:44:54 +0000 Subject: Redo changes made in r674056... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674272 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/AbstractRenderer.java | 62 ++++++++++++---------- 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index cfadc3e98..5618f2b4d 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -245,15 +245,25 @@ public abstract class AbstractRenderer last here. */ RegionViewport viewport; viewport = page.getRegionViewport(FO_REGION_BEFORE); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_START); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_END); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_AFTER); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } viewport = page.getRegionViewport(FO_REGION_BODY); - renderRegionViewport(viewport); + if (viewport != null) { + renderRegionViewport(viewport); + } } /** @@ -265,27 +275,25 @@ public abstract class AbstractRenderer * @param port The region viewport to be rendered */ protected void renderRegionViewport(RegionViewport port) { - if (port != null) { - Rectangle2D view = port.getViewArea(); - // The CTM will transform coordinates relative to - // this region-reference area into page coords, so - // set origin for the region to 0,0. - currentBPPosition = 0; - currentIPPosition = 0; - - RegionReference regionReference = port.getRegionReference(); - handleRegionTraits(port); - - // shouldn't the viewport have the CTM - startVParea(regionReference.getCTM(), port.isClip() ? view : null); - // do after starting viewport area - if (regionReference.getRegionClass() == FO_REGION_BODY) { - renderBodyRegion((BodyRegion) regionReference); - } else { - renderRegion(regionReference); - } - endVParea(); + Rectangle2D view = port.getViewArea(); + // The CTM will transform coordinates relative to + // this region-reference area into page coords, so + // set origin for the region to 0,0. + currentBPPosition = 0; + currentIPPosition = 0; + + RegionReference regionReference = port.getRegionReference(); + handleRegionTraits(port); + + // shouldn't the viewport have the CTM + startVParea(regionReference.getCTM(), port.isClip() ? view : null); + // do after starting viewport area + if (regionReference.getRegionClass() == FO_REGION_BODY) { + renderBodyRegion((BodyRegion) regionReference); + } else { + renderRegion(regionReference); } + endVParea(); } /** @@ -500,7 +508,7 @@ public abstract class AbstractRenderer int saveBP = currentBPPosition; // Calculate the position of the content rectangle. - if (parent != null && !Boolean.TRUE.equals(parent.getTrait(Trait.IS_VIEWPORT_AREA))) { + if (parent != null && !parent.getTraitAsBoolean(Trait.IS_VIEWPORT_AREA)) { currentBPPosition += parent.getBorderAndPaddingWidthBefore(); /* This is unnecessary now as we're going to use the *-indent traits currentIPPosition += parent.getBorderAndPaddingWidthStart(); @@ -556,7 +564,7 @@ public abstract class AbstractRenderer // simply move position currentBPPosition += block.getAllocBPD(); } - } else if (Boolean.TRUE.equals(block.getTrait(Trait.IS_REFERENCE_AREA))) { + } else if (!block.getTraitAsBoolean(Trait.IS_REFERENCE_AREA)) { renderReferenceArea(block); } else { // save position and offset -- cgit v1.2.3 From d1be091687e009562c1e9a56c83cdee47c96459a Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 6 Jul 2008 08:46:50 +0000 Subject: Simplified implementation of Area.getTraitAsBoolean() git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674273 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/Area.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index d656b7b7d..30911700f 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -415,17 +415,11 @@ public class Area extends AreaTreeObject implements Serializable { /** * Get a boolean trait from this area. - * * @param oTraitCode the trait key * @return the trait value */ public boolean getTraitAsBoolean(Object oTraitCode) { - final Object obj = getTrait(oTraitCode); - if (obj instanceof Boolean) { - return ((Boolean)obj).booleanValue(); - } else { - return false; - } + return Boolean.TRUE.equals(getTrait(oTraitCode)); } /** -- cgit v1.2.3 From f4a4b961297c7cb7af08d47e9c804b64fcf65875 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 6 Jul 2008 09:17:14 +0000 Subject: Extracted conversion methods for String to int[] or double[] to a utility class. Made AreaTreeParser.getAttributeAsXXX() methods static to stress their utility character, and removed the private parseRect() in favor of getAttributeAsRectangle2D(). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674276 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/AreaTreeParser.java | 68 ++++--------- src/java/org/apache/fop/util/ConversionUtils.java | 110 ++++++++++++++++++++++ 2 files changed, 130 insertions(+), 48 deletions(-) create mode 100644 src/java/org/apache/fop/util/ConversionUtils.java (limited to 'src') diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index 68ad6eb6d..6d9fd4f32 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -78,6 +78,7 @@ import org.apache.fop.traits.BorderProps; import org.apache.fop.util.ColorUtil; import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactoryRegistry; +import org.apache.fop.util.ConversionUtils; import org.apache.fop.util.DefaultErrorListener; /** @@ -187,15 +188,6 @@ public class AreaTreeParser { makers.put("destination", new DestinationMaker()); } - private static Rectangle2D parseRect(String rect) { - StringTokenizer tokenizer = new StringTokenizer(rect, " "); - return new Rectangle2D.Double( - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())); - } - private Area findAreaType(Class clazz) { if (areaStack.size() > 0) { int pos = areaStack.size() - 1; @@ -394,7 +386,7 @@ public class AreaTreeParser { if (currentPageViewport != null) { throw new IllegalStateException("currentPageViewport must be null"); } - Rectangle2D viewArea = parseRect(attributes.getValue("bounds")); + Rectangle2D viewArea = getAttributeAsRectangle2D(attributes, "bounds"); int pageNumber = getAttributeAsInteger(attributes, "nr", -1); String key = attributes.getValue("key"); String pageNumberString = attributes.getValue("formatted-nr"); @@ -430,7 +422,7 @@ public class AreaTreeParser { if (rv != null) { throw new IllegalStateException("Current RegionViewport must be null"); } - Rectangle2D viewArea = parseRect(attributes.getValue("rect")); + Rectangle2D viewArea = getAttributeAsRectangle2D(attributes, "rect"); rv = new RegionViewport(viewArea); transferForeignObjects(attributes, rv); rv.setClip(getAttributeAsBoolean(attributes, "clipped", false)); @@ -750,25 +742,11 @@ public class AreaTreeParser { private class WordMaker extends AbstractMaker { - private int[] toIntArray(String s) { - if (s == null || s.length() == 0) { - return null; - } - StringTokenizer tokenizer = new StringTokenizer(s, " "); - List values = new java.util.ArrayList(); - while (tokenizer.hasMoreTokens()) { - values.add(new Integer(tokenizer.nextToken())); - } - int[] res = new int[values.size()]; - for (int i = 0, c = res.length; i < c; i++) { - res[i] = ((Integer)values.get(i)).intValue(); - } - return res; - } - public void endElement() { int offset = getAttributeAsInteger(lastAttributes, "offset", 0); - int[] letterAdjust = toIntArray(lastAttributes.getValue("letter-adjust")); + int[] letterAdjust + = ConversionUtils.toIntArray( + lastAttributes.getValue("letter-adjust"), "\\s"); content.flip(); WordArea word = new WordArea(content.toString().trim(), offset, letterAdjust); AbstractTextArea text = getCurrentText(); @@ -1094,7 +1072,7 @@ public class AreaTreeParser { } } - private boolean getAttributeAsBoolean(Attributes attributes, String name, + private static boolean getAttributeAsBoolean(Attributes attributes, String name, boolean defaultValue) { String s = attributes.getValue(name); if (s == null) { @@ -1104,7 +1082,7 @@ public class AreaTreeParser { } } - private int getAttributeAsInteger(Attributes attributes, String name, + private static int getAttributeAsInteger(Attributes attributes, String name, int defaultValue) { String s = attributes.getValue(name); if (s == null) { @@ -1114,36 +1092,30 @@ public class AreaTreeParser { } } - private CTM getAttributeAsCTM(Attributes attributes, String name) { + private static CTM getAttributeAsCTM(Attributes attributes, String name) { String s = attributes.getValue(name).trim(); if (s.startsWith("[") && s.endsWith("]")) { s = s.substring(1, s.length() - 1); - StringTokenizer tokenizer = new StringTokenizer(s, " "); - double[] values = new double[] { - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())}; + double[] values = ConversionUtils.toDoubleArray(s, "\\s"); + if (values.length != 6) { + throw new IllegalArgumentException("CTM must consist of 6 double values!"); + } return new CTM(values[0], values[1], values[2], values[3], values[4], values[5]); } else { - throw new IllegalArgumentException("CTM must be surrounded by square brackets"); + throw new IllegalArgumentException("CTM must be surrounded by square brackets!"); } } - private Rectangle2D getAttributeAsRectangle2D(Attributes attributes, String name) { + private static Rectangle2D getAttributeAsRectangle2D(Attributes attributes, String name) { String s = attributes.getValue(name).trim(); - StringTokenizer tokenizer = new StringTokenizer(s, " "); - double[] values = new double[] { - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())}; + double[] values = ConversionUtils.toDoubleArray(s, "\\s"); + if (values.length != 4) { + throw new IllegalArgumentException("Rectangle must consist of 4 double values!"); + } return new Rectangle2D.Double(values[0], values[1], values[2], values[3]); } - private void transferForeignObjects(Attributes atts, AreaTreeObject ato) { + private static void transferForeignObjects(Attributes atts, AreaTreeObject ato) { for (int i = 0, c = atts.getLength(); i < c; i++) { String ns = atts.getURI(i); if (ns.length() > 0) { diff --git a/src/java/org/apache/fop/util/ConversionUtils.java b/src/java/org/apache/fop/util/ConversionUtils.java new file mode 100644 index 000000000..e2d93fbd3 --- /dev/null +++ b/src/java/org/apache/fop/util/ConversionUtils.java @@ -0,0 +1,110 @@ +/* + * 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; + +/** + * This class contains utility methods for conversions, like + * a java.lang.String to an array of int or double. + */ +public final class ConversionUtils { + + /** + * Converts the given base String into + * an array of int, splitting the base along the + * given separator pattern. + * Note: this method assumes the input is a string containing + * only decimal integers, signed or unsigned, that are parsable + * by java.lang.Integer.parseInt(String). If this + * is not the case, the resulting NumberFormatException + * will have to be handled by the caller. + * + * @param baseString the base string + * @param separatorPattern the pattern separating the integer values + * (if this is null, the baseString is parsed as one + * integer value) + * @return an array of int whose size is equal to the number + * values in the input string; null if this number + * is equal to zero. + */ + public static int[] toIntArray(String baseString, String separatorPattern) { + + if (baseString == null || "".equals(baseString)) { + return null; + } + + if (separatorPattern == null || "".equals(separatorPattern)) { + return new int[] { Integer.parseInt(baseString) }; + } + + String[] values = baseString.split(separatorPattern); + int numValues = values.length; + if (numValues == 0) { + return null; + } + + int[] returnArray = new int[numValues]; + for (int i = 0; i < numValues; ++i) { + returnArray[i] = Integer.parseInt(values[i]); + } + return returnArray; + + } + + /** + * Converts the given base String into + * an array of double, splitting the base along the + * given separator pattern. + * Note: this method assumes the input is a string containing + * only decimal doubles, signed or unsigned, that are parsable + * by java.lang.Double.parseDouble(String). If this + * is not the case, the resulting NumberFormatException + * will have to be handled by the caller. + * + * @param baseString the base string + * @param separatorPattern the pattern separating the integer values + * (if this is null, the baseString is parsed as one + * double value) + * @return an array of double whose size is equal to the number + * values in the input string; null if this number + * is equal to zero. + */ + public static double[] toDoubleArray(String baseString, String separatorPattern) { + + if (baseString == null || "".equals(baseString)) { + return null; + } + + if (separatorPattern == null || "".equals(separatorPattern)) { + return new double[] { Double.parseDouble(baseString) }; + } + + String[] values = baseString.split(separatorPattern); + int numValues = values.length; + if (numValues == 0) { + return null; + } + + double[] returnArray = new double[numValues]; + for (int i = 0; i < numValues; ++i) { + returnArray[i] = Double.parseDouble(values[i]); + } + return returnArray; + + } + +} -- cgit v1.2.3 From 709cfb2f955f6898898a1f9056d6557ceb2b33ee Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 6 Jul 2008 18:19:48 +0000 Subject: Fixed error; inadvertently switched the condition with r674272... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674325 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/AbstractRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 5618f2b4d..ebff5323b 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -564,7 +564,7 @@ public abstract class AbstractRenderer // simply move position currentBPPosition += block.getAllocBPD(); } - } else if (!block.getTraitAsBoolean(Trait.IS_REFERENCE_AREA)) { + } else if (block.getTraitAsBoolean(Trait.IS_REFERENCE_AREA)) { renderReferenceArea(block); } else { // save position and offset -- cgit v1.2.3 From 4d2b45644555c5fb6029c6b08f47dccd2a1d4d96 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 7 Jul 2008 12:36:57 +0000 Subject: Possible NullPointerException avoided git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674468 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFDocument.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index bd44595fb..020a594b4 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -528,10 +528,10 @@ public class PDFDocument { public void setEncryption(PDFEncryptionParams params) { getProfile().verifyEncryptionAllowed(); this.encryption = PDFEncryptionManager.newInstance(++this.objectcount, params); - ((PDFObject)this.encryption).setDocument(this); if (encryption != null) { - /**@todo this cast is ugly. PDFObject should be transformed to an interface. */ - addTrailerObject((PDFObject)this.encryption); + PDFObject pdfObject = (PDFObject)encryption; + pdfObject.setDocument(this); + addTrailerObject(pdfObject); } else { log.warn( "PDF encryption is unavailable. PDF will be " -- cgit v1.2.3 From 6b9a616033d0278cd3c4734ac6e6a227a934f547 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 7 Jul 2008 12:38:04 +0000 Subject: Added new set accessor method for EncryptionParams. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674470 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/pdf/PDFRenderer.java | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index c4f045786..154365209 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -1841,5 +1841,13 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { public void setFilterMap(Map filterMap) { this.filterMap = filterMap; } + + /** + * Sets the encryption parameters used by the PDF renderer. + * @param encryptionParams the encryption parameters + */ + public void setEncryptionParams(PDFEncryptionParams encryptionParams) { + this.encryptionParams = encryptionParams; + } } -- cgit v1.2.3 From b7948c5519c5dee7f6c60f5159ee0b7d6631f856 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 7 Jul 2008 12:42:12 +0000 Subject: Added PDF encryption parameter support in configuration. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674471 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/configuration.xml | 21 ++++++++++ .../fop/render/pdf/PDFRendererConfigurator.java | 48 ++++++++++++++++++++-- status.xml | 3 ++ 3 files changed, 69 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/trunk/configuration.xml b/src/documentation/content/xdocs/trunk/configuration.xml index e82a6e862..8d6b1f1c8 100644 --- a/src/documentation/content/xdocs/trunk/configuration.xml +++ b/src/documentation/content/xdocs/trunk/configuration.xml @@ -294,6 +294,27 @@ ]]> + +

    FOP supports encryption of PDF output, thanks to Patrick C. Lankswert. + This feature is commonly used to prevent unauthorized viewing, printing, editing, copying text + from the document and doing annotations. It is also possible to ask the user for a password in + order to view the contents. Note that there already exist third party applications which can + decrypt an encrypted PDF without effort and allow the aforementioned operations, therefore the + degree of protection is limited. For further information about features and restrictions + regarding PDF encryption, look at the documentation coming with Adobe Acrobat or the technical + documentation on the Adobe web site.

    + + + testuserpass + testownerpass + + + + + + ]]> +
    Special Settings for the PostScript Renderer diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java index 2fce8859a..51e13dde1 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java @@ -28,6 +28,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.pdf.PDFAMode; +import org.apache.fop.pdf.PDFEncryptionParams; import org.apache.fop.pdf.PDFFilterList; import org.apache.fop.pdf.PDFXMode; import org.apache.fop.render.PrintRendererConfigurator; @@ -78,13 +79,54 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator { if (s != null) { pdfRenderer.setXMode(PDFXMode.valueOf(s)); } + Configuration encryptionParamsConfig = cfg.getChild(PDFRenderer.ENCRYPTION_PARAMS, false); + if (encryptionParamsConfig != null) { + PDFEncryptionParams encryptionParams = new PDFEncryptionParams(); + Configuration ownerPasswordConfig = encryptionParamsConfig.getChild( + PDFRenderer.OWNER_PASSWORD, false); + if (ownerPasswordConfig != null) { + String ownerPassword = ownerPasswordConfig.getValue(null); + if (ownerPassword != null) { + encryptionParams.setOwnerPassword(ownerPassword); + } + } + Configuration userPasswordConfig = encryptionParamsConfig.getChild( + PDFRenderer.USER_PASSWORD, false); + if (userPasswordConfig != null) { + String userPassword = userPasswordConfig.getValue(null); + if (userPassword != null) { + encryptionParams.setUserPassword(userPassword); + } + } + Configuration noPrintConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_PRINT, false); + if (noPrintConfig != null) { + encryptionParams.setAllowPrint(false); + } + Configuration noCopyContentConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_COPY_CONTENT, false); + if (noCopyContentConfig != null) { + encryptionParams.setAllowCopyContent(false); + } + Configuration noEditContentConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_EDIT_CONTENT, false); + if (noEditContentConfig != null) { + encryptionParams.setAllowEditContent(false); + } + Configuration noAnnotationsConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_ANNOTATIONS, false); + if (noAnnotationsConfig != null) { + encryptionParams.setAllowEditAnnotations(false); + } + pdfRenderer.setEncryptionParams(encryptionParams); + } s = cfg.getChild(PDFRenderer.KEY_OUTPUT_PROFILE, true).getValue(null); if (s != null) { pdfRenderer.setOutputProfileURI(s); } - Configuration child = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); - if (child != null) { - pdfRenderer.disableSRGBColorSpace = child.getValueAsBoolean(false); + Configuration disableColorSpaceConfig = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); + if (disableColorSpaceConfig != null) { + pdfRenderer.disableSRGBColorSpace = disableColorSpaceConfig.getValueAsBoolean(false); } } } diff --git a/status.xml b/status.xml index 20caa0e1a..5bbcd4bd1 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,9 @@ + + Added PDF encryption parameter support in configuration. + Allowing non-zero borders and padding on page regions when relaxed validation is turned on. -- cgit v1.2.3 From b4e36e8d652c1d9c5afc61ab68ef765616be7f57 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 7 Jul 2008 13:28:26 +0000 Subject: Added new AbstractXMLRenderer base class. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674484 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/render/xml/AbstractXMLRenderer.java | 263 +++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java (limited to 'src') diff --git a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java new file mode 100644 index 000000000..e0667815d --- /dev/null +++ b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java @@ -0,0 +1,263 @@ +/* + * 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.render.xml; + +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.apache.fop.area.BookmarkData; +import org.apache.fop.area.OffDocumentExtensionAttachment; +import org.apache.fop.area.OffDocumentItem; +import org.apache.fop.area.PageViewport; +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.render.PrintRenderer; +import org.apache.fop.render.RendererContext; +import org.apache.xmlgraphics.util.QName; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.helpers.AttributesImpl; + +public abstract class AbstractXMLRenderer extends PrintRenderer { + /** Main namespace in use. */ + public static final String NS = ""; + + /** CDATA type */ + public static final String CDATA = "CDATA"; + + /** An empty Attributes object used when no attributes are needed. */ + public static final Attributes EMPTY_ATTS = new AttributesImpl(); + + /** AttributesImpl instance that can be used during XML generation. */ + protected AttributesImpl atts = new AttributesImpl(); + + /** ContentHandler that the generated XML is written to */ + protected ContentHandler handler; + + /** The OutputStream to write the generated XML to. */ + protected OutputStream out; + + protected RendererContext context; + + /** A list of ExtensionAttachements received through processOffDocumentItem() */ + protected List extensionAttachments; + + /** + * Handles SAXExceptions. + * @param saxe the SAXException to handle + */ + protected void handleSAXException(SAXException saxe) { + throw new RuntimeException(saxe.getMessage()); + } + + /** + * Handles page extension attachments + * @param page the page viewport + */ + protected void handlePageExtensionAttachments(PageViewport page) { + handleExtensionAttachments(page.getExtensionAttachments()); + } + + /** + * Writes a comment to the generated XML. + * @param comment the comment + */ + protected void comment(String comment) { + if (handler instanceof LexicalHandler) { + try { + ((LexicalHandler) handler).comment(comment.toCharArray(), 0, comment.length()); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + } + + /** + * Starts a new element (without attributes). + * @param tagName tag name of the element + */ + protected void startElement(String tagName) { + startElement(tagName, EMPTY_ATTS); + } + + /** + * Starts a new element. + * @param tagName tag name of the element + * @param atts attributes to add + */ + protected void startElement(String tagName, Attributes atts) { + try { + handler.startElement(NS, tagName, tagName, atts); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + + /** + * Ends an element. + * @param tagName tag name of the element + */ + protected void endElement(String tagName) { + try { + handler.endElement(NS, tagName, tagName); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + + /** + * Sends plain text to the XML + * @param text the text + */ + protected void characters(String text) { + try { + char[] ca = text.toCharArray(); + handler.characters(ca, 0, ca.length); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + + /** + * Adds a new attribute to the protected member variable "atts". + * @param name name of the attribute + * @param value value of the attribute + */ + protected void addAttribute(String name, String value) { + atts.addAttribute(NS, name, name, CDATA, value); + } + + /** + * Adds a new attribute to the protected member variable "atts". + * @param name name of the attribute + * @param value value of the attribute + */ + protected void addAttribute(QName name, String value) { + atts.addAttribute(name.getNamespaceURI(), name.getLocalName(), name.getQName(), + CDATA, value); + } + + /** + * Adds a new attribute to the protected member variable "atts". + * @param name name of the attribute + * @param value value of the attribute + */ + protected void addAttribute(String name, int value) { + addAttribute(name, Integer.toString(value)); + } + + private String createString(Rectangle2D rect) { + return "" + (int) rect.getX() + " " + (int) rect.getY() + " " + + (int) rect.getWidth() + " " + (int) rect.getHeight(); + } + + /** + * Adds a new attribute to the protected member variable "atts". + * @param name name of the attribute + * @param rect a Rectangle2D to format and use as attribute value + */ + protected void addAttribute(String name, Rectangle2D rect) { + addAttribute(name, createString(rect)); + } + + /** + * {@inheritDoc} + */ + public void startRenderer(OutputStream outputStream) + throws IOException { + if (this.handler == null) { + SAXTransformerFactory factory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + try { + TransformerHandler transformerHandler = factory.newTransformerHandler(); + setContentHandler(transformerHandler); + StreamResult res = new StreamResult(outputStream); + transformerHandler.setResult(res); + } catch (TransformerConfigurationException tce) { + throw new RuntimeException(tce.getMessage()); + } + this.out = outputStream; + } + + try { + handler.startDocument(); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + } + + /** + * {@inheritDoc} + */ + public void stopRenderer() throws IOException { + try { + handler.endDocument(); + } catch (SAXException saxe) { + handleSAXException(saxe); + } + if (this.out != null) { + this.out.flush(); + } + } + + /** {@inheritDoc} */ + public void processOffDocumentItem(OffDocumentItem oDI) { + if (oDI instanceof BookmarkData) { + renderBookmarkTree((BookmarkData) oDI); + } else if (oDI instanceof OffDocumentExtensionAttachment) { + ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment(); + if (extensionAttachments == null) { + extensionAttachments = new java.util.ArrayList(); + } + extensionAttachments.add(attachment); + } else { + String warn = "Ignoring OffDocumentItem: " + oDI; + log.warn(warn); + } + } + + protected void handleDocumentExtensionAttachments() { + if (extensionAttachments != null && extensionAttachments.size() > 0) { + handleExtensionAttachments(extensionAttachments); + extensionAttachments.clear(); + } + } + + /** + * Sets an outside TransformerHandler to use instead of the default one + * create in this class in startRenderer(). + * @param handler Overriding TransformerHandler + */ + public void setContentHandler(ContentHandler handler) { + this.handler = handler; + } + + protected abstract void handleExtensionAttachments(List attachments); + + protected abstract void renderBookmarkTree(BookmarkData odi); +} -- cgit v1.2.3 From b394f66fa0ed13fd491d83d21143784e100bc8d2 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 7 Jul 2008 13:43:19 +0000 Subject: Cleaned up some javadocs. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674486 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/render/xml/AbstractXMLRenderer.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java index e0667815d..7aa22e080 100644 --- a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java @@ -15,7 +15,7 @@ * limitations under the License. */ -/* $Id: $ */ +/* $Id$ */ package org.apache.fop.render.xml; @@ -185,9 +185,7 @@ public abstract class AbstractXMLRenderer extends PrintRenderer { addAttribute(name, createString(rect)); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startRenderer(OutputStream outputStream) throws IOException { if (this.handler == null) { @@ -211,9 +209,7 @@ public abstract class AbstractXMLRenderer extends PrintRenderer { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void stopRenderer() throws IOException { try { handler.endDocument(); @@ -241,6 +237,7 @@ public abstract class AbstractXMLRenderer extends PrintRenderer { } } + /** {@inheritDoc} */ protected void handleDocumentExtensionAttachments() { if (extensionAttachments != null && extensionAttachments.size() > 0) { handleExtensionAttachments(extensionAttachments); @@ -257,7 +254,15 @@ public abstract class AbstractXMLRenderer extends PrintRenderer { this.handler = handler; } + /** + * Handles a list of extension attachments + * @param attachments a list of extension attachments + */ protected abstract void handleExtensionAttachments(List attachments); + /** + * Renders a bookmark tree + * @param odi the bookmark data + */ protected abstract void renderBookmarkTree(BookmarkData odi); } -- cgit v1.2.3 From 61ce6bf89af376daa19d905d5c3dbf69d7e82713 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 7 Jul 2008 13:44:14 +0000 Subject: Refactored this class, moving much of its behaviour to the base AbstractXMLRenderer class. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674487 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/xml/XMLRenderer.java | 169 +-------------------- 1 file changed, 5 insertions(+), 164 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 94cd107c7..b41de7387 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -35,11 +35,7 @@ import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; -import org.xml.sax.ext.LexicalHandler; -import org.xml.sax.helpers.AttributesImpl; import org.apache.xmlgraphics.util.QName; import org.apache.xmlgraphics.util.XMLizable; @@ -99,39 +95,17 @@ import org.apache.fop.util.ColorUtil; * The output can be used to build a new area tree which can be * rendered to any renderer. */ -public class XMLRenderer extends PrintRenderer { +public class XMLRenderer extends AbstractXMLRenderer { /** XML MIME type */ public static final String XML_MIME_TYPE = MimeConstants.MIME_FOP_AREA_TREE; - /** Main namespace in use. */ - public static final String NS = ""; - - /** CDATA type */ - public static final String CDATA = "CDATA"; - - /** An empty Attributes object used when no attributes are needed. */ - public static final Attributes EMPTY_ATTS = new AttributesImpl(); - private boolean startedSequence = false; - private RendererContext context; private boolean compactFormat = false; /** If not null, the XMLRenderer will mimic another renderer by using its font setup. */ protected Renderer mimic; - /** ContentHandler that the generated XML is written to */ - protected ContentHandler handler; - - /** AttributesImpl instance that can be used during XML generation. */ - protected AttributesImpl atts = new AttributesImpl(); - - /** The OutputStream to write the generated XML to. */ - protected OutputStream out; - - /** A list of ExtensionAttachements received through processOffDocumentItem() */ - protected List extensionAttachments; - /** * Creates a new XML renderer. */ @@ -171,15 +145,6 @@ public class XMLRenderer extends PrintRenderer { } } - /** - * Sets an outside TransformerHandler to use instead of the default one - * create in this class in startRenderer(). - * @param handler Overriding TransformerHandler - */ - public void setContentHandler(ContentHandler handler) { - this.handler = handler; - } - public void setCompactFormat(boolean compact) { this.compactFormat = compact; } @@ -188,111 +153,6 @@ public class XMLRenderer extends PrintRenderer { return !this.compactFormat; } - /** - * Handles SAXExceptions. - * @param saxe the SAXException to handle - */ - protected void handleSAXException(SAXException saxe) { - throw new RuntimeException(saxe.getMessage()); - } - - /** - * Writes a comment to the generated XML. - * @param comment the comment - */ - protected void comment(String comment) { - if (handler instanceof LexicalHandler) { - try { - ((LexicalHandler) handler).comment(comment.toCharArray(), 0, comment.length()); - } catch (SAXException saxe) { - handleSAXException(saxe); - } - } - } - - /** - * Starts a new element (without attributes). - * @param tagName tag name of the element - */ - protected void startElement(String tagName) { - startElement(tagName, EMPTY_ATTS); - } - - /** - * Starts a new element. - * @param tagName tag name of the element - * @param atts attributes to add - */ - protected void startElement(String tagName, Attributes atts) { - try { - handler.startElement(NS, tagName, tagName, atts); - } catch (SAXException saxe) { - handleSAXException(saxe); - } - } - - /** - * Ends an element. - * @param tagName tag name of the element - */ - protected void endElement(String tagName) { - try { - handler.endElement(NS, tagName, tagName); - } catch (SAXException saxe) { - handleSAXException(saxe); - } - } - - /** - * Sends plain text to the XML - * @param text the text - */ - protected void characters(String text) { - try { - char[] ca = text.toCharArray(); - handler.characters(ca, 0, ca.length); - } catch (SAXException saxe) { - handleSAXException(saxe); - } - } - - /** - * Adds a new attribute to the protected member variable "atts". - * @param name name of the attribute - * @param value value of the attribute - */ - protected void addAttribute(String name, String value) { - atts.addAttribute(NS, name, name, CDATA, value); - } - - /** - * Adds a new attribute to the protected member variable "atts". - * @param name name of the attribute - * @param value value of the attribute - */ - protected void addAttribute(QName name, String value) { - atts.addAttribute(name.getNamespaceURI(), name.getLocalName(), name.getQName(), - CDATA, value); - } - - /** - * Adds a new attribute to the protected member variable "atts". - * @param name name of the attribute - * @param value value of the attribute - */ - protected void addAttribute(String name, int value) { - addAttribute(name, Integer.toString(value)); - } - - /** - * Adds a new attribute to the protected member variable "atts". - * @param name name of the attribute - * @param rect a Rectangle2D to format and use as attribute value - */ - protected void addAttribute(String name, Rectangle2D rect) { - addAttribute(name, createString(rect)); - } - /** * Adds the general Area attributes. * @param area Area to extract attributes from @@ -406,18 +266,6 @@ public class XMLRenderer extends PrintRenderer { } } - private String createString(Rectangle2D rect) { - return "" + (int) rect.getX() + " " + (int) rect.getY() + " " - + (int) rect.getWidth() + " " + (int) rect.getHeight(); - } - - private void handleDocumentExtensionAttachments() { - if (extensionAttachments != null && extensionAttachments.size() > 0) { - handleExtensionAttachments(extensionAttachments); - extensionAttachments.clear(); - } - } - /** {@inheritDoc} */ public void processOffDocumentItem(OffDocumentItem oDI) { if (oDI instanceof BookmarkData) { @@ -518,9 +366,7 @@ public class XMLRenderer extends PrintRenderer { startElement("areaTree"); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void stopRenderer() throws IOException { endPageSequence(); endElement("areaTree"); @@ -535,9 +381,7 @@ public class XMLRenderer extends PrintRenderer { log.debug("Written out Area Tree XML"); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderPage(PageViewport page) throws IOException, FOPException { atts.clear(); addAttribute("bounds", page.getViewArea()); @@ -561,7 +405,8 @@ public class XMLRenderer extends PrintRenderer { endElement("pageViewport"); } - private void handleExtensionAttachments(List attachments) { + /** {@inheritDoc} */ + protected void handleExtensionAttachments(List attachments) { if (attachments != null && attachments.size() > 0) { startElement("extension-attachments"); Iterator i = attachments.iterator(); @@ -582,10 +427,6 @@ public class XMLRenderer extends PrintRenderer { } } - private void handlePageExtensionAttachments(PageViewport page) { - handleExtensionAttachments(page.getExtensionAttachments()); - } - /** {@inheritDoc} */ public void startPageSequence(PageSequence pageSequence) { handleDocumentExtensionAttachments(); -- cgit v1.2.3 From b8afaae2940a6020e8593a4e83ee9036b9f97666 Mon Sep 17 00:00:00 2001 From: Luca Furini Date: Mon, 7 Jul 2008 13:52:36 +0000 Subject: Fixing absolute positioning of block-containers: bottom and right distances were not taken into account git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674489 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/BlockContainerLayoutManager.java | 9 +++ status.xml | 4 + .../block-container_absolute-position_tblr.xml | 87 ++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 test/layoutengine/standard-testcases/block-container_absolute-position_tblr.xml (limited to 'src') diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 732cb1ae7..022ba1d90 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -694,9 +694,17 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager int y = 0; if (abProps.left.getEnum() != EN_AUTO) { x = abProps.left.getValue(this); + } else if (abProps.right.getEnum() != EN_AUTO + && width.getEnum() != EN_AUTO) { + x = getReferenceAreaIPD() + - abProps.right.getValue(this) - width.getValue(this); } if (abProps.top.getEnum() != EN_AUTO) { y = abProps.top.getValue(this); + } else if (abProps.bottom.getEnum() != EN_AUTO + && height.getEnum() != EN_AUTO) { + y = getReferenceAreaBPD() + - abProps.bottom.getValue(this) - height.getValue(this); } return new Point(x, y); } @@ -1085,3 +1093,4 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } + diff --git a/status.xml b/status.xml index 5bbcd4bd1..4dc8b9d05 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,10 @@ + + Fixed absolute positioning of block-containers when specified + using right and bottom instead of left and top. + Added PDF encryption parameter support in configuration. diff --git a/test/layoutengine/standard-testcases/block-container_absolute-position_tblr.xml b/test/layoutengine/standard-testcases/block-container_absolute-position_tblr.xml new file mode 100644 index 000000000..f9919d2c1 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_absolute-position_tblr.xml @@ -0,0 +1,87 @@ + + + + + +

    + This test checks absolutely positioned block-containers using top, bottom, left and right distances +

    +
    + + + + + + + + + + position + NOT ok! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -- cgit v1.2.3 From 151be92aabeb1911de261cee9a318fb6280c2d4b Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 7 Jul 2008 16:24:54 +0000 Subject: Correct indentation git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674540 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/flow/table/TableFObj.java | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index faf1f7aba..f459ecd65 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -256,19 +256,19 @@ public abstract class TableFObj extends FObj { BorderSpecification borderSpec = new BorderSpecification( getCommonBorderPaddingBackground().getBorderInfo(side), getNameId()); switch (side) { - case CommonBorderPaddingBackground.BEFORE: - borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); - break; - case CommonBorderPaddingBackground.AFTER: - borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); - break; - case CommonBorderPaddingBackground.START: - borderStart = borderSpec; - break; - case CommonBorderPaddingBackground.END: - borderEnd = borderSpec; - break; - default: assert false; + case CommonBorderPaddingBackground.BEFORE: + borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.START: + borderStart = borderSpec; + break; + case CommonBorderPaddingBackground.END: + borderEnd = borderSpec; + break; + default: assert false; } } } -- cgit v1.2.3 From 4cc1ea22e21af35c1abe27238149ed36eb410ec9 Mon Sep 17 00:00:00 2001 From: Clay Leeds Date: Mon, 7 Jul 2008 19:15:34 +0000 Subject: updated info. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674599 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/team.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index e493e7f11..d9ab77e4d 100644 --- a/src/documentation/content/xdocs/team.xml +++ b/src/documentation/content/xdocs/team.xml @@ -54,7 +54,7 @@ is a web/WAP/Palm developer from Laguna Beach, California, USA. A recent XML/XSL-FO convert, he has been nit-picking FAQs & assorted web pages since his first webmaster position @brain.com in 1996. Most - important creation? His li'l Jeremy was born June 18, 2002. + important creation? He's got a couple kids.
  • Manuel Mall (MM) is an independant software engineer resident in Perth, Australia. Born a long time ago in Germany he has been involved in Software Engineering (Informatik) since the -- cgit v1.2.3 From 26b18e9d4f593142182db465f070a9fe4b152763 Mon Sep 17 00:00:00 2001 From: Clay Leeds Date: Mon, 7 Jul 2008 19:19:00 +0000 Subject: One more minor update. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@674602 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/team.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index d9ab77e4d..084c54ba8 100644 --- a/src/documentation/content/xdocs/team.xml +++ b/src/documentation/content/xdocs/team.xml @@ -54,7 +54,7 @@ is a web/WAP/Palm developer from Laguna Beach, California, USA. A recent XML/XSL-FO convert, he has been nit-picking FAQs & assorted web pages since his first webmaster position @brain.com in 1996. Most - important creation? He's got a couple kids.
  • + important creation? He's got a couple of cool kids.
  • Manuel Mall (MM) is an independant software engineer resident in Perth, Australia. Born a long time ago in Germany he has been involved in Software Engineering (Informatik) since the -- cgit v1.2.3 From 43f708b12c985226ee713a4492c97526727c4129 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 9 Jul 2008 15:34:01 +0000 Subject: Minor javadoc cleanup. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@675231 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/ps/PSRenderer.java | 27 ++++++----------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index 3f1769295..f84f46bf9 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -734,8 +734,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer gen.useColor(col); } - /** {@inheritDoc} - * Area, float, float, float, float) */ + /** {@inheritDoc} */ protected void drawBackAndBorders(Area area, float startx, float starty, float width, float height) { if (area.hasTrait(Trait.BACKGROUND) @@ -904,9 +903,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startRenderer(OutputStream outputStream) throws IOException { log.debug("Rendering areas to PostScript..."); @@ -980,9 +977,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer gen.writeDSCComment(DSCConstants.END_SETUP); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void stopRenderer() throws IOException { //Notify resource usage for font which are not supplied /* done in useFont now @@ -1134,9 +1129,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderPage(PageViewport page) throws IOException, FOPException { log.debug("renderPage(): " + page); @@ -1313,9 +1306,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderText(TextArea area) { renderInlineAreaBackAndBorders(area); String fontkey = getInternalFontNameForArea(area); @@ -1346,17 +1337,13 @@ public class PSRenderer extends AbstractPathOrientedRenderer renderTextDecoration(tf, fontsize, area, bl, rx); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void renderWord(WordArea word) { renderText((TextArea)word.getParentArea(), word.getWord(), word.getLetterAdjustArray()); super.renderWord(word); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void renderSpace(SpaceArea space) { AbstractTextArea textArea = (AbstractTextArea)space.getParentArea(); String s = space.getSpace(); -- cgit v1.2.3 From ee77527091a08faefa4718d6887d87fe2d468e54 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 9 Jul 2008 16:53:01 +0000 Subject: Added throwexceptions attribute to FOP ant task. This works around the problem with executing examples/fo/build.xml. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@675253 13f79535-47bb-0310-9956-ffa450edef68 --- examples/fo/build.xml | 2 +- src/documentation/content/xdocs/trunk/anttask.xml | 5 +++++ src/java/org/apache/fop/tools/anttasks/Fop.java | 24 ++++++++++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/examples/fo/build.xml b/examples/fo/build.xml index 8ecfbee18..2c7c18259 100644 --- a/examples/fo/build.xml +++ b/examples/fo/build.xml @@ -45,7 +45,7 @@ - + diff --git a/src/documentation/content/xdocs/trunk/anttask.xml b/src/documentation/content/xdocs/trunk/anttask.xml index 44550c3d7..7b07802b1 100644 --- a/src/documentation/content/xdocs/trunk/anttask.xml +++ b/src/documentation/content/xdocs/trunk/anttask.xml @@ -148,6 +148,11 @@ (true) or not (false). Currently doesn't work in FOP Trunk!!! No, default is true + + throwexceptions + Controls whether or not an exception is thrown if an error occurs during rendering. + Default is true +

    diff --git a/src/java/org/apache/fop/tools/anttasks/Fop.java b/src/java/org/apache/fop/tools/anttasks/Fop.java index 6f9b2fc34..0f28d70e7 100644 --- a/src/java/org/apache/fop/tools/anttasks/Fop.java +++ b/src/java/org/apache/fop/tools/anttasks/Fop.java @@ -77,6 +77,7 @@ public class Fop extends Task { private boolean logFiles = true; private boolean force = false; private boolean relativebase = false; + private boolean throwExceptions = false; /** * Sets the filename for the userconfig.xml. @@ -211,6 +212,24 @@ public class Fop extends Task { return this.format; } + /** + * Set whether exceptions are thrown. + * default is false. + * + * @param force true if always generate. + */ + public void setThrowexceptions(boolean throwExceptions) { + this.throwExceptions = throwExceptions; + } + + /** + * Gets the throw exceptions attribute + * @return the throw exceptions attribute + */ + public boolean getThrowexceptions() { + return this.throwExceptions; + } + /** * Sets the message level to be used while processing. * @param messageLevel (error | warn| info | verbose | debug) @@ -558,7 +577,10 @@ class FOPTaskStarter { inputHandler.renderTo(userAgent, outputFormat, out); success = true; } catch (Exception ex) { - throw new BuildException(ex); + if (task.getThrowexceptions()) { + throw new BuildException(ex); + } + logger.error("Error rendering fo file: " + foFile, ex); } finally { try { out.close(); -- cgit v1.2.3 From cea7f083af235f885c0d577f6a7537e5e3a71845 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 9 Jul 2008 17:05:27 +0000 Subject: Whoops.. default value should be true :). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@675258 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/tools/anttasks/Fop.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/tools/anttasks/Fop.java b/src/java/org/apache/fop/tools/anttasks/Fop.java index 0f28d70e7..a33c396d4 100644 --- a/src/java/org/apache/fop/tools/anttasks/Fop.java +++ b/src/java/org/apache/fop/tools/anttasks/Fop.java @@ -77,7 +77,7 @@ public class Fop extends Task { private boolean logFiles = true; private boolean force = false; private boolean relativebase = false; - private boolean throwExceptions = false; + private boolean throwExceptions = true; /** * Sets the filename for the userconfig.xml. -- cgit v1.2.3 From cfa07fa31d84d76ee264bd187bd1ed46c8d05129 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 10 Jul 2008 10:23:54 +0000 Subject: Duplicated operation scaleX and scaleY replaced simply with scale. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@675501 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/render/java2d/Java2DRenderer.java | 30 ++++++++++------------ 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 5996c5d0c..ed6f29ab9 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -189,12 +189,12 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem * @param newScaleFactor ]0 ; 1] */ public void setScaleFactor(double newScaleFactor) { - scaleFactor = newScaleFactor; + this.scaleFactor = newScaleFactor; } /** @return the scale factor */ public double getScaleFactor() { - return scaleFactor; + return this.scaleFactor; } /** {@inheritDoc} */ @@ -292,22 +292,19 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem this.currentPageViewport = pageViewport; try { Rectangle2D bounds = pageViewport.getViewArea(); - pageWidth = (int) Math.round(bounds.getWidth() / 1000f); - pageHeight = (int) Math.round(bounds.getHeight() / 1000f); + this.pageWidth = (int) Math.round(bounds.getWidth() / 1000f); + this.pageHeight = (int) Math.round(bounds.getHeight() / 1000f); log.info( "Rendering Page " + pageViewport.getPageNumberString() + " (pageWidth " + pageWidth + ", pageHeight " + pageHeight + ")"); - double scaleX = scaleFactor - * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) + double scale = scaleFactor + * (25.4f / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) / userAgent.getTargetPixelUnitToMillimeter(); - double scaleY = scaleFactor - * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) - / userAgent.getTargetPixelUnitToMillimeter(); - int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5); - int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5); + int bitmapWidth = (int) ((pageWidth * scale) + 0.5); + int bitmapHeight = (int) ((pageHeight * scale) + 0.5); BufferedImage currentPageImage = getBufferedImage(bitmapWidth, bitmapHeight); @@ -330,7 +327,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem // transform page based on scale factor supplied AffineTransform at = graphics.getTransform(); - at.scale(scaleX, scaleY); + at.scale(scale, scale); graphics.setTransform(at); // draw page frame @@ -466,11 +463,11 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem protected void restoreStateStackAfterBreakOut(List breakOutList) { log.debug("Block.FIXED --> restoring context after break-out"); - Iterator i = breakOutList.iterator(); - while (i.hasNext()) { - Java2DGraphicsState s = (Java2DGraphicsState)i.next(); + Iterator it = breakOutList.iterator(); + while (it.hasNext()) { + Java2DGraphicsState s = (Java2DGraphicsState)it.next(); stateStack.push(state); - state = s; + this.state = s; } } @@ -1015,5 +1012,4 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem public void setTransparentPageBackground(boolean transparentPageBackground) { this.transparentPageBackground = transparentPageBackground; } - } -- cgit v1.2.3 From a8534f0b6d0194272e0eb571a956748caeb1089a Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 10 Jul 2008 14:31:52 +0000 Subject: Bugzilla #45369: footnotes were rendered at the top of the region-body when using the intermediate format git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@675590 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/AreaTreeParser.java | 28 ++++++++++------------ .../org/apache/fop/render/xml/XMLRenderer.java | 4 +++- .../standard-testcases/footnote_basic.xml | 1 + 3 files changed, 16 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index 6d9fd4f32..e4de505b0 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -21,12 +21,11 @@ package org.apache.fop.area; import java.awt.Color; import java.awt.geom.Rectangle2D; +import java.nio.CharBuffer; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; -import java.util.StringTokenizer; -import java.nio.CharBuffer; import javax.xml.transform.Source; import javax.xml.transform.Transformer; @@ -37,22 +36,8 @@ import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; -import org.w3c.dom.DOMImplementation; -import org.w3c.dom.Document; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -import org.apache.xmlgraphics.image.loader.ImageInfo; -import org.apache.xmlgraphics.image.loader.ImageManager; -import org.apache.xmlgraphics.image.loader.ImageSessionContext; -import org.apache.xmlgraphics.util.QName; - import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Trait.Background; import org.apache.fop.area.Trait.InternalLink; @@ -80,6 +65,16 @@ import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactoryRegistry; import org.apache.fop.util.ConversionUtils; import org.apache.fop.util.DefaultErrorListener; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.util.QName; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; /** * This is a parser for the area tree XML (intermediate format) which is used to reread an area @@ -559,6 +554,7 @@ public class AreaTreeParser { public void startElement(Attributes attributes) { Footnote fn = getCurrentBodyRegion().getFootnote(); transferForeignObjects(attributes, fn); + fn.setTop(getAttributeAsInteger(attributes, "top-offset", 0)); areaStack.push(fn); } diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index b41de7387..aec067b91 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -544,7 +544,9 @@ public class XMLRenderer extends AbstractXMLRenderer { * {@inheritDoc} */ protected void renderFootnote(Footnote footnote) { - startElement("footnote"); + atts.clear(); + addAttribute("top-offset", footnote.getTop()); + startElement("footnote", atts); super.renderFootnote(footnote); endElement("footnote"); } diff --git a/test/layoutengine/standard-testcases/footnote_basic.xml b/test/layoutengine/standard-testcases/footnote_basic.xml index 29678fab9..402f1d6ad 100644 --- a/test/layoutengine/standard-testcases/footnote_basic.xml +++ b/test/layoutengine/standard-testcases/footnote_basic.xml @@ -68,6 +68,7 @@ + -- cgit v1.2.3 From a7d678ce0944c0e28f86380f0ac11ab1f5d482b9 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 10 Jul 2008 15:02:15 +0000 Subject: Beware! An evil tab character! But it's been eliminated. ;-) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@675604 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/tools/anttasks/Fop.java | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/tools/anttasks/Fop.java b/src/java/org/apache/fop/tools/anttasks/Fop.java index a33c396d4..83217651e 100644 --- a/src/java/org/apache/fop/tools/anttasks/Fop.java +++ b/src/java/org/apache/fop/tools/anttasks/Fop.java @@ -5,9 +5,9 @@ * 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. @@ -54,7 +54,7 @@ import org.xml.sax.SAXException; *
  • format -> MIME type of the format to generate ex. "application/pdf"
  • *
  • outfile -> output filename
  • *
  • baseDir -> directory to work from
  • - *
  • relativebase -> (true | false) control whether to use each FO's + *
  • relativebase -> (true | false) control whether to use each FO's * directory as base directory. false uses the baseDir parameter.
  • *
  • userconfig -> file with user configuration (same as the "-c" command * line option)
  • @@ -137,7 +137,7 @@ public class Fop extends Task { public void setRelativebase(boolean relbase) { this.relativebase = relbase; } - + /** * Gets the relative base attribute * @return the relative base attribute @@ -294,7 +294,7 @@ public class Fop extends Task { public boolean getLogFiles() { return this.logFiles; } - + /** * {@inheritDoc} */ @@ -330,7 +330,7 @@ class FOPTaskStarter { // configure fopFactory as desired private FopFactory fopFactory = FopFactory.newInstance(); - + private Fop task; private String baseURL = null; @@ -411,13 +411,13 @@ class FOPTaskStarter { {MimeConstants.MIME_AFP_ALT, ".afp"}, {MimeConstants.MIME_XSL_FO, ".fo"} }; - + private String determineExtension(String outputFormat) { for (int i = 0; i < EXTENSIONS.length; i++) { if (EXTENSIONS[i][0].equals(outputFormat)) { String ext = EXTENSIONS[i][1]; if (ext == null) { - throw new RuntimeException("Output format '" + throw new RuntimeException("Output format '" + outputFormat + "' does not produce a file."); } else { return ext; @@ -467,7 +467,7 @@ class FOPTaskStarter { // actioncount = # of fofiles actually processed through FOP int actioncount = 0; // skippedcount = # of fofiles which haven't changed (force = "false") - int skippedcount = 0; + int skippedcount = 0; // deal with single source file if (task.getFofile() != null) { @@ -479,14 +479,14 @@ class FOPTaskStarter { if (task.getOutdir() != null) { outf = new File(task.getOutdir(), outf.getName()); } - // Render if "force" flag is set OR + // Render if "force" flag is set OR // OR output file doesn't exist OR // output file is older than input file - if (task.getForce() || !outf.exists() + if (task.getForce() || !outf.exists() || (task.getFofile().lastModified() > outf.lastModified() )) { render(task.getFofile(), outf, outputFormat); actioncount++; - } else if (outf.exists() + } else if (outf.exists() && (task.getFofile().lastModified() <= outf.lastModified() )) { skippedcount++; } @@ -531,10 +531,10 @@ class FOPTaskStarter { task.log("Error setting base URL", Project.MSG_DEBUG); } - // Render if "force" flag is set OR + // Render if "force" flag is set OR // OR output file doesn't exist OR // output file is older than input file - if (task.getForce() || !outf.exists() + if (task.getForce() || !outf.exists() || (f.lastModified() > outf.lastModified() )) { render(f, outf, outputFormat); actioncount++; @@ -543,11 +543,11 @@ class FOPTaskStarter { } } } - + if (actioncount + skippedcount == 0) { task.log("No files processed. No files were selected by the filesets " + "and no fofile was set." , Project.MSG_WARN); - } else if (skippedcount > 0) { + } else if (skippedcount > 0) { task.log(skippedcount + " xslfo file(s) skipped (no change found" + " since last generation; set force=\"true\" to override)." , Project.MSG_INFO); @@ -579,7 +579,7 @@ class FOPTaskStarter { } catch (Exception ex) { if (task.getThrowexceptions()) { throw new BuildException(ex); - } + } logger.error("Error rendering fo file: " + foFile, ex); } finally { try { -- cgit v1.2.3 From 058fb8cefcd6c70decd75605ed1b2504b3888d00 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 10 Jul 2008 19:47:12 +0000 Subject: Added support for piping: - input from stdin (-imagein not supported) - output to stdout Syntax: fop -xml # -xsl mystylesheet.xsl -pdf # (reads the XML from stdin and sends the generated PDF to stdout) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@675698 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/cli/CommandLineOptions.java | 149 +++++++++++++++------ src/java/org/apache/fop/cli/InputHandler.java | 67 +++++---- src/java/org/apache/fop/cli/Main.java | 18 +-- 3 files changed, 163 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index 4e5c8ae44..c740339b2 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -59,7 +59,7 @@ public class CommandLineOptions { /** Used to indicate that only the result of the XSL transformation should be output */ public static final int RENDER_NONE = -1; - /* These following constants are used to describe the input (either .FO, .XML/.XSL or + /* These following constants are used to describe the input (either .FO, .XML/.XSL or * intermediate format) */ @@ -96,11 +96,15 @@ public class CommandLineOptions { private int inputmode = NOT_SET; /* output mode */ private String outputmode = null; + /* true if System.in (stdin) should be used for the input file */ + private boolean useStdIn = false; + /* true if System.out (stdout) should be used for the output file */ + private boolean useStdOut = false; /* rendering options (for the user agent) */ private Map renderingOptions = new java.util.HashMap(); /* target resolution (for the user agent) */ private int targetResolution = 0; - + private FopFactory factory = FopFactory.newInstance(); private FOUserAgent foUserAgent; @@ -149,7 +153,7 @@ public class CommandLineOptions { } checkSettings(); setUserConfig(); - + //Factory config is set up, now we can create the user agent foUserAgent = factory.newFOUserAgent(); foUserAgent.getRendererOptions().putAll(renderingOptions); @@ -372,7 +376,12 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the fo file for the '-fo' option"); } else { - fofile = new File(args[i + 1]); + String filename = args[i + 1]; + if (isSystemInOutFile(filename)) { + this.useStdIn = true; + } else { + fofile = new File(filename); + } return 1; } } @@ -396,7 +405,12 @@ public class CommandLineOptions { throw new FOPException("you must specify the input file " + "for the '-xml' option"); } else { - xmlfile = new File(args[i + 1]); + String filename = args[i + 1]; + if (isSystemInOutFile(filename)) { + this.useStdIn = true; + } else { + xmlfile = new File(filename); + } return 1; } } @@ -412,7 +426,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the PDF output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); if (pdfAMode != null) { if (renderingOptions.get("pdf-a-mode") != null) { throw new FOPException("PDF/A mode already set"); @@ -423,13 +437,25 @@ public class CommandLineOptions { } } + private void setOutputFile(String filename) { + if (isSystemInOutFile(filename)) { + this.useStdOut = true; + } else { + outfile = new File(filename); + } + } + + private boolean isSystemInOutFile(String filename) { + return "#".equals(filename); + } + private int parseMIFOutputOption(String[] args, int i) throws FOPException { setOutputMode(MimeConstants.MIME_MIF); if ((i + 1 == args.length) || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the MIF output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -440,7 +466,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the RTF output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -451,7 +477,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the TIFF output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -462,7 +488,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the PNG output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -508,7 +534,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the PDF output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -519,7 +545,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the PostScript output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -530,7 +556,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the text output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -541,7 +567,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the SVG output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -552,7 +578,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the AFP output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -563,7 +589,7 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the FO output file"); } else { - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } } @@ -588,7 +614,7 @@ public class CommandLineOptions { throw new FOPException("you must specify the output format and the output file"); } else { setOutputMode(mime); - outfile = new File(args[i + 2]); + setOutputFile(args[i + 2]); return 2; } } @@ -599,7 +625,7 @@ public class CommandLineOptions { fofile = new File(args[i]); } else if (outputmode == null) { outputmode = MimeConstants.MIME_PDF; - outfile = new File(args[i]); + setOutputFile(args[i]); } else { throw new FOPException("Don't know what to do with " + args[i]); @@ -612,15 +638,15 @@ public class CommandLineOptions { if ((i + 1 == args.length) || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the area-tree output file"); - } else if ((i + 2 == args.length) + } else if ((i + 2 == args.length) || (args[i + 2].charAt(0) == '-')) { // only output file is specified - outfile = new File(args[i + 1]); + setOutputFile(args[i + 1]); return 1; } else { // mimic format and output file have been specified mimicRenderer = args[i + 1]; - outfile = new File(args[i + 2]); + setOutputFile(args[i + 2]); return 2; } } @@ -631,7 +657,12 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the Area Tree file for the '-atin' option"); } else { - areatreefile = new File(args[i + 1]); + String filename = args[i + 1]; + if (isSystemInOutFile(filename)) { + this.useStdIn = true; + } else { + areatreefile = new File(filename); + } return 1; } } @@ -642,14 +673,19 @@ public class CommandLineOptions { || (args[i + 1].charAt(0) == '-')) { throw new FOPException("you must specify the image file for the '-imagein' option"); } else { - imagefile = new File(args[i + 1]); + String filename = args[i + 1]; + if (isSystemInOutFile(filename)) { + this.useStdIn = true; + } else { + imagefile = new File(filename); + } return 1; } } private PDFEncryptionParams getPDFEncryptionParams() throws FOPException { PDFEncryptionParams params = (PDFEncryptionParams)renderingOptions.get( - PDFRenderer.ENCRYPTION_PARAMS); + PDFRenderer.ENCRYPTION_PARAMS); if (params == null) { if (!PDFEncryptionManager.checkAvailableAlgorithms()) { throw new FOPException("PDF encryption requested but it is not available." @@ -760,7 +796,7 @@ public class CommandLineOptions { if (inputmode == XSLT_INPUT) { // check whether xml *and* xslt file have been set - if (xmlfile == null) { + if (xmlfile == null && !this.useStdIn) { throw new FOPException("XML file must be specified for the transform mode"); } if (xsltfile == null) { @@ -777,7 +813,7 @@ public class CommandLineOptions { + "\n fofile: " + fofile.getAbsolutePath()); } - if (!xmlfile.exists()) { + if (xmlfile != null && !xmlfile.exists()) { throw new FileNotFoundException("Error: xml file " + xmlfile.getAbsolutePath() + " not found "); @@ -795,10 +831,10 @@ public class CommandLineOptions { } if (xmlfile != null || xsltfile != null) { log.warn("fo input mode, but xmlfile or xslt file are set:"); - log.error("xml file: " + xmlfile.toString()); - log.error("xslt file: " + xsltfile.toString()); + log.error("xml file: " + xmlfile); + log.error("xslt file: " + xsltfile); } - if (!fofile.exists()) { + if (fofile != null && !fofile.exists()) { throw new FileNotFoundException("Error: fo file " + fofile.getAbsolutePath() + " not found "); @@ -813,10 +849,10 @@ public class CommandLineOptions { } if (xmlfile != null || xsltfile != null) { log.warn("area tree input mode, but xmlfile or xslt file are set:"); - log.error("xml file: " + xmlfile.toString()); - log.error("xslt file: " + xsltfile.toString()); + log.error("xml file: " + xmlfile); + log.error("xslt file: " + xsltfile); } - if (!areatreefile.exists()) { + if (areatreefile != null && !areatreefile.exists()) { throw new FileNotFoundException("Error: area tree file " + areatreefile.getAbsolutePath() + " not found "); @@ -830,7 +866,7 @@ public class CommandLineOptions { log.warn("image input mode, but XML file is set:"); log.error("XML file: " + xmlfile.toString()); } - if (!imagefile.exists()) { + if (imagefile != null && !imagefile.exists()) { throw new FileNotFoundException("Error: image file " + imagefile.getAbsolutePath() + " not found "); @@ -944,6 +980,22 @@ public class CommandLineOptions { return suppressLowLevelAreas; } + /** + * Indicates whether input comes from standard input (stdin). + * @return true if input comes from standard input (stdin) + */ + public boolean isInputFromStdIn() { + return this.useStdIn; + } + + /** + * Indicates whether output is sent to standard output (stdout). + * @return true if output is sent to standard output (stdout) + */ + public boolean isOutputToStdOut() { + return this.useStdOut; + } + /** * Returns the input file. * @return either the fofile or the xmlfile @@ -986,15 +1038,17 @@ public class CommandLineOptions { + " (Examples for prof: PDF/A-1b or PDF/X-3:2003)\n\n" + " [INPUT] \n" + " infile xsl:fo input file (the same as the next) \n" + + " (use # for infile to pipe input from stdin)\n" + " -fo infile xsl:fo input file \n" + " -xml infile xml input file, must be used together with -xsl \n" + " -atin infile area tree input file \n" - + " -imagein infile image input file \n" + + " -imagein infile image input file (piping through stdin not supported)\n" + " -xsl stylesheet xslt stylesheet \n \n" + " -param name value to use for parameter in xslt stylesheet\n" + " (repeat '-param name value' for each parameter)\n \n" + " [OUTPUT] \n" + " outfile input will be rendered as PDF into outfile\n" + + " (use # for outfile to pipe output to stdout)\n" + " -pdf outfile input will be rendered as PDF (outfile req'd)\n" + " -pdfa1b outfile input will be rendered as PDF/A-1b compliant PDF\n" + " (outfile req'd, same as \"-pdf outfile -pdfprofile PDF/A-1b\")\n" @@ -1027,6 +1081,7 @@ public class CommandLineOptions { + " Fop -fo foo.fo -pdf foo.pdf (does the same as the previous line)\n" + " Fop -xml foo.xml -xsl foo.xsl -pdf foo.pdf\n" + " Fop -xml foo.xml -xsl foo.xsl -foout foo.fo\n" + + " Fop -xml # -xsl foo.xsl -pdf #\n" + " Fop foo.fo -mif foo.mif\n" + " Fop foo.fo -rtf foo.rtf\n" + " Fop foo.fo -print\n" @@ -1057,11 +1112,19 @@ public class CommandLineOptions { break; case FO_INPUT: log.info("FO "); - log.info("fo input file: " + fofile.toString()); + if (this.useStdIn) { + log.info("fo input file: from stdin"); + } else { + log.info("fo input file: " + fofile.toString()); + } break; case XSLT_INPUT: log.info("xslt transformation"); - log.info("xml input file: " + xmlfile.toString()); + if (this.useStdIn) { + log.info("xml input file: from stdin"); + } else { + log.info("xml input file: " + xmlfile.toString()); + } log.info("xslt stylesheet: " + xsltfile.toString()); break; default: @@ -1074,7 +1137,7 @@ public class CommandLineOptions { log.info("awt on screen"); if (outfile != null) { log.error("awt mode, but outfile is set:"); - log.info("out file: " + outfile.toString()); + log.error("out file: " + outfile.toString()); } } else if (MimeConstants.MIME_FOP_PRINT.equals(outputmode)) { log.info("print directly"); @@ -1087,10 +1150,18 @@ public class CommandLineOptions { if (mimicRenderer != null) { log.info("mimic renderer: " + mimicRenderer); } - log.info("output file: " + outfile.toString()); + if (this.useStdOut) { + log.info("output file: to stdout"); + } else { + log.info("output file: " + outfile.toString()); + } } else { log.info(outputmode); - log.info("output file: " + outfile.toString()); + if (this.useStdOut) { + log.info("output file: to stdout"); + } else { + log.info("output file: " + outfile.toString()); + } } log.info("OPTIONS"); diff --git a/src/java/org/apache/fop/cli/InputHandler.java b/src/java/org/apache/fop/cli/InputHandler.java index 7ad89bfab..b3ea35e0d 100644 --- a/src/java/org/apache/fop/cli/InputHandler.java +++ b/src/java/org/apache/fop/cli/InputHandler.java @@ -5,9 +5,9 @@ * 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. @@ -21,8 +21,8 @@ package org.apache.fop.cli; // Imported java.io classes import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.InputStream; import java.io.OutputStream; import java.util.Vector; @@ -58,7 +58,7 @@ import org.apache.fop.render.awt.viewer.Renderable; * parameters) or FO File input alone */ public class InputHandler implements ErrorListener, Renderable { - + /** original source file */ protected File sourcefile = null; private File stylesheet = null; // for XML/XSLT usage @@ -66,12 +66,12 @@ public class InputHandler implements ErrorListener, Renderable { /** the logger */ protected Log log = LogFactory.getLog(InputHandler.class); - + /** * Constructor for XML->XSLT->FO input * @param xmlfile XML file * @param xsltfile XSLT file - * @param params Vector of command-line parameters (name, value, + * @param params Vector of command-line parameters (name, value, * name, value, ...) for XSL stylesheet, null if none */ public InputHandler(File xmlfile, File xsltfile, Vector params) { @@ -95,7 +95,7 @@ public class InputHandler implements ErrorListener, Renderable { * @param out the output stream to write the generated output to (may be null if not applicable) * @throws FOPException in case of an error during processing */ - public void renderTo(FOUserAgent userAgent, String outputFormat, OutputStream out) + public void renderTo(FOUserAgent userAgent, String outputFormat, OutputStream out) throws FOPException { FopFactory factory = userAgent.getFactory(); @@ -107,7 +107,7 @@ public class InputHandler implements ErrorListener, Renderable { } // if base URL was not explicitly set in FOUserAgent, obtain here - if (fop.getUserAgent().getBaseURL() == null) { + if (fop.getUserAgent().getBaseURL() == null && sourcefile != null) { String baseURL = null; try { @@ -124,7 +124,7 @@ public class InputHandler implements ErrorListener, Renderable { transformTo(res); } - + /** {@inheritDoc} */ public void renderTo(FOUserAgent userAgent, String outputFormat) throws FOPException { renderTo(userAgent, outputFormat, null); @@ -140,34 +140,53 @@ public class InputHandler implements ErrorListener, Renderable { Result res = new StreamResult(out); transformTo(res); } - + /** * Creates a Source for the main input file. Processes XInclude if * available in the XML parser. - * + * * @return the Source for the main input file */ protected Source createMainSource() { Source result; + InputStream in; + String uri; + if (this.sourcefile != null) { + try { + in = new java.io.FileInputStream(this.sourcefile); + uri = this.sourcefile.toURI().toASCIIString(); + } catch (FileNotFoundException e) { + //handled elsewhere + return new StreamSource(this.sourcefile); + } + } else { + in = System.in; + uri = null; + } try { - InputSource is = new InputSource(new FileInputStream( - this.sourcefile)); - is.setSystemId(this.sourcefile.toURI().toASCIIString()); + InputSource is = new InputSource(in); + is.setSystemId(uri); SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setFeature("http://xml.org/sax/features/namespaces", true); spf.setFeature("http://apache.org/xml/features/xinclude", true); XMLReader xr = spf.newSAXParser().getXMLReader(); result = new SAXSource(xr, is); } catch (SAXException e) { - result = new StreamSource(this.sourcefile); - } catch (IOException e) { - result = new StreamSource(this.sourcefile); + if (this.sourcefile != null) { + result = new StreamSource(this.sourcefile); + } else { + result = new StreamSource(in, uri); + } } catch (ParserConfigurationException e) { - result = new StreamSource(this.sourcefile); + if (this.sourcefile != null) { + result = new StreamSource(this.sourcefile); + } else { + result = new StreamSource(in, uri); + } } return result; } - + /** * Creates a Source for the selected stylesheet. * @return the Source for the selected stylesheet or null if there's no stylesheet @@ -179,7 +198,7 @@ public class InputHandler implements ErrorListener, Renderable { return null; } } - + /** * Transforms the input document to the input format expected by FOP using XSLT. * @param result the Result object where the result of the XSL transformation is sent to @@ -190,15 +209,15 @@ public class InputHandler implements ErrorListener, Renderable { // Setup XSLT TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer; - + Source xsltSource = createXSLTSource(); if (xsltSource == null) { // FO Input transformer = factory.newTransformer(); } else { // XML/XSLT input transformer = factory.newTransformer(xsltSource); - + // Set the value of parameters, if any, defined for stylesheet - if (xsltParams != null) { + if (xsltParams != null) { for (int i = 0; i < xsltParams.size(); i += 2) { transformer.setParameter((String) xsltParams.elementAt(i), (String) xsltParams.elementAt(i + 1)); diff --git a/src/java/org/apache/fop/cli/Main.java b/src/java/org/apache/fop/cli/Main.java index 43da8d966..545aef7ff 100644 --- a/src/java/org/apache/fop/cli/Main.java +++ b/src/java/org/apache/fop/cli/Main.java @@ -62,7 +62,7 @@ public class Main { fopJar = new File(baseDir, "fop.jar"); } if (!fopJar.exists()) { - throw new RuntimeException("fop.jar not found in directory: " + throw new RuntimeException("fop.jar not found in directory: " + baseDir.getAbsolutePath() + " (or below)"); } List jars = new java.util.ArrayList(); @@ -99,7 +99,7 @@ public class Main { }*/ return urls; } - + /** * @return true if FOP's dependecies are available in the current ClassLoader setup. */ @@ -115,7 +115,7 @@ public class Main { return false; } } - + /** * Dynamically builds a ClassLoader and executes FOP. * @param args command-line arguments @@ -123,7 +123,7 @@ public class Main { public static void startFOPWithDynamicClasspath(String[] args) { try { URL[] urls = getJARList(); - //System.out.println("CCL: " + //System.out.println("CCL: " // + Thread.currentThread().getContextClassLoader().toString()); ClassLoader loader = new java.net.URLClassLoader(urls, null); Thread.currentThread().setContextClassLoader(loader); @@ -137,13 +137,13 @@ public class Main { System.exit(-1); } } - + /** * Executes FOP with the given ClassLoader setup. * @param args command-line arguments */ public static void startFOP(String[] args) { - //System.out.println("static CCL: " + //System.out.println("static CCL: " // + Thread.currentThread().getContextClassLoader().toString()); //System.out.println("static CL: " + Fop.class.getClassLoader().toString()); CommandLineOptions options = null; @@ -155,7 +155,7 @@ public class Main { if (!options.parse(args)) { System.exit(1); } - + foUserAgent = options.getFOUserAgent(); String outputFormat = options.getOutputFormat(); @@ -164,6 +164,8 @@ public class Main { out = new java.io.BufferedOutputStream( new java.io.FileOutputStream(options.getOutputFile())); foUserAgent.setOutputFile(options.getOutputFile()); + } else if (options.isOutputToStdOut()) { + out = new java.io.BufferedOutputStream(System.out); } if (!MimeConstants.MIME_XSL_FO.equals(outputFormat)) { options.getInputHandler().renderTo(foUserAgent, outputFormat, out); @@ -190,7 +192,7 @@ public class Main { System.exit(1); } } - + /** * The main routine for the command line interface * @param args the command line parameters -- cgit v1.2.3 From d59cd6c6b44c7040edcaf45af6c0df5d037b6bcc Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 11 Jul 2008 07:22:29 +0000 Subject: Check the result of mkdirs() to see if the target directory could be created. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@675845 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/tools/EventProducerCollectorTask.java | 32 ++++++++++++---------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java index 60ffaf103..743811142 100644 --- a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java @@ -56,13 +56,17 @@ public class EventProducerCollectorTask extends Task { private List filesets = new java.util.ArrayList(); private File modelFile; private File translationFile; - + /** {@inheritDoc} */ public void execute() throws BuildException { try { EventProducerCollector collector = new EventProducerCollector(); processFileSets(collector); - getModelFile().getParentFile().mkdirs(); + File parentDir = getModelFile().getParentFile(); + if (!parentDir.exists() && !parentDir.mkdirs()) { + throw new BuildException( + "Could not create target directory for event model file: " + parentDir); + } collector.saveModelToXML(getModelFile()); log("Event model written to " + getModelFile()); if (getTranslationFile() != null) { @@ -76,10 +80,10 @@ public class EventProducerCollectorTask extends Task { throw new BuildException(ioe); } } - + private static final String MODEL2TRANSLATION = "model2translation.xsl"; private static final String MERGETRANSLATION = "merge-translation.xsl"; - + /** * Updates the translation file with new entries for newly found event producer methods. * @throws IOException if an I/O error occurs @@ -89,7 +93,7 @@ public class EventProducerCollectorTask extends Task { boolean resultExists = getTranslationFile().exists(); SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); - + //Generate fresh generated translation file as template Source src = new StreamSource(getModelFile()); StreamSource xslt1 = new StreamSource( @@ -101,7 +105,7 @@ public class EventProducerCollectorTask extends Task { Transformer transformer = tFactory.newTransformer(xslt1); transformer.transform(src, domres); final Node generated = domres.getNode(); - + Node sourceDocument; if (resultExists) { //Load existing translation file into memory (because we overwrite it later) @@ -176,7 +180,7 @@ public class EventProducerCollectorTask extends Task { public void addFileset(FileSet set) { filesets.add(set); } - + /** * Sets the model file to be written. * @param f the model file @@ -184,7 +188,7 @@ public class EventProducerCollectorTask extends Task { public void setModelFile(File f) { this.modelFile = f; } - + /** * Returns the model file to be written. * @return the model file @@ -192,7 +196,7 @@ public class EventProducerCollectorTask extends Task { public File getModelFile() { return this.modelFile; } - + /** * Sets the translation file for the event producer methods. * @param f the translation file @@ -200,7 +204,7 @@ public class EventProducerCollectorTask extends Task { public void setTranslationFile(File f) { this.translationFile = f; } - + /** * Returns the translation file for the event producer methods. * @return the translation file @@ -208,7 +212,7 @@ public class EventProducerCollectorTask extends Task { public File getTranslationFile() { return this.translationFile; } - + /** * Command-line interface for testing purposes. * @param args the command-line arguments @@ -222,15 +226,15 @@ public class EventProducerCollectorTask extends Task { project.setName("Test"); FileSet fileset = new FileSet(); fileset.setDir(new File("test/java")); - + FilenameSelector selector = new FilenameSelector(); selector.setName("**/*.java"); fileset.add(selector); generator.addFileset(fileset); - + File targetDir = new File("build/codegen1"); targetDir.mkdirs(); - + generator.setModelFile(new File("D:/out.xml")); generator.setTranslationFile(new File("D:/out1.xml")); generator.execute(); -- cgit v1.2.3 From d98eb3e8a5612dd77b12613e5245da9d3461a750 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Sat, 12 Jul 2008 12:19:40 +0000 Subject: Attempt to fix a potential build problem. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@676161 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/model/EventModel.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/model/EventModel.java b/src/java/org/apache/fop/events/model/EventModel.java index 61e221b3b..54c58bd4b 100644 --- a/src/java/org/apache/fop/events/model/EventModel.java +++ b/src/java/org/apache/fop/events/model/EventModel.java @@ -46,15 +46,15 @@ import org.apache.xmlgraphics.util.XMLizable; public class EventModel implements Serializable, XMLizable { private static final long serialVersionUID = 7468592614934605082L; - + private Map producers = new java.util.LinkedHashMap(); - + /** * Creates a new, empty event model */ public EventModel() { } - + /** * Adds the model of an event producer to the event model. * @param producer the event producer model @@ -62,7 +62,7 @@ public class EventModel implements Serializable, XMLizable { public void addProducer(EventProducerModel producer) { this.producers.put(producer.getInterfaceName(), producer); } - + /** * Returns an iterator over the contained event producer models. * @return an iterator (Iterator<EventProducerModel>) @@ -79,7 +79,7 @@ public class EventModel implements Serializable, XMLizable { public EventProducerModel getProducer(String interfaceName) { return (EventProducerModel)this.producers.get(interfaceName); } - + /** * Returns the model of an event producer with the given interface. * @param clazz the interface of the event producer @@ -88,7 +88,7 @@ public class EventModel implements Serializable, XMLizable { public EventProducerModel getProducer(Class clazz) { return getProducer(clazz.getName()); } - + /** {@inheritDoc} */ public void toSAX(ContentHandler handler) throws SAXException { AttributesImpl atts = new AttributesImpl(); @@ -102,8 +102,9 @@ public class EventModel implements Serializable, XMLizable { } private void writeXMLizable(XMLizable object, File outputFile) throws IOException { - Result res = new StreamResult(outputFile); - + //Result res = new StreamResult(outputFile); //Does not seem to work in all environments + Result res = new StreamResult(outputFile.toURI().toURL().toExternalForm()); + try { SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); -- cgit v1.2.3 From 65ff8feed50291ddc834006d279fc26a640d0fb5 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 13 Jul 2008 10:26:48 +0000 Subject: Replace occurrences of File.toURL() by File.toURI().toURL() (recommended as of Java 6, where File.toURL() is deprecated) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@676297 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/apps/FOURIResolver.java | 6 +++--- src/java/org/apache/fop/cli/InputHandler.java | 2 +- src/java/org/apache/fop/cli/Main.java | 18 +++++++++--------- .../org/apache/fop/fo/extensions/svg/SVGElement.java | 2 +- .../org/apache/fop/hyphenation/HyphenationTree.java | 2 +- src/java/org/apache/fop/hyphenation/PatternParser.java | 2 +- .../org/apache/fop/render/afp/fonts/AFPFontReader.java | 8 ++++---- src/java/org/apache/fop/tools/TestConverter.java | 2 +- src/java/org/apache/fop/tools/anttasks/Fop.java | 8 ++++---- src/java/org/apache/fop/tools/anttasks/RunTest.java | 4 ++-- 10 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/apps/FOURIResolver.java b/src/java/org/apache/fop/apps/FOURIResolver.java index 76b0bedd5..878a2745a 100644 --- a/src/java/org/apache/fop/apps/FOURIResolver.java +++ b/src/java/org/apache/fop/apps/FOURIResolver.java @@ -77,7 +77,7 @@ public class FOURIResolver implements javax.xml.transform.URIResolver { } File dir = new File(base); try { - base = (dir.isDirectory() ? dir.toURL() : new URL(base)).toExternalForm(); + base = (dir.isDirectory() ? dir.toURI().toURL() : new URL(base)).toExternalForm(); } catch (MalformedURLException mfue) { if (throwExceptions) { throw mfue; @@ -173,9 +173,9 @@ public class FOURIResolver implements javax.xml.transform.URIResolver { if (file.canRead() && file.isFile()) { try { if (fragment != null) { - absoluteURL = new URL(file.toURL().toExternalForm() + fragment); + absoluteURL = new URL(file.toURI().toURL().toExternalForm() + fragment); } else { - absoluteURL = file.toURL(); + absoluteURL = file.toURI().toURL(); } } catch (MalformedURLException mfue) { handleException(mfue, "Could not convert filename '" + href diff --git a/src/java/org/apache/fop/cli/InputHandler.java b/src/java/org/apache/fop/cli/InputHandler.java index b3ea35e0d..5e38b803a 100644 --- a/src/java/org/apache/fop/cli/InputHandler.java +++ b/src/java/org/apache/fop/cli/InputHandler.java @@ -112,7 +112,7 @@ public class InputHandler implements ErrorListener, Renderable { try { baseURL = new File(sourcefile.getAbsolutePath()). - getParentFile().toURL().toExternalForm(); + getParentFile().toURI().toURL().toExternalForm(); } catch (Exception e) { baseURL = ""; } diff --git a/src/java/org/apache/fop/cli/Main.java b/src/java/org/apache/fop/cli/Main.java index 545aef7ff..f1a23ea46 100644 --- a/src/java/org/apache/fop/cli/Main.java +++ b/src/java/org/apache/fop/cli/Main.java @@ -66,7 +66,7 @@ public class Main { + baseDir.getAbsolutePath() + " (or below)"); } List jars = new java.util.ArrayList(); - jars.add(fopJar.toURL()); + jars.add(fopJar.toURI().toURL()); File[] files; FileFilter filter = new FileFilter() { public boolean accept(File pathname) { @@ -80,7 +80,7 @@ public class Main { files = libDir.listFiles(filter); if (files != null) { for (int i = 0, size = files.length; i < size; i++) { - jars.add(files[i].toURL()); + jars.add(files[i].toURI().toURL()); } } String optionalLib = System.getProperty("fop.optional.lib"); @@ -88,7 +88,7 @@ public class Main { files = new File(optionalLib).listFiles(filter); if (files != null) { for (int i = 0, size = files.length; i < size; i++) { - jars.add(files[i].toURL()); + jars.add(files[i].toURI().toURL()); } } } @@ -172,9 +172,9 @@ public class Main { } else { options.getInputHandler().transformTo(out); } - } finally { - IOUtils.closeQuietly(out); - } + } finally { + IOUtils.closeQuietly(out); + } // System.exit(0) called to close AWT/SVG-created threads, if any. // AWTRenderer closes with window shutdown, so exit() should not @@ -185,9 +185,9 @@ public class Main { } catch (Exception e) { if (options != null) { options.getLogger().error("Exception", e); - } - if (options.getOutputFile() != null) { - options.getOutputFile().delete(); + if (options.getOutputFile() != null) { + options.getOutputFile().delete(); + } } System.exit(1); } diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java index 521f3b81b..7711130b1 100644 --- a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java @@ -92,7 +92,7 @@ public class SVGElement extends SVGObj { try { URL baseURL = new URL(getUserAgent().getBaseURL() == null - ? new java.io.File("").toURL().toExternalForm() + ? new java.io.File("").toURI().toURL().toExternalForm() : getUserAgent().getBaseURL()); if (baseURL != null) { SVGOMDocument svgdoc = (SVGOMDocument)doc; diff --git a/src/java/org/apache/fop/hyphenation/HyphenationTree.java b/src/java/org/apache/fop/hyphenation/HyphenationTree.java index 67488c5b5..d145936c6 100644 --- a/src/java/org/apache/fop/hyphenation/HyphenationTree.java +++ b/src/java/org/apache/fop/hyphenation/HyphenationTree.java @@ -125,7 +125,7 @@ public class HyphenationTree extends TernaryTree public void loadPatterns(String filename) throws HyphenationException { File f = new File(filename); try { - InputSource src = new InputSource(f.toURL().toExternalForm()); + InputSource src = new InputSource(f.toURI().toURL().toExternalForm()); loadPatterns(src); } catch (MalformedURLException e) { throw new HyphenationException("Error converting the File '" + f + "' to a URL: " diff --git a/src/java/org/apache/fop/hyphenation/PatternParser.java b/src/java/org/apache/fop/hyphenation/PatternParser.java index b0378a40b..2edf64676 100644 --- a/src/java/org/apache/fop/hyphenation/PatternParser.java +++ b/src/java/org/apache/fop/hyphenation/PatternParser.java @@ -92,7 +92,7 @@ public class PatternParser extends DefaultHandler implements PatternConsumer { */ public void parse(File file) throws HyphenationException { try { - InputSource src = new InputSource(file.toURL().toExternalForm()); + InputSource src = new InputSource(file.toURI().toURL().toExternalForm()); parse(src); } catch (MalformedURLException e) { throw new HyphenationException("Error converting the File '" + file + "' to a URL: " diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java index 77792267c..7951be26c 100644 --- a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java +++ b/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java @@ -157,7 +157,7 @@ public final class AFPFontReader { if (url == null) { try { File file = new File(path); - url = file.toURL(); + url = file.toURI().toURL(); if (url == null) { String msg = "CharacterSet file not found for " + characterset + " in classpath: " + path; @@ -194,7 +194,7 @@ public final class AFPFontReader { log.warn(msg); } - inputStream = csfont[0].toURL().openStream(); + inputStream = csfont[0].toURI().toURL().openStream(); if (inputStream == null) { String msg = "Failed to open character set resource " + characterset; @@ -258,7 +258,7 @@ public final class AFPFontReader { if (url == null) { try { File file = new File(path); - url = file.toURL(); + url = file.toURI().toURL(); if (url == null) { String msg = "CodePage file not found for " + codePage + " in classpath: " + path; @@ -300,7 +300,7 @@ public final class AFPFontReader { log.warn(msg); } - InputStream is = codepage[0].toURL().openStream(); + InputStream is = codepage[0].toURI().toURL().openStream(); if (is == null) { String msg = "AFPFontReader:: loadCodePage(String):: code page file not found for " diff --git a/src/java/org/apache/fop/tools/TestConverter.java b/src/java/org/apache/fop/tools/TestConverter.java index 145f88187..5cbd3c095 100644 --- a/src/java/org/apache/fop/tools/TestConverter.java +++ b/src/java/org/apache/fop/tools/TestConverter.java @@ -274,7 +274,7 @@ public class TestConverter { File xmlFile = new File(baseDir + "/" + xml); String baseURL = null; try { - baseURL = xmlFile.getParentFile().toURL().toExternalForm(); + baseURL = xmlFile.getParentFile().toURI().toURL().toExternalForm(); } catch (Exception e) { logger.error("Error setting base directory"); } diff --git a/src/java/org/apache/fop/tools/anttasks/Fop.java b/src/java/org/apache/fop/tools/anttasks/Fop.java index 83217651e..da25478c3 100644 --- a/src/java/org/apache/fop/tools/anttasks/Fop.java +++ b/src/java/org/apache/fop/tools/anttasks/Fop.java @@ -444,14 +444,14 @@ class FOPTaskStarter { //Set base directory if (task.getBasedir() != null) { try { - this.baseURL = task.getBasedir().toURL().toExternalForm(); + this.baseURL = task.getBasedir().toURI().toURL().toExternalForm(); } catch (MalformedURLException mfue) { logger.error("Error creating base URL from base directory", mfue); } } else { try { if (task.getFofile() != null) { - this.baseURL = task.getFofile().getParentFile().toURL(). + this.baseURL = task.getFofile().getParentFile().toURI().toURL(). toExternalForm(); } } catch (MalformedURLException mfue) { @@ -519,11 +519,11 @@ class FOPTaskStarter { try { if (task.getRelativebase()) { - this.baseURL = f.getParentFile().toURL(). + this.baseURL = f.getParentFile().toURI().toURL(). toExternalForm(); } if (this.baseURL == null) { - this.baseURL = fs.getDir(task.getProject()).toURL(). + this.baseURL = fs.getDir(task.getProject()).toURI().toURL(). toExternalForm(); } diff --git a/src/java/org/apache/fop/tools/anttasks/RunTest.java b/src/java/org/apache/fop/tools/anttasks/RunTest.java index b11c75242..2bc13e8b2 100644 --- a/src/java/org/apache/fop/tools/anttasks/RunTest.java +++ b/src/java/org/apache/fop/tools/anttasks/RunTest.java @@ -224,11 +224,11 @@ public class RunTest extends Task { */ private URL[] createUrls(String mainJar) throws MalformedURLException { ArrayList urls = new ArrayList(); - urls.add(new File(mainJar).toURL()); + urls.add(new File(mainJar).toURI().toURL()); File[] libFiles = new File("lib").listFiles(); for (int i = 0; i < libFiles.length; i++) { if (libFiles[i].getPath().endsWith(".jar")) { - urls.add(libFiles[i].toURL()); + urls.add(libFiles[i].toURI().toURL()); } } return (URL[]) urls.toArray(new URL[urls.size()]); -- cgit v1.2.3 From fcabb741e1c100cc2f461f2ebd731f824120c563 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Sun, 13 Jul 2008 12:11:17 +0000 Subject: null is not correct here, an empty String needs to be used for the default namespace. Saxon 9 fails with a NullPointerException otherwise. Xalan is more tolerant. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@676307 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/events/model/EventMethodModel.java | 58 +++++++++++----------- .../org/apache/fop/events/model/EventModel.java | 4 +- .../fop/events/model/EventProducerModel.java | 24 ++++----- 3 files changed, 43 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/model/EventMethodModel.java b/src/java/org/apache/fop/events/model/EventMethodModel.java index 930cda53d..b9c62f8ab 100644 --- a/src/java/org/apache/fop/events/model/EventMethodModel.java +++ b/src/java/org/apache/fop/events/model/EventMethodModel.java @@ -37,12 +37,12 @@ import org.apache.xmlgraphics.util.XMLizable; public class EventMethodModel implements Serializable, XMLizable { private static final long serialVersionUID = -7548882973341444354L; - + private String methodName; private EventSeverity severity; private List params = new java.util.ArrayList(); private String exceptionClass; - + /** * Creates an new instance. * @param methodName the event method's name @@ -52,7 +52,7 @@ public class EventMethodModel implements Serializable, XMLizable { this.methodName = methodName; this.severity = severity; } - + /** * Adds a method parameter. * @param param the method parameter @@ -60,7 +60,7 @@ public class EventMethodModel implements Serializable, XMLizable { public void addParameter(Parameter param) { this.params.add(param); } - + /** * Adds a method parameter. * @param type the type of the parameter @@ -68,11 +68,11 @@ public class EventMethodModel implements Serializable, XMLizable { * @return the resulting Parameter instance */ public Parameter addParameter(Class type, String name) { - Parameter param = new Parameter(type, name); + Parameter param = new Parameter(type, name); addParameter(param); return param; } - + /** * Sets the event method name. * @param name the event name @@ -80,7 +80,7 @@ public class EventMethodModel implements Serializable, XMLizable { public void setMethodName(String name) { this.methodName = name; } - + /** * Returns the event method name * @return the event name @@ -88,7 +88,7 @@ public class EventMethodModel implements Serializable, XMLizable { public String getMethodName() { return this.methodName; } - + /** * Sets the event's severity level. * @param severity the severity @@ -96,7 +96,7 @@ public class EventMethodModel implements Serializable, XMLizable { public void setSeverity(EventSeverity severity) { this.severity = severity; } - + /** * Returns the event's severity level. * @return the severity @@ -104,7 +104,7 @@ public class EventMethodModel implements Serializable, XMLizable { public EventSeverity getSeverity() { return this.severity; } - + /** * Returns an unmodifiable list of parameters for this event method. * @return the list of parameters @@ -112,7 +112,7 @@ public class EventMethodModel implements Serializable, XMLizable { public List getParameters() { return Collections.unmodifiableList(this.params); } - + /** * Sets the primary exception class for this event method. Note: Not all event methods throw * exceptions! @@ -121,7 +121,7 @@ public class EventMethodModel implements Serializable, XMLizable { public void setExceptionClass(String exceptionClass) { this.exceptionClass = exceptionClass; } - + /** * Returns the primary exception class for this event method. This method returns null if * the event is only informational or just a warning. @@ -130,34 +130,34 @@ public class EventMethodModel implements Serializable, XMLizable { public String getExceptionClass() { return this.exceptionClass; } - + /** {@inheritDoc} */ public void toSAX(ContentHandler handler) throws SAXException { AttributesImpl atts = new AttributesImpl(); - atts.addAttribute(null, "name", "name", "CDATA", getMethodName()); - atts.addAttribute(null, "severity", "severity", "CDATA", getSeverity().getName()); + atts.addAttribute("", "name", "name", "CDATA", getMethodName()); + atts.addAttribute("", "severity", "severity", "CDATA", getSeverity().getName()); if (getExceptionClass() != null) { - atts.addAttribute(null, "exception", "exception", "CDATA", getExceptionClass()); + atts.addAttribute("", "exception", "exception", "CDATA", getExceptionClass()); } String elName = "method"; - handler.startElement(null, elName, elName, atts); + handler.startElement("", elName, elName, atts); Iterator iter = this.params.iterator(); while (iter.hasNext()) { ((XMLizable)iter.next()).toSAX(handler); } - handler.endElement(null, elName, elName); + handler.endElement("", elName, elName); } - + /** * Represents an event parameter. */ public static class Parameter implements Serializable, XMLizable { - + private static final long serialVersionUID = 6062500277953887099L; - + private Class type; private String name; - + /** * Creates a new event parameter. * @param type the parameter type @@ -167,7 +167,7 @@ public class EventMethodModel implements Serializable, XMLizable { this.type = type; this.name = name; } - + /** * Returns the parameter type. * @return the parameter type @@ -175,7 +175,7 @@ public class EventMethodModel implements Serializable, XMLizable { public Class getType() { return this.type; } - + /** * Returns the parameter name. * @return the parameter name @@ -187,12 +187,12 @@ public class EventMethodModel implements Serializable, XMLizable { /** {@inheritDoc} */ public void toSAX(ContentHandler handler) throws SAXException { AttributesImpl atts = new AttributesImpl(); - atts.addAttribute(null, "type", "type", "CDATA", getType().getName()); - atts.addAttribute(null, "name", "name", "CDATA", getName()); + atts.addAttribute("", "type", "type", "CDATA", getType().getName()); + atts.addAttribute("", "name", "name", "CDATA", getName()); String elName = "parameter"; - handler.startElement(null, elName, elName, atts); - handler.endElement(null, elName, elName); + handler.startElement("", elName, elName, atts); + handler.endElement("", elName, elName); } - + } } diff --git a/src/java/org/apache/fop/events/model/EventModel.java b/src/java/org/apache/fop/events/model/EventModel.java index 54c58bd4b..a10237ad5 100644 --- a/src/java/org/apache/fop/events/model/EventModel.java +++ b/src/java/org/apache/fop/events/model/EventModel.java @@ -93,12 +93,12 @@ public class EventModel implements Serializable, XMLizable { public void toSAX(ContentHandler handler) throws SAXException { AttributesImpl atts = new AttributesImpl(); String elName = "event-model"; - handler.startElement(null, elName, elName, atts); + handler.startElement("", elName, elName, atts); Iterator iter = getProducers(); while (iter.hasNext()) { ((XMLizable)iter.next()).toSAX(handler); } - handler.endElement(null, elName, elName); + handler.endElement("", elName, elName); } private void writeXMLizable(XMLizable object, File outputFile) throws IOException { diff --git a/src/java/org/apache/fop/events/model/EventProducerModel.java b/src/java/org/apache/fop/events/model/EventProducerModel.java index 938609cd9..b0d334e99 100644 --- a/src/java/org/apache/fop/events/model/EventProducerModel.java +++ b/src/java/org/apache/fop/events/model/EventProducerModel.java @@ -35,18 +35,18 @@ import org.apache.xmlgraphics.util.XMLizable; public class EventProducerModel implements Serializable, XMLizable { private static final long serialVersionUID = 122267104123721902L; - + private String interfaceName; private Map methods = new java.util.LinkedHashMap(); - + /** * Creates a new instance. - * @param interfaceName the fully qualified interface name of the event producer + * @param interfaceName the fully qualified interface name of the event producer */ public EventProducerModel(String interfaceName) { this.interfaceName = interfaceName; } - + /** * Returns the fully qualified interface name of the event producer. * @return the fully qualified interface name @@ -54,7 +54,7 @@ public class EventProducerModel implements Serializable, XMLizable { public String getInterfaceName() { return this.interfaceName; } - + /** * Sets the fully qualified interface name of the event producer. * @param name the fully qualified interface name @@ -62,7 +62,7 @@ public class EventProducerModel implements Serializable, XMLizable { public void setInterfaceName(String name) { this.interfaceName = name; } - + /** * Adds a model instance of an event method. * @param method the event method model @@ -70,7 +70,7 @@ public class EventProducerModel implements Serializable, XMLizable { public void addMethod(EventMethodModel method) { this.methods.put(method.getMethodName(), method); } - + /** * Returns the model instance of an event method for the given method name. * @param methodName the method name @@ -79,7 +79,7 @@ public class EventProducerModel implements Serializable, XMLizable { public EventMethodModel getMethod(String methodName) { return (EventMethodModel)this.methods.get(methodName); } - + /** * Returns an iterator over the contained event producer methods. * @return an iterator (Iterator<EventMethodModel>) @@ -91,15 +91,15 @@ public class EventProducerModel implements Serializable, XMLizable { /** {@inheritDoc} */ public void toSAX(ContentHandler handler) throws SAXException { AttributesImpl atts = new AttributesImpl(); - atts.addAttribute(null, "name", "name", "CDATA", getInterfaceName()); + atts.addAttribute("", "name", "name", "CDATA", getInterfaceName()); String elName = "producer"; - handler.startElement(null, elName, elName, atts); + handler.startElement("", elName, elName, atts); Iterator iter = getMethods(); while (iter.hasNext()) { ((XMLizable)iter.next()).toSAX(handler); } - handler.endElement(null, elName, elName); + handler.endElement("", elName, elName); } - + } -- cgit v1.2.3 From 5744a4c36782d5e8698b903d4e13891d9aff37be Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 13 Jul 2008 18:31:30 +0000 Subject: Another attempt at avoiding build issues (?) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@676397 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/fop/tools/EventProducerCollectorTask.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java index 743811142..ed92a55e0 100644 --- a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java @@ -95,7 +95,7 @@ public class EventProducerCollectorTask extends Task { = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); //Generate fresh generated translation file as template - Source src = new StreamSource(getModelFile()); + Source src = new StreamSource(getModelFile().toURI().toURL().toExternalForm()); StreamSource xslt1 = new StreamSource( getClass().getResourceAsStream(MODEL2TRANSLATION)); if (xslt1.getInputStream() == null) { @@ -109,7 +109,7 @@ public class EventProducerCollectorTask extends Task { Node sourceDocument; if (resultExists) { //Load existing translation file into memory (because we overwrite it later) - src = new StreamSource(getTranslationFile()); + src = new StreamSource(getTranslationFile().toURI().toURL().toExternalForm()); domres = new DOMResult(); transformer = tFactory.newTransformer(); transformer.transform(src, domres); @@ -121,7 +121,7 @@ public class EventProducerCollectorTask extends Task { //Generate translation file (with potentially new translations) src = new DOMSource(sourceDocument); - Result res = new StreamResult(getTranslationFile()); + Result res = new StreamResult(getTranslationFile().toURI().toURL().toExternalForm()); StreamSource xslt2 = new StreamSource( getClass().getResourceAsStream(MERGETRANSLATION)); if (xslt2.getInputStream() == null) { -- cgit v1.2.3 From 93d283b53b864778a2c87af1d7072c1a520b35f8 Mon Sep 17 00:00:00 2001 From: Chris Bowditch Date: Mon, 14 Jul 2008 14:44:53 +0000 Subject: A nit: clarify message so its more meaningful to end user git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@676608 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/EventFormatter.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml index 3e6cc181e..1f08456c9 100644 --- a/src/java/org/apache/fop/events/EventFormatter.xml +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -81,7 +81,7 @@ Any reference to it will be considered a reference to the first occurrence in th The contents of table-row {row} are taller than they should be (there is a block-progression-dimension or height constraint on the indicated row). Due to its contents the row grows to {effCellBPD} millipoints, but the row shouldn't get any taller than {maxCellBPD} millipoints.{{locator}} table-layout="fixed" and width="auto", but auto-layout not supported => assuming width="100%".{{locator}} The extent in inline-progression-direction (width) of a {elementName} is bigger than the available space ({effIPD}mpt > {maxIPD}mpt).{{locator}} - Adjusting end-indent based on overconstrained geometry rules for {elementName}.{{locator}} + An {elementName} {{locator}} is wider than the available room in inline-progression-dimension. Adjusting end-indent based on overconstrained geometry rules (XSL 1.1, ch. 5.3.4) Content overflows the viewport of an {elementName} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}} Content overflows the viewport of the {elementName} on page {page} in block-progression direction by {amount} millipoints.{clip,if, Content will be clipped.}{{locator}} Flow "{flowName}" does not map to the region-body in page-master "{masterName}". FOP presently does not support this.{{locator}} -- cgit v1.2.3 From 1ec5f0c34786a0589aa34cf06a523c05bb42ec61 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 16 Jul 2008 20:16:51 +0000 Subject: Worked around a bug in Xalan 2.4.0 (bundled with Sun Java 1.4.2_xx) where file URLs like file:/C:/.... got converted to file:\C:\.... on Windows causing a FileNotFoundException. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@677404 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/tools/EventProducerCollectorTask.java | 53 +++++++++++++--------- .../org/apache/fop/events/model/EventModel.java | 15 +++++- 2 files changed, 45 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java index ed92a55e0..e00b05b55 100644 --- a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java @@ -22,6 +22,7 @@ package org.apache.fop.tools; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.OutputStream; import java.util.Iterator; import java.util.List; @@ -38,6 +39,7 @@ import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Node; +import org.apache.commons.io.IOUtils; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; @@ -121,29 +123,38 @@ public class EventProducerCollectorTask extends Task { //Generate translation file (with potentially new translations) src = new DOMSource(sourceDocument); - Result res = new StreamResult(getTranslationFile().toURI().toURL().toExternalForm()); - StreamSource xslt2 = new StreamSource( - getClass().getResourceAsStream(MERGETRANSLATION)); - if (xslt2.getInputStream() == null) { - throw new FileNotFoundException(MERGETRANSLATION + " not found"); - } - transformer = tFactory.newTransformer(xslt2); - transformer.setURIResolver(new URIResolver() { - public Source resolve(String href, String base) throws TransformerException { - if ("my:dom".equals(href)) { - return new DOMSource(generated); + + //The following triggers a bug in older Xalan versions + //Result res = new StreamResult(getTranslationFile()); + OutputStream out = new java.io.FileOutputStream(getTranslationFile()); + out = new java.io.BufferedOutputStream(out); + Result res = new StreamResult(out); + try { + StreamSource xslt2 = new StreamSource( + getClass().getResourceAsStream(MERGETRANSLATION)); + if (xslt2.getInputStream() == null) { + throw new FileNotFoundException(MERGETRANSLATION + " not found"); + } + transformer = tFactory.newTransformer(xslt2); + transformer.setURIResolver(new URIResolver() { + public Source resolve(String href, String base) throws TransformerException { + if ("my:dom".equals(href)) { + return new DOMSource(generated); + } + return null; } - return null; + }); + if (resultExists) { + transformer.setParameter("generated-url", "my:dom"); } - }); - if (resultExists) { - transformer.setParameter("generated-url", "my:dom"); - } - transformer.transform(src, res); - if (resultExists) { - log("Translation file updated: " + getTranslationFile()); - } else { - log("Translation file generated: " + getTranslationFile()); + transformer.transform(src, res); + if (resultExists) { + log("Translation file updated: " + getTranslationFile()); + } else { + log("Translation file generated: " + getTranslationFile()); + } + } finally { + IOUtils.closeQuietly(out); } } catch (TransformerException te) { throw new IOException(te.getMessage()); diff --git a/src/java/org/apache/fop/events/model/EventModel.java b/src/java/org/apache/fop/events/model/EventModel.java index a10237ad5..454e4a8ef 100644 --- a/src/java/org/apache/fop/events/model/EventModel.java +++ b/src/java/org/apache/fop/events/model/EventModel.java @@ -21,6 +21,7 @@ package org.apache.fop.events.model; import java.io.File; import java.io.IOException; +import java.io.OutputStream; import java.io.Serializable; import java.util.Iterator; import java.util.Map; @@ -38,6 +39,8 @@ import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; +import org.apache.commons.io.IOUtils; + import org.apache.xmlgraphics.util.XMLizable; /** @@ -102,12 +105,18 @@ public class EventModel implements Serializable, XMLizable { } private void writeXMLizable(XMLizable object, File outputFile) throws IOException { - //Result res = new StreamResult(outputFile); //Does not seem to work in all environments - Result res = new StreamResult(outputFile.toURI().toURL().toExternalForm()); + //These two approaches do not seem to work in all environments: + //Result res = new StreamResult(outputFile); + //Result res = new StreamResult(outputFile.toURI().toURL().toExternalForm()); + //With an old Xalan version: file:/C:/.... --> file:\C:\..... + OutputStream out = new java.io.FileOutputStream(outputFile); + out = new java.io.BufferedOutputStream(out); + Result res = new StreamResult(out); try { SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + System.out.println(tFactory.getClass().getName()); TransformerHandler handler = tFactory.newTransformerHandler(); Transformer transformer = handler.getTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); @@ -121,6 +130,8 @@ public class EventModel implements Serializable, XMLizable { throw new IOException(e.getMessage()); } catch (SAXException e) { throw new IOException(e.getMessage()); + } finally { + IOUtils.closeQuietly(out); } } -- cgit v1.2.3 From 7a56940e312c85dc0c0ec1a4729f990d0ff55358 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 16 Jul 2008 20:22:17 +0000 Subject: Removed stray System.out. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@677405 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/model/EventModel.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/java/org/apache/fop/events/model/EventModel.java b/src/java/org/apache/fop/events/model/EventModel.java index 454e4a8ef..9c11b79a3 100644 --- a/src/java/org/apache/fop/events/model/EventModel.java +++ b/src/java/org/apache/fop/events/model/EventModel.java @@ -116,7 +116,6 @@ public class EventModel implements Serializable, XMLizable { try { SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); - System.out.println(tFactory.getClass().getName()); TransformerHandler handler = tFactory.newTransformerHandler(); Transformer transformer = handler.getTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); -- cgit v1.2.3 From 1867bcc73af7bbb10a7729ff01184a1909abbb4d Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 17 Jul 2008 09:11:09 +0000 Subject: fonts package must not depend on the render package. Refactored to restore that rule. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@677543 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fonts/CustomFontCollection.java | 37 ++++++------- src/java/org/apache/fop/fonts/FontManager.java | 60 ++++------------------ src/java/org/apache/fop/render/PrintRenderer.java | 29 +++++++---- .../render/java2d/ConfiguredFontCollection.java | 45 ++++++++-------- .../apache/fop/render/java2d/Java2DRenderer.java | 9 +++- .../org/apache/fop/render/pcl/PCLRenderer.java | 34 +++++++----- .../fop/config/FontsSubstitutionTestCase.java | 13 +++-- 7 files changed, 108 insertions(+), 119 deletions(-) (limited to 'src') diff --git a/src/java/org/apache/fop/fonts/CustomFontCollection.java b/src/java/org/apache/fop/fonts/CustomFontCollection.java index 5e5a61189..5a0bba782 100644 --- a/src/java/org/apache/fop/fonts/CustomFontCollection.java +++ b/src/java/org/apache/fop/fonts/CustomFontCollection.java @@ -5,9 +5,9 @@ * 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. @@ -21,38 +21,35 @@ package org.apache.fop.fonts; import java.util.List; -import org.apache.fop.render.PrintRenderer; - /** * Sets up a set of custom (embedded) fonts */ public class CustomFontCollection implements FontCollection { - private PrintRenderer renderer = null; + private FontResolver fontResolver; + private List/**/ embedFontInfoList; /** - * A print renderer to configure - * @param renderer a print renderer + * Main constructor. + * @param fontResolver a font resolver + * @param customFonts the list of custom fonts */ - public CustomFontCollection(PrintRenderer renderer) { - this.renderer = renderer; + public CustomFontCollection(FontResolver fontResolver, + List/**/ customFonts) { + this.fontResolver = fontResolver; + if (this.fontResolver == null) { + //Ensure that we have minimal font resolution capabilities + this.fontResolver = FontManager.createMinimalFontResolver(); + } + this.embedFontInfoList = customFonts; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int setup(int num, FontInfo fontInfo) { - List/**/ embedFontInfoList = renderer.getFontList(); if (embedFontInfoList == null) { return num; //No fonts to process } - FontResolver resolver = renderer.getFontResolver(); - if (resolver == null) { - //Ensure that we have minimal font resolution capabilities - resolver = FontManager.createMinimalFontResolver(); - } - String internalName = null; //FontReader reader = null; @@ -69,7 +66,7 @@ public class CustomFontCollection implements FontCollection { fontInfo.addMetrics(internalName, reader.getFont()); */ - LazyFont font = new LazyFont(embedFontInfo, resolver); + LazyFont font = new LazyFont(embedFontInfo, this.fontResolver); fontInfo.addMetrics(internalName, font); List triplets = embedFontInfo.getFontTriplets(); diff --git a/src/java/org/apache/fop/fonts/FontManager.java b/src/java/org/apache/fop/fonts/FontManager.java index c180fbcc9..b3833cf50 100644 --- a/src/java/org/apache/fop/fonts/FontManager.java +++ b/src/java/org/apache/fop/fonts/FontManager.java @@ -5,9 +5,9 @@ * 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. @@ -19,7 +19,6 @@ package org.apache.fop.fonts; -import java.awt.Graphics2D; import java.net.MalformedURLException; import javax.xml.transform.Source; @@ -27,7 +26,6 @@ import javax.xml.transform.stream.StreamSource; import org.apache.fop.fonts.FontTriplet.Matcher; import org.apache.fop.fonts.substitute.FontSubstitutions; -import org.apache.fop.render.PrintRenderer; // TODO: Refactor fonts package so major font activities (autodetection etc) // are all centrally managed and delegated from this class, also remove dependency on FopFactory @@ -144,55 +142,17 @@ public class FontManager { } /** - * Sets up the fonts on a given PrintRenderer - * @param renderer a print renderer + * Sets up the fonts on a given FontInfo object. The fonts to setup are defined by an + * array of {@code FontCollection} objects. + * @param fontInfo the FontInfo object to set up + * @param fontCollections the array of font collections/sources */ - public void setupRenderer(PrintRenderer renderer) { - FontInfo fontInfo = renderer.getFontInfo(); - + public void setup(FontInfo fontInfo, FontCollection[] fontCollections) { int startNum = 1; - // Configure base 14 fonts - org.apache.fop.fonts.base14.Base14FontCollection base14FontCollection - = new org.apache.fop.fonts.base14.Base14FontCollection(this.enableBase14Kerning); - startNum = base14FontCollection.setup(startNum, fontInfo); - - // Configure any custom font collection - org.apache.fop.fonts.CustomFontCollection customFontCollection - = new org.apache.fop.fonts.CustomFontCollection(renderer); - startNum = customFontCollection.setup(startNum, fontInfo); - - // Make any defined substitutions in the font info - getFontSubstitutions().adjustFontInfo(fontInfo); - } - - /** - * Sets up the fonts on a given PrintRenderer with Graphics2D - * @param renderer a print renderer - * @param graphics2D a graphics 2D - */ - public void setupRenderer(PrintRenderer renderer, Graphics2D graphics2D) { - FontInfo fontInfo = renderer.getFontInfo(); - - int startNum = 1; - - // setup base 14 fonts - org.apache.fop.render.java2d.Base14FontCollection base14FontCollection - = new org.apache.fop.render.java2d.Base14FontCollection(graphics2D); - - // setup any custom font collection - startNum = base14FontCollection.setup(startNum, fontInfo); - - // setup any installed fonts - org.apache.fop.render.java2d.InstalledFontCollection installedFontCollection - = new org.apache.fop.render.java2d.InstalledFontCollection(graphics2D); - startNum = installedFontCollection.setup(startNum, fontInfo); - - // setup any configured fonts - org.apache.fop.render.java2d.ConfiguredFontCollection configuredFontCollection - = new org.apache.fop.render.java2d.ConfiguredFontCollection(renderer); - startNum = configuredFontCollection.setup(startNum, fontInfo); - + for (int i = 0, c = fontCollections.length; i < c; i++) { + startNum = fontCollections[i].setup(startNum, fontInfo); + } // Make any defined substitutions in the font info getFontSubstitutions().adjustFontInfo(fontInfo); } diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index 35630d628..44b0a211d 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -5,9 +5,9 @@ * 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. @@ -20,19 +20,23 @@ package org.apache.fop.render; // FOP +import java.awt.Color; +import java.awt.geom.Rectangle2D; +import java.util.List; +import java.util.Map; + +import org.w3c.dom.Document; + import org.apache.fop.area.Area; import org.apache.fop.area.Trait; +import org.apache.fop.fonts.CustomFontCollection; import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontCollection; import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontTriplet; -import org.w3c.dom.Document; - -// Java -import java.awt.Color; -import java.awt.geom.Rectangle2D; -import java.util.List; -import java.util.Map; +import org.apache.fop.fonts.base14.Base14FontCollection; /** Abstract base class of "Print" type renderers. */ public abstract class PrintRenderer extends AbstractRenderer { @@ -79,7 +83,12 @@ public abstract class PrintRenderer extends AbstractRenderer { */ public void setupFontInfo(FontInfo inFontInfo) { this.fontInfo = inFontInfo; - userAgent.getFactory().getFontManager().setupRenderer(this); + FontManager fontManager = userAgent.getFactory().getFontManager(); + FontCollection[] fontCollections = new FontCollection[] { + new Base14FontCollection(fontManager.isBase14KerningEnabled()), + new CustomFontCollection(getFontResolver(), getFontList()) + }; + fontManager.setup(getFontInfo(), fontCollections); } /** diff --git a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java index 843ab8413..26d64af74 100644 --- a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java +++ b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java @@ -5,9 +5,9 @@ * 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. @@ -35,7 +35,6 @@ import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.LazyFont; -import org.apache.fop.render.PrintRenderer; /** * A java2d configured font collection @@ -44,37 +43,36 @@ public class ConfiguredFontCollection implements FontCollection { private static Log log = LogFactory.getLog(ConfiguredFontCollection.class); - private PrintRenderer renderer = null; + private FontResolver fontResolver; + private List/**/ embedFontInfoList; /** * Main constructor - * - * @param renderer a print renderer + * @param fontResolver a font resolver + * @param customFonts the list of custom fonts */ - public ConfiguredFontCollection(PrintRenderer renderer) { - this.renderer = renderer; + public ConfiguredFontCollection(FontResolver fontResolver, + List/**/ customFonts) { + this.fontResolver = fontResolver; + if (this.fontResolver == null) { + //Ensure that we have minimal font resolution capabilities + this.fontResolver = FontManager.createMinimalFontResolver(); + } + this.embedFontInfoList = customFonts; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public int setup(int start, FontInfo fontInfo) { - List/**/ fontList = renderer.getFontList(); - FontResolver resolver = renderer.getFontResolver(); int num = start; - if (fontList == null || fontList.size() < 1) { + if (embedFontInfoList == null || embedFontInfoList.size() < 1) { log.debug("No user configured fonts found."); return num; } - if (resolver == null) { - // Ensure that we have minimal font resolution capabilities - resolver = FontManager.createMinimalFontResolver(); - } String internalName = null; - for (int i = 0; i < fontList.size(); i++) { + for (int i = 0; i < embedFontInfoList.size(); i++) { - EmbedFontInfo configFontInfo = (EmbedFontInfo) fontList.get(i); + EmbedFontInfo configFontInfo = (EmbedFontInfo) embedFontInfoList.get(i); String fontFile = configFontInfo.getEmbedFile(); internalName = "F" + num; num++; @@ -84,11 +82,12 @@ public class ConfiguredFontCollection implements FontCollection { // If the user specified an XML-based metrics file, we'll use it // Otherwise, calculate metrics directly from the font file. if (metricsUrl != null) { - LazyFont fontMetrics = new LazyFont(configFontInfo, resolver); - Source fontSource = resolver.resolve(configFontInfo.getEmbedFile()); + LazyFont fontMetrics = new LazyFont(configFontInfo, fontResolver); + Source fontSource = fontResolver.resolve(configFontInfo.getEmbedFile()); font = new CustomFontMetricsMapper(fontMetrics, fontSource); } else { - CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, true, resolver); + CustomFont fontMetrics = FontLoader.loadFont( + fontFile, null, true, fontResolver); font = new CustomFontMetricsMapper(fontMetrics); } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index ed6f29ab9..1dd353b3b 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -69,6 +69,7 @@ import org.apache.fop.datatypes.URISpecification; import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontCollection; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.Typeface; import org.apache.fop.render.AbstractPathOrientedRenderer; @@ -176,7 +177,13 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - userAgent.getFactory().getFontManager().setupRenderer(this, graphics2D); + FontCollection[] fontCollections = new FontCollection[] { + new Base14FontCollection(graphics2D), + new InstalledFontCollection(graphics2D), + new ConfiguredFontCollection(getFontResolver(), getFontList()) + }; + userAgent.getFactory().getFontManager().setup( + getFontInfo(), fontCollections); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 7ab46c24e..11366f985 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -5,9 +5,9 @@ * 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. @@ -82,6 +82,7 @@ import org.apache.fop.datatypes.URISpecification; import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontCollection; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontMetrics; import org.apache.fop.render.Graphics2DAdapter; @@ -89,7 +90,10 @@ import org.apache.fop.render.PrintRenderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; import org.apache.fop.render.RendererEventProducer; +import org.apache.fop.render.java2d.Base14FontCollection; +import org.apache.fop.render.java2d.ConfiguredFontCollection; import org.apache.fop.render.java2d.FontMetricsMapper; +import org.apache.fop.render.java2d.InstalledFontCollection; import org.apache.fop.render.java2d.Java2DRenderer; import org.apache.fop.render.pcl.extensions.PCLElementMapping; import org.apache.fop.traits.BorderProps; @@ -207,7 +211,13 @@ public class PCLRenderer extends PrintRenderer { graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - userAgent.getFactory().getFontManager().setupRenderer(this, graphics2D); + FontCollection[] fontCollections = new FontCollection[] { + new Base14FontCollection(graphics2D), + new InstalledFontCollection(graphics2D), + new ConfiguredFontCollection(getFontResolver(), getFontList()) + }; + userAgent.getFactory().getFontManager().setup( + getFontInfo(), fontCollections); } /** @@ -1035,7 +1045,7 @@ public class PCLRenderer extends PrintRenderer { //So there's some optimization potential but not otherwise PCLRenderer is a little //difficult to derive from AbstractPathOrientedRenderer. Maybe an additional layer //between PrintRenderer and AbstractPathOrientedRenderer is necessary. - + // save position and offset int saveIP = currentIPPosition; int saveBP = currentBPPosition; @@ -1045,7 +1055,7 @@ public class PCLRenderer extends PrintRenderer { at.translate(currentIPPosition, currentBPPosition); at.translate(block.getXOffset(), block.getYOffset()); at.translate(0, block.getSpaceBefore()); - + if (!at.isIdentity()) { saveGraphicsState(); concatenateTransformationMatrix(mptToPt(at)); @@ -1063,12 +1073,12 @@ public class PCLRenderer extends PrintRenderer { if (!at.isIdentity()) { restoreGraphicsState(); } - + // stacked and relative blocks effect stacking currentIPPosition = saveIP; currentBPPosition = saveBP; } - + /** {@inheritDoc} */ protected void renderFlow(NormalFlow flow) { //TODO This is the same code as in AbstractPathOrientedRenderer @@ -1083,7 +1093,7 @@ public class PCLRenderer extends PrintRenderer { //Establish a new coordinate system AffineTransform at = new AffineTransform(); at.translate(currentIPPosition, currentBPPosition); - + if (!at.isIdentity()) { saveGraphicsState(); concatenateTransformationMatrix(mptToPt(at)); @@ -1092,16 +1102,16 @@ public class PCLRenderer extends PrintRenderer { currentIPPosition = 0; currentBPPosition = 0; super.renderFlow(flow); - + if (!at.isIdentity()) { restoreGraphicsState(); } - + // stacked and relative blocks effect stacking currentIPPosition = saveIP; currentBPPosition = saveBP; } - + /** * Concatenates the current transformation matrix with the given one, therefore establishing * a new coordinate system. @@ -1225,7 +1235,7 @@ public class PCLRenderer extends PrintRenderer { renderDocument(doc, ns, pos, fo.getForeignAttributes()); } - /** + /** * Common method to render the background and borders for any inline area. * The all borders and padding are drawn outside the specified area. * @param area the inline area for which the background, border and padding is to be diff --git a/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java b/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java index 6f286a3fb..725f0d4d7 100644 --- a/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java +++ b/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java @@ -5,9 +5,9 @@ * 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. @@ -23,10 +23,13 @@ import java.io.File; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; +import org.apache.fop.fonts.CustomFontCollection; import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontCollection; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.base14.Base14FontCollection; import org.apache.fop.render.PrintRenderer; /** @@ -53,7 +56,11 @@ public class FontsSubstitutionTestCase extends FontInfo fontInfo = new FontInfo(); renderer.setupFontInfo(fontInfo); FontManager fontManager = ua.getFactory().getFontManager(); - fontManager.setupRenderer(renderer); + FontCollection[] fontCollections = new FontCollection[] { + new Base14FontCollection(fontManager.isBase14KerningEnabled()), + new CustomFontCollection(renderer.getFontResolver(), renderer.getFontList()) + }; + fontManager.setup(fontInfo, fontCollections); FontTriplet triplet = new FontTriplet("Times", "italic", Font.WEIGHT_NORMAL); String internalFontKey = fontInfo.getInternalFontKey(triplet); -- cgit v1.2.3
    Parameters specified as nested elements