From 3cb2a24bcdc2558d1db95bab63cba628fa554d3c Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 27 Mar 2008 15:50:59 +0000 Subject: This package has been moved to its own top level. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@641860 13f79535-47bb-0310-9956-ffa450edef68 --- .../afp/modca/goca/AbstractGraphicsContainer.java | 95 ----------- .../afp/modca/goca/AbstractGraphicsCoord.java | 126 --------------- .../afp/modca/goca/AbstractPreparedAFPObject.java | 56 ------- .../fop/render/afp/modca/goca/GraphicsArea.java | 82 ---------- .../fop/render/afp/modca/goca/GraphicsBox.java | 66 -------- .../afp/modca/goca/GraphicsChainedSegment.java | 179 --------------------- .../fop/render/afp/modca/goca/GraphicsData.java | 147 ----------------- .../fop/render/afp/modca/goca/GraphicsFillet.java | 41 ----- .../fop/render/afp/modca/goca/GraphicsFullArc.java | 81 ---------- .../render/afp/modca/goca/GraphicsImageBegin.java | 85 ---------- .../render/afp/modca/goca/GraphicsImageData.java | 57 ------- .../render/afp/modca/goca/GraphicsImageEnd.java | 50 ------ .../fop/render/afp/modca/goca/GraphicsLine.java | 42 ----- .../afp/modca/goca/GraphicsSetArcParameters.java | 53 ------ .../afp/modca/goca/GraphicsSetCharacterSet.java | 55 ------- .../afp/modca/goca/GraphicsSetCurrentPosition.java | 41 ----- .../render/afp/modca/goca/GraphicsSetLineType.java | 86 ---------- .../afp/modca/goca/GraphicsSetLineWidth.java | 54 ------- .../afp/modca/goca/GraphicsSetPatternSymbol.java | 106 ------------ .../afp/modca/goca/GraphicsSetProcessColor.java | 92 ----------- .../fop/render/afp/modca/goca/GraphicsString.java | 115 ------------- 21 files changed, 1709 deletions(-) delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java (limited to 'src/java') 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 deleted file mode 100644 index c0520fbf1..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java +++ /dev/null @@ -1,95 +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.goca; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.Iterator; -import java.util.List; - -import org.apache.fop.render.afp.modca.AbstractStructuredAFPObject; -import org.apache.fop.render.afp.modca.PreparedAFPObject; - -/** - * A base class container of GOCA structured objects - */ -public abstract class AbstractGraphicsContainer extends AbstractStructuredAFPObject -implements PreparedAFPObject { - - /** - * list of objects contained within this container - */ - protected List list = null; - - /** - * Default constructor - */ - public AbstractGraphicsContainer() { - } - - /** - * Named constructor - * @param name the name of the container - */ - public AbstractGraphicsContainer(String name) { - super(name); - } - - /** - * {@inheritDoc} - */ - protected void writeContent(OutputStream os) throws IOException { - if (list != null) { - super.writeObjectList(list, os); - } - } - - /** - * Adds a given graphics drawing order to this container - * @param drawingOrder the graphics drawing order - * @return the drawingOrder if it was added, null otherwise - */ - protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { - log.debug(this + " adding " + drawingOrder); - if (list == null) { - this.list = new java.util.ArrayList(); - } - list.add(drawingOrder); - return drawingOrder; - } - - /** - * @return the current data length of this container including - * all enclosed GOCA drawing objects (and their containers) - */ - public int getDataLength() { - int dataLen = 0; - if (list != null) { - Iterator it = list.iterator(); - while (it.hasNext()) { - Object obj = it.next(); - if (obj instanceof PreparedAFPObject) { - dataLen += ((PreparedAFPObject)obj).getDataLength(); - } - } - } - return dataLen; - } -} 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 deleted file mode 100644 index 8f6e55b23..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java +++ /dev/null @@ -1,126 +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.goca; - -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * A base class encapsulating the structure of coordinate based GOCA objects - */ -public abstract class AbstractGraphicsCoord extends AbstractPreparedAFPObject { - - /** array of x/y coordinates */ - protected int[] coords = null; - - /** - * @param coords the x/y coordinates for this object - */ - public AbstractGraphicsCoord(int[] coords) { - this.coords = coords; - prepareData(); - } - - /** - * @param x the x coordinate for this object - * @param y the y coordinate for this object - */ - public AbstractGraphicsCoord(int x, int y) { - this(new int[] {x, y}); - } - - /** - * @param x1 the x1 coordinate for this object - * @param y1 the y1 coordinate for this object - * @param x2 the x2 coordinate for this object - * @param y2 the y2 coordinate for this object - */ - public AbstractGraphicsCoord(int x1, int y1, int x2, int y2) { - this(new int[] {x1, y1, x2, y2}); - } - - /** - * @return the order code to use - */ - protected abstract byte getOrderCode(); - - /** - * @return the length of this order code - * (typically this is the same as the coordinate length) - */ - protected int getLength() { - return this.coords.length * 2; - } - - /** - * Creates a newly created and initialized byte data - * @return a newly created and initialized byte data - */ - protected byte[] createData() { - int len = getLength(); - byte[] data = new byte[len + 2]; - data[0] = getOrderCode(); // ORDER CODE - data[1] = (byte)len; // LENGTH - return data; - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - super.data = createData(); - int fromIndex = data.length - getLength(); - addCoords(data, fromIndex); - } - - /** - * Adds the coordinates to the structured field data - * @param data the structured field data - * @param fromIndex the start index - */ - protected void addCoords(byte[] data, int fromIndex) { - // X/Y POS - for (int i = 0; i < coords.length; i++, fromIndex += 2) { - byte[] coord = BinaryUtils.convert(coords[i], 2); - data[fromIndex] = coord[0]; - data[fromIndex + 1] = coord[1]; - } - } - - /** - * @return the short name of this GOCA object - */ - protected String getName() { - String className = getClass().getName(); - return className.substring(className.lastIndexOf(".") + 1); - } - - /** - * {@inheritDoc} - */ - public String toString() { - String coordsStr = ""; - for (int i = 0; i < coords.length; i++) { - coordsStr += (i % 2 == 0) ? "x" : "y"; - coordsStr += (i / 2) + "=" + coords[i] + ","; - } - coordsStr = coordsStr.substring(0, coordsStr.length() - 1); - return getName() + "(" + coordsStr + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index b064896c7..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.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.render.afp.modca.goca; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.fop.render.afp.modca.AbstractAFPObject; -import org.apache.fop.render.afp.modca.PreparedAFPObject; - -/** - * A base class that carries out early preparation of structured field data - * for the AFP object (so the data length can be pre-calculated) - */ -public abstract class AbstractPreparedAFPObject extends AbstractAFPObject -implements PreparedAFPObject { - - /** structured field data to be written */ - protected byte[] data = null; - - /** - * {@inheritDoc} - */ - public void writeDataStream(OutputStream os) throws IOException { - if (this.data != null) { - os.write(this.data); - } - } - - /** - * @return the data length of this prepared AFP object - */ - public int getDataLength() { - if (this.data != null) { - return this.data.length; - } - return 0; - } -} \ No newline at end of file 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 deleted file mode 100644 index 88173d6d1..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java +++ /dev/null @@ -1,82 +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.goca; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * A GOCA graphics area (container for filled shapes/objects) - */ -public final class GraphicsArea extends AbstractGraphicsContainer { - - /** draw boundary lines around this area */ - private boolean drawBoundary = false; - - /** - * Sets whether boundary lines are drawn - * @param drawBoundaryLines whether boundary lines are drawn - */ - public void setDrawBoundaryLines(boolean drawBoundaryLines) { - this.drawBoundary = drawBoundaryLines; - } - - private static final int RES1 = 1; - private static final int BOUNDARY = 2; - private static final int NO_BOUNDARY = 0; - - /** - * {@inheritDoc} - */ - public int getDataLength() { - // start len + end len + data len - return 4 + super.getDataLength(); - } - - /** - * {@inheritDoc} - */ - protected void writeStart(OutputStream os) throws IOException { - super.writeStart(os); - byte[] data = new byte[] { - (byte)0x68, // GBAR order code - (byte)(RES1 + (drawBoundary ? BOUNDARY : NO_BOUNDARY)) - }; - os.write(data); - } - - /** - * {@inheritDoc} - */ - protected void writeEnd(OutputStream os) throws IOException { - byte[] endData = new byte[] { - (byte)0x60, // GEAR order code - 0x00, // LENGTH - }; - os.write(endData); - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsArea"; - } -} \ No newline at end of file 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 deleted file mode 100644 index ba87dad9f..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java +++ /dev/null @@ -1,66 +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.goca; - -/** - * A GOCA graphics rectangular box - */ -public final class GraphicsBox extends AbstractGraphicsCoord { - - /** - * @param coords the x/y coordinates for this object - */ - public GraphicsBox(int[] coords) { - super(coords); - } - - /** - * {@inheritDoc} - */ - protected byte getOrderCode() { - return (byte)0xC0; - } - - /** - * {@inheritDoc} - */ - protected int getLength() { - return 10; - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - super.data = createData(); - final int fromIndex = 4; - addCoords(data, fromIndex); - } - - /** - * {@inheritDoc} - */ - protected byte[] createData() { - byte[] data = super.createData(); - data[2] = (byte)0x20; // CONTROL draw control flags - data[3] = 0x00; // reserved - return data; - } -} \ No newline at end of file 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 deleted file mode 100644 index 4485370b9..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java +++ /dev/null @@ -1,179 +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.goca; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.fop.render.afp.modca.PreparedAFPObject; -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * A GOCA graphics segment - */ -public final class GraphicsChainedSegment extends AbstractGraphicsContainer { - - /** - * The maximum segment data length - */ - protected static final int MAX_DATA_LEN = 8192; - - /** the current area */ - private GraphicsArea currentArea = null; - - /** the previous segment in the chain */ - private GraphicsChainedSegment previous = null; - - /** the next segment in the chain */ - private GraphicsChainedSegment next = null; - - /** - * Main constructor - * - * @param name - * the name of this graphics segment - */ - public GraphicsChainedSegment(String name) { - super(name); - } - - /** - * Constructor - * - * @param name - * the name of this graphics segment - * @param previous - * the previous graphics segment in this chain - */ - public GraphicsChainedSegment(String name, GraphicsChainedSegment previous) { - super(name); - previous.next = this; - this.previous = previous; - } - - /** - * {@inheritDoc} - */ - public int getDataLength() { - int dataLen = 14 + super.getDataLength(); - if (previous == null) { - GraphicsChainedSegment current = this.next; - while (current != null) { - dataLen += current.getDataLength(); - current = current.next; - } - } - return dataLen; - } - - /** - * {@inheritDoc} - */ - protected int getNameLength() { - return 4; - } - - private static final byte APPEND_NEW_SEGMENT = 0; - - private static final byte PROLOG = 4; - - private static final byte APPEND_TO_EXISING = 48; - - /** - * {@inheritDoc} - */ - protected void writeStart(OutputStream os) throws IOException { - super.writeStart(os); - int len = super.getDataLength(); - byte[] segLen = BinaryUtils.convert(len, 2); - byte[] data = new byte[] { - 0x70, // BEGIN_SEGMENT - 0x0C, // Length of following parameters - this.nameBytes[0], - this.nameBytes[1], - this.nameBytes[2], - this.nameBytes[3], - 0x00, // FLAG1 (ignored) - APPEND_NEW_SEGMENT, - segLen[0], // SEGL - segLen[1], - 0x00, - 0x00, - 0x00, - 0x00 - }; - // P/S NAME (predecessor name) - if (previous != null) { - data[10] = previous.nameBytes[0]; - data[11] = previous.nameBytes[1]; - data[12] = previous.nameBytes[2]; - data[13] = previous.nameBytes[3]; - } - os.write(data); - } - - /** - * {@inheritDoc} - */ - protected void writeEnd(OutputStream os) throws IOException { - // I am the first segment in the chain so write out the rest - if (previous == null) { - GraphicsChainedSegment current = this.next; - while (current != null) { - current.writeDataStream(os); - current = current.next; - } - } - } - - /** - * Begins a graphics area (start of fill) - */ - protected void beginArea() { - this.currentArea = new GraphicsArea(); - super.addDrawingOrder(currentArea); - } - - /** - * Ends a graphics area (end of fill) - */ - protected void endArea() { - this.currentArea = null; - } - - /** - * {@inheritDoc} - */ - protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { - if (currentArea != null) { - currentArea.addDrawingOrder(drawingOrder); - } else { - super.addDrawingOrder(drawingOrder); - } - return drawingOrder; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsChainedSegment(name=" + super.name + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index ccbb537f6..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java +++ /dev/null @@ -1,147 +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.goca; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.fop.render.afp.modca.PreparedAFPObject; -import org.apache.fop.render.afp.tools.BinaryUtils; -import org.apache.fop.render.afp.tools.StringUtils; - -/** - * A GOCA graphics data - */ -public final class GraphicsData extends AbstractGraphicsContainer { - - /** - * The maximum graphics data length - */ - public static final int MAX_DATA_LEN = 32767; - - /** - * Default constructor - */ - public GraphicsData() { - } - - /** - * The graphics segment - */ - private GraphicsChainedSegment currentSegment = null; - - /** - * {@inheritDoc} - */ - public int getDataLength() { - return 8 + super.getDataLength(); - } - - /** - * {@inheritDoc} - */ - protected void writeStart(OutputStream os) throws IOException { - super.writeStart(os); - int l = getDataLength(); - byte[] len = BinaryUtils.convert(l, 2); - byte[] data = new byte[] { - 0x5A, // Structured field identifier - len[0], // Length byte 1 - len[1], // Length byte 2 - (byte) 0xD3, // Structured field id byte 1 - (byte) 0xEE, // Structured field id byte 2 - (byte) 0xBB, // Structured field id byte 3 - 0x00, // Flags - 0x00, // Reserved - 0x00 // Reserved - }; - os.write(data); - } - - /** - * Begins a graphics area (start of fill) - */ - public void beginArea() { - getSegment().beginArea(); - } - - /** - * Ends a graphics area (end of fill) - */ - public void endArea() { - getSegment().endArea(); - } - - /** - * Returns a new segment name - * @return a new segment name - */ - private String createSegmentName() { - return StringUtils.lpad(String.valueOf( - (super.list != null ? super.list.size() : 0) + 1), - '0', 4); - } - - /** - * Returns the current graphics segment, creating one if one does not exist - * @return the current graphics chained segment - */ - GraphicsChainedSegment getSegment() { - if (currentSegment == null) { - newSegment(); - } - return this.currentSegment; - } - - /** - * Creates a new graphics segment - * @return a newly created graphics segment - */ - public GraphicsChainedSegment newSegment() { - String name = createSegmentName(); - if (currentSegment == null) { - this.currentSegment = new GraphicsChainedSegment(name); - } else { - this.currentSegment = new GraphicsChainedSegment(name, currentSegment); - } - super.addDrawingOrder(currentSegment); - return currentSegment; - } - - /** - * {@inheritDoc} - */ - public PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { - if (currentSegment == null - || (currentSegment.getDataLength() + drawingOrder.getDataLength()) - >= GraphicsChainedSegment.MAX_DATA_LEN) { - newSegment(); - } - currentSegment.addDrawingOrder(drawingOrder); - return drawingOrder; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsData"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 1bac5b149..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java +++ /dev/null @@ -1,41 +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.goca; - -/** - * A GOCA graphics curved tangential line to a specified set of - * straight lines drawn from the given position or current position - */ -public final class GraphicsFillet extends AbstractGraphicsCoord { - - /** - * @param coords the x/y coordinates for this object - */ - public GraphicsFillet(int[] coords) { - super(coords); - } - - /** - * {@inheritDoc} - */ - protected byte getOrderCode() { - return (byte)0xC5; - } -} \ No newline at end of file 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 deleted file mode 100644 index 43f0d370d..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java +++ /dev/null @@ -1,81 +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.goca; - -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * A GOCA graphics arc (circle/ellipse) - */ -public class GraphicsFullArc extends AbstractGraphicsCoord { - /** the integer portion of the multiplier */ - private int mh; - - /** the fractional portion of the multiplier */ - private int mhr; - - /** - * @param x the x coordinate of the center of the circle/ellipse - * @param y the y coordinate of the center of the circle/ellipse - * @param mh the integer portion of the multiplier - * @param mhr the fractional portion of the multiplier - */ - public GraphicsFullArc(int x, int y, int mh, int mhr) { - super(x, y); - this.mh = mh; - this.mhr = mhr; - // integer portion of multiplier - data[data.length - 2] = BinaryUtils.convert(mh, 1)[0]; - // fractional portion of multiplier - data[data.length - 1] = BinaryUtils.convert(mhr, 1)[0]; - } - - /** - * {@inheritDoc} - */ - protected byte getOrderCode() { - return (byte)0xC7; - } - - /** - * {@inheritDoc} - */ - protected int getLength() { - return super.getLength() + 2; - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - super.data = super.createData(); - final int fromIndex = 2; - super.addCoords(data, fromIndex); - } - - /** - * {@inheritDoc} - */ - public String toString() { - return super.getName() - + "(centerx=" + coords[0] + ",centery=" + coords[1] - + ",mh=" + mh + ",mhr=" + mhr + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index e37b4b196..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java +++ /dev/null @@ -1,85 +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.goca; - -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * A GOCA graphics begin image object - */ -public final class GraphicsImageBegin extends AbstractPreparedAFPObject { - /** x coordinate */ - private int x; - - /** y coordinate */ - private int y; - - /** width */ - private int width; - - /** height */ - private int height; - - /** - * @param x the x coordinate of the image - * @param y the y coordinate of the image - * @param width the image width - * @param height the image height - */ - public GraphicsImageBegin(int x, int y, int width, int height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - prepareData(); - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - byte[] xcoord = BinaryUtils.convert(x, 2); - byte[] ycoord = BinaryUtils.convert(y, 2); - byte[] w = BinaryUtils.convert(width, 2); - byte[] h = BinaryUtils.convert(height, 2); - super.data = new byte[] { - (byte) 0xD1, // GBIMG order code - (byte) 0x0A, // LENGTH - xcoord[0], - xcoord[1], - ycoord[0], - ycoord[1], - 0x00, // FORMAT - 0x00, // RES - w[0], // WIDTH - w[1], // - h[0], // HEIGHT - h[1] // - }; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsImageBegin(x=" + x + ",y=" + y - + ",width=" + width + ",height=" + height + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 38b81ecd6..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.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.render.afp.modca.goca; - -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * A GOCA graphics image data - */ -public final class GraphicsImageData extends AbstractPreparedAFPObject { - - /** the maximum image data length */ - public static final short MAX_DATA_LEN = 255; - - /** - * Main constructor - * - * @param imageData the image data - * @param startIndex the start index to read the image data from - */ - public GraphicsImageData(byte[] imageData, int startIndex) { - int dataLen = MAX_DATA_LEN; - if (startIndex + MAX_DATA_LEN >= imageData.length) { - dataLen = imageData.length - startIndex - 1; - } - super.data = new byte[dataLen + 2]; - data[0] = (byte) 0x92; // GIMD - data[1] = BinaryUtils.convert(dataLen, 1)[0]; // LENGTH - System.arraycopy(imageData, startIndex, data, 2, dataLen); - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsImageData(" - + (data != null ? "" + (data.length - 2) : "null") - + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 40a518c4b..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java +++ /dev/null @@ -1,50 +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.goca; - -/** - * A GOCA graphics image data - */ -public class GraphicsImageEnd extends AbstractPreparedAFPObject { - - /** - * Default constructor - */ - public GraphicsImageEnd() { - prepareData(); - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - super.data = new byte[] { - (byte) 0x93, // GEIMG order code - 0x00 // LENGTH - }; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsImageEnd"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 07127c387..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java +++ /dev/null @@ -1,42 +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.goca; - - -/** - * A GOCA graphics straight line drawn from the - * given position or current position. - */ -public class GraphicsLine extends AbstractGraphicsCoord { - - /** - * @param coords the x/y coordinates for this object - */ - public GraphicsLine(int[] coords) { - super(coords); - } - - /** - * {@inheritDoc} - */ - protected byte getOrderCode() { - return (byte)0xC1; - } -} \ No newline at end of file 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 deleted file mode 100644 index d39e1e167..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.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.render.afp.modca.goca; - -/** - * Sets the arc parameters for a GOCA graphics arc (circle/ellipse) - */ -public class GraphicsSetArcParameters extends AbstractGraphicsCoord { - - /** - * @param xmaj x coordinate of the major axis point - * @param ymin y coordinate of the minor axis point - * @param xmin x coordinate of the minor axis point - * @param ymaj y coordinate of the major axis point - */ - public GraphicsSetArcParameters(int xmaj, int ymin, int xmin, int ymaj) { - super(xmaj, ymin, xmin, ymaj); - } - - /** - * {@inheritDoc} - */ - protected byte getOrderCode() { - return 0x22; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return getName() + "(xmaj=" + coords[0] - + ",ymin=" + coords[1] - + ",xmin=" + coords[2] - + ",ymaj=" + coords[3] + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index aeca3e9c5..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java +++ /dev/null @@ -1,55 +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.goca; - -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * Sets the current character set (font) to be used for following graphics strings - */ -public class GraphicsSetCharacterSet extends AbstractPreparedAFPObject { - /** font character set reference */ - private int fontReference; - - /** - * @param fontReference character set font reference - */ - public GraphicsSetCharacterSet(int fontReference) { - this.fontReference = fontReference; - prepareData(); - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - super.data = new byte[] { - 0x38, // GSCS order code - BinaryUtils.convert(fontReference)[0] - }; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsSetCharacterSet(" + fontReference + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 91597e8e3..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java +++ /dev/null @@ -1,41 +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.goca; - - -/** - * Sets the current painting position of the graphics object - */ -public class GraphicsSetCurrentPosition extends AbstractGraphicsCoord { - - /** - * @param coords the x/y coordinates for this object - */ - public GraphicsSetCurrentPosition(int[] coords) { - super(coords); - } - - /** - * {@inheritDoc} - */ - protected byte getOrderCode() { - return (byte)0x21; - } -} \ No newline at end of file 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 deleted file mode 100644 index 339902e2c..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java +++ /dev/null @@ -1,86 +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.goca; - -/** - * Sets the value of the current line type attribute when stroking GOCA shapes (structured fields) - */ -public class GraphicsSetLineType extends AbstractPreparedAFPObject { - /** the default line type */ - public static final byte DEFAULT = 0x00; // normally SOLID - - /** the default line type */ - public static final byte DOTTED = 0x01; - - /** short dashed line type */ - public static final byte SHORT_DASHED = 0x02; - - /** dashed dotted line type */ - public static final byte DASH_DOT = 0x03; - - /** double dotted line type */ - public static final byte DOUBLE_DOTTED = 0x04; - - /** long dashed line type */ - public static final byte LONG_DASHED = 0x05; - - /** dash double dotted line type */ - public static final byte DASH_DOUBLE_DOTTED = 0x06; - - /** solid line type */ - public static final byte SOLID = 0x07; - - /** invisible line type */ - public static final byte INVISIBLE = 0x08; - - /** line type */ - private byte type = DEFAULT; - - /** - * Main constructor - * @param type line type - */ - public GraphicsSetLineType(byte type) { - this.type = type; - prepareData(); - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - super.data = new byte[] { - 0x18, // GSLW order code - type // line type - }; - } - - private static final String[] TYPES = { - "DEFAULT", "DOTTED", "SHORT_DASHED", "DASH_DOT", "DOUBLE_DOTTED", - "LONG_DASHED", "DASH_DOUBLE_DOTTED", "SOLID", "INVISIBLE" - }; - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsSetLineType(type=" + TYPES[type] + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 0cd077567..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java +++ /dev/null @@ -1,54 +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.goca; - -/** - * Sets the line width to use when stroking GOCA shapes (structured fields) - */ -public class GraphicsSetLineWidth extends AbstractPreparedAFPObject { - /** line width multiplier */ - private int multiplier = 1; - - /** - * Main constructor - * @param multiplier the line width multiplier - */ - public GraphicsSetLineWidth(int multiplier) { - this.multiplier = multiplier; - prepareData(); - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - super.data = new byte[] { - 0x19, // GSLW order code - (byte)multiplier // MH (line-width) - }; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsSetLineWidth(multiplier=" + multiplier + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 23c0ac73c..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java +++ /dev/null @@ -1,106 +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.goca; - -/** - * Sets the pattern symbol to use when filling following GOCA structured fields - */ -public class GraphicsSetPatternSymbol extends AbstractPreparedAFPObject { - /** dotted density 1 */ - public static final byte DOTTED_DENSITY_1 = 0x01; - - /** dotted density 2 */ - public static final byte DOTTED_DENSITY_2 = 0x02; - - /** dotted density 3 */ - public static final byte DOTTED_DENSITY_3 = 0x03; - - /** dotted density 4 */ - public static final byte DOTTED_DENSITY_4 = 0x04; - - /** dotted density 5 */ - public static final byte DOTTED_DENSITY_5 = 0x05; - - /** dotted density 6 */ - public static final byte DOTTED_DENSITY_6 = 0x06; - - /** dotted density 7 */ - public static final byte DOTTED_DENSITY_7 = 0x07; - - /** dotted density 8 */ - public static final byte DOTTED_DENSITY_8 = 0x08; - - /** dotted density 9 */ - public static final byte VERTICAL_LINES = 0x09; - - /** horizontal lines */ - public static final byte HORIZONTAL_LINES = 0x0A; - - /** diagonal lines, bottom left to top right 1 */ - public static final byte DIAGONAL_LINES_BLTR_1 = 0x0B; - - /** diagonal lines, bottom left to top right 2 */ - public static final byte DIAGONAL_LINES_BLTR_2 = 0x0C; - - /** diagonal lines, top left to bottom right 1 */ - public static final byte DIAGONAL_LINES_TLBR_1 = 0x0D; - - /** diagonal lines, top left to bottom right 2 */ - public static final byte DIAGONAL_LINES_TLBR_2 = 0x0E; - - /** no fill */ - public static final byte NO_FILL = 0x0F; - - /** solid fill */ - public static final byte SOLID_FILL = 0x10; - - /** blank (same as no fill) */ - public static final byte BLANK = 0x40; // processed same as NO_FILL - - /** the graphics pattern symbol to use */ - private byte symbol; - - /** - * Main constructor - * @param symb the pattern symbol to use - */ - public GraphicsSetPatternSymbol(byte symb) { - this.symbol = symb; - prepareData(); - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - super.data = new byte[] { - 0x28, // GSPT order code - symbol - }; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsSetPatternSymbol(fill=" - + (symbol == SOLID_FILL ? true : false) + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 51153f065..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java +++ /dev/null @@ -1,92 +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.goca; - -import java.awt.Color; -import java.awt.color.ColorSpace; - -import org.apache.fop.render.afp.modca.GraphicsObject; - -/** - * Sets the current processing color for the following GOCA structured fields - */ -public class GraphicsSetProcessColor extends AbstractPreparedAFPObject { - /** the color to set */ - private Color col; - - /** - * Main constructor - * @param col the color to set - */ - public GraphicsSetProcessColor(Color col) { - this.col = col; - prepareData(); - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - // COLSPCE - byte colspace; - int colSpaceType = col.getColorSpace().getType(); - if (colSpaceType == ColorSpace.TYPE_CMYK) { - colspace = 0x04; - } else if (colSpaceType == ColorSpace.TYPE_RGB) { - colspace = 0x01; - } else { - GraphicsObject.log.error("unsupported colorspace " + colSpaceType); - colspace = 0x01; - } - - // COLSIZE(S) - float[] colcomp = col.getColorComponents(null); - byte[] colsizes = new byte[] {0x00, 0x00, 0x00, 0x00}; - for (int i = 0; i < colcomp.length; i++) { - colsizes[i] = (byte)8; - } - - int len = 10 + colcomp.length; - super.data = new byte[len + 2]; - data[0] = (byte)0xB2; // GSPCOL order code - data[1] = (byte)len; // LEN - data[2] = 0x00; // reserved; must be zero - data[3] = colspace; // COLSPCE - data[4] = 0x00; // reserved; must be zero - data[5] = 0x00; // reserved; must be zero - data[6] = 0x00; // reserved; must be zero - data[7] = 0x00; // reserved; must be zero - data[8] = colsizes[0]; // COLSIZE(S) - data[9] = colsizes[1]; - data[10] = colsizes[2]; - data[11] = colsizes[3]; - // COLVALUE(S) - for (int i = 0; i < colcomp.length; i++) { - data[i + 12] = (byte)(colcomp[i] * 255); - } - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "GraphicsSetProcessColor(col=" + col + ")"; - } -} \ No newline at end of file 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 deleted file mode 100644 index 7033ce92f..000000000 --- a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.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.render.afp.modca.goca; - -import java.io.UnsupportedEncodingException; - -import org.apache.fop.render.afp.modca.AFPConstants; -import org.apache.fop.render.afp.modca.GraphicsObject; -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * A GOCA graphics string - */ -public class GraphicsString extends AbstractPreparedAFPObject { - /** Up to 255 bytes of character data */ - private static final int MAX_STR_LEN = 255; - - /** drawn from the current position */ - private boolean fromCurrentPosition = false; - - /** the string to draw */ - private String str = null; - - /** x coordinate */ - private int x; - - /** y coordinate */ - private int y; - - /** - * @param str the character string - */ - public GraphicsString(String str) { - this.str = str; - fromCurrentPosition = true; - prepareData(); - } - - /** - * @param str the character string - * @param x the x coordinate - * @param y the y coordinate - */ - public GraphicsString(String str, int x, int y) { - this.str = str; - this.x = x; - this.y = y; - prepareData(); - } - - /** - * {@inheritDoc} - */ - protected void prepareData() { - int maxStrLen = MAX_STR_LEN - (fromCurrentPosition ? 0 : 4); - if (str.length() > maxStrLen) { - str = str.substring(0, maxStrLen); - log.warn("truncated character string, longer than " + maxStrLen + " chars"); - } - byte[] strData = null; - try { - strData = str.getBytes(AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException ex) { - GraphicsObject.log.error("unsupported encoding: " + ex.getMessage()); - } - int len = strData.length; - if (fromCurrentPosition) { - data = new byte[len + 2]; - data[0] = (byte)0x83; - data[1] = (byte)len; - System.arraycopy(strData, 0, data, 2, strData.length); - } else { - len += 4; // x/y coordinates - byte[] osx = BinaryUtils.convert(x, 2); - byte[] osy = BinaryUtils.convert(y, 2); - data = new byte[len + 2]; - data[0] = (byte)0xC3; - data[1] = (byte)len; - data[2] = osx[0]; - data[3] = osx[1]; - data[4] = osy[0]; - data[5] = osy[1]; - System.arraycopy(strData, 0, data, 6, strData.length); - } - } - - /** - * {@inheritDoc} - */ - public String toString() { - String string = "GraphicsString(str='" + str + "'"; - if (!fromCurrentPosition) { - string += ",x=" + x + ",y=" + y; - } - string += ")"; - return string; - } -} \ No newline at end of file -- cgit v1.2.3 From 1105f2129784f6d85485ad222bdbc835473ee7ca Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 27 Mar 2008 16:12:00 +0000 Subject: Moved goca package to level above modca. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@641870 13f79535-47bb-0310-9956-ffa450edef68 --- .../render/afp/goca/AbstractGraphicsContainer.java | 95 +++++++++++ .../fop/render/afp/goca/AbstractGraphicsCoord.java | 127 +++++++++++++++ .../apache/fop/render/afp/goca/GraphicsArea.java | 82 ++++++++++ .../apache/fop/render/afp/goca/GraphicsBox.java | 66 ++++++++ .../render/afp/goca/GraphicsChainedSegment.java | 179 +++++++++++++++++++++ .../apache/fop/render/afp/goca/GraphicsData.java | 141 ++++++++++++++++ .../apache/fop/render/afp/goca/GraphicsFillet.java | 41 +++++ .../fop/render/afp/goca/GraphicsFullArc.java | 81 ++++++++++ .../fop/render/afp/goca/GraphicsImageBegin.java | 86 ++++++++++ .../fop/render/afp/goca/GraphicsImageData.java | 58 +++++++ .../fop/render/afp/goca/GraphicsImageEnd.java | 52 ++++++ .../apache/fop/render/afp/goca/GraphicsLine.java | 42 +++++ .../render/afp/goca/GraphicsSetArcParameters.java | 53 ++++++ .../render/afp/goca/GraphicsSetCharacterSet.java | 56 +++++++ .../afp/goca/GraphicsSetCurrentPosition.java | 41 +++++ .../fop/render/afp/goca/GraphicsSetLineType.java | 88 ++++++++++ .../fop/render/afp/goca/GraphicsSetLineWidth.java | 56 +++++++ .../render/afp/goca/GraphicsSetPatternSymbol.java | 108 +++++++++++++ .../render/afp/goca/GraphicsSetProcessColor.java | 93 +++++++++++ .../apache/fop/render/afp/goca/GraphicsString.java | 116 +++++++++++++ 20 files changed, 1661 insertions(+) create mode 100644 src/java/org/apache/fop/render/afp/goca/AbstractGraphicsContainer.java create mode 100644 src/java/org/apache/fop/render/afp/goca/AbstractGraphicsCoord.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsArea.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsBox.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsData.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsFillet.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsFullArc.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsImageBegin.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsImageData.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsImageEnd.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsLine.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsSetArcParameters.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsSetCharacterSet.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsSetCurrentPosition.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsSetLineType.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsSetLineWidth.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsSetPatternSymbol.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsSetProcessColor.java create mode 100644 src/java/org/apache/fop/render/afp/goca/GraphicsString.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsContainer.java b/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsContainer.java new file mode 100644 index 000000000..e6966d5d3 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsContainer.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.render.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.List; + +import org.apache.fop.render.afp.modca.AbstractNamedAFPObject; +import org.apache.fop.render.afp.modca.PreparedAFPObject; + +/** + * A base class container of GOCA structured objects + */ +public abstract class AbstractGraphicsContainer extends AbstractNamedAFPObject +implements PreparedAFPObject { + + /** + * list of objects contained within this container + */ + protected List objects = null; + + /** + * Default constructor + */ + protected AbstractGraphicsContainer() { + } + + /** + * Named constructor + * @param name the name of the container + */ + protected AbstractGraphicsContainer(String name) { + super(name); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + if (objects != null) { + super.writeObjects(objects, os); + } + } + + /** + * Adds a given graphics drawing order to this container + * @param drawingOrder the graphics drawing order + * @return the drawingOrder if it was added, null otherwise + */ + protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { + log.debug(this + " adding " + drawingOrder); + if (objects == null) { + this.objects = new java.util.ArrayList(); + } + objects.add(drawingOrder); + return drawingOrder; + } + + /** + * @return the current data length of this container including + * all enclosed GOCA drawing objects (and their containers) + */ + public int getDataLength() { + int dataLen = 0; + if (objects != null) { + Iterator it = objects.iterator(); + while (it.hasNext()) { + Object obj = it.next(); + if (obj instanceof PreparedAFPObject) { + dataLen += ((PreparedAFPObject)obj).getDataLength(); + } + } + } + return dataLen; + } +} diff --git a/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsCoord.java b/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsCoord.java new file mode 100644 index 000000000..12d6e13a7 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsCoord.java @@ -0,0 +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 org.apache.fop.render.afp.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * A base class encapsulating the structure of coordinate based GOCA objects + */ +public abstract class AbstractGraphicsCoord extends AbstractPreparedAFPObject { + + /** array of x/y coordinates */ + protected int[] coords = null; + + /** + * @param coords the x/y coordinates for this object + */ + public AbstractGraphicsCoord(int[] coords) { + this.coords = coords; + prepareData(); + } + + /** + * @param x the x coordinate for this object + * @param y the y coordinate for this object + */ + public AbstractGraphicsCoord(int x, int y) { + this(new int[] {x, y}); + } + + /** + * @param x1 the x1 coordinate for this object + * @param y1 the y1 coordinate for this object + * @param x2 the x2 coordinate for this object + * @param y2 the y2 coordinate for this object + */ + public AbstractGraphicsCoord(int x1, int y1, int x2, int y2) { + this(new int[] {x1, y1, x2, y2}); + } + + /** + * @return the order code to use + */ + protected abstract byte getOrderCode(); + + /** + * @return the length of this order code + * (typically this is the same as the coordinate length) + */ + protected int getLength() { + return this.coords.length * 2; + } + + /** + * Creates a newly created and initialized byte data + * @return a newly created and initialized byte data + */ + protected byte[] createData() { + int len = getLength(); + byte[] data = new byte[len + 2]; + data[0] = getOrderCode(); // ORDER CODE + data[1] = (byte)len; // LENGTH + return data; + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + super.data = createData(); + int fromIndex = data.length - getLength(); + addCoords(data, fromIndex); + } + + /** + * Adds the coordinates to the structured field data + * @param data the structured field data + * @param fromIndex the start index + */ + protected void addCoords(byte[] data, int fromIndex) { + // X/Y POS + for (int i = 0; i < coords.length; i++, fromIndex += 2) { + byte[] coord = BinaryUtils.convert(coords[i], 2); + data[fromIndex] = coord[0]; + data[fromIndex + 1] = coord[1]; + } + } + + /** + * @return the short name of this GOCA object + */ + public String getName() { + String className = getClass().getName(); + return className.substring(className.lastIndexOf(".") + 1); + } + + /** + * {@inheritDoc} + */ + public String toString() { + String coordsStr = ""; + for (int i = 0; i < coords.length; i++) { + coordsStr += (i % 2 == 0) ? "x" : "y"; + coordsStr += (i / 2) + "=" + coords[i] + ","; + } + coordsStr = coordsStr.substring(0, coordsStr.length() - 1); + return getName() + "(" + coordsStr + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsArea.java b/src/java/org/apache/fop/render/afp/goca/GraphicsArea.java new file mode 100644 index 000000000..c0d1040c8 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsArea.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.render.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * A GOCA graphics area (container for filled shapes/objects) + */ +public final class GraphicsArea extends AbstractGraphicsContainer { + + /** draw boundary lines around this area */ + private boolean drawBoundary = false; + + /** + * Sets whether boundary lines are drawn + * @param drawBoundaryLines whether boundary lines are drawn + */ + public void setDrawBoundaryLines(boolean drawBoundaryLines) { + this.drawBoundary = drawBoundaryLines; + } + + private static final int RES1 = 1; + private static final int BOUNDARY = 2; + private static final int NO_BOUNDARY = 0; + + /** + * {@inheritDoc} + */ + public int getDataLength() { + // start len + end len + data len + return 4 + super.getDataLength(); + } + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + byte[] data = new byte[] { + (byte)0x68, // GBAR order code + (byte)(RES1 + (drawBoundary ? BOUNDARY : NO_BOUNDARY)) + }; + os.write(data); + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] endData = new byte[] { + (byte)0x60, // GEAR order code + 0x00, // LENGTH + }; + os.write(endData); + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsArea"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsBox.java b/src/java/org/apache/fop/render/afp/goca/GraphicsBox.java new file mode 100644 index 000000000..8f1bc2378 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsBox.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.afp.goca; + +/** + * A GOCA graphics rectangular box + */ +public final class GraphicsBox extends AbstractGraphicsCoord { + + /** + * @param coords the x/y coordinates for this object + */ + public GraphicsBox(int[] coords) { + super(coords); + } + + /** + * {@inheritDoc} + */ + protected byte getOrderCode() { + return (byte)0xC0; + } + + /** + * {@inheritDoc} + */ + protected int getLength() { + return 10; + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + super.data = createData(); + final int fromIndex = 4; + addCoords(data, fromIndex); + } + + /** + * {@inheritDoc} + */ + protected byte[] createData() { + byte[] data = super.createData(); + data[2] = (byte)0x20; // CONTROL draw control flags + data[3] = 0x00; // reserved + return data; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java b/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java new file mode 100644 index 000000000..f63aff1ea --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java @@ -0,0 +1,179 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.goca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.render.afp.modca.PreparedAFPObject; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * A GOCA graphics segment + */ +public final class GraphicsChainedSegment extends AbstractGraphicsContainer { + + /** + * The maximum segment data length + */ + protected static final int MAX_DATA_LEN = 8192; + + /** the current area */ + private GraphicsArea currentArea = null; + + /** the previous segment in the chain */ + private GraphicsChainedSegment previous = null; + + /** the next segment in the chain */ + private GraphicsChainedSegment next = null; + + /** + * Main constructor + * + * @param name + * the name of this graphics segment + */ + public GraphicsChainedSegment(String name) { + super(name); + } + + /** + * Constructor + * + * @param name + * the name of this graphics segment + * @param previous + * the previous graphics segment in this chain + */ + public GraphicsChainedSegment(String name, GraphicsChainedSegment previous) { + super(name); + previous.next = this; + this.previous = previous; + } + + /** + * {@inheritDoc} + */ + public int getDataLength() { + int dataLen = 14 + super.getDataLength(); + if (previous == null) { + GraphicsChainedSegment current = this.next; + while (current != null) { + dataLen += current.getDataLength(); + current = current.next; + } + } + return dataLen; + } + + /** + * {@inheritDoc} + */ + protected int getNameLength() { + return 4; + } + + private static final byte APPEND_NEW_SEGMENT = 0; + + private static final byte PROLOG = 4; + + private static final byte APPEND_TO_EXISING = 48; + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + int len = super.getDataLength(); + byte[] segLen = BinaryUtils.convert(len, 2); + byte[] data = new byte[] { + 0x70, // BEGIN_SEGMENT + 0x0C, // Length of following parameters + this.nameBytes[0], + this.nameBytes[1], + this.nameBytes[2], + this.nameBytes[3], + 0x00, // FLAG1 (ignored) + APPEND_NEW_SEGMENT, + segLen[0], // SEGL + segLen[1], + 0x00, + 0x00, + 0x00, + 0x00 + }; + // P/S NAME (predecessor name) + if (previous != null) { + data[10] = previous.nameBytes[0]; + data[11] = previous.nameBytes[1]; + data[12] = previous.nameBytes[2]; + data[13] = previous.nameBytes[3]; + } + os.write(data); + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(OutputStream os) throws IOException { + // I am the first segment in the chain so write out the rest + if (previous == null) { + GraphicsChainedSegment current = this.next; + while (current != null) { + current.writeDataStream(os); + current = current.next; + } + } + } + + /** + * Begins a graphics area (start of fill) + */ + protected void beginArea() { + this.currentArea = new GraphicsArea(); + super.addDrawingOrder(currentArea); + } + + /** + * Ends a graphics area (end of fill) + */ + protected void endArea() { + this.currentArea = null; + } + + /** + * {@inheritDoc} + */ + protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { + if (currentArea != null) { + currentArea.addDrawingOrder(drawingOrder); + } else { + super.addDrawingOrder(drawingOrder); + } + return drawingOrder; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsChainedSegment(name=" + super.getName() + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsData.java b/src/java/org/apache/fop/render/afp/goca/GraphicsData.java new file mode 100644 index 000000000..3c95bb245 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsData.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.goca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.render.afp.modca.PreparedAFPObject; +import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.fop.render.afp.tools.StringUtils; + +/** + * A GOCA graphics data + */ +public final class GraphicsData extends AbstractGraphicsContainer { + + /** + * The maximum graphics data length + */ + public static final int MAX_DATA_LEN = 32767; + + /** + * The graphics segment + */ + private GraphicsChainedSegment currentSegment = null; + + /** + * {@inheritDoc} + */ + public int getDataLength() { + return 8 + super.getDataLength(); + } + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + int l = getDataLength(); + byte[] len = BinaryUtils.convert(l, 2); + byte[] data = new byte[] { + 0x5A, // Structured field identifier + len[0], // Length byte 1 + len[1], // Length byte 2 + (byte) 0xD3, // Structured field id byte 1 + (byte) 0xEE, // Structured field id byte 2 + (byte) 0xBB, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00 // Reserved + }; + os.write(data); + } + + /** + * Begins a graphics area (start of fill) + */ + public void beginArea() { + getSegment().beginArea(); + } + + /** + * Ends a graphics area (end of fill) + */ + public void endArea() { + getSegment().endArea(); + } + + /** + * Returns a new segment name + * @return a new segment name + */ + private String createSegmentName() { + return StringUtils.lpad(String.valueOf( + (super.objects != null ? super.objects.size() : 0) + 1), + '0', 4); + } + + /** + * Returns the current graphics segment, creating one if one does not exist + * @return the current graphics chained segment + */ + private GraphicsChainedSegment getSegment() { + if (currentSegment == null) { + newSegment(); + } + return this.currentSegment; + } + + /** + * Creates a new graphics segment + * @return a newly created graphics segment + */ + public GraphicsChainedSegment newSegment() { + String name = createSegmentName(); + if (currentSegment == null) { + this.currentSegment = new GraphicsChainedSegment(name); + } else { + this.currentSegment = new GraphicsChainedSegment(name, currentSegment); + } + super.addDrawingOrder(currentSegment); + return currentSegment; + } + + /** + * {@inheritDoc} + */ + public PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { + if (currentSegment == null + || (currentSegment.getDataLength() + drawingOrder.getDataLength()) + >= GraphicsChainedSegment.MAX_DATA_LEN) { + newSegment(); + } + currentSegment.addDrawingOrder(drawingOrder); + return drawingOrder; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsData"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsFillet.java b/src/java/org/apache/fop/render/afp/goca/GraphicsFillet.java new file mode 100644 index 000000000..122dcd04e --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsFillet.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.render.afp.goca; + +/** + * A GOCA graphics curved tangential line to a specified set of + * straight lines drawn from the given position or current position + */ +public final class GraphicsFillet extends AbstractGraphicsCoord { + + /** + * @param coords the x/y coordinates for this object + */ + public GraphicsFillet(int[] coords) { + super(coords); + } + + /** + * {@inheritDoc} + */ + protected byte getOrderCode() { + return (byte)0xC5; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsFullArc.java b/src/java/org/apache/fop/render/afp/goca/GraphicsFullArc.java new file mode 100644 index 000000000..92ce66d88 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsFullArc.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.render.afp.goca; + +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * A GOCA graphics arc (circle/ellipse) + */ +public class GraphicsFullArc extends AbstractGraphicsCoord { + /** the integer portion of the multiplier */ + private int mh; + + /** the fractional portion of the multiplier */ + private int mhr; + + /** + * @param x the x coordinate of the center of the circle/ellipse + * @param y the y coordinate of the center of the circle/ellipse + * @param mh the integer portion of the multiplier + * @param mhr the fractional portion of the multiplier + */ + public GraphicsFullArc(int x, int y, int mh, int mhr) { + super(x, y); + this.mh = mh; + this.mhr = mhr; + // integer portion of multiplier + data[data.length - 2] = BinaryUtils.convert(mh, 1)[0]; + // fractional portion of multiplier + data[data.length - 1] = BinaryUtils.convert(mhr, 1)[0]; + } + + /** + * {@inheritDoc} + */ + protected byte getOrderCode() { + return (byte)0xC7; + } + + /** + * {@inheritDoc} + */ + protected int getLength() { + return super.getLength() + 2; + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + super.data = super.createData(); + final int fromIndex = 2; + super.addCoords(data, fromIndex); + } + + /** + * {@inheritDoc} + */ + public String toString() { + return super.getName() + + "(centerx=" + coords[0] + ",centery=" + coords[1] + + ",mh=" + mh + ",mhr=" + mhr + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsImageBegin.java b/src/java/org/apache/fop/render/afp/goca/GraphicsImageBegin.java new file mode 100644 index 000000000..b55a5139d --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsImageBegin.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * A GOCA graphics begin image object + */ +public final class GraphicsImageBegin extends AbstractPreparedAFPObject { + /** x coordinate */ + private int x; + + /** y coordinate */ + private int y; + + /** width */ + private int width; + + /** height */ + private int height; + + /** + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the image width + * @param height the image height + */ + public GraphicsImageBegin(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + prepareData(); + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + byte[] xcoord = BinaryUtils.convert(x, 2); + byte[] ycoord = BinaryUtils.convert(y, 2); + byte[] w = BinaryUtils.convert(width, 2); + byte[] h = BinaryUtils.convert(height, 2); + super.data = new byte[] { + (byte) 0xD1, // GBIMG order code + (byte) 0x0A, // LENGTH + xcoord[0], + xcoord[1], + ycoord[0], + ycoord[1], + 0x00, // FORMAT + 0x00, // RES + w[0], // WIDTH + w[1], // + h[0], // HEIGHT + h[1] // + }; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsImageBegin(x=" + x + ",y=" + y + + ",width=" + width + ",height=" + height + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsImageData.java b/src/java/org/apache/fop/render/afp/goca/GraphicsImageData.java new file mode 100644 index 000000000..b17c3d7d4 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsImageData.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * A GOCA graphics image data + */ +public final class GraphicsImageData extends AbstractPreparedAFPObject { + + /** the maximum image data length */ + public static final short MAX_DATA_LEN = 255; + + /** + * Main constructor + * + * @param imageData the image data + * @param startIndex the start index to read the image data from + */ + public GraphicsImageData(byte[] imageData, int startIndex) { + int dataLen = MAX_DATA_LEN; + if (startIndex + MAX_DATA_LEN >= imageData.length) { + dataLen = imageData.length - startIndex - 1; + } + super.data = new byte[dataLen + 2]; + data[0] = (byte) 0x92; // GIMD + data[1] = BinaryUtils.convert(dataLen, 1)[0]; // LENGTH + System.arraycopy(imageData, startIndex, data, 2, dataLen); + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsImageData(" + + (data != null ? "" + (data.length - 2) : "null") + + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsImageEnd.java b/src/java/org/apache/fop/render/afp/goca/GraphicsImageEnd.java new file mode 100644 index 000000000..24c272445 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsImageEnd.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.render.afp.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; + +/** + * A GOCA graphics image data + */ +public class GraphicsImageEnd extends AbstractPreparedAFPObject { + + /** + * Default constructor + */ + public GraphicsImageEnd() { + prepareData(); + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + super.data = new byte[] { + (byte) 0x93, // GEIMG order code + 0x00 // LENGTH + }; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsImageEnd"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsLine.java b/src/java/org/apache/fop/render/afp/goca/GraphicsLine.java new file mode 100644 index 000000000..306acb448 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsLine.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.render.afp.goca; + + +/** + * A GOCA graphics straight line drawn from the + * given position or current position. + */ +public class GraphicsLine extends AbstractGraphicsCoord { + + /** + * @param coords the x/y coordinates for this object + */ + public GraphicsLine(int[] coords) { + super(coords); + } + + /** + * {@inheritDoc} + */ + protected byte getOrderCode() { + return (byte)0xC1; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsSetArcParameters.java b/src/java/org/apache/fop/render/afp/goca/GraphicsSetArcParameters.java new file mode 100644 index 000000000..ce9bd1665 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsSetArcParameters.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.afp.goca; + +/** + * Sets the arc parameters for a GOCA graphics arc (circle/ellipse) + */ +public class GraphicsSetArcParameters extends AbstractGraphicsCoord { + + /** + * @param xmaj x coordinate of the major axis point + * @param ymin y coordinate of the minor axis point + * @param xmin x coordinate of the minor axis point + * @param ymaj y coordinate of the major axis point + */ + public GraphicsSetArcParameters(int xmaj, int ymin, int xmin, int ymaj) { + super(xmaj, ymin, xmin, ymaj); + } + + /** + * {@inheritDoc} + */ + protected byte getOrderCode() { + return 0x22; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return getName() + "(xmaj=" + coords[0] + + ",ymin=" + coords[1] + + ",xmin=" + coords[2] + + ",ymaj=" + coords[3] + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsSetCharacterSet.java b/src/java/org/apache/fop/render/afp/goca/GraphicsSetCharacterSet.java new file mode 100644 index 000000000..2671908c9 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsSetCharacterSet.java @@ -0,0 +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.afp.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * Sets the current character set (font) to be used for following graphics strings + */ +public class GraphicsSetCharacterSet extends AbstractPreparedAFPObject { + /** font character set reference */ + private int fontReference; + + /** + * @param fontReference character set font reference + */ + public GraphicsSetCharacterSet(int fontReference) { + this.fontReference = fontReference; + prepareData(); + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + super.data = new byte[] { + 0x38, // GSCS order code + BinaryUtils.convert(fontReference)[0] + }; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsSetCharacterSet(" + fontReference + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsSetCurrentPosition.java b/src/java/org/apache/fop/render/afp/goca/GraphicsSetCurrentPosition.java new file mode 100644 index 000000000..866c37b38 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsSetCurrentPosition.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.render.afp.goca; + + +/** + * Sets the current painting position of the graphics object + */ +public class GraphicsSetCurrentPosition extends AbstractGraphicsCoord { + + /** + * @param coords the x/y coordinates for this object + */ + public GraphicsSetCurrentPosition(int[] coords) { + super(coords); + } + + /** + * {@inheritDoc} + */ + protected byte getOrderCode() { + return (byte)0x21; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsSetLineType.java b/src/java/org/apache/fop/render/afp/goca/GraphicsSetLineType.java new file mode 100644 index 000000000..998304d84 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsSetLineType.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; + +/** + * Sets the value of the current line type attribute when stroking GOCA shapes (structured fields) + */ +public class GraphicsSetLineType extends AbstractPreparedAFPObject { + /** the default line type */ + public static final byte DEFAULT = 0x00; // normally SOLID + + /** the default line type */ + public static final byte DOTTED = 0x01; + + /** short dashed line type */ + public static final byte SHORT_DASHED = 0x02; + + /** dashed dotted line type */ + public static final byte DASH_DOT = 0x03; + + /** double dotted line type */ + public static final byte DOUBLE_DOTTED = 0x04; + + /** long dashed line type */ + public static final byte LONG_DASHED = 0x05; + + /** dash double dotted line type */ + public static final byte DASH_DOUBLE_DOTTED = 0x06; + + /** solid line type */ + public static final byte SOLID = 0x07; + + /** invisible line type */ + public static final byte INVISIBLE = 0x08; + + /** line type */ + private byte type = DEFAULT; + + /** + * Main constructor + * @param type line type + */ + public GraphicsSetLineType(byte type) { + this.type = type; + prepareData(); + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + super.data = new byte[] { + 0x18, // GSLW order code + type // line type + }; + } + + private static final String[] TYPES = { + "DEFAULT", "DOTTED", "SHORT_DASHED", "DASH_DOT", "DOUBLE_DOTTED", + "LONG_DASHED", "DASH_DOUBLE_DOTTED", "SOLID", "INVISIBLE" + }; + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsSetLineType(type=" + TYPES[type] + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsSetLineWidth.java b/src/java/org/apache/fop/render/afp/goca/GraphicsSetLineWidth.java new file mode 100644 index 000000000..b526f4385 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsSetLineWidth.java @@ -0,0 +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.afp.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; + +/** + * Sets the line width to use when stroking GOCA shapes (structured fields) + */ +public class GraphicsSetLineWidth extends AbstractPreparedAFPObject { + /** line width multiplier */ + private int multiplier = 1; + + /** + * Main constructor + * @param multiplier the line width multiplier + */ + public GraphicsSetLineWidth(int multiplier) { + this.multiplier = multiplier; + prepareData(); + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + super.data = new byte[] { + 0x19, // GSLW order code + (byte)multiplier // MH (line-width) + }; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsSetLineWidth(multiplier=" + multiplier + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsSetPatternSymbol.java b/src/java/org/apache/fop/render/afp/goca/GraphicsSetPatternSymbol.java new file mode 100644 index 000000000..eddb531ed --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsSetPatternSymbol.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; + +/** + * Sets the pattern symbol to use when filling following GOCA structured fields + */ +public class GraphicsSetPatternSymbol extends AbstractPreparedAFPObject { + /** dotted density 1 */ + public static final byte DOTTED_DENSITY_1 = 0x01; + + /** dotted density 2 */ + public static final byte DOTTED_DENSITY_2 = 0x02; + + /** dotted density 3 */ + public static final byte DOTTED_DENSITY_3 = 0x03; + + /** dotted density 4 */ + public static final byte DOTTED_DENSITY_4 = 0x04; + + /** dotted density 5 */ + public static final byte DOTTED_DENSITY_5 = 0x05; + + /** dotted density 6 */ + public static final byte DOTTED_DENSITY_6 = 0x06; + + /** dotted density 7 */ + public static final byte DOTTED_DENSITY_7 = 0x07; + + /** dotted density 8 */ + public static final byte DOTTED_DENSITY_8 = 0x08; + + /** dotted density 9 */ + public static final byte VERTICAL_LINES = 0x09; + + /** horizontal lines */ + public static final byte HORIZONTAL_LINES = 0x0A; + + /** diagonal lines, bottom left to top right 1 */ + public static final byte DIAGONAL_LINES_BLTR_1 = 0x0B; + + /** diagonal lines, bottom left to top right 2 */ + public static final byte DIAGONAL_LINES_BLTR_2 = 0x0C; + + /** diagonal lines, top left to bottom right 1 */ + public static final byte DIAGONAL_LINES_TLBR_1 = 0x0D; + + /** diagonal lines, top left to bottom right 2 */ + public static final byte DIAGONAL_LINES_TLBR_2 = 0x0E; + + /** no fill */ + public static final byte NO_FILL = 0x0F; + + /** solid fill */ + public static final byte SOLID_FILL = 0x10; + + /** blank (same as no fill) */ + public static final byte BLANK = 0x40; // processed same as NO_FILL + + /** the graphics pattern symbol to use */ + private byte symbol; + + /** + * Main constructor + * @param symb the pattern symbol to use + */ + public GraphicsSetPatternSymbol(byte symb) { + this.symbol = symb; + prepareData(); + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + super.data = new byte[] { + 0x28, // GSPT order code + symbol + }; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsSetPatternSymbol(fill=" + + (symbol == SOLID_FILL ? true : false) + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsSetProcessColor.java b/src/java/org/apache/fop/render/afp/goca/GraphicsSetProcessColor.java new file mode 100644 index 000000000..e0dc9ed13 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsSetProcessColor.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.goca; + +import java.awt.Color; +import java.awt.color.ColorSpace; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; +import org.apache.fop.render.afp.modca.GraphicsObject; + +/** + * Sets the current processing color for the following GOCA structured fields + */ +public class GraphicsSetProcessColor extends AbstractPreparedAFPObject { + /** the color to set */ + private Color col; + + /** + * Main constructor + * @param col the color to set + */ + public GraphicsSetProcessColor(Color col) { + this.col = col; + prepareData(); + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + // COLSPCE + byte colspace; + int colSpaceType = col.getColorSpace().getType(); + if (colSpaceType == ColorSpace.TYPE_CMYK) { + colspace = 0x04; + } else if (colSpaceType == ColorSpace.TYPE_RGB) { + colspace = 0x01; + } else { + GraphicsObject.log.error("unsupported colorspace " + colSpaceType); + colspace = 0x01; + } + + // COLSIZE(S) + float[] colcomp = col.getColorComponents(null); + byte[] colsizes = new byte[] {0x00, 0x00, 0x00, 0x00}; + for (int i = 0; i < colcomp.length; i++) { + colsizes[i] = (byte)8; + } + + int len = 10 + colcomp.length; + super.data = new byte[len + 2]; + data[0] = (byte)0xB2; // GSPCOL order code + data[1] = (byte)len; // LEN + data[2] = 0x00; // reserved; must be zero + data[3] = colspace; // COLSPCE + data[4] = 0x00; // reserved; must be zero + data[5] = 0x00; // reserved; must be zero + data[6] = 0x00; // reserved; must be zero + data[7] = 0x00; // reserved; must be zero + data[8] = colsizes[0]; // COLSIZE(S) + data[9] = colsizes[1]; + data[10] = colsizes[2]; + data[11] = colsizes[3]; + // COLVALUE(S) + for (int i = 0; i < colcomp.length; i++) { + data[i + 12] = (byte)(colcomp[i] * 255); + } + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "GraphicsSetProcessColor(col=" + col + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsString.java b/src/java/org/apache/fop/render/afp/goca/GraphicsString.java new file mode 100644 index 000000000..fdeeea5bb --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsString.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.render.afp.goca; + +import java.io.UnsupportedEncodingException; + +import org.apache.fop.render.afp.modca.AFPConstants; +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; +import org.apache.fop.render.afp.modca.GraphicsObject; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * A GOCA graphics string + */ +public class GraphicsString extends AbstractPreparedAFPObject { + /** Up to 255 bytes of character data */ + private static final int MAX_STR_LEN = 255; + + /** drawn from the current position */ + private boolean fromCurrentPosition = false; + + /** the string to draw */ + private String str = null; + + /** x coordinate */ + private int x; + + /** y coordinate */ + private int y; + + /** + * @param str the character string + */ + public GraphicsString(String str) { + this.str = str; + fromCurrentPosition = true; + prepareData(); + } + + /** + * @param str the character string + * @param x the x coordinate + * @param y the y coordinate + */ + public GraphicsString(String str, int x, int y) { + this.str = str; + this.x = x; + this.y = y; + prepareData(); + } + + /** + * {@inheritDoc} + */ + protected void prepareData() { + int maxStrLen = MAX_STR_LEN - (fromCurrentPosition ? 0 : 4); + if (str.length() > maxStrLen) { + str = str.substring(0, maxStrLen); + log.warn("truncated character string, longer than " + maxStrLen + " chars"); + } + byte[] strData = null; + try { + strData = str.getBytes(AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException ex) { + GraphicsObject.log.error("unsupported encoding: " + ex.getMessage()); + } + int len = strData.length; + if (fromCurrentPosition) { + data = new byte[len + 2]; + data[0] = (byte)0x83; + data[1] = (byte)len; + System.arraycopy(strData, 0, data, 2, strData.length); + } else { + len += 4; // x/y coordinates + byte[] osx = BinaryUtils.convert(x, 2); + byte[] osy = BinaryUtils.convert(y, 2); + data = new byte[len + 2]; + data[0] = (byte)0xC3; + data[1] = (byte)len; + data[2] = osx[0]; + data[3] = osx[1]; + data[4] = osy[0]; + data[5] = osy[1]; + System.arraycopy(strData, 0, data, 6, strData.length); + } + } + + /** + * {@inheritDoc} + */ + public String toString() { + String string = "GraphicsString(str='" + str + "'"; + if (!fromCurrentPosition) { + string += ",x=" + x + ",y=" + y; + } + string += ")"; + return string; + } +} \ No newline at end of file -- cgit v1.2.3 From f466690aaeed2dc93360d5f5f14fede90f2f5ad2 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 27 Mar 2008 16:16:30 +0000 Subject: Committing in preparation for trunk merge. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@641873 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/image/AbstractFopImage.java | 4 +- src/java/org/apache/fop/image/FopImage.java | 4 +- .../org/apache/fop/render/afp/AFPGraphics2D.java | 157 +-- .../fop/render/afp/AFPGraphics2DAdapter.java | 7 +- src/java/org/apache/fop/render/afp/AFPInfo.java | 124 ++- .../org/apache/fop/render/afp/AFPRenderer.java | 1099 ++++++++++++-------- .../fop/render/afp/AFPRendererConfigurator.java | 30 +- .../org/apache/fop/render/afp/AFPSVGHandler.java | 91 +- src/java/org/apache/fop/render/afp/AFPState.java | 198 ++-- .../fop/render/afp/DataObjectParameters.java | 173 +++ .../fop/render/afp/ImageObjectParameters.java | 138 +++ .../org/apache/fop/render/afp/ResourceLevel.java | 123 +++ .../fop/render/afp/extensions/AFPAttribute.java | 4 +- .../fop/render/afp/extensions/AFPElement.java | 4 + .../render/afp/extensions/AFPElementMapping.java | 3 + .../afp/extensions/AFPExtensionAttachment.java | 155 +++ .../render/afp/extensions/AFPExtensionHandler.java | 4 +- .../fop/render/afp/extensions/AFPPageSetup.java | 100 +- .../render/afp/extensions/AFPPageSetupElement.java | 9 +- .../afp/extensions/AbstractAFPExtensionObject.java | 79 +- .../apache/fop/render/afp/modca/AFPDataStream.java | 313 ++++-- .../fop/render/afp/modca/AbstractAFPObject.java | 18 +- .../fop/render/afp/modca/AbstractDataObject.java | 2 +- .../render/afp/modca/AbstractEnvironmentGroup.java | 100 ++ .../render/afp/modca/AbstractNamedAFPObject.java | 40 +- .../fop/render/afp/modca/AbstractPageObject.java | 152 +-- .../afp/modca/AbstractPreparedAFPObject.java | 83 ++ .../AbstractResourceEnvironmentGroupContainer.java | 108 ++ .../afp/modca/AbstractResourceGroupContainer.java | 124 +++ .../afp/modca/AbstractStructuredAFPObject.java | 192 +++- .../render/afp/modca/ActiveEnvironmentGroup.java | 198 +--- .../org/apache/fop/render/afp/modca/Document.java | 100 +- .../fop/render/afp/modca/GraphicsObject.java | 34 +- .../apache/fop/render/afp/modca/IMImageObject.java | 46 +- .../apache/fop/render/afp/modca/ImageContent.java | 78 +- .../apache/fop/render/afp/modca/ImageSegment.java | 65 +- .../apache/fop/render/afp/modca/IncludeObject.java | 220 +++- .../fop/render/afp/modca/IncludePageOverlay.java | 11 +- .../fop/render/afp/modca/IncludePageSegment.java | 18 +- .../fop/render/afp/modca/InvokeMediumMap.java | 26 +- .../apache/fop/render/afp/modca/MapCodedFont.java | 2 - .../fop/render/afp/modca/MapDataResource.java | 72 ++ .../fop/render/afp/modca/MapPageOverlay.java | 20 +- .../fop/render/afp/modca/ObjectAreaPosition.java | 4 - .../render/afp/modca/ObjectEnvironmentGroup.java | 6 +- .../org/apache/fop/render/afp/modca/Overlay.java | 52 +- .../org/apache/fop/render/afp/modca/PageGroup.java | 107 +- .../apache/fop/render/afp/modca/PageObject.java | 79 +- .../apache/fop/render/afp/modca/PageSegment.java | 102 ++ .../afp/modca/PreprocessPresentationObject.java | 153 +++ .../render/afp/modca/PresentationTextObject.java | 93 +- .../org/apache/fop/render/afp/modca/Registry.java | 353 +++++++ .../render/afp/modca/ResourceEnvironmentGroup.java | 158 +++ .../apache/fop/render/afp/modca/ResourceGroup.java | 257 ++++- .../fop/render/afp/modca/ResourceObject.java | 180 ++++ .../modca/triplets/FullyQualifiedNameTriplet.java | 102 ++ .../modca/triplets/MeasurementUnitsTriplet.java | 50 + .../afp/modca/triplets/ObjectAreaSizeTriplet.java | 49 + .../triplets/ObjectClassificationTriplet.java | 70 ++ .../modca/triplets/ResourceObjectTypeTriplet.java | 21 + .../fop/render/afp/modca/triplets/Triplet.java | 158 +++ .../org/apache/fop/render/pdf/PDFRenderer.java | 9 +- .../ps/extensions/PSCommentAfterElement.java | 4 +- .../ps/extensions/PSCommentBeforeElement.java | 4 +- .../ps/extensions/PSExtensionElementMapping.java | 4 +- 65 files changed, 4772 insertions(+), 1771 deletions(-) create mode 100644 src/java/org/apache/fop/render/afp/DataObjectParameters.java create mode 100644 src/java/org/apache/fop/render/afp/ImageObjectParameters.java create mode 100644 src/java/org/apache/fop/render/afp/ResourceLevel.java create mode 100644 src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java create mode 100644 src/java/org/apache/fop/render/afp/modca/AbstractEnvironmentGroup.java create mode 100644 src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java create mode 100644 src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java create mode 100644 src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java create mode 100644 src/java/org/apache/fop/render/afp/modca/MapDataResource.java create mode 100644 src/java/org/apache/fop/render/afp/modca/PageSegment.java create mode 100644 src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java create mode 100644 src/java/org/apache/fop/render/afp/modca/Registry.java create mode 100644 src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java create mode 100644 src/java/org/apache/fop/render/afp/modca/ResourceObject.java create mode 100644 src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java create mode 100644 src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java create mode 100644 src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java create mode 100644 src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java create mode 100644 src/java/org/apache/fop/render/afp/modca/triplets/ResourceObjectTypeTriplet.java create mode 100644 src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/image/AbstractFopImage.java b/src/java/org/apache/fop/image/AbstractFopImage.java index 8d5180149..68949b9c9 100644 --- a/src/java/org/apache/fop/image/AbstractFopImage.java +++ b/src/java/org/apache/fop/image/AbstractFopImage.java @@ -360,7 +360,7 @@ public abstract class AbstractFopImage implements FopImage { * Return the original image data (compressed). * @return the original image data */ - public byte[] getRessourceBytes() { + public byte[] getResourceBytes() { return raw; } @@ -368,7 +368,7 @@ public abstract class AbstractFopImage implements FopImage { * Return the original image data size (compressed). * @return the original image data size */ - public int getRessourceBytesSize() { + public int getResourceBytesSize() { return (raw != null ? raw.length : 0); } diff --git a/src/java/org/apache/fop/image/FopImage.java b/src/java/org/apache/fop/image/FopImage.java index 0f780ad57..abe11ef25 100644 --- a/src/java/org/apache/fop/image/FopImage.java +++ b/src/java/org/apache/fop/image/FopImage.java @@ -168,13 +168,13 @@ public interface FopImage { * Returns the encoded/compressed image as an array of bytes. * @return the raw image */ - byte[] getRessourceBytes(); + byte[] getResourceBytes(); /** * Returns the number of bytes of the raw image. * @return the size in bytes */ - int getRessourceBytesSize(); + int getResourceBytesSize(); /** * Image info class. diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java index 3e477e224..974155630 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java @@ -44,14 +44,14 @@ import org.apache.batik.ext.awt.geom.ExtendedGeneralPath; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.modca.AFPDataStream; +import org.apache.fop.render.afp.goca.GraphicsSetLineType; import org.apache.fop.render.afp.modca.GraphicsObject; -import org.apache.fop.render.afp.modca.ImageObject; -import org.apache.fop.render.afp.modca.goca.GraphicsSetLineType; +import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; import org.apache.xmlgraphics.java2d.StrokingTextHandler; import org.apache.xmlgraphics.java2d.TextHandler; +import org.apache.xmlgraphics.ps.ImageEncodingHelper; /** * This is a concrete implementation of AbstractGraphics2D (and @@ -78,6 +78,9 @@ public class AFPGraphics2D extends AbstractGraphics2D { /** Current AFP state */ private AFPState afpState = null; + /** The SVG document URI */ + private String documentURI = null; + /** * @param textAsShapes * if true, all text is turned into shapes in the convertion. No @@ -295,7 +298,7 @@ public class AFPGraphics2D extends AbstractGraphics2D { graphicsObj.addBox(coords); } else if (shape instanceof Ellipse2D) { Ellipse2D elip = (Ellipse2D) shape; - final double factor = afpInfo.resolution / 100f; + final double factor = afpInfo.getResolution() / 100f; graphicsObj.setArcParams( (int)Math.round(elip.getWidth() * factor), (int)Math.round(elip.getHeight() * factor), @@ -345,23 +348,10 @@ public class AFPGraphics2D extends AbstractGraphics2D { */ public void handleIOException(IOException ioe) { // TODO Surely, there's a better way to do this. + log.error(ioe.getMessage()); ioe.printStackTrace(); } - /** - * {@inheritDoc} - */ - public void drawRenderableImage(RenderableImage img, AffineTransform xform) { - log.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform); - } - - /** - * {@inheritDoc} - */ - public void drawRenderedImage(RenderedImage img, AffineTransform xform) { - log.debug("drawRenderedImage() NYI: img=" + img + ", xform=" + xform); - } - /** * {@inheritDoc} */ @@ -402,7 +392,7 @@ public class AFPGraphics2D extends AbstractGraphics2D { * {@inheritDoc} */ public void dispose() { - log.debug("dispose() NYI: "); + this.graphicsObj = null; } /** @@ -411,54 +401,62 @@ public class AFPGraphics2D extends AbstractGraphics2D { public boolean drawImage(Image img, int x, int y, ImageObserver observer) { return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), observer); } - + /** * {@inheritDoc} */ public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { - log.debug("drawImage() img=" + img + ", x=" + x + ", y=" + y + //TODO: this might be achieved by creating a new IOCA image (ImageObject) + // and placing it in an Overlay - but then stacking order would not be preserved. + log.debug("drawImage(): NYI img=" + img + ", x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + ", obs=" + observer); - - int afpres = afpInfo.resolution; - int afpBitsPerPixel = afpInfo.bitsPerPixel; - int afpx = x; - int afpy = y; - int afpw = width; - int afph = height; - boolean colorImages = !afpInfo.grayscale; - int imageResolution = afpres; - if (img instanceof BufferedImage) { - BufferedImage bi = (BufferedImage)img; - ByteArrayOutputStream baout = new ByteArrayOutputStream(); - try { - // Serialize image - AFPRenderer.writeImage(bi, baout); - byte[] buf = baout.toByteArray(); - - // Generate image - AFPDataStream afpDataStream = afpInfo.afpDataStream; - ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, - afph, afpres, afpres); - io.setImageParameters(imageResolution, imageResolution, - afpw, afph); - if (colorImages) { - io.setImageIDESize((byte)24); - io.setImageData(buf); - } else { - AFPRenderer.convertToGrayScaleImage(io, buf, afpw, afph, afpBitsPerPixel); - } - } catch (IOException ioe) { - log.error("Error while serializing bitmap: " + ioe.getMessage(), - ioe); - return false; - } - return true; - } else { - log.debug("drawImage() NYI: img=" + img + ", x=" + x + ", y=" + y - + ", observer=" + observer); - } return false; +// log.debug("drawImage() img=" + img + ", x=" + x + ", y=" + y +// + ", width=" + width + ", height=" + height + ", obs=" + observer); +// if (img instanceof BufferedImage) { +// try { +// BufferedImage bi = (BufferedImage)img; +// ByteArrayOutputStream baout = new ByteArrayOutputStream(); +// +// // Serialize image +// ImageEncodingHelper.encodeRenderedImageAsRGB(bi, baout); +// +// int res = afpInfo.getResolution(); +// ImageObjectParameters params = new ImageObjectParameters( +// //TODO: provide a real url +// img.toString(), x, y, +// width, height, res, res, baout.toByteArray(), +// img.getWidth(observer), img.getHeight(observer), +// afpInfo.isColorSupported(), afpInfo.getBitsPerPixel()); +// +// afpInfo.getAFPDataStream().createImageObject(params); +// +// // Generate image +// } catch (IOException ioe) { +// log.error("Error while serializing bitmap: " + ioe.getMessage(), +// ioe); +// return false; +// } +// return true; +// } else { +// log.debug("drawImage() image type not supported: " + img); +// } +// return false; + } + + /** + * {@inheritDoc} + */ + public void drawRenderableImage(RenderableImage img, AffineTransform xform) { + log.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform); + } + + /** + * {@inheritDoc} + */ + public void drawRenderedImage(RenderedImage img, AffineTransform xform) { + log.debug("drawRenderedImage() NYI: img=" + img + ", xform=" + xform); } /** @@ -488,19 +486,40 @@ public class AFPGraphics2D extends AbstractGraphics2D { this.customTextHandler = handler; } + /** + * Sets the SVG document URI + * @param documentURI the SVG document URI + */ + public void setDocumentURI(String documentURI) { + this.documentURI = documentURI; + } + /** * @return the GOCA graphics object */ protected GraphicsObject getGraphicsObject() { - if (this.graphicsObj == null) { - int x = (int)Math.round((afpInfo.currentXPosition * 25.4f) / 1000); - int y = (int)Math.round((afpInfo.currentYPosition * 25.4f) / 1000); - int res = afpInfo.resolution; - int width = (int)Math.round((afpInfo.width * res) / 72000f); - int height = (int)Math.round((afpInfo.height * res) / 72000f); - this.graphicsObj = afpInfo.getAFPDataStream().getGraphicsObject( - x, y, width, height, res, res); - } +// if (this.graphicsObj == null) { +//// DataObjectParameters params = new DataObjectParameters( +//// ((AbstractDocument)doc).getDocumentURI(), +//// afpInfo.getX(), afpInfo.getY(), +//// afpInfo.getWidth(), afpInfo.getHeight(), res, res); +//// +//// afpInfo.getAFPDataStream().createGraphicsObject(params); +// +// int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000); +// int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000); +// int res = afpInfo.getResolution(); +// int width = (int)Math.round((afpInfo.getWidth() * res) / 72000f); +// int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f); +// DataObjectParameters params = new DataObjectParameters( +// this.documentURI, x, y, width, height, res, res); +// IncludeObject includeObj = afpInfo.getAFPDataStream().createGraphicsObject(params); +// this.graphicsObj = (GraphicsObject)includeObj.getReferencedObject(); +// } return this.graphicsObj; } + + protected void setGraphicsObject(GraphicsObject graphicsObj) { + this.graphicsObj = graphicsObj; + } } \ 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 687a0373e..1abe7c0d1 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -51,8 +51,11 @@ public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter { //Paint to a BufferedImage int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, gray, false); - - afp.drawBufferedImage(bi, resolution, x, y, width, height); + + //TODO: uri + String uri = null; + java.util.Map foreignAttributes = null; + afp.drawBufferedImage(uri, bi, resolution, x, y, width, height, foreignAttributes); } } diff --git a/src/java/org/apache/fop/render/afp/AFPInfo.java b/src/java/org/apache/fop/render/afp/AFPInfo.java index 026ab4dfe..19e58d30f 100644 --- a/src/java/org/apache/fop/render/afp/AFPInfo.java +++ b/src/java/org/apache/fop/render/afp/AFPInfo.java @@ -28,28 +28,28 @@ import org.apache.fop.render.afp.modca.AFPDataStream; */ public final class AFPInfo { /** see WIDTH */ - protected int width; + private int width; /** see HEIGHT */ - protected int height; + private int height; /** see XPOS */ - protected int currentXPosition; + private int x; /** see YPOS */ - protected int currentYPosition; + private int y; /** see HANDLER_CONFIGURATION */ - protected Configuration cfg; + private Configuration cfg; /** see AFP_FONT_INFO */ - protected FontInfo fontInfo; + private FontInfo fontInfo; /** See AFP_DATASTREAM */ - protected AFPDataStream afpDataStream; + private AFPDataStream afpDataStream; /** See AFP_STATE */ - protected AFPState afpState; + private AFPState afpState; /** see AFP_GRAYSCALE */ - protected boolean grayscale; + private boolean color; /** see AFP_RESOLUTION */ - protected int resolution; + private int resolution; /** see AFP_BITS_PER_PIXEL */ - protected int bitsPerPixel; + private int bitsPerPixel; /** * Returns the width. @@ -90,6 +90,14 @@ public final class AFPInfo { return this.cfg; } + /** + * Sets the handler configuration + * @param cfg the handler configuration + */ + public void setHandlerConfiguration(Configuration cfg) { + this.cfg = cfg; + } + /** * @return FontInfo the font info */ @@ -115,6 +123,98 @@ public final class AFPInfo { * @return true if supports color */ public boolean isColorSupported() { - return !this.grayscale; + return this.color; + } + + /** + * @return the current x position coordinate + */ + protected int getX() { + return x; + } + + /** + * @return the current y position coordinate + */ + protected int getY() { + return y; + } + + /** + * @return the resolution + */ + protected int getResolution() { + return resolution; + } + + /** + * @return the number of bits per pixel to use + */ + protected int getBitsPerPixel() { + return bitsPerPixel; + } + + /** + * Sets the current x position coordinate + * @param x the current x position coordinate + */ + protected void setX(int x) { + this.x = x; + } + + /** + * Sets the current y position coordinate + * @param y the current y position coordinate + */ + protected void setY(int y) { + this.y = y; + } + + /** + * Sets the current resolution + * @param resolution the current resolution + */ + protected void setResolution(int resolution) { + this.resolution = resolution; + } + + /** + * Sets the current font info + * @param fontInfo the current font info + */ + protected void setFontInfo(FontInfo fontInfo) { + this.fontInfo = fontInfo; + } + + /** + * Sets the AFP state + * @param state the AFP state + */ + public void setState(AFPState state) { + this.afpState = state; + } + + /** + * Sets the AFP datastream + * @param afpDataStream the AFP datastream + */ + public void setAFPDataStream(AFPDataStream afpDataStream) { + this.afpDataStream = afpDataStream; + } + + /** + * Sets if we are supporing color + * @param color true if color is supported + */ + public void setColor(boolean color) { + this.color = color; + } + + /** + * Sets the number of bits per pixel + * @param bitsPerPixel the number of bits per pixel + */ + public void setBitsPerPixel(int bitsPerPixel) { + this.bitsPerPixel = bitsPerPixel; } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 5cdd55d98..b10f4b30f 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -23,6 +23,7 @@ import java.awt.Color; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; import java.io.FileNotFoundException; @@ -30,8 +31,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -39,7 +38,6 @@ 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; @@ -58,6 +56,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.LineArea; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; @@ -89,6 +88,7 @@ import org.apache.fop.render.afp.fonts.OutlineFont; 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.IncludeObject; import org.apache.fop.render.afp.modca.PageObject; /** @@ -139,39 +139,69 @@ import org.apache.fop.render.afp.modca.PageObject; * handle all types of inline area, text, image etc and draws various lines and * rectangles. *

- * - * Note: There are specific extensions that have been added to the FO. They are - * specific to their location within the FO and have to be processed accordingly - * (ie. at the start or end of the page). - * + * + * Note: There are specific extensions that have been added to the + * FO. They are specific to their location within the FO and have to be + * processed accordingly (ie. at the start or end of the page). + * */ public class AFPRenderer extends AbstractPathOrientedRenderer { /** - * 2400 dpi renderer resolution - */ - protected static final int DPI_240_RESOLUTION = 240; - - /** - * 14400 dpi renderer resolution + * The default afp renderer output resolution */ - protected static final int DPI_1440_RESOLUTION = 1440; + public static final int DPI_240_RESOLUTION = 240; /** * The afp factor for calculating resolutions (e.g. 72000/240 = 300) */ - protected static final int DPI_CONVERSION_FACTOR = 72000; + private static final int DPI_CONVERSION_FACTOR = 72000; /** * The afp data stream object responsible for generating afp data */ private AFPDataStream afpDataStream = null; + /** + * The map of afp root extensions + */ + // UNUSED + // private HashMap rootExtensionMap = null; /** * The map of page segments */ private Map pageSegmentsMap = null; + /** + * The fonts on the current page + */ + private Map currentPageFonts = null; + + /** + * The current color object + */ + private Color currentColor = null; + + /** + * The page font number counter, used to determine the next font reference + */ + private int pageFontCounter = 0; + + /** + * The current font family + */ + // UNUSED + // private String currentFontFamily = ""; + /** + * The current font size + */ + private int currentFontSize = 0; + + /** + * The Options to be set on the AFPRenderer + */ + // UNUSED + // private Map afpOptions = null; /** * The page width */ @@ -182,6 +212,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ private int pageHeight = 0; + /** + * The current page sequence id + */ + // UNUSED + // private String pageSequenceId = null; /** * The portrait rotation */ @@ -192,6 +227,21 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ private int landscapeRotation = 270; + /** + * The line cache, avoids drawing duplicate lines in tables. + */ + // UNUSED + // private HashSet lineCache = null; + /** + * The current x position for line drawing + */ + // UNUSED + // private float x; + /** + * The current y position for line drawing + */ + // UNUSED + // private float y; /** * The map of saved incomplete pages */ @@ -213,7 +263,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private int resolution = DPI_240_RESOLUTION; /** drawing state */ - protected AFPState currentState = null; + private AFPState currentState = null; /** * Constructor for AFPRenderer. @@ -224,22 +274,20 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Set up the font info - * - * @param inFontInfo - * font info to set up + * + * @param inFontInfo font info to set up */ 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();) { - AFPFontInfo afi = (AFPFontInfo) it.next(); - AFPFont bf = (AFPFont) afi.getAFPFont(); - for (Iterator it2 = afi.getFontTriplets().iterator(); it2 - .hasNext();) { - FontTriplet ft = (FontTriplet) it2.next(); - this.fontInfo.addFontProperties("F" + num, ft.getName(), ft - .getStyle(), ft.getWeight()); + AFPFontInfo afi = (AFPFontInfo)it.next(); + AFPFont bf = (AFPFont)afi.getAFPFont(); + for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) { + FontTriplet ft = (FontTriplet)it2.next(); + this.fontInfo.addFontProperties("F" + num, ft.getName() + , ft.getStyle(), ft.getWeight()); this.fontInfo.addMetrics("F" + num, bf); num++; } @@ -248,36 +296,33 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { log.warn("No AFP fonts configured - using default setup"); } if (this.fontInfo.fontLookup("sans-serif", "normal", 400) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", - "CZH200 ", 1, new Helvetica()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZH200 ", + 1, new Helvetica()); AFPFont bf = new OutlineFont("Helvetica", cs); - this.fontInfo.addFontProperties("F" + num, "sans-serif", "normal", - 400); + this.fontInfo.addFontProperties("F" + num, "sans-serif", "normal", 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("serif", "normal", 400) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", - "CZN200 ", 1, new TimesRoman()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZN200 ", + 1, new TimesRoman()); AFPFont bf = new OutlineFont("Helvetica", cs); this.fontInfo.addFontProperties("F" + num, "serif", "normal", 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("monospace", "normal", 400) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", - "CZ4200 ", 1, new Courier()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZ4200 ", + 1, new Courier()); AFPFont bf = new OutlineFont("Helvetica", cs); - this.fontInfo.addFontProperties("F" + num, "monospace", "normal", - 400); + this.fontInfo.addFontProperties("F" + num, "monospace", "normal", 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("any", "normal", 400) == null) { - FontTriplet ft = this.fontInfo.fontLookup("sans-serif", "normal", - 400); - this.fontInfo.addFontProperties(this.fontInfo - .getInternalFontKey(ft), "any", "normal", 400); + FontTriplet ft = this.fontInfo.fontLookup("sans-serif", "normal", 400); + this.fontInfo.addFontProperties( + this.fontInfo.getInternalFontKey(ft), "any", "normal", 400); } } @@ -292,54 +337,62 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ public void startRenderer(OutputStream outputStream) throws IOException { - this.currentState = new AFPState(); - this.afpDataStream = new AFPDataStream(); - this.afpDataStream.setPortraitRotation(portraitRotation); - this.afpDataStream.setLandscapeRotation(landscapeRotation); - this.afpDataStream.startDocument(outputStream); + currentPageFonts = new java.util.HashMap(); + currentColor = new Color(255, 255, 255); + afpDataStream = new AFPDataStream(); + afpDataStream.setPortraitRotation(portraitRotation); + afpDataStream.setLandscapeRotation(landscapeRotation); + afpDataStream.setOutputStream(outputStream); } /** * {@inheritDoc} */ public void stopRenderer() throws IOException { - this.afpDataStream.endDocument(); + afpDataStream.write(); } /** * {@inheritDoc} */ public boolean supportsOutOfOrder() { - // return false; + //return false; return true; } /** - * 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. - * + * 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} */ public void preparePage(PageViewport page) { + // initializeRootExtensions(page); - this.currentState.reset(); + // this.currentFontFamily = ""; + this.currentFontSize = 0; + this.pageFontCounter = 0; + this.currentPageFonts.clear(); + // this.lineCache = new HashSet(); Rectangle2D bounds = page.getViewArea(); this.pageWidth = mpts2units(bounds.getWidth()); this.pageHeight = mpts2units(bounds.getHeight()); + // renderPageGroupExtensions(page); + final int pageRotation = 0; this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation, - this.resolution, this.resolution); + getResolution(), getResolution()); renderPageObjectExtensions(page); if (this.pages == null) { - this.pages = new HashMap(); + this.pages = new java.util.HashMap(); } this.pages.put(page, afpDataStream.savePage()); @@ -372,15 +425,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } /** - * Renders a region viewport. - *

- * - * The region may clip the area and it establishes a position from where the - * region is placed. - *

- * - * @param port - * The region viewport to be rendered + * Renders a region viewport.

+ * + * The region may clip the area and it establishes a position from where + * the region is placed.

+ * + * @param port The region viewport to be rendered */ public void renderRegionViewport(RegionViewport port) { if (port != null) { @@ -395,9 +445,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { handleRegionTraits(port); /* - * _afpDataStream.startOverlay(mpts2units(view.getX()) , - * mpts2units(view.getY()) , mpts2units(view.getWidth()) , - * mpts2units(view.getHeight()) , rotation); + _afpDataStream.startOverlay(mpts2units(view.getX()) + , mpts2units(view.getY()) + , mpts2units(view.getWidth()) + , mpts2units(view.getHeight()) + , rotation); */ pushViewPortPos(new ViewPortPos(view, regionReference.getCTM())); @@ -408,7 +460,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { renderRegion(regionReference); } /* - * _afpDataStream.endOverlay(); + _afpDataStream.endOverlay(); */ popViewPortPos(); } @@ -423,65 +475,77 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // 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; + //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. + //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. List breakOutList = null; if (bv.getPositioning() == Block.FIXED) { 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(); - - y += bv.getSpaceBefore() / 1000f; - currentBPPosition += bv.getSpaceBefore(); - - float bpwidth = (borderPaddingStart + bv - .getBorderAndPaddingWidthEnd()) / 1000f; - float bpheight = (borderPaddingBefore + bv - .getBorderAndPaddingWidthAfter()) / 1000f; - - drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight); - - // Now adjust for border/padding - currentIPPosition += borderPaddingStart; - currentBPPosition += borderPaddingBefore; + 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); - Rectangle2D clippingRect = null; - clippingRect = new Rectangle(currentIPPosition, currentBPPosition, - bv.getIPD(), bv.getBPD()); + //skipping fox:transform here - // startVParea(ctm, clippingRect); - pushViewPortPos(new ViewPortPos(clippingRect, ctm)); + //saveGraphicsState(); + //Viewport position + //concatenateTransformationMatrix(mptToPt(positionTransform)); + + //Background and borders + float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; + float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; + Point2D ptSrc = new Point(0, 0); + Point2D ptDst = positionTransform.transform(ptSrc, null); + Rectangle2D borderRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(), + 1000 * (width + bpwidth), 1000 * (height + bpheight)); + pushViewPortPos(new ViewPortPos(borderRect, new CTM(positionTransform))); + drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight); + + //Shift to content rectangle after border painting + AffineTransform contentRectTransform = new AffineTransform(); + contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); + //concatenateTransformationMatrix(mptToPt(contentRectTransform)); + ptSrc = new Point(0, 0); + ptDst = contentRectTransform.transform(ptSrc, null); + Rectangle2D contentRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(), + 1000 * width, 1000 * height); + pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentRectTransform))); + + //Clipping is not supported, yet + //Rectangle2D clippingRect = null; + //clippingRect = new Rectangle(0, 0, bv.getIPD(), bv.getBPD()); + + //saveGraphicsState(); + //Set up coordinate system for content rectangle + AffineTransform contentTransform = ctm.toAffineTransform(); + //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); - // endVParea(); + popViewPortPos(); + popViewPortPos(); + //restoreGraphicsState(); + popViewPortPos(); + //restoreGraphicsState(); if (breakOutList != null) { restoreStateStackAfterBreakOut(breakOutList); @@ -493,37 +557,36 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { currentBPPosition += bv.getSpaceBefore(); - // borders and background in the old coordinate system + //borders and background in the old coordinate system handleBlockTraits(bv); - // Advance to start of content area + //Advance to start of content area currentIPPosition += bv.getStartIndent(); CTM tempctm = new CTM(containingIPPosition, currentBPPosition); ctm = tempctm.multiply(ctm); - // Now adjust for border/padding + //Now adjust for border/padding currentBPPosition += borderPaddingBefore; Rectangle2D clippingRect = null; clippingRect = new Rectangle(currentIPPosition, currentBPPosition, bv.getIPD(), bv.getBPD()); - // startVParea(ctm, clippingRect); + //startVParea(ctm, clippingRect); pushViewPortPos(new ViewPortPos(clippingRect, ctm)); currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); - // endVParea(); + //endVParea(); popViewPortPos(); currentIPPosition = saveIP; currentBPPosition = saveBP; - currentBPPosition += (int) (bv.getAllocBPD()); + currentBPPosition += (int)(bv.getAllocBPD()); } - // currentFontName = saveFontName; } /** {@inheritDoc} */ @@ -537,7 +600,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ public void renderPage(PageViewport pageViewport) { - currentState.reset(); + // initializeRootExtensions(page); + + // this.currentFontFamily = ""; + this.currentFontSize = 0; + this.pageFontCounter = 0; + this.currentPageFonts.clear(); + // this.lineCache = new HashSet(); Rectangle2D bounds = pageViewport.getViewArea(); @@ -546,14 +615,14 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (pages != null && pages.containsKey(pageViewport)) { - this.afpDataStream.restorePage((PageObject) pages - .remove(pageViewport)); + this.afpDataStream.restorePage((PageObject) pages.remove(pageViewport)); } else { + // renderPageGroupExtensions(page); final int pageRotation = 0; this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation, - this.resolution, this.resolution); + getResolution(), getResolution()); renderPageObjectExtensions(pageViewport); @@ -563,16 +632,20 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { renderPageAreas(pageViewport.getPage()); - this.afpDataStream.addFontsToCurrentPage(currentState.getPageFonts()); + Iterator i = currentPageFonts.values().iterator(); + while (i.hasNext()) { + AFPFontAttributes afpFontAttributes = (AFPFontAttributes) i.next(); + + afpDataStream.createFont( + (byte)afpFontAttributes.getFontReference(), + afpFontAttributes.getFont(), + afpFontAttributes.getPointSize()); - try { - afpDataStream.endPage(); - } catch (IOException ioex) { - // TODO What shall we do? } + afpDataStream.endPage(); + popViewPortPos(); - } /** @@ -615,12 +688,22 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ public void fillRect(float x, float y, float width, float height) { /* - * afpDataStream.createShading( pts2units(x), pts2units(y), - * pts2units(width), pts2units(height), currentColor.getRed(), - * currentColor.getGreen(), currentColor.getBlue()); + afpDataStream.createShading( + pts2units(x), + pts2units(y), + pts2units(width), + pts2units(height), + currentColor.getRed(), + currentColor.getGreen(), + currentColor.getBlue()); */ - afpDataStream.createLine(pts2units(x), pts2units(y), pts2units(x - + width), pts2units(y), pts2units(height), currentState.getColor()); + afpDataStream.createLine( + pts2units(x), + pts2units(y), + pts2units(x + width), + pts2units(y), + pts2units(height), + currentColor); } /** @@ -635,112 +718,193 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { return; } switch (style) { - case Constants.EN_DOUBLE: - if (horz) { - float h3 = h / 3; - float ym1 = y1; - float ym2 = ym1 + h3 + h3; - afpDataStream.createLine(pts2units(x1), pts2units(ym1), - pts2units(x2), pts2units(ym1), pts2units(h3), col); - afpDataStream.createLine(pts2units(x1), pts2units(ym2), - pts2units(x2), pts2units(ym2), pts2units(h3), col); - } else { - float w3 = w / 3; - float xm1 = x1; - float xm2 = xm1 + w3 + w3; - afpDataStream.createLine(pts2units(xm1), pts2units(y1), - pts2units(xm1), pts2units(y2), pts2units(w3), col); - afpDataStream.createLine(pts2units(xm2), pts2units(y1), - pts2units(xm2), pts2units(y2), pts2units(w3), col); - } - break; - case Constants.EN_DASHED: - if (horz) { - float w2 = 2 * h; - while (x1 + w2 < x2) { - afpDataStream.createLine(pts2units(x1), pts2units(y1), - pts2units(x1 + w2), pts2units(y1), pts2units(h), - col); - x1 += 2 * w2; + case Constants.EN_DOUBLE: + if (horz) { + float h3 = h / 3; + float ym1 = y1; + float ym2 = ym1 + h3 + h3; + afpDataStream.createLine( + pts2units(x1), + pts2units(ym1), + pts2units(x2), + pts2units(ym1), + pts2units(h3), + col + ); + afpDataStream.createLine( + pts2units(x1), + pts2units(ym2), + pts2units(x2), + pts2units(ym2), + pts2units(h3), + col + ); + } else { + float w3 = w / 3; + float xm1 = x1; + float xm2 = xm1 + w3 + w3; + afpDataStream.createLine( + pts2units(xm1), + pts2units(y1), + pts2units(xm1), + pts2units(y2), + pts2units(w3), + col + ); + afpDataStream.createLine( + pts2units(xm2), + pts2units(y1), + pts2units(xm2), + pts2units(y2), + pts2units(w3), + col + ); } - } else { - float h2 = 2 * w; - while (y1 + h2 < y2) { - afpDataStream.createLine(pts2units(x1), pts2units(y1), - pts2units(x1), pts2units(y1 + h2), pts2units(w), - col); - y1 += 2 * h2; + break; + case Constants.EN_DASHED: + if (horz) { + float w2 = 2 * h; + while (x1 + w2 < x2) { + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(x1 + w2), + pts2units(y1), + pts2units(h), + col + ); + x1 += 2 * w2; + } + } else { + float h2 = 2 * w; + while (y1 + h2 < y2) { + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(x1), + pts2units(y1 + h2), + pts2units(w), + col + ); + y1 += 2 * h2; + } } - } - break; - case Constants.EN_DOTTED: - if (horz) { - while (x1 + h < x2) { - afpDataStream - .createLine(pts2units(x1), pts2units(y1), - pts2units(x1 + h), pts2units(y1), - pts2units(h), col); - x1 += 2 * h; + break; + case Constants.EN_DOTTED: + if (horz) { + while (x1 + h < x2) { + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(x1 + h), + pts2units(y1), + pts2units(h), + col + ); + x1 += 2 * h; + } + } else { + while (y1 + w < y2) { + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(x1), + pts2units(y1 + w), + pts2units(w), + col + ); + y1 += 2 * w; + } } - } else { - while (y1 + w < y2) { - afpDataStream - .createLine(pts2units(x1), pts2units(y1), - pts2units(x1), pts2units(y1 + w), - pts2units(w), col); - y1 += 2 * w; + break; + case Constants.EN_GROOVE: + case Constants.EN_RIDGE: + { + float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f); + if (horz) { + Color uppercol = lightenColor(col, -colFactor); + Color lowercol = lightenColor(col, colFactor); + float h3 = h / 3; + float ym1 = y1; + afpDataStream.createLine( + pts2units(x1), + pts2units(ym1), + pts2units(x2), + pts2units(ym1), + pts2units(h3), + uppercol + ); + afpDataStream.createLine( + pts2units(x1), + pts2units(ym1 + h3), + pts2units(x2), + pts2units(ym1 + h3), + pts2units(h3), + col + ); + afpDataStream.createLine( + pts2units(x1), + pts2units(ym1 + h3 + h3), + pts2units(x2), + pts2units(ym1 + h3 + h3), + pts2units(h3), + lowercol + ); + } else { + Color leftcol = lightenColor(col, -colFactor); + Color rightcol = lightenColor(col, colFactor); + float w3 = w / 3; + float xm1 = x1 + (w3 / 2); + afpDataStream.createLine( + pts2units(xm1), + pts2units(y1), + pts2units(xm1), + pts2units(y2), + pts2units(w3), + leftcol + ); + afpDataStream.createLine( + pts2units(xm1 + w3), + pts2units(y1), + pts2units(xm1 + w3), + pts2units(y2), + pts2units(w3), + col + ); + afpDataStream.createLine( + pts2units(xm1 + w3 + w3), + pts2units(y1), + pts2units(xm1 + w3 + w3), + pts2units(y2), + pts2units(w3), + rightcol + ); } + break; } - break; - case Constants.EN_GROOVE: - case Constants.EN_RIDGE: { - float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f); - if (horz) { - Color uppercol = lightenColor(col, -colFactor); - Color lowercol = lightenColor(col, colFactor); - float h3 = h / 3; - float ym1 = y1; - afpDataStream.createLine(pts2units(x1), pts2units(ym1), - pts2units(x2), pts2units(ym1), pts2units(h3), uppercol); - afpDataStream.createLine(pts2units(x1), pts2units(ym1 + h3), - pts2units(x2), pts2units(ym1 + h3), pts2units(h3), col); - afpDataStream.createLine(pts2units(x1), - pts2units(ym1 + h3 + h3), pts2units(x2), pts2units(ym1 - + h3 + h3), pts2units(h3), lowercol); - } else { - Color leftcol = lightenColor(col, -colFactor); - Color rightcol = lightenColor(col, colFactor); - float w3 = w / 3; - float xm1 = x1 + (w3 / 2); - afpDataStream.createLine(pts2units(xm1), pts2units(y1), - pts2units(xm1), pts2units(y2), pts2units(w3), leftcol); - afpDataStream.createLine(pts2units(xm1 + w3), pts2units(y1), - pts2units(xm1 + w3), pts2units(y2), pts2units(w3), col); - afpDataStream.createLine(pts2units(xm1 + w3 + w3), - pts2units(y1), pts2units(xm1 + w3 + w3), pts2units(y2), - pts2units(w3), rightcol); - } - break; - } - case Constants.EN_HIDDEN: - break; - case Constants.EN_INSET: - case Constants.EN_OUTSET: - default: - afpDataStream.createLine(pts2units(x1), pts2units(y1), - pts2units(horz ? x2 : x1), pts2units(horz ? y1 : y2), - pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), col); + case Constants.EN_HIDDEN: + break; + case Constants.EN_INSET: + case Constants.EN_OUTSET: + default: + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(horz ? x2 : x1), + pts2units(horz ? y1 : y2), + pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), + col + ); } } /** * {@inheritDoc} */ - protected RendererContext createRendererContext(int x, int y, int width, - int height, Map foreignAttributes) { + protected RendererContext createRendererContext(int x, int y, int width, int height, + Map foreignAttributes) { RendererContext context; - context = super.createRendererContext(x, y, width, height, - foreignAttributes); + context = super.createRendererContext(x, y, width, height, foreignAttributes); context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, new Boolean(!this.colorImages)); context.setProperty(AFPRendererContextConstants.AFP_FONT_INFO, @@ -750,9 +914,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { context.setProperty(AFPRendererContextConstants.AFP_BITS_PER_PIXEL, new Integer(this.bitsPerPixel)); context.setProperty(AFPRendererContextConstants.AFP_DATASTREAM, - this.afpDataStream); + getAFPDataStream()); context.setProperty(AFPRendererContextConstants.AFP_STATE, - this.currentState); + getState()); return context; } @@ -763,6 +927,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { ImageFlavor.RENDERED_IMAGE, ImageFlavor.XML_DOM}; + /** {@inheritDoc} */ public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { uri = URISpecification.getURL(uri); @@ -784,6 +949,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } else { ImageManager manager = getUserAgent().getFactory().getImageManager(); ImageInfo info = null; + InputStream in = null; try { ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); @@ -806,48 +972,62 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } else if (img instanceof ImageRendered) { ImageRendered imgRend = (ImageRendered)img; RenderedImage ri = imgRend.getRenderedImage(); - - drawBufferedImage(ri, getResolution(), + drawBufferedImage(uri, ri, getResolution(), posInt.x + currentIPPosition, posInt.y + currentBPPosition, posInt.width, - posInt.height); + posInt.height, foreignAttributes); } else if (img instanceof ImageRawCCITTFax) { ImageRawCCITTFax ccitt = (ImageRawCCITTFax)img; + in = ccitt.createInputStream(); + byte[] buf = IOUtils.toByteArray(in); 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), + ImageObjectParameters params = new ImageObjectParameters( + uri, afpx, afpy, afpw, afph, afpres, afpres, + buf, 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); - } + ccitt.getSize().getHeightPx(), + colorImages, bitsPerPixel + ); + params.setCompression(ccitt.getCompression()); + params.setResourceLevelFromForeignAttributes(foreignAttributes); +// params.setData(buf); + afpDataStream.createImageObject(params); + + +// 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(), @@ -864,6 +1044,10 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } catch (IOException ioe) { log.error("I/O error while processing image: " + (info != null ? info.toString() : uri), ioe); + } finally { + if (in != null) { + IOUtils.closeQuietly(in); + } } /* @@ -906,46 +1090,47 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * io.setImageData(fopimage.getRessourceBytes()); *//* } else if (MimeConstants.MIME_TIFF.equals(mime) - && fopimage instanceof TIFFImage) { + && fopimage instanceof TIFFImage) { TIFFImage tiffImage = (TIFFImage) fopimage; int x = mpts2units(pos.getX() + currentIPPosition); int y = mpts2units(pos.getY() + currentBPPosition); int w = mpts2units(pos.getWidth()); int h = mpts2units(pos.getHeight()); - int res = getResolution(); - ImageObject io = afpDataStream.getImageObject(x, y, w, h, res, - res); + ImageObject io = afpDataStream.getImageObject(x, y, w, h, + getResolution(), getResolution()); io.setImageParameters( - (int) (fopimage.getHorizontalResolution() * 10), - (int) (fopimage.getVerticalResolution() * 10), fopimage - .getWidth(), fopimage.getHeight()); + (int)(fopimage.getHorizontalResolution() * 10), + (int)(fopimage.getVerticalResolution() * 10), + fopimage.getWidth(), + fopimage.getHeight() + ); if (tiffImage.getStripCount() == 1) { int comp = tiffImage.getCompression(); if (comp == 3) { if (!fopimage.load(FopImage.ORIGINAL_DATA)) { return; } - io.setImageEncoding((byte) 0x81); + io.setImageEncoding((byte)0x81); io.setImageData(fopimage.getRessourceBytes()); } else if (comp == 4) { if (!fopimage.load(FopImage.ORIGINAL_DATA)) { return; } - io.setImageEncoding((byte) 0x82); + io.setImageEncoding((byte)0x82); io.setImageData(fopimage.getRessourceBytes()); } else { if (!fopimage.load(FopImage.BITMAP)) { return; } - convertToGrayScaleImage(io, fopimage.getBitmaps(), - fopimage.getWidth(), fopimage.getHeight(), this.bitsPerPixel); + convertToGrayScaleImage(io, fopimage.getBitmaps(), + fopimage.getWidth(), fopimage.getHeight()); } } else { if (!fopimage.load(FopImage.BITMAP)) { return; } - convertToGrayScaleImage(io, fopimage.getBitmaps(), fopimage - .getWidth(), fopimage.getHeight(), this.bitsPerPixel); + convertToGrayScaleImage(io, fopimage.getBitmaps(), + fopimage.getWidth(), fopimage.getHeight()); } } else { if (!fopimage.load(FopImage.BITMAP)) { @@ -957,19 +1142,20 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int y = mpts2units(pos.getY() + currentBPPosition); int w = mpts2units(pos.getWidth()); int h = mpts2units(pos.getHeight()); - int res = getResolution(); - ImageObject io = afpDataStream.getImageObject(x, y, w, h, res, - res); + ImageObject io = afpDataStream.getImageObject(x, y, w, h, + getResolution(), getResolution()); io.setImageParameters( - (int) (fopimage.getHorizontalResolution() * 10), - (int) (fopimage.getVerticalResolution() * 10), fopimage - .getWidth(), fopimage.getHeight()); + (int)(fopimage.getHorizontalResolution() * 10), + (int)(fopimage.getVerticalResolution() * 10), + fopimage.getWidth(), + fopimage.getHeight() + ); if (colorImages) { - io.setImageIDESize((byte) 24); + io.setImageIDESize((byte)24); io.setImageData(fopimage.getBitmaps()); } else { - convertToGrayScaleImage(io, fopimage.getBitmaps(), fopimage - .getWidth(), fopimage.getHeight(), this.bitsPerPixel); + convertToGrayScaleImage(io, fopimage.getBitmaps(), + fopimage.getWidth(), fopimage.getHeight()); } }*/ } @@ -983,7 +1169,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @param out * the OutputStream * @throws IOException - * In case of an I/O error. + * In case of an I/O error. + * @deprecated + * use ImageEncodingHelper.encodeRenderedImageAsRGB(image, out) directly instead */ public static void writeImage(RenderedImage image, OutputStream out) throws IOException { @@ -993,9 +1181,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Draws a BufferedImage to AFP. * + * @param uri + * the uri of the image * @param image * the RenderedImage - * @param imageResolution + * @param imageRes * the resolution of the BufferedImage * @param x * the x coordinate (in mpt) @@ -1006,55 +1196,67 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @param h * the height of the viewport (in mpt) */ - public void drawBufferedImage(RenderedImage image, int imageResolution, int x, - int y, int w, int h) { - int afpx = mpts2units(x); - int afpy = mpts2units(y); - int afpw = mpts2units(w); - int afph = mpts2units(h); - int afpres = getResolution(); + public void drawBufferedImage(String uri, RenderedImage image, int imageRes, int x, + int y, int w, int h, Map foreignAttributes) { +// int afpx = mpts2units(x); +// int afpy = mpts2units(y); +// int afpw = mpts2units(w); +// int afph = mpts2units(h); ByteArrayOutputStream baout = new ByteArrayOutputStream(); try { // Serialize image //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, - 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, - image.getWidth(), image.getHeight(), this.bitsPerPixel); - } + ImageEncodingHelper.encodeRenderedImageAsRGB(image, baout); } catch (IOException ioe) { - log.error("Error while serializing bitmap: " + ioe.getMessage(), - ioe); + log.error("Error while serializing bitmap: " + ioe.getMessage(), ioe); + return; } + //int res = getResolution(); +// String uri = null;// = image.getProperty(name); +// String uri = image.getProperty(name); + // Generate image + ImageObjectParameters params = new ImageObjectParameters( + uri, + mpts2units(x), mpts2units(y), + mpts2units(w), mpts2units(h), + imageRes, imageRes, + baout.toByteArray(), + image.getWidth(), + image.getHeight(), + colorImages, + bitsPerPixel); + + params.setResourceLevelFromForeignAttributes(foreignAttributes); + IncludeObject io = afpDataStream.createImageObject(params); +// ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, +// afph, afpres, afpres); +// io.setImageParameters(imageResolution, imageResolution, +// 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, +// image.getWidth(), image.getHeight(), this.bitsPerPixel); +// } } /** - * Establishes a new foreground or fill color. {@inheritDoc} + * Establishes a new foreground or fill color. + * {@inheritDoc} */ public void updateColor(Color col, boolean fill) { if (fill) { - currentState.setColor(col); + currentColor = col; } } /** * Restores the state stack after a break out. - * - * @param breakOutList - * the state stack to restore. + * @param breakOutList the state stack to restore. */ public void restoreStateStackAfterBreakOut(List breakOutList) { @@ -1062,7 +1264,6 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Breaks out of the state stack to handle fixed block-containers. - * * @return the saved state stack to recreate later */ public List breakOutOfStateStack() { @@ -1093,8 +1294,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { - String url = image.getURL(); - drawImage(url, pos); + drawImage(image.getURL(), pos, image.getForeignAttributes()); } /** @@ -1103,58 +1303,76 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { public void renderText(TextArea text) { renderInlineAreaBackAndBorders(text); - String internalFontName = getInternalFontNameForArea(text); - this.currentState.setFontName(internalFontName); - int currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); - this.currentState.setFontSize(currentFontSize); - AFPFont font = (AFPFont) fontInfo.getFonts().get(internalFontName); + String name = getInternalFontNameForArea(text); + currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); + AFPFont tf = (AFPFont) fontInfo.getFonts().get(name); Color col = (Color) text.getTrait(Trait.COLOR); - int vsci = mpts2units(font.getWidth(' ', currentFontSize) / 1000 - + text.getTextWordSpaceAdjust() - + text.getTextLetterSpaceAdjust()); + int vsci = mpts2units(tf.getWidth(' ', currentFontSize) / 1000 + + text.getTextWordSpaceAdjust() + + text.getTextLetterSpaceAdjust()); // word.getOffset() = only height of text itself // currentBlockIPPosition: 0 for beginning of line; nonzero - // where previous line area failed to take up entire allocated space + // where previous line area failed to take up entire allocated space int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); - int bl = currentBPPosition + text.getOffset() - + text.getBaselineOffset(); + int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); // Set letterSpacing - // float ls = fs.getLetterSpacing() / this.currentFontSize; + //float ls = fs.getLetterSpacing() / this.currentFontSize; String worddata = text.getText(); - AFPPageFonts pageFonts = this.currentState.getPageFonts(); - AFPFontAttributes afpFontAttributes = pageFonts.registerFont( - internalFontName, font, currentFontSize); + // Create an AFPFontAttributes object from the current font details + AFPFontAttributes afpFontAttributes = new AFPFontAttributes(name, tf, currentFontSize); + + if (!currentPageFonts.containsKey(afpFontAttributes.getFontKey())) { + // Font not found on current page, so add the new one + pageFontCounter++; + afpFontAttributes.setFontReference(pageFontCounter); + currentPageFonts.put( + afpFontAttributes.getFontKey(), + afpFontAttributes); + + } else { + // Use the previously stored font attributes + afpFontAttributes = (AFPFontAttributes) currentPageFonts.get( + afpFontAttributes.getFontKey()); + } // Try and get the encoding to use for the font String encoding = null; try { - encoding = font.getCharacterSet(currentFontSize).getEncoding(); + encoding = tf.getCharacterSet(currentFontSize).getEncoding(); } catch (Throwable ex) { encoding = AFPConstants.EBCIDIC_ENCODING; - log.warn("renderText():: Error getting encoding for font " - + " - using default encoding " + encoding); + log.warn( + "renderText():: Error getting encoding for font " + + " - using default encoding " + + encoding); } try { - afpDataStream.createText(afpFontAttributes.getFontReference(), - mpts2units(rx), pts2units(bl), col, vsci, mpts2units(text - .getTextLetterSpaceAdjust()), worddata - .getBytes(encoding)); + afpDataStream.createText( + afpFontAttributes.getFontReference(), + mpts2units(rx), + mpts2units(bl), + col, + vsci, + mpts2units(text.getTextLetterSpaceAdjust()), + worddata.getBytes(encoding)); } catch (UnsupportedEncodingException usee) { - log.error("renderText:: Font " + afpFontAttributes.getFontKey() - + " caused UnsupportedEncodingException"); + log.error( + "renderText:: Font " + + afpFontAttributes.getFontKey() + + " caused UnsupportedEncodingException"); } super.renderText(text); - renderTextDecoration(font, currentFontSize, text, bl, rx); + renderTextDecoration(tf, currentFontSize, text, bl, rx); } /** @@ -1192,40 +1410,87 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } /** - * Render leader area. This renders a leader area which is an area with a - * rule. - * - * @param area - * the leader area to render + * Render leader area. + * This renders a leader area which is an area with a rule. + * @param area the leader area to render */ public void renderLeader(Leader area) { renderInlineAreaBackAndBorders(area); int style = area.getRuleStyle(); - float startx = (currentIPPosition + area - .getBorderAndPaddingWidthStart()) / 1000f; + float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; float starty = (currentBPPosition + area.getOffset()) / 1000f; - float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + area - .getIPD()) / 1000f; + float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + + area.getIPD()) / 1000f; float ruleThickness = area.getRuleThickness() / 1000f; - Color col = (Color) area.getTrait(Trait.COLOR); + Color col = (Color)area.getTrait(Trait.COLOR); switch (style) { - case EN_SOLID: - case EN_DASHED: - case EN_DOUBLE: - case EN_DOTTED: - case EN_GROOVE: - case EN_RIDGE: - drawBorderLine(startx, starty, endx, starty + ruleThickness, true, - true, style, col); - break; - default: - throw new UnsupportedOperationException("rule style not supported"); + case EN_SOLID: + case EN_DASHED: + case EN_DOUBLE: + case EN_DOTTED: + case EN_GROOVE: + case EN_RIDGE: + drawBorderLine(startx, starty, endx, starty + ruleThickness, + true, true, style, col); + break; + default: + throw new UnsupportedOperationException("rule style not supported"); } super.renderLeader(area); } + /** + * Sets the AFPRenderer options + * @param options the Map containing the options + */ +// UNUSED +// public void setOptions(Map options) { +// +// this.afpOptions = options; +// +// } + /** + * Determines the orientation from the string representation, this method + * guarantees to return a value of either 0, 90, 180 or 270. + * + * @return the orientation + */ +// UNUSED +// private int getOrientation(String orientationString) { +// +// int orientation = 0; +// if (orientationString != null && orientationString.length() > 0) { +// try { +// orientation = Integer.parseInt(orientationString); +// } catch (NumberFormatException nfe) { +// log.error("Cannot use orientation of " + orientation +// + " defaulting to zero."); +// orientation = 0; +// } +// } else { +// orientation = 0; +// } +// switch (orientation) { +// case 0: +// break; +// case 90: +// break; +// case 180: +// break; +// case 270: +// break; +// default: +// log.error("Cannot use orientation of " + orientation +// + " defaulting to zero."); +// orientation = 0; +// break; +// } +// +// return orientation; +// +// } /** * Sets the rotation to be used for portrait pages, valid values are 0 * (default), 90, 180, 270. @@ -1235,13 +1500,14 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ public void setPortraitRotation(int rotation) { - if (rotation == 0 || rotation == 90 || rotation == 180 - || rotation == 270) { + if (rotation == 0 + || rotation == 90 + || rotation == 180 + || rotation == 270) { portraitRotation = rotation; } else { - throw new IllegalArgumentException( - "The portrait rotation must be one" - + " of the values 0, 90, 180, 270"); + throw new IllegalArgumentException("The portrait rotation must be one" + + " of the values 0, 90, 180, 270"); } @@ -1250,19 +1516,20 @@ 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. */ public void setLandscapeRotation(int rotation) { - if (rotation == 0 || rotation == 90 || rotation == 180 - || rotation == 270) { + if (rotation == 0 + || rotation == 90 + || rotation == 180 + || rotation == 270) { landscapeRotation = rotation; } else { - throw new IllegalArgumentException( - "The landscape rotation must be one" - + " of the values 0, 90, 180, 270"); + throw new IllegalArgumentException("The landscape rotation must be one" + + " of the values 0, 90, 180, 270"); } } @@ -1270,7 +1537,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Get the MIME type of the renderer. * - * @return The MIME type of the renderer + * @return The MIME type of the renderer */ public String getMimeType() { return MimeConstants.MIME_AFP; @@ -1280,8 +1547,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * Method to render the page extension. *

* - * @param pageViewport - * the page object + * @param pageViewport the page object */ private void renderPageObjectExtensions(PageViewport pageViewport) { @@ -1292,7 +1558,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // the s-p-m Iterator i = pageViewport.getExtensionAttachments().iterator(); while (i.hasNext()) { - ExtensionAttachment attachment = (ExtensionAttachment) i.next(); + ExtensionAttachment attachment = (ExtensionAttachment)i.next(); if (AFPPageSetup.CATEGORY.equals(attachment.getCategory())) { AFPPageSetup aps = (AFPPageSetup) attachment; String element = aps.getElementName(); @@ -1306,7 +1572,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { String name = aps.getName(); String source = aps.getValue(); if (pageSegmentsMap == null) { - pageSegmentsMap = new HashMap(); + pageSegmentsMap = new java.util.HashMap(); } pageSegmentsMap.put(source, name); } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT @@ -1314,7 +1580,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { String name = aps.getName(); String value = aps.getValue(); if (pageSegmentsMap == null) { - pageSegmentsMap = new HashMap(); + pageSegmentsMap = new java.util.HashMap(); } afpDataStream.createTagLogicalElement(name, value); } else if (AFPElementMapping.NO_OPERATION.equals(element)) { @@ -1322,6 +1588,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (content != null) { afpDataStream.createNoOperation(content); } + } else if (AFPElementMapping.RESOURCE.equals(element)) { + System.out.println("resource: " + attachment); } } } @@ -1331,9 +1599,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Converts FOP mpt measurement to afp measurement units - * - * @param mpt - * the millipoints value + * @param mpt the millipoints value */ private int mpts2units(int mpt) { return mpts2units((double) mpt); @@ -1341,9 +1607,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Converts FOP pt measurement to afp measurement units - * - * @param mpt - * the millipoints value + * @param mpt the millipoints value */ private int pts2units(float mpt) { return mpts2units(mpt * 1000d); @@ -1357,8 +1621,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @return afp measurement unit value */ private int mpts2units(double mpt) { - return (int) Math - .round(mpt / (DPI_CONVERSION_FACTOR / getResolution())); + return (int)Math.round(mpt / (DPI_CONVERSION_FACTOR / getResolution())); } /** @@ -1422,7 +1685,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { io.setImageIDESize((byte) bitsPerPixel); io.setImageData(bw); } - + private final class ViewPortPos { private int x = 0; @@ -1521,7 +1784,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } - private List viewPortPositions = new ArrayList(); + private List viewPortPositions = new java.util.ArrayList(); private void pushViewPortPos(ViewPortPos vpp) { viewPortPositions.add(vpp); @@ -1531,8 +1794,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private void popViewPortPos() { viewPortPositions.remove(viewPortPositions.size() - 1); if (viewPortPositions.size() > 0) { - ViewPortPos vpp = (ViewPortPos) viewPortPositions - .get(viewPortPositions.size() - 1); + ViewPortPos vpp = (ViewPortPos)viewPortPositions.get(viewPortPositions.size() - 1); afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); } } @@ -1546,9 +1808,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { public void setBitsPerPixel(int bitsPerPixel) { this.bitsPerPixel = bitsPerPixel; switch (bitsPerPixel) { - case 1: - case 4: - case 8: + case 1: + case 4: + case 8: break; default: log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8."); @@ -1573,6 +1835,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @return the AFPDataStream */ public AFPDataStream getAFPDataStream() { + if (afpDataStream == null) { + this.afpDataStream = new AFPDataStream(); + } return afpDataStream; } @@ -1583,24 +1848,46 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * the output resolution (dpi) */ public void setResolution(int resolution) { - if (resolution == DPI_240_RESOLUTION - || resolution == DPI_1440_RESOLUTION) { - this.resolution = resolution; - if (log.isDebugEnabled()) { - log.debug("renderer-resolution set to: " + resolution + " dpi"); - } - } else { - log.error("invalid resolution, can only be " + DPI_240_RESOLUTION - + " or " + DPI_1440_RESOLUTION + " dpi"); + if (log.isDebugEnabled()) { + log.debug("renderer-resolution set to: " + resolution + "dpi"); } + this.resolution = resolution; } - + /** * Returns the output/device resolution. - * * @return the resolution in dpi */ public int getResolution() { return this.resolution; } + + private AFPState getState() { + if (currentState == null) { + currentState = new AFPState(); + } + return currentState; + } + + private boolean gocaEnabled = false; + + /** + * @param enabled true if AFP GOCA is enabled for SVG support + */ + protected void setGOCAEnabled(boolean enabled) { + this.gocaEnabled = enabled; + } + + /** + * @return true of AFP GOCA is enabled for SVG support + */ + protected boolean isGOCAEnabled() { + return this.gocaEnabled; + } + + /** {@inheritDoc} */ + public void startPageSequence(LineArea seqTitle) { + afpDataStream.endPageGroup(); + afpDataStream.startPageGroup(); + } } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index 9917eec70..4c8a3dc9f 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -140,18 +140,14 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { return new AFPFontInfo(font, tripleList); } else if ("outline".equalsIgnoreCase(type)) { - String characterset = afpFontCfg.getAttribute("characterset"); if (characterset == null) { log.error("Mandatory afp-font configuration attribute 'characterset=' is missing"); return null; } String name = afpFontCfg.getAttribute("name", characterset); - CharacterSet characterSet = null; - String base14 = afpFontCfg.getAttribute("base14-font", null); - if (base14 != null) { try { Class clazz = Class.forName("org.apache.fop.fonts.base14." @@ -205,7 +201,6 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { + triplet.getWeight()); } } - fontList.add(afi); } } @@ -242,6 +237,31 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger( AFPRenderer.DPI_240_RESOLUTION)); } + + Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false); + if (gocaSupportCfg != null) { + afpRenderer.setGOCAEnabled(true); + } + +// Configuration resourceGroupsCfg = cfg.getChild("resource-groups", false); +// if (resourceGroupsCfg != null) { +// resourceGroupsCfg.getValue("print-file-level"); +// } +// if (externalCfg != null) { +// Configuration[] resourceGroups = externalCfg.getChildren("resource-groups"); +// for (int i = 0; i < resourceGroups.length; i++) { +// String resourceresourceGroups[i].getAttribute("url", null); +// Configuration resourceGroup = externalCfg.getChild("resource-group", false); +// } +// } +// Configuration externalResourceGroupCfg = cfg.getChild("external-resource-group", false); +// if (externalResourceGroupCfg != null) { +//// afpRenderer.setExternalResources(true); +// String resourceLibraryUrl = externalResourceGroupCfg.getAttribute("url", null); +// if (resourceLibraryUrl != null) { +// afpRenderer.setExternalResourceLibraryUrl(resourceLibraryUrl); +// } +// } } } } diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 13fa62514..2641e6fbe 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -22,10 +22,12 @@ package org.apache.fop.render.afp; // FOP import java.awt.geom.AffineTransform; import java.io.IOException; +import java.util.Map; import org.apache.avalon.framework.configuration.Configuration; 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; @@ -33,7 +35,10 @@ import org.apache.commons.logging.LogFactory; 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.render.afp.modca.AFPDataStream; +import org.apache.fop.render.afp.modca.GraphicsObject; +import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.fop.svg.SVGUserAgent; import org.w3c.dom.Document; @@ -65,28 +70,29 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { */ public static AFPInfo getAFPInfo(RendererContext context) { AFPInfo afpi = new AFPInfo(); - afpi.width = ((Integer)context.getProperty(WIDTH)).intValue(); - afpi.height = ((Integer)context.getProperty(HEIGHT)).intValue(); - afpi.currentXPosition = ((Integer)context.getProperty(XPOS)).intValue(); - afpi.currentYPosition = ((Integer)context.getProperty(YPOS)).intValue(); - afpi.cfg = (Configuration)context.getProperty(HANDLER_CONFIGURATION); - afpi.fontInfo = (org.apache.fop.fonts.FontInfo)context.getProperty( - AFPRendererContextConstants.AFP_FONT_INFO); - afpi.resolution = ((Integer)context.getProperty( - AFPRendererContextConstants.AFP_RESOLUTION)).intValue(); - afpi.afpState = (AFPState)context.getProperty( - AFPRendererContextConstants.AFP_STATE); - afpi.afpDataStream = (AFPDataStream)context.getProperty( - AFPRendererContextConstants.AFP_DATASTREAM); - afpi.grayscale = ((Boolean)context.getProperty( - AFPRendererContextConstants.AFP_GRAYSCALE)).booleanValue(); - afpi.bitsPerPixel = ((Integer)context.getProperty( - AFPRendererContextConstants.AFP_BITS_PER_PIXEL)).intValue(); + afpi.setWidth(((Integer)context.getProperty(WIDTH)).intValue()); + afpi.setHeight(((Integer)context.getProperty(HEIGHT)).intValue()); + afpi.setX(((Integer)context.getProperty(XPOS)).intValue()); + afpi.setY(((Integer)context.getProperty(YPOS)).intValue()); + afpi.setHandlerConfiguration((Configuration)context.getProperty(HANDLER_CONFIGURATION)); + afpi.setFontInfo((org.apache.fop.fonts.FontInfo)context.getProperty( + AFPRendererContextConstants.AFP_FONT_INFO)); + afpi.setResolution(((Integer)context.getProperty( + AFPRendererContextConstants.AFP_RESOLUTION)).intValue()); + afpi.setState((AFPState)context.getProperty( + AFPRendererContextConstants.AFP_STATE)); + afpi.setAFPDataStream((AFPDataStream)context.getProperty( + AFPRendererContextConstants.AFP_DATASTREAM)); + afpi.setColor(!((Boolean)context.getProperty( + AFPRendererContextConstants.AFP_GRAYSCALE)).booleanValue()); + afpi.setBitsPerPixel(((Integer)context.getProperty( + AFPRendererContextConstants.AFP_BITS_PER_PIXEL)).intValue()); return afpi; } /** * Render the SVG document. + * * @param context the renderer context * @param doc the SVG document * @param afpInfo the AFPInfo renderer parameters @@ -100,14 +106,16 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); graphics.setAFPInfo(afpInfo); + String uri = ((AbstractDocument)doc).getDocumentURI(); + graphics.setDocumentURI(uri); + GVTBuilder builder = new GVTBuilder(); boolean strokeText = false; - Configuration cfg = afpInfo.cfg; + Configuration cfg = afpInfo.getHandlerConfiguration(); if (cfg != null) { strokeText = cfg.getChild("stroke-text", true).getValueAsBoolean(strokeText); } - final float uaResolution = context.getUserAgent().getSourceResolution(); SVGUserAgent svgUserAgent = new SVGUserAgent(25.4f / uaResolution, new AffineTransform()); @@ -122,7 +130,7 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { AFPTextElementBridge tBridge = new AFPTextElementBridge(textPainter); ctx.putBridge(tBridge); } - + GraphicsNode root; try { root = builder.build(ctx, doc); @@ -132,33 +140,59 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { return; } log.debug("Generating SVG at " - + afpInfo.resolution + "dpi."); + + afpInfo.getResolution() + "dpi."); - int res = afpInfo.resolution; - + int res = afpInfo.getResolution(); double w = ctx.getDocumentSize().getWidth() * 1000f; double h = ctx.getDocumentSize().getHeight() * 1000f; // convert to afp inches - double sx = ((afpInfo.width / w) * res) / 72f; - double sy = ((afpInfo.height / h) * res) / 72f; - double xOffset = (afpInfo.currentXPosition * res) / 72000f; - double yOffset = ((afpInfo.height - afpInfo.currentYPosition) * res) / 72000f; + double sx = ((afpInfo.getWidth() / w) * res) / 72f; + double sy = ((afpInfo.getHeight() / h) * res) / 72f; + double xOffset = (afpInfo.getX() * res) / 72000f; + double yOffset = ((afpInfo.getHeight() - afpInfo.getY()) * res) / 72000f; // Transformation matrix that establishes the local coordinate system for the SVG graphic // in relation to the current coordinate system (note: y axis is inverted) AffineTransform trans = new AffineTransform(sx, 0, 0, -sy, xOffset, yOffset); graphics.setTransform(trans); + + int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000); + int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000); + int width = (int)Math.round((afpInfo.getWidth() * res) / 72000f); + int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f); + + DataObjectParameters params = new DataObjectParameters( + uri, x, y, width, height, res, res); + + Map/**/ foreignAttributes + = (Map/**/)context.getProperty( + RendererContextConstants.FOREIGN_ATTRIBUTES); + + if (foreignAttributes != null) { + params.setResourceLevelFromForeignAttributes(foreignAttributes); + } + + IncludeObject includeObj = afpInfo.getAFPDataStream().createGraphicsObject(params); + GraphicsObject graphicsObj = (GraphicsObject)includeObj.getReferencedObject(); + graphics.setGraphicsObject(graphicsObj); + try { root.paint(graphics); } catch (Exception e) { log.error("SVG graphic could not be rendered: " + e.getMessage(), e); } + + graphics.dispose(); } /** {@inheritDoc} */ public boolean supportsRenderer(Renderer renderer) { - return (renderer instanceof AFPRenderer); + if (renderer instanceof AFPRenderer) { + AFPRenderer afpRenderer = (AFPRenderer)renderer; + return afpRenderer.isGOCAEnabled(); + } + return false; } /** {@inheritDoc} */ @@ -166,4 +200,3 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { return SVGDOMImplementation.SVG_NAMESPACE_URI; } } - diff --git a/src/java/org/apache/fop/render/afp/AFPState.java b/src/java/org/apache/fop/render/afp/AFPState.java index 7cb37e2f3..5977d0de2 100644 --- a/src/java/org/apache/fop/render/afp/AFPState.java +++ b/src/java/org/apache/fop/render/afp/AFPState.java @@ -20,51 +20,18 @@ package org.apache.fop.render.afp; import java.awt.Color; +import java.awt.geom.AffineTransform; +import java.io.Serializable; import java.util.Arrays; +import java.util.List; /** * This keeps information about the current state when writing to pdf. */ public class AFPState { - /** - * The current color - */ - private Color color = null; - - /** - * The current background color - */ - private Color backColor = null; - - /** - * The current font name - */ - private String fontName = null; - - /** - * The current font size - */ - private int fontSize = 0; - - /** - * The current line width - */ - private float lineWidth = 0; - - /** - * The dash array for the current basic stroke (line type) - */ - private float[] dashArray = null; - - /** - * The current fill status - */ - private boolean filled = false; + private Data data = new Data(); - /** - * The fonts on the current page - */ - private AFPPageFonts pageFonts = null; + private List stateStack = new java.util.ArrayList(); /** * Set the current color. @@ -74,8 +41,8 @@ public class AFPState { * @return true if the color has changed */ protected boolean setColor(Color col) { - if (!col.equals(this.color)) { - this.color = col; + if (!col.equals(getData().color)) { + getData().color = col; return true; } return false; @@ -87,8 +54,8 @@ public class AFPState { * @return true if the fill value has changed */ protected boolean setFill(boolean fill) { - if (fill != this.filled) { - this.filled = fill; + if (fill != getData().filled) { + getData().filled = fill; return true; } return false; @@ -99,10 +66,10 @@ public class AFPState { * @return the color */ protected Color getColor() { - if (this.color == null) { - this.color = Color.black; + if (getData().color == null) { + getData().color = Color.black; } - return this.color; + return getData().color; } /** @@ -111,8 +78,8 @@ public class AFPState { * @return true if the line width has changed */ protected boolean setLineWidth(float width) { - if (this.lineWidth != width) { - this.lineWidth = width; + if (getData().lineWidth != width) { + getData().lineWidth = width; return true; } return false; @@ -124,8 +91,8 @@ public class AFPState { * @return true if the dash array has changed */ public boolean setDashArray(float[] dash) { - if (!Arrays.equals(dash, this.dashArray)) { - this.dashArray = dash; + if (!Arrays.equals(dash, getData().dashArray)) { + getData().dashArray = dash; return true; } return false; @@ -136,7 +103,7 @@ public class AFPState { * @return the current line width */ protected float getLineWidth() { - return lineWidth; + return getData().lineWidth; } /** @@ -144,10 +111,10 @@ public class AFPState { * @return the background color */ protected Color getBackColor() { - if (this.backColor == null) { - this.backColor = Color.white; + if (getData().backColor == null) { + getData().backColor = Color.white; } - return backColor; + return getData().backColor; } /** @@ -158,8 +125,8 @@ public class AFPState { * @return true if the color has changed */ protected boolean setBackColor(Color col) { - if (!col.equals(this.backColor)) { - this.backColor = col; + if (!col.equals(getData().backColor)) { + getData().backColor = col; return true; } return false; @@ -171,8 +138,8 @@ public class AFPState { * @return true if the font name has changed */ protected boolean setFontName(String internalFontName) { - if (!internalFontName.equals(this.fontName)) { - this.fontName = internalFontName; + if (!internalFontName.equals(getData().fontName)) { + getData().fontName = internalFontName; return true; } return false; @@ -183,7 +150,7 @@ public class AFPState { * @return the current font name */ protected String getFontName() { - return this.fontName; + return getData().fontName; } /** @@ -191,7 +158,7 @@ public class AFPState { * @return the current font size */ protected int getFontSize() { - return this.fontSize; + return getData().fontSize; } /** @@ -202,8 +169,8 @@ public class AFPState { * @return true if the font size has changed */ protected boolean setFontSize(int size) { - if (size != this.fontSize) { - this.fontSize = size; + if (size != getData().fontSize) { + getData().fontSize = size; return true; } return false; @@ -214,25 +181,98 @@ public class AFPState { * @return the current page fonts */ protected AFPPageFonts getPageFonts() { - if (this.pageFonts == null) { - this.pageFonts = new AFPPageFonts(); + if (getData().pageFonts == null) { + getData().pageFonts = new AFPPageFonts(); } - return this.pageFonts; - } - - /** - * Resets the current state - */ - protected void reset() { - this.color = null; - this.backColor = null; - this.fontName = null; - this.fontSize = 0; - this.lineWidth = 0; - this.dashArray = null; - this.filled = false; - if (this.pageFonts != null) { - this.pageFonts.clear(); + return getData().pageFonts; + } + + /** + * Push the current state onto the stack. + * This call should be used when the q operator is used + * so that the state is known when popped. + */ + public void push() { + Data copy; + try { + copy = (Data)getData().clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e.getMessage()); + } + stateStack.add(copy); + } + + /** + * Get the current stack level. + * + * @return the current stack level + */ + public int getStackLevel() { + return stateStack.size(); + } + + /** + * Pop the state from the stack and set current values to popped state. + * This should be called when a Q operator is used so + * the state is restored to the correct values. + * @return the restored state, null if the stack is empty + */ + public Data pop() { + if (getStackLevel() > 0) { + Data popped = (Data)stateStack.remove(stateStack.size() - 1); + data = popped; + return popped; + } else { + return null; + } + } + + /** + * @return the currently valid state + */ + public Data getData() { + return data; + } + + public class Data implements Cloneable, Serializable { + private static final long serialVersionUID = -1789481244175275686L; + + /** The current color */ + private Color color = null; + + /** The current background color */ + private Color backColor = null; + + /** The current font name */ + private String fontName = null; + + /** The current font size */ + private int fontSize = 0; + + /** The current line width */ + private float lineWidth = 0; + + /** The dash array for the current basic stroke (line type) */ + private float[] dashArray = null; + + /** The current fill status */ + private boolean filled = false; + + /** The fonts on the current page */ + private AFPPageFonts pageFonts = null; + + /** {@inheritDoc} */ + public Object clone() throws CloneNotSupportedException { + Data obj = new Data(); + obj.color = this.color; + obj.backColor = this.backColor; + obj.fontName = this.fontName; + obj.fontSize = this.fontSize; + obj.lineWidth = this.lineWidth; + obj.dashArray = this.dashArray; + obj.filled = this.filled; + obj.pageFonts = this.pageFonts; + return obj; } } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/DataObjectParameters.java b/src/java/org/apache/fop/render/afp/DataObjectParameters.java new file mode 100644 index 000000000..2ec56a4e3 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/DataObjectParameters.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.render.afp; + +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.render.afp.extensions.AFPElementMapping; +import org.apache.fop.util.QName; + +/** + * A list of parameters associated with an AFP data objects + */ +public class DataObjectParameters { + private static final ResourceLevel DEFAULT_RESOURCE_LEVEL = new ResourceLevel(); + + private String uri; + private int x; + private int y; + private int width; + private int height; + private int widthRes; + private int heightRes; + private ResourceLevel resourceLevel = DEFAULT_RESOURCE_LEVEL; + + /** + * Main constructor + * + * @param uri the data object uri + * @param x the data object x coordinate + * @param y the data object y coordinate + * @param width the data object width + * @param height the data object height + * @param widthRes the data object width resolution + * @param heightRes the data object height resolution + */ + public DataObjectParameters(String uri, int x, int y, int width, int height, + int widthRes, int heightRes) { + this.uri = uri; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.widthRes = widthRes; + this.heightRes = heightRes; + } + + /** + * @return the uri of this data object + */ + public String getUri() { + return uri; + } + + /** + * @return the x coordinate of this data object + */ + public int getX() { + return x; + } + + /** + * @return the y coordinate of this data object + */ + public int getY() { + return y; + } + + /** + * @return the width of this data object + */ + public int getWidth() { + return width; + } + + /** + * @return the height of this data object + */ + public int getHeight() { + return height; + } + + /** + * @return the width resolution of this data object + */ + public int getWidthRes() { + return widthRes; + } + + /** + * @return the height resolution of this data object + */ + public int getHeightRes() { + return heightRes; + } + + /** + * @return returns the resource level at which this data object should reside + */ + public ResourceLevel getResourceLevel() { + return resourceLevel; + } + + /** + * Sets the resource level at which this object should reside + * @param resourceLevel the resource level at which this data object should reside + */ + public void setResourceLevel(ResourceLevel resourceLevel) { + this.resourceLevel = resourceLevel; + } + + /** + * Sets the resource level using the given foreign attributes + * @param foreignAttributes a mapping of element attributes names to values + */ + public void setResourceLevelFromForeignAttributes(Map/**/ foreignAttributes) { + if (foreignAttributes != null) { + QName resourceLevelKey = new QName( + AFPElementMapping.NAMESPACE, + "afp:resource-level"); + if (foreignAttributes.containsKey(resourceLevelKey)) { + String level = (String)foreignAttributes.get(resourceLevelKey); + this.resourceLevel = new ResourceLevel(); + if (resourceLevel.setLevel(level)) { + if (resourceLevel.isExternal()) { + QName resourceDestKey = new QName( + AFPElementMapping.NAMESPACE, + "afp:resource-dest"); + String resourceExternalDest + = (String)foreignAttributes.get(resourceDestKey); + resourceLevel.setExternalDest(resourceExternalDest); + } + } else { + Log log = LogFactory.getLog("org.apache.fop.afp"); + log.warn("invalid resource level '" + level + + "', using default document level"); + } + } + } + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "uri=" + uri + + ", x=" + x + + ", y=" + y + + ", width=" + width + + ", height=" + height + + ", widthRes=" + widthRes + + ", heightRes=" + heightRes + + (resourceLevel != null ? ", resourceLevel=" + resourceLevel : ""); + } +} diff --git a/src/java/org/apache/fop/render/afp/ImageObjectParameters.java b/src/java/org/apache/fop/render/afp/ImageObjectParameters.java new file mode 100644 index 000000000..8b430f042 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/ImageObjectParameters.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.afp; + +/** + * A list of parameters associated with an image + */ +public class ImageObjectParameters extends DataObjectParameters { + private int bitsPerPixel; + private boolean color; + private int compression = -1; + private byte[] imageData; + private int imageDataWidth; + private int imageDataHeight; + + /** + * Main constructor + * + * @param uri the image uri + * @param x the image x coordinate + * @param y the image y coordinate + * @param width the image width + * @param height the image height + * @param widthRes the image width resolution + * @param heightRes the image height resolution + */ + public ImageObjectParameters(String uri, int x, int y, int width, int height, + int widthRes, int heightRes, byte[] imageData, + int imageDataWidth, int imageDataHeight, boolean color, int bitsPerPixel) { + super(uri, x, y, width, height, widthRes, heightRes); + this.imageData = imageData; + this.imageDataWidth = imageDataWidth; + this.imageDataHeight = imageDataHeight; + this.color = color; + this.bitsPerPixel = bitsPerPixel; + } + + /** + * @return the numner of bits used per pixel + */ + public int getBitsPerPixel() { + return bitsPerPixel; + } + + /** + * @return true if this is a color image + */ + public boolean isColor() { + return color; + } + + /** + * @return the image data + */ + public byte[] getData() { + return imageData; + } + + /** + * @return true of this image uses compression + */ + public boolean hasCompression() { + return compression > -1; + } + + /** + * @return the compression type + */ + public int getCompression() { + return compression; + } + + /** + * Sets the compression used with this image + * @param compression the type of compression used with this image + */ + public void setCompression(int compression) { + this.compression = compression; + } + + /** + * @return the image data width + */ + public int getImageDataWidth() { + return imageDataWidth; + } + + /** + * Sets the image data width + * @param imageDataWidth the image data width + */ + protected void setImageDataWidth(int imageDataWidth) { + this.imageDataWidth = imageDataWidth; + } + + /** + * @return the image data height + */ + public int getImageDataHeight() { + return imageDataHeight; + } + + /** + * Sets the image data height + * @param imageDataHeight the image data height + */ + protected void setImageDataHeight(int imageDataHeight) { + this.imageDataHeight = imageDataHeight; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return super.toString() + + ", imageDataWidth=" + imageDataWidth + + ", imageDataHeight=" + imageDataHeight + + ", color=" + color + + ", bitPerPixel=" + bitsPerPixel; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/ResourceLevel.java b/src/java/org/apache/fop/render/afp/ResourceLevel.java new file mode 100644 index 000000000..f397edb04 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/ResourceLevel.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; + +/** + * The level at which a resource is to reside in the AFP output + */ +public class ResourceLevel { + private static final String EXTERNAL = "external"; + + private static final String PRINT_FILE = "print-file"; + + private static final String DOCUMENT = "document"; + + private static final String PAGE_GROUP = "page-group"; + + private static final String PAGE = "page"; + + /** + * where the resource will reside in the AFP output + */ + private String level = PAGE; // default is page level + + /** + * the destination location of the resource + */ + private String dest = null; + + /** + * @return true if this is a page level resource group + */ + public boolean isPage() { + return level.equals(PAGE); + } + + /** + * @return true if this is a page group level resource group + */ + public boolean isPageGroup() { + return level.equals(PAGE_GROUP); + } + + /** + * @return true if this is a document level resource group + */ + public boolean isDocument() { + return level.equals(DOCUMENT); + } + + /** + * @return true if this is an external level resource group + */ + public boolean isExternal() { + return level.equals(EXTERNAL); + } + + /** + * @return true if this is a print-file level resource group + */ + public boolean isPrintFile() { + return level.equals(PRINT_FILE); + } + + private boolean isValid(String lvl) { + return lvl.equals(EXTERNAL) + || lvl.equals(PRINT_FILE) + || lvl.equals(DOCUMENT) + || lvl.equals(PAGE_GROUP) + || lvl.equals(PAGE); + } + + /** + * Sets the resource placement level within the AFP output + * @param level the resource level (page, page-group, document, print-file or external) + * @return true if the resource level was successfully set + */ + public boolean setLevel(String level) { + if (isValid(level)) { + this.level = level; + return true; + } + return false; + } + + /** + * @return the external destination of the resource + */ + public String getExternalDest() { + return dest; + } + + /** + * Sets the external destination of the resource + * @param dest the external destination of the resource + */ + public void setExternalDest(String dest) { + this.dest = dest; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "level=" + level + (isExternal() ? ", dest=" + dest : ""); + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java b/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java index 665a77562..6b4bc4eb9 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java @@ -19,14 +19,13 @@ package org.apache.fop.render.afp.extensions; -import org.apache.fop.apps.FOPException; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.StringProperty; /** * This class extends the org.apache.fop.fo.StringProperty.Maker inner class - * in order to provide a static property maker. The object faciliates + * in order to provide a static property maker. The object facilitates * extraction of attributes from formatted objects based on the static list * as defined in the AFPElementMapping implementation. *

@@ -58,5 +57,4 @@ public class AFPAttribute extends StringProperty.Maker { } return property; } - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java index b8bfa74b6..808cd88f1 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java @@ -23,6 +23,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; /** * This class extends the org.apache.fop.extensions.ExtensionObj class. The @@ -54,4 +55,7 @@ public class AFPElement extends AbstractAFPExtensionObject { } } + protected ExtensionAttachment instantiateExtensionAttachment() { + return null; + } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java index 216379cc0..8d4b0ae5e 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java @@ -50,6 +50,9 @@ public class AFPElementMapping extends ElementMapping { /** include page segment element */ public static final String INCLUDE_PAGE_SEGMENT = "include-page-segment"; + /** include resource element (external) */ + public static final String RESOURCE = "resource"; + /** NOP */ public static final String NO_OPERATION = "no-operation"; diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java new file mode 100644 index 000000000..9a8429b00 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.Serializable; + +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.xmlgraphics.util.XMLizable; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * This is the pass-through value object for the AFP extension. + */ +public abstract class AFPExtensionAttachment + implements ExtensionAttachment, Serializable, XMLizable { + private static final long serialVersionUID = 7190606822558332901L; + + /** The category URI for this extension attachment. */ + public static final String CATEGORY = "apache:fop:extensions:afp"; + + /** + * the extension element name + */ + protected String elementName; + + /** + * the extension content + */ + protected String content; + + /** + * the extension name attribute + */ + protected String name; + + /** + * the extension value attribute + */ + protected String value; + + /** + * Default constructor. + * + * @param elementName the name of the afp extension attachment, may be null + */ + public AFPExtensionAttachment(String elementName) { + this.elementName = elementName; + } + + /** @return the name */ + public String getElementName() { + return elementName; + } + + /** + * @return true if this element has a name attribute + */ + protected boolean hasName() { + return name != null; + } + + /** @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 the value + */ + public String getValue() { + return value; + } + + /** + * Sets the value + * @param source The value name to set. + */ + public void setValue(String source) { + this.value = source; + } + + /** {@inheritDoc} */ + public String getCategory() { + return CATEGORY; + } + + /** + * @return the data + */ + public String getContent() { + return content; + } + + /** + * Sets the data + * @param content The byte data to set. + */ + public void setContent(String content) { + this.content = content; + } + + /** + * name attribute + */ + protected static final String ATT_NAME = "name"; + + /** + * value attribute + */ + protected static final String ATT_VALUE = "value"; + + /** {@inheritDoc} */ + 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); + } + if (value != null && value.length() > 0) { + atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value); + } + handler.startElement(CATEGORY, elementName, elementName, atts); + if (content != null && content.length() > 0) { + char[] chars = content.toCharArray(); + handler.characters(chars, 0, chars.length); + } + handler.endElement(CATEGORY, elementName, elementName); + } +} 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 7fdf7cd11..72d7639bd 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java @@ -54,7 +54,9 @@ public class AFPExtensionHandler extends DefaultHandler || localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) || localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) || localName.equals(AFPElementMapping.PAGE) - || localName.equals(AFPElementMapping.PAGE_GROUP)) { + || localName.equals(AFPElementMapping.PAGE_GROUP) + || localName.equals(AFPElementMapping.PAGE_GROUP) + || localName.equals(AFPResource.ELEMENT)) { //handled in endElement } else { handled = false; 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 91ab2dfa5..437222daa 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java @@ -19,33 +19,10 @@ package org.apache.fop.render.afp.extensions; -import java.io.Serializable; - -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 class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizable { - - private static final long serialVersionUID = 7190606822558332901L; - - /** The category URI for this extension attachment. */ - public static final String CATEGORY = "apache:fop:extensions:afp"; - - private String elementName; - - private String name; - - private String value; - - private String content; +public class AFPPageSetup extends AFPExtensionAttachment { /** * Default constructor. @@ -53,85 +30,16 @@ public class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizabl * @param elementName the name of the setup code object, may be null */ public AFPPageSetup(String elementName) { - this.elementName = elementName; + super(elementName); } - /** @return the name */ - public String getElementName() { - return elementName; - } - - /** @return the name */ - public String getName() { - return name; - } + private static final long serialVersionUID = -549941295384013190L; /** - * Sets the name of the setup code object. - * @param name The name to set. + * {@inheritDoc} */ - public void setName(String name) { - this.name = name; - } - - /** - * @return the value - */ - public String getValue() { - return value; - } - - /** - * Sets the value - * @param source The value name to set. - */ - public void setValue(String source) { - this.value = source; - } - - /** {@inheritDoc} */ - public String getCategory() { - return CATEGORY; - } - - /** - * @return the data - */ - public String getContent() { - return content; - } - - /** - * Sets the data - * @param content The byte data to set. - */ - public void setContent(String content) { - this.content = content; - } - - /** {@inheritDoc} */ public String toString() { return "AFPPageSetup(element-name=" + getElementName() + " name=" + getName() + " value=" + getValue() + ")"; } - - private static final String ATT_NAME = "name"; - private static final String ATT_VALUE = "value"; - - /** {@inheritDoc} */ - 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); - } - if (value != null && value.length() > 0) { - atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value); - } - handler.startElement(CATEGORY, elementName, elementName, atts); - if (content != null && content.length() > 0) { - char[] chars = content.toCharArray(); - handler.characters(chars, 0, chars.length); - } - handler.endElement(CATEGORY, elementName, elementName); - } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java index 4971928f8..d167a8d4b 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java @@ -23,9 +23,10 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; /** - * Extension element for fox:ps-page-setup-code. + * Extension element for afp:ps-page-setup-code. */ public class AFPPageSetupElement extends AbstractAFPExtensionObject { @@ -45,4 +46,10 @@ public class AFPPageSetupElement extends AbstractAFPExtensionObject { } } + /** + * {@inheritDoc} + */ + protected ExtensionAttachment instantiateExtensionAttachment() { + return new AFPPageSetup(this.name); + } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java index e641d2df8..ff6d56785 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java +++ b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java @@ -34,11 +34,14 @@ import org.xml.sax.Locator; public abstract class AbstractAFPExtensionObject extends FONode { /** - * AFP setup code + * the AFP extension attachment */ - private AFPPageSetup setupCode; + protected AFPExtensionAttachment extensionAttachment; - private String name; + /** + * the element name of this extension + */ + protected String name; /** * @see org.apache.fop.fo.FONode#FONode(FONode) @@ -48,10 +51,11 @@ public abstract class AbstractAFPExtensionObject extends FONode { public AbstractAFPExtensionObject(FONode parent, String name) { super(parent); this.name = name; - this.setupCode = new AFPPageSetup(name); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { @@ -59,60 +63,85 @@ public abstract class AbstractAFPExtensionObject extends FONode { } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected void addCharacters(char[] data, int start, int end, - PropertyList pList, Locator locator) { - setupCode.setContent(new String(data, start, end - start)); + PropertyList pList, Locator locator) throws FOPException { + ((AFPExtensionAttachment)getExtensionAttachment()).setContent( + new String(data, start, end - start)); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getNamespaceURI() { return AFPElementMapping.NAMESPACE; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getNormalNamespacePrefix() { return AFPElementMapping.NAMESPACE_PREFIX; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException { - String name = attlist.getValue("name"); - if (name != null && name.length() > 0) { - setupCode.setName(name); + getExtensionAttachment(); + String attr = attlist.getValue("name"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setName(attr); } else { throw new FOPException(elementName + " must have a name attribute."); } if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) { - name = attlist.getValue("src"); - if (name != null && name.length() > 0) { - setupCode.setValue(name); + attr = attlist.getValue("src"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setValue(attr); } else { throw new FOPException(elementName + " must have a src attribute."); } } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) { - name = attlist.getValue("value"); - if (name != null && name.length() > 0) { - setupCode.setValue(name); + attr = attlist.getValue("value"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setValue(attr); } else { throw new FOPException(elementName + " must have a value attribute."); } } } - - /** {@inheritDoc} */ + + /** + * {@inheritDoc} + */ protected void endOfNode() throws FOPException { super.endOfNode(); } - /** {@inheritDoc} */ + /** + * Instantiates extension attachment object + * @return extension attachment + */ + protected abstract ExtensionAttachment instantiateExtensionAttachment(); + + /** + * {@inheritDoc} + */ public ExtensionAttachment getExtensionAttachment() { - return this.setupCode; + if (extensionAttachment == null) { + this.extensionAttachment = (AFPExtensionAttachment)instantiateExtensionAttachment(); + } + return this.extensionAttachment; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getLocalName() { return name; } diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java index 62de923c8..bf534e3c7 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java @@ -20,6 +20,7 @@ package org.apache.fop.render.afp.modca; import java.awt.Color; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; @@ -28,7 +29,11 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.render.afp.AFPFontAttributes; +import org.apache.fop.render.afp.DataObjectParameters; +import org.apache.fop.render.afp.ImageObjectParameters; +import org.apache.fop.render.afp.ResourceLevel; import org.apache.fop.render.afp.fonts.AFPFont; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.tools.StringUtils; /** @@ -47,7 +52,7 @@ import org.apache.fop.render.afp.tools.StringUtils; * them. * */ -public class AFPDataStream { +public class AFPDataStream extends AbstractResourceGroupContainer { /** * Static logging instance @@ -80,6 +85,11 @@ public class AFPDataStream { */ private PageObject currentPageObject = null; + /** + * The current resource group + */ +// private ResourceGroup currentResourceGroup = null; + /** * The current overlay object */ @@ -98,8 +108,7 @@ public class AFPDataStream { /** * The page group count */ -// not used -// private int pageGroupCount = 0; + private int pageGroupCount = 0; /** * The overlay count @@ -135,40 +144,71 @@ public class AFPDataStream { * The outputstream for the data stream */ private OutputStream outputStream = null; + + /** + * A mapping of external resource destinations to resource groups + */ + private Map/**/ externalResourceGroups = null; /** * Default constructor for the AFPDataStream. */ public AFPDataStream() { + this.document = new Document(); + } + + private Document getDocument() { + return this.document; + } + + private AbstractPageObject getCurrentPage() { + return this.currentPage; } /** * The document is started by invoking this method which creates an instance * of the AFP Document object. * - * @param docOutputStream - * the outputStream which the document is written to. - */ - public void startDocument(OutputStream docOutputStream) { - if (document != null) { - String msg = "Invalid state - document already started."; - log.warn("startDocument():: " + msg); - throw new IllegalStateException(msg); + * @param name + * the name of this document. + */ + public void setDocumentName(String name) { +// if (document != null) { +// String msg = "Invalid state - document already started."; +// log.warn("startDocument():: " + msg); +// throw new IllegalStateException(msg); +// } +// if (document != null) { +// String msg = "Invalid state - print file level document already started"; +// log.warn(msg); +// throw new IllegalStateException(msg); +// } + + if (name != null) { + document.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_DOCUMENT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, + name); } - - this.document = new Document(); - this.outputStream = docOutputStream; } /** - * The document is ended by invoking this method which creates an instance + * Sets the OutputStream + * @param outputStream the AFP OutputStream + */ + public void setOutputStream(OutputStream outputStream) { + this.outputStream = outputStream; + } + + /** + * The document is written/ended by invoking this method which creates an instance * of the AFP Document object and registers the start with a validation map * which ensures that methods are not invoked out of the correct sequence. * * @throws java.io.IOException * throws an I/O exception of some sort has occurred */ - public void endDocument() throws IOException { + public void write() throws IOException { if (complete) { String msg = "Invalid state - document already ended."; log.warn("endDocument():: " + msg); @@ -185,8 +225,22 @@ public class AFPDataStream { endPageGroup(); } - document.endDocument(); - document.writeDataStream(this.outputStream); + // Write out any external resource groups + if (externalResourceGroups != null) { + writeExternalResources(); + } + + // Write out any print-file level resources + if (hasResources()) { + getResourceGroup().writeDataStream(this.outputStream); + } + + // Write out document + if (document != null) { + document.endDocument(); + document.writeDataStream(this.outputStream); + } + this.outputStream.flush(); complete = true; @@ -195,7 +249,7 @@ public class AFPDataStream { this.outputStream = null; } - + /** * Start a new page. When processing has finished on the current page, the * {@link #endPage()}method must be invoked to mark the page ending. @@ -213,7 +267,6 @@ public class AFPDataStream { */ public void startPage(int pageWidth, int pageHeight, int pageRotation, int pageWidthRes, int pageHeightRes) { - String pageName = "PGN" + StringUtils.lpad(String.valueOf(pageCount++), '0', 5); @@ -229,34 +282,30 @@ public class AFPDataStream { * the {@link #endOverlay()}method must be invoked to mark the overlay * ending. * - * @param overlayX + * @param x * the x position of the overlay on the page - * @param overlayY + * @param y * the y position of the overlay on the page - * @param overlayWidth + * @param width * the width of the overlay - * @param overlayHeight + * @param height * the height of the overlay - * @param overlayWidthResolution + * @param widthRes * the width resolution of the overlay - * @param overlayHeightResolution + * @param heightRes * the height resolution of the overlay - * @param overlayRotation + * @param rotation * the rotation of the overlay */ - public void startOverlay(int overlayX, int overlayY, int overlayWidth, - int overlayHeight, int overlayWidthResolution, - int overlayHeightResolution, int overlayRotation) { - + public void startOverlay(int x, int y, int width, int height, int widthRes, + int heightRes, int rotation) { String overlayName = "OVL" + StringUtils.lpad(String.valueOf(ovlCount++), '0', 5); - currentOverlay = new Overlay(overlayName, overlayWidth, overlayHeight, - overlayWidthResolution, overlayHeightResolution, - overlayRotation); - currentPageObject.addOverlay(currentOverlay); - currentPageObject.createIncludePageOverlay(overlayName, overlayX, - overlayY, 0); + currentOverlay = new Overlay(overlayName, width, height, + widthRes, heightRes, rotation); + + currentPageObject.createIncludePageOverlay(overlayName, x, y, 0); currentPage = currentOverlay; setOffsets(0, 0, 0); } @@ -300,17 +349,13 @@ public class AFPDataStream { /** * Helper method to mark the end of the current page. - * - * @throws java.io.IOException - * thrown when an I/O exception of some sort has occurred */ - public void endPage() throws IOException { + public void endPage() { currentPageObject.endPage(); if (currentPageGroup != null) { currentPageGroup.addPage(currentPageObject); } else { document.addPage(currentPageObject); - document.writeDataStream(this.outputStream); } currentPageObject = null; currentPage = null; @@ -363,7 +408,6 @@ public class AFPDataStream { currentPage.createFont(fontReference, font, size); } - /** * Helper method to create text on the current page, this method delegates * to the current presentation text object in order to construct the text. @@ -388,55 +432,46 @@ public class AFPDataStream { currentPage.createText(fontReference, x + xOffset, y + yOffset, rotation, col, vsci, ica, data); } - + /** - * Returns an ImageObject used to create an image in the datastream. - * - * @param x - * the x position of the image - * @param y - * the y position of the image - * @param width - * the width of the image - * @param height - * the height of the image - * @param widthRes - * the resolution width of the image - * @param heightRes - * the resolution height of the image + * Returns true if the resource exists within this resource group, + * false otherwise. + * + * @param uri the uri of the resource + * @return true if the resource exists within this resource group + */ + public boolean resourceExists(String uri) { + return getResourceGroup().resourceExists(uri); + } + + /** + * Returns an IncludeObject referencing an image in the datastream. + * + * @param params + * the unique uri of the image * @return - * a new image object + * a new include object referencing an image object */ - public ImageObject getImageObject(int x, int y, int width, int height, - int widthRes, int heightRes) { - ImageObject imageObj = currentPage.getImageObject(); - setObjectViewPort(imageObj, x, y, width, height, widthRes, heightRes); - return imageObj; + public IncludeObject createImageObject(ImageObjectParameters params) { + ResourceLevel resourceLevel = params.getResourceLevel(); + IncludeObject includeObj = getResourceGroup(resourceLevel).addObject(params); + currentPage.addObject(includeObj); + return includeObj; } /** - * Returns an GraphicObject used to create an graphic in the datastream. + * Returns an IncludeObject referencing a graphic in the datastream. * - * @param x - * the x position of the graphic - * @param y - * the y position of the graphic - * @param width - * the width of the graphic - * @param height - * the height of the graphic - * @param widthRes - * the resolution width of the graphic - * @param heightRes - * the resolution height of the graphic + * @param params + * the data object parameters * @return - * a new graphics object + * a new include object referencing the graphics object */ - public GraphicsObject getGraphicsObject(int x, int y, int width, int height, - int widthRes, int heightRes) { - GraphicsObject graphicsObj = currentPage.getGraphicsObject(); - setObjectViewPort(graphicsObj, x, y, width, height, widthRes, heightRes); - return graphicsObj; + public IncludeObject createGraphicsObject(DataObjectParameters params) { + ResourceLevel resourceLevel = params.getResourceLevel(); + IncludeObject includeObj = getResourceGroup(resourceLevel).addObject(params); + currentPage.addObject(includeObj); + return includeObj; } /** @@ -559,9 +594,7 @@ public class AFPDataStream { */ public void createIncludePageOverlay(String name) { currentPageObject.createIncludePageOverlay(name, 0, 0, rotation); - ActiveEnvironmentGroup aeg = currentPageObject - .getActiveEnvironmentGroup(); - aeg.createOverlay(name); + currentPageObject.getActiveEnvironmentGroup().createOverlay(name); } /** @@ -571,10 +604,7 @@ public class AFPDataStream { * the name of the medium map */ public void createInvokeMediumMap(String name) { - if (currentPageGroup == null) { - startPageGroup(); - } - currentPageGroup.createInvokeMediumMap(name); + getCurrentPageGroup().createInvokeMediumMap(name); } /** @@ -621,7 +651,7 @@ public class AFPDataStream { for (int i = 0; i < attributes.length; i++) { String name = (String) attributes[i].getKey(); String value = (String) attributes[i].getValue(); - currentPage.createTagLogicalElement(name, value); + getCurrentPage().createTagLogicalElement(name, value); } } @@ -635,7 +665,7 @@ public class AFPDataStream { for (int i = 0; i < attributes.length; i++) { String name = (String) attributes[i].getKey(); String value = (String) attributes[i].getValue(); - currentPageGroup.createTagLogicalElement(name, value); + getCurrentPageGroup().createTagLogicalElement(name, value); } } @@ -665,31 +695,33 @@ public class AFPDataStream { currentPage.createNoOperation(content); } + private PageGroup getCurrentPageGroup() { + if (currentPageGroup == null) { + String pageGroupName = "PGP" + + StringUtils.lpad(String.valueOf(pageGroupCount++), '0', 5); + this.currentPageGroup = new PageGroup(pageGroupName); + } + return currentPageGroup; + } + /** * Start a new page group. When processing has finished on the current page * group the {@link #endPageGroup()}method must be invoked to mark the page * group ending. */ public void startPageGroup() { - - String pageGroupName = "PGP" - + StringUtils.lpad(String.valueOf(pageCount++), '0', 5); - - currentPageGroup = new PageGroup(pageGroupName); - + getCurrentPageGroup(); } /** * Helper method to mark the end of the page group. - * @throws IOException thrown if an I/O exception of some sort has occurred */ - public void endPageGroup() throws IOException { - - currentPageGroup.endPageGroup(); - document.addPageGroup(currentPageGroup); - document.writeDataStream(outputStream); - currentPageGroup = null; - + public void endPageGroup() { + if (currentPageGroup != null) { + currentPageGroup.endPageGroup(); + document.addPageGroup(currentPageGroup); + currentPageGroup = null; + } } /** @@ -700,7 +732,6 @@ public class AFPDataStream { * The rotation in degrees. */ public void setPortraitRotation(int pageRotation) { - if (pageRotation == 0 || pageRotation == 90 || pageRotation == 180 || pageRotation == 270) { this.portraitRotation = pageRotation; @@ -708,7 +739,6 @@ public class AFPDataStream { throw new IllegalArgumentException( "The portrait rotation must be one of the values 0, 90, 180, 270"); } - } /** @@ -719,7 +749,6 @@ public class AFPDataStream { * The rotation in degrees. */ public void setLandscapeRotation(int pageRotation) { - if (pageRotation == 0 || pageRotation == 90 || pageRotation == 180 || pageRotation == 270) { this.landscapeRotation = pageRotation; @@ -727,6 +756,72 @@ public class AFPDataStream { throw new IllegalArgumentException( "The landscape rotation must be one of the values 0, 90, 180, 270"); } + } + + /** + * Writes out external AFP resources + */ + private void writeExternalResources() { + // write any external resources + Iterator it = getExternalResourceGroups().keySet().iterator(); + while (it.hasNext()) { + String externalDest = (String)it.next(); + ResourceGroup resourceGroup + = (ResourceGroup)getExternalResourceGroups().get(externalDest); + OutputStream os = null; + try { + log.debug("Writing external AFP resource file " + externalDest); + os = new java.io.FileOutputStream(externalDest); + resourceGroup.writeDataStream(os); + } catch (FileNotFoundException e) { + log.error("Failed to open external AFP resource file " + + externalDest); + } catch (IOException e) { + log.error("An error occurred when attempting to write external AFP resource file " + + externalDest); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + log.error("Failed to close outputstream for external AFP resource file " + + externalDest); + } + } + } + } + } + /** + * Returns the resource group for a given resource level + * @param resourceLevel a resource level + * @return a resource group container for the given level + */ + private ResourceGroup getResourceGroup(ResourceLevel resourceLevel) { + ResourceGroup resourceGroup = null; + if (resourceLevel.isPrintFile()) { + resourceGroup = this.getResourceGroup(); + } else if (resourceLevel.isDocument()) { + resourceGroup = document.getResourceGroup(); + } else if (resourceLevel.isPageGroup()) { + resourceGroup = getCurrentPageGroup().getResourceGroup(); + } else if (resourceLevel.isPage()) { + resourceGroup = getCurrentPage().getResourceGroup(); + } else if (resourceLevel.isExternal()) { + String externalDest = resourceLevel.getExternalDest(); + resourceGroup = (ResourceGroup)getExternalResourceGroups().get(externalDest); + if (resourceGroup == null) { + resourceGroup = new ResourceGroup(); + externalResourceGroups.put(externalDest, resourceGroup); + } + } + return resourceGroup; + } + + private Map/**/ getExternalResourceGroups() { + if (externalResourceGroups == null) { + externalResourceGroups = new java.util.HashMap(); + } + return externalResourceGroups; } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java index cd8b25810..26d42b2d4 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java @@ -21,8 +21,8 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +import java.util.Collection; import java.util.Iterator; -import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -50,16 +50,18 @@ public abstract class AbstractAFPObject { /** * Help method to write a set of AFPObjects to the AFP datastream. - * @param afpObjects a list of AFPObjects + * @param objects a list of AFPObjects * @param os The stream to write to * @throws java.io.IOException in the event that an I/O exception occurred */ - protected void writeObjectList(List afpObjects, OutputStream os) + protected void writeObjects(Collection/**/ objects, OutputStream os) throws IOException { - - Iterator it = afpObjects.iterator(); - while (it.hasNext()) { - ((AbstractAFPObject)it.next()).writeDataStream(os); + if (objects != null) { + for (Iterator it = objects.iterator(); it.hasNext();) { + Object obj1 = it.next(); + AbstractAFPObject obj = (AbstractAFPObject)obj1; + obj.writeDataStream(os); + } } } -} +} \ No newline at end of file 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 cf5aad382..aa97065d1 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java @@ -22,7 +22,7 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.modca.goca.AbstractGraphicsContainer; +import org.apache.fop.render.afp.goca.AbstractGraphicsContainer; /** * Abstract base class used by the ImageObject and GraphicsObject which both diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/AbstractEnvironmentGroup.java new file mode 100644 index 000000000..3f371d628 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractEnvironmentGroup.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; +import java.util.List; + +/** + * A base class that encapsulates common features of + * ActiveEnvironmentGroup and ResourceEnvironmentGroup + */ +public abstract class AbstractEnvironmentGroup extends AbstractNamedAFPObject { + + /** + * The collection of MapPageOverlay objects + */ + protected List mapPageOverlays = null; + + /** + * Main constructor + * @param name the object name + */ + public AbstractEnvironmentGroup(String name) { + super(name); + } + + private List getMapPageOverlays() { + if (mapPageOverlays == null) { + mapPageOverlays = new java.util.ArrayList(); + } + return mapPageOverlays; + } + + /** + * Actually creates the MPO object. + * Also creates the supporting object (an IPO) + * @param name the name of the overlay to be used + */ + public void createOverlay(String name) { + MapPageOverlay mpo = getCurrentMapPageOverlay(); + if (mpo == null) { + mpo = new MapPageOverlay(); + getMapPageOverlays().add(mpo); + } + + try { + mpo.addOverlay(name); + } catch (MaximumSizeExceededException msee) { + mpo = new MapPageOverlay(); + getMapPageOverlays().add(mpo); + try { + mpo.addOverlay(name); + } catch (MaximumSizeExceededException ex) { + // Should never happen (but log just in case) + log.error("createOverlay():: resulted in a MaximumSizeExceededException"); + } + } + } + + /** + * Getter method for the most recent MapPageOverlay added to the + * Active Environment Group (returns null if no MapPageOverlay exist) + * @return the most recent Map Coded Font + */ + private MapPageOverlay getCurrentMapPageOverlay() { + if (mapPageOverlays != null && mapPageOverlays.size() > 0) { + return (MapPageOverlay) mapPageOverlays.get(mapPageOverlays.size() - 1); + } else { + return null; + } + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + if (mapPageOverlays != null) { + writeObjects(mapPageOverlays, os); + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java index 7545ee3af..393cff84b 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java @@ -18,14 +18,17 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.UnsupportedEncodingException; /** * This is the base class for all named data stream objects. * A named data stream object has an 8 byte EBCIDIC name. */ -public abstract class AbstractNamedAFPObject extends AbstractAFPObject { - +public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject { + + private static final int DEFAULT_NAME_LENGTH = 8; + /** * The actual name of the object */ @@ -41,22 +44,13 @@ public abstract class AbstractNamedAFPObject extends AbstractAFPObject { */ protected AbstractNamedAFPObject() { } - - private static final int DEFAULT_NAME_LENGTH = 8; - - /** - * @return the name length of this object - */ - protected int getNameLength() { - return DEFAULT_NAME_LENGTH; - } - + /** * Constructor for the ActiveEnvironmentGroup, this takes a * name parameter which should be 8 characters long. * @param name the object name */ - public AbstractNamedAFPObject(String name) { + protected AbstractNamedAFPObject(String name) { int nameLen = getNameLength(); if (name.length() < nameLen) { this.name = (name + " ").substring(0, nameLen); @@ -66,19 +60,27 @@ public abstract class AbstractNamedAFPObject extends AbstractAFPObject { } else { this.name = name; } - try { - this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException usee) { - this.nameBytes = name.getBytes(); log.warn( "Constructor:: UnsupportedEncodingException translating the name " + name); - } - + } + + /** + * @return the name length of this object + */ + protected int getNameLength() { + return DEFAULT_NAME_LENGTH; + } + + /** + * @return the name of the page group + */ + public String getName() { + return name; } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java index 4ffcc4d94..f373b5bf7 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java @@ -20,7 +20,8 @@ package org.apache.fop.render.afp.modca; import java.awt.Color; -import java.util.ArrayList; +import java.io.IOException; +import java.io.OutputStream; import java.util.List; import org.apache.fop.render.afp.fonts.AFPFont; @@ -46,32 +47,27 @@ import org.apache.fop.render.afp.tools.StringUtils; * in page state. * */ -public abstract class AbstractPageObject extends AbstractNamedAFPObject { +public abstract class AbstractPageObject extends AbstractResourceGroupContainer { /** * The active environment group for the page */ - protected ActiveEnvironmentGroup activeEnvironmentGroup = null; + protected ActiveEnvironmentGroup activeEnvironmentGroup; /** * The presentation text object, we only have one per page */ - private PresentationTextObject presentationTextObject = null; - - /** - * The list of objects within the page - */ - protected List objects = new ArrayList(); + private PresentationTextObject presentationTextObject; /** * The list of tag logical elements */ - protected ArrayList tagLogicalElements = new ArrayList(); + protected List tagLogicalElements; /** * The list of the include page segments */ - protected ArrayList segments = new ArrayList(); + protected List segments; /** * The page width @@ -112,8 +108,8 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { */ public AbstractPageObject(String name, int width, int height, int rotation, int widthRes, int heightRes) { - super(name); + this.width = width; this.height = height; this.rotation = rotation; @@ -121,7 +117,8 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { /** * Every page object must have an ActiveEnvironmentGroup */ - activeEnvironmentGroup = new ActiveEnvironmentGroup(width, height, widthRes, heightRes); + this.activeEnvironmentGroup = new ActiveEnvironmentGroup( + width, height, widthRes, heightRes); if (rotation != 0) { switch (rotation) { @@ -152,7 +149,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * the point size of the font */ public void createFont(int fontReference, AFPFont font, int size) { - activeEnvironmentGroup.createFont(fontReference, font, size, 0); + getActiveEnvironmentGroup().createFont(fontReference, font, size, 0); } /** @@ -183,7 +180,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * Helper method to create text on the current page, this method delegates * to the presentation text object in order to construct the text. * - * @param fontReference + * @param fontRef * the font number used as the resource identifier * @param x * the x coordinate of the text data @@ -200,15 +197,15 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * @param data * the text data to create */ - public void createText(int fontReference, int x, int y, int textRotation, Color col, + public void createText(int fontRef, int x, int y, int textRotation, Color col, int vsci, int ica, byte[] data) { getPresentationTextObject().createTextData( - fontReference, x, y, textRotation, col, vsci, ica, data); + fontRef, x, y, textRotation, col, vsci, ica, data); } /** * Helper method to mark the end of the page. This should end the control - * sequence on the current presenation text object. + * sequence on the current presentation text object. */ public void endPage() { if (presentationTextObject != null) { @@ -237,14 +234,11 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * @param blue * the blue value */ - public void createShading(int x, int y, int w, int h, int red, int green, - int blue) { - + public void createShading(int x, int y, int w, int h, int red, int green, int blue) { int xCoord = 0; int yCoord = 0; int areaWidth = 0; int areaHeight = 0; - switch (rotation) { case 90: xCoord = areaWidth - y - h; @@ -278,7 +272,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { int greyscale = Math.round((shade / 255) * 16); String imageName = "IMG" - + StringUtils.lpad(String.valueOf(objects.size() + 1), + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); IMImageObject io = new IMImageObject(imageName); @@ -291,17 +285,23 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { icp.setYSize(8); //defining this as a resource - ImageRasterData ird = new ImageRasterData(ImageRasterPattern - .getRasterData(greyscale)); + ImageRasterData ird = new ImageRasterData( + ImageRasterPattern.getRasterData(greyscale)); io.setImageOutputControl(ioc); io.setImageInputDescriptor(iid); io.setImageCellPosition(icp); io.setImageRasterData(ird); - objects.add(io); - + addObject(io); } + private void endPresentationObject() { + if (presentationTextObject != null) { + presentationTextObject.endControlSequence(); + presentationTextObject = null; + } + } + /** * Helper method to create a presentation text object * on the current page and to return the object. @@ -310,48 +310,11 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { private PresentationTextObject getPresentationTextObject() { if (presentationTextObject == null) { this.presentationTextObject = new PresentationTextObject(); - objects.add(this.presentationTextObject); + addObject(this.presentationTextObject); } return presentationTextObject; } - /** - * Helper method to create an image on the current page and to return - * the object. - * @return the image object - */ - public ImageObject getImageObject() { - - if (presentationTextObject != null) { - presentationTextObject.endControlSequence(); - presentationTextObject = null; - } - String imageName = "IMG" - + StringUtils.lpad(String.valueOf(objects.size() + 1), - '0', 5); - ImageObject imageObj = new ImageObject(imageName); - objects.add(imageObj); - return imageObj; - } - - /** - * Helper method to create a graphic on the current page and to return - * the object. - * @return the graphics object - */ - public GraphicsObject getGraphicsObject() { - if (presentationTextObject != null) { - presentationTextObject.endControlSequence(); - presentationTextObject = null; - } - String graphicName = "GRA" - + StringUtils.lpad(String.valueOf(objects.size() + 1), - '0', 5); - GraphicsObject graphicsObj = new GraphicsObject(graphicName); - objects.add(graphicsObj); - return graphicsObj; - } - /** * Creates a TagLogicalElement on the page. * @@ -362,6 +325,9 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { */ public void createTagLogicalElement(String name, String value) { TagLogicalElement tle = new TagLogicalElement(name, value); + if (tagLogicalElements == null) { + tagLogicalElements = new java.util.ArrayList(); + } tagLogicalElements.add(tle); } @@ -371,8 +337,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * @param content the byte data */ public void createNoOperation(String content) { - NoOperation noOp = new NoOperation(content); - objects.add(noOp); + addObject(new NoOperation(content)); } /** @@ -387,6 +352,9 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { */ public void createIncludePageSegment(String name, int xCoor, int yCoor) { IncludePageSegment ips = new IncludePageSegment(name, xCoor, yCoor); + if (segments == null) { + segments = new java.util.ArrayList(); + } segments.add(ips); } @@ -430,4 +398,54 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { public int getRotation() { return rotation; } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + getActiveEnvironmentGroup().writeDataStream(os); + writeObjects(segments, os); + writeObjects(tagLogicalElements, os); + writeObjects(objects, os); + } + +// /** +// * {@inheritDoc} +// */ +// public IncludeObject createImageObject(ImageObjectParameters params) { +// endPresentationObject(); +// return super.createImageObject(params); +// } +// +// /** +// * {@inheritDoc} +// */ +// public IncludeObject createGraphicsObject(DataObjectParameters params) { +// endPresentationObject(); +// return super.createGraphicsObject(params); +// } + + /** + * {@inheritDoc} + */ + protected void addObject(AbstractStructuredAFPObject obj) { + if (obj instanceof IncludeObject) { + IncludeObject includeObj = (IncludeObject)obj; + AbstractStructuredAFPObject refObj = includeObj.getReferencedObject(); + if (refObj instanceof ImageObject || refObj instanceof GraphicsObject) { + getActiveEnvironmentGroup().createResource(refObj); + } + } + endPresentationObject(); + super.addObject(obj); + } + +// /** +// * {@inheritDoc} +// */ +// protected void addObject(AbstractStructuredAFPObject obj) { +// endPresentationObject(); +// super.addObject(obj); +// } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java new file mode 100644 index 000000000..e40aa1b4f --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + + +/** + * A base class that carries out early preparation of structured field data + * for the AFP object (so the data length can be pre-calculated) + */ +public abstract class AbstractPreparedAFPObject extends AbstractNamedAFPObject +implements PreparedAFPObject { + + /** structured field data to be written */ + protected byte[] data = null; + + /** + * Default constructor + */ + public AbstractPreparedAFPObject() { + } + + /** + * Named constructor + * @param name the name of this AFP object + */ + public AbstractPreparedAFPObject(String name) { + super(name); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); // write triplets + if (this.data != null) { + os.write(this.data); + } + } + + /** + * @return the start data length of this structured field + */ + protected int getStartDataLength() { + return 0; + } + + /** + * @return the data length of the structured field data of this AFP object + */ + public int getDataLength() { + if (this.data != null) { + return this.data.length; + } + return 0; + } + + /** + * @return the structured field length + */ + protected int getLength() { + return getStartDataLength() + getTripletDataLength() + getDataLength(); + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java new file mode 100644 index 000000000..eac4b778f --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; +import java.util.Iterator; + +/** + * An abstract class which encapsulates the common features of + * Document and PageGroup resource containers + */ +public abstract class AbstractResourceEnvironmentGroupContainer + extends AbstractResourceGroupContainer { + + /** + * The resource environment group used to store complex resources + */ + protected ResourceEnvironmentGroup resourceEnvironmentGroup = null; + + /** + * Main constructor + * @param name the name of this resource container + */ + public AbstractResourceEnvironmentGroupContainer(String name) { + super(name); + } + + /** + * Adds a page to the resource container. + * @param page - the Page object + */ + public void addPage(PageObject page) { + addObject(page); + } + + /** + * Adds a PageGroup to the resource container. + * @param pageGroup the PageGroup object + */ + public void addPageGroup(PageGroup pageGroup) { + addObject(pageGroup); + } + + /** + * Creates an InvokeMediaMap on the page. + * + * @param name + * the name of the media map + */ + public void createInvokeMediumMap(String name) { + addObject(new InvokeMediumMap(name)); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + if (resourceEnvironmentGroup != null) { + resourceEnvironmentGroup.writeDataStream(os); + } + if (objects != null) { + for (Iterator it = objects.iterator(); it.hasNext();) { + AbstractAFPObject ao = (AbstractAFPObject)it.next(); + if (ao instanceof PageObject && ((PageObject)ao).isComplete() + || ao instanceof PageGroup && ((PageGroup)ao).isComplete()) { + ao.writeDataStream(os); + it.remove(); + } else { + break; + } + } + } + } + + private ResourceEnvironmentGroup getResourceEnvironmentGroup() { + if (resourceEnvironmentGroup == null) { + this.resourceEnvironmentGroup = new ResourceEnvironmentGroup(); + } + return this.resourceEnvironmentGroup; + } + + /** + * Adds a resource mapping to this resource environment group + * @param obj a resource to be referenced in this resource environment group + */ + protected void addResource(AbstractStructuredAFPObject obj) { + getResourceEnvironmentGroup().addObject(obj); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java new file mode 100644 index 000000000..e8e25b6b8 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; +import java.util.Set; + +import org.apache.fop.render.afp.DataObjectParameters; +import org.apache.fop.render.afp.ImageObjectParameters; + +/** + * An abstract container of resource objects + */ +public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObject { + /** + * The resource group object + */ + private ResourceGroup resourceGroup = null; + + /** + * The list of objects within this resource container + */ + protected Set/**/ objects = null; + + /** + * Unnamed constructor + */ + public AbstractResourceGroupContainer() { + } + + /** + * Named constructor + * @param name the name of this resource container + */ + public AbstractResourceGroupContainer(String name) { + super(name); + } + + /** + * @return the number of resources in this container + */ + protected int getResourceCount() { + if (resourceGroup != null) { + return resourceGroup.getResourceCount(); + } + return 0; + } + + /** + * Adds an AFP object to the resource group in this container + * @param obj an AFP object + */ + protected void addObject(AbstractAFPObject obj) { + if (objects == null) { + this.objects = new java.util.LinkedHashSet/**/(); + } + objects.add(obj); + } + + /** + * @return true if this resource group container contains resources + */ + protected boolean hasResources() { + return resourceGroup != null && resourceGroup.getResourceCount() > 0; + } + + /** + * @return the resource group in this resource group container + */ + protected ResourceGroup getResourceGroup() { + if (resourceGroup == null) { + resourceGroup = new ResourceGroup(); + } + return resourceGroup; + } + + /** + * Helper method to create an image on the current container and to return + * the object. + * @param params the image object parameters + * @return the image object + */ + public IncludeObject createImageObject(ImageObjectParameters params) { + return getResourceGroup().addObject(params); + } + + /** + * Helper method to create a graphic in the current container and to return + * the object. + * @param params the data object parameters + * @return the graphics object + */ + public IncludeObject createGraphicsObject(DataObjectParameters params) { + return getResourceGroup().addObject(params); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + if (resourceGroup != null) { + resourceGroup.writeDataStream(os); + } + } +} 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 e061748ca..3c448b2ab 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java @@ -19,45 +19,86 @@ package org.apache.fop.render.afp.modca; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.modca.triplets.MeasurementUnitsTriplet; +import org.apache.fop.render.afp.modca.triplets.ObjectAreaSizeTriplet; +import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; +import org.apache.fop.render.afp.modca.triplets.Triplet; /** * An abstract class encapsulating an MODCA structured object */ -public abstract class AbstractStructuredAFPObject extends AbstractNamedAFPObject { +public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { + /** + * list of object triplets + */ + protected List/**/ triplets = null; + + /** + * triplet data created from triplet list + */ + protected byte[] tripletData = null; + /** * Default constructor */ - public AbstractStructuredAFPObject() { - super(); + protected AbstractStructuredAFPObject() { } /** - * Named constructor - * @param name name of structured object + * @return the triplet data length */ - public AbstractStructuredAFPObject(String name) { - super(name); + protected int getTripletDataLength() { + if (tripletData != null) { + return tripletData.length; + } + return 0; } - + /** * Helper method to write the start of the Object. * @param os The stream to write to * @throws IOException an I/O exception if one occurred */ protected void writeStart(OutputStream os) throws IOException { + if (triplets != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + writeObjects(triplets, baos); + this.tripletData = baos.toByteArray(); + } } /** * Helper method to write the contents of the Object. * @param os The stream to write to - * @throws IOException an I/O exception if one occurred + * @throws IOException The stream to write to */ protected void writeContent(OutputStream os) throws IOException { + writeTriplets(os); } + /** + * Writes any triplet data + * @param os The stream to write to + * @throws IOException The stream to write to + */ + protected void writeTriplets(OutputStream os) throws IOException { + if (tripletData != null) { + os.write(tripletData); + } else if (triplets != null) { + writeObjects(triplets, os); + } + } + /** * Helper method to write the end of the Object. * @param os The stream to write to @@ -65,19 +106,138 @@ public abstract class AbstractStructuredAFPObject extends AbstractNamedAFPObject */ protected void writeEnd(OutputStream os) throws IOException { } - + /** * Accessor method to write the AFP datastream for the Image Object * @param os The stream to write to * @throws IOException in the event that an I/O exception occurred */ - public void writeDataStream(OutputStream os) - throws IOException { - + public void writeDataStream(OutputStream os) throws IOException { writeStart(os); - writeContent(os); - writeEnd(os); - } + } + + /** + * Returns the first matching triplet found in the structured field triplet list + * @param tripletId the triplet identifier + */ + private Triplet getTriplet(byte tripletId) { + Iterator it = getTriplets().iterator(); + while (it.hasNext()) { + Triplet triplet = (Triplet)it.next(); + if (triplet.getId() == tripletId) { + return triplet; + } + } + return null; + } + + /** + * @param tripletId the triplet identifier + * @return true if the structured field has the given triplet + */ + private boolean hasTriplet(byte tripletId) { + return getTriplet(tripletId) != null; + } + + /** + * Adds a triplet to this structured object + * @param triplet the triplet to add + */ + private void addTriplet(Triplet triplet) { + getTriplets().add(triplet); + } + + /** + * Adds a list of triplets to the triplets contained within this structured field + * @param tripletCollection a collection of triplets + */ + private void addTriplets(Collection/**/ tripletCollection) { + if (tripletCollection != null) { + getTriplets().addAll(tripletCollection); + } + } + + /** + * @return the triplet list pertaining to this resource + */ + protected List/**/ getTriplets() { + if (triplets == null) { + triplets = new java.util.ArrayList(); + } + return triplets; + } + + /** + * Sets the fully qualified name of this resource + * @param fqnType the fully qualified name type of this resource + * @param fqnFormat the fully qualified name format of this resource + * @param fqName the fully qualified name of this resource + */ + public void setFullyQualifiedName(byte fqnType, byte fqnFormat, String fqName) { + byte[] fqNameBytes; + try { + fqNameBytes = fqName.getBytes(AFPConstants.EBCIDIC_ENCODING); + addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqNameBytes)); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage()); + } + } + + /** + * @return the fully qualified name of this triplet or null if it does not exist + */ + public String getFullyQualifiedName() { + FullyQualifiedNameTriplet fqNameTriplet + = (FullyQualifiedNameTriplet)getTriplet(Triplet.FULLY_QUALIFIED_NAME); + byte[] nameBytes = fqNameTriplet.getFullyQualifiedName(); + if (nameBytes != null) { + try { + return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage()); + } + } else { + log.warn(this + " has no fully qualified name"); + } + return null; + } + + /** + * Sets the objects classification + * @param objectClass the classification of the object + * @param componentId the component Id of the object + */ + public void setObjectClassification(byte objectClass, byte componentId) { + addTriplet(new ObjectClassificationTriplet(objectClass, componentId)); + } + + /** + * Specifies the extent of an object area in the X and Y directions + * @param x the x direction extent + * @param y the y direction extent + */ + public void setObjectAreaSize(int x, int y) { + addTriplet(new ObjectAreaSizeTriplet(x, y)); + } + + /** + * Sets the measurement units used to specify the units of measure + */ + public void setMeasurementUnits() { + addTriplet(new MeasurementUnitsTriplet()); + } + + /** + * Sets a comment on this resource + * @param comment a comment string + */ + public void setComment(String comment) { + try { + addTriplet(new Triplet(Triplet.COMMENT, comment)); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage()); + } + } } diff --git a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java index eb537b0d7..845af4dfc 100644 --- a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java @@ -18,6 +18,7 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; import java.util.List; @@ -37,7 +38,7 @@ import org.apache.fop.render.afp.fonts.AFPFont; * containing page or overlay. * */ -public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { +public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { /** * Default name for the active environment group @@ -47,7 +48,12 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { /** * The collection of MapCodedFont objects */ - private List mapCodedFonts = new java.util.ArrayList(); + private List mapCodedFonts = null; + + /** + * The collection of MapDataResource objects + */ + private List mapDataResources = null; /** * The Object Area Descriptor for the active environment group @@ -69,11 +75,6 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { */ private PageDescriptor pageDescriptor = null; - /** - * The collection of MapPageOverlay objects - */ - private List mapPageOverlays = new java.util.ArrayList(); - /** * Default constructor for the ActiveEnvironmentGroup. * @param width the page width @@ -81,11 +82,8 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @param widthRes the page width resolution * @param heightRes the page height resolution */ - public ActiveEnvironmentGroup(int width, int height, - int widthRes, int heightRes) { - + public ActiveEnvironmentGroup(int width, int height, int widthRes, int heightRes) { this(DEFAULT_NAME, width, height, widthRes, heightRes); - } /** @@ -97,9 +95,7 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @param widthRes the page width resolution * @param heightRes the page height resolution */ - public ActiveEnvironmentGroup(String name, int width, int height, - int widthRes, int heightRes) { - + public ActiveEnvironmentGroup(String name, int width, int height, int widthRes, int heightRes) { super(name); // Create PageDescriptor @@ -112,7 +108,6 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { // Create PresentationTextDataDescriptor presentationTextDataDescriptor = new PresentationTextDescriptor(width, height, widthRes, heightRes); - } /** @@ -122,10 +117,8 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @param rotation the rotation */ public void setPosition(int x, int y, int rotation) { - // Create ObjectAreaPosition objectAreaPosition = new ObjectAreaPosition(x, y, rotation); - } /** @@ -134,9 +127,7 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @return the page descriptor object */ public PageDescriptor getPageDescriptor() { - return pageDescriptor; - } /** @@ -145,47 +136,36 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @return the presentation text descriptor */ public PresentationTextDescriptor getPresentationTextDataDescriptor() { - return presentationTextDataDescriptor; - } /** - * Accessor method to write the AFP datastream for the active environment group. - * @param os The stream to write to - * @throws java.io.IOException throws if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(mapCodedFonts, os); - - writeObjectList(mapPageOverlays, os); - - pageDescriptor.writeDataStream(os); - + public void writeContent(OutputStream os) throws IOException { + super.writeTriplets(os); + + writeObjects(mapCodedFonts, os); + writeObjects(mapPageOverlays, os); + writeObjects(mapDataResources, os); + + if (pageDescriptor != null) { + pageDescriptor.writeDataStream(os); + } if (objectAreaDescriptor != null && objectAreaPosition != null) { objectAreaDescriptor.writeDataStream(os); objectAreaPosition.writeDataStream(os); } - - presentationTextDataDescriptor.writeDataStream(os); - - writeEnd(os); - + if (presentationTextDataDescriptor != null) { + presentationTextDataDescriptor.writeDataStream(os); + } } /** - * Helper method to write the start of the active environment group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(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 @@ -195,26 +175,17 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { 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); - + os.write(data); } /** - * Helper method to write the end of the active environment group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(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 @@ -224,130 +195,75 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { 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); + } + private List getMapCodedFonts() { + if (mapCodedFonts == null) { + mapCodedFonts = new java.util.ArrayList(); + } + return mapCodedFonts; + } + + private List getMapDataResources() { + if (mapDataResources == null) { + mapDataResources = new java.util.ArrayList(); + } + return mapDataResources; } /** * Method to create a map coded font object - * @param fontReference the font number used as the resource identifier + * @param fontRef the font number used as the resource identifier * @param font the font * @param size the point size of the font * @param orientation the orientation of the font (e.g. 0, 90, 180, 270) */ - public void createFont( - int fontReference, - AFPFont font, - int size, - int orientation) { - + public void createFont(int fontRef, AFPFont font, int size, int orientation) { MapCodedFont mcf = getCurrentMapCodedFont(); - if (mcf == null) { mcf = new MapCodedFont(); - mapCodedFonts.add(mcf); + getMapCodedFonts().add(mcf); } try { - - mcf.addFont( - fontReference, - font, - size, - orientation); - + mcf.addFont(fontRef, font, size, orientation); } catch (MaximumSizeExceededException msee) { - mcf = new MapCodedFont(); - mapCodedFonts.add(mcf); + getMapCodedFonts().add(mcf); try { - - mcf.addFont( - fontReference, - font, - size, - orientation); - + mcf.addFont(fontRef, font, size, orientation); } catch (MaximumSizeExceededException ex) { - // Should never happen (but log just in case) log.error("createFont():: resulted in a MaximumSizeExceededException"); - - } - - } - - } - - /** - * Actually creates the MPO object. - * Also creates the supporting object (an IPO) - * @param name the name of the overlay to be used - */ - public void createOverlay(String name) { - - MapPageOverlay mpo = getCurrentMapPageOverlay(); - - if (mpo == null) { - mpo = new MapPageOverlay(); - mapPageOverlays.add(mpo); - } - - try { - - mpo.addOverlay(name); - - } catch (MaximumSizeExceededException msee) { - mpo = new MapPageOverlay(); - mapPageOverlays.add(mpo); - try { - mpo.addOverlay(name); - } catch (MaximumSizeExceededException ex) { - // Should never happen (but log just in case) - log.error("createOverlay():: resulted in a MaximumSizeExceededException"); } } } - + /** * Getter method for the most recent MapCodedFont added to the * Active Environment Group (returns null if no MapCodedFonts exist) * @return the most recent Map Coded Font. */ private MapCodedFont getCurrentMapCodedFont() { - - int size = mapCodedFonts.size(); + int size = getMapCodedFonts().size(); if (size > 0) { - return (MapCodedFont) mapCodedFonts.get(mapCodedFonts.size() - 1); + return (MapCodedFont)mapCodedFonts.get(size - 1); } else { return null; } - } - + + /** - * Getter method for the most recent MapPageOverlay added to the - * Active Environment Group (returns null if no MapPageOverlay exist) - * @return the most recent Map Coded Font + * Method to create a map data resource object + * @param obj creates a map data resource entry for a given AFP data resource object */ - private MapPageOverlay getCurrentMapPageOverlay() { - - int size = mapPageOverlays.size(); - if (size > 0) { - return (MapPageOverlay) mapPageOverlays.get( - mapPageOverlays.size() - 1); - } else { - return null; - } - + public void createResource(AbstractStructuredAFPObject obj) { + getMapDataResources().add(new MapDataResource(obj)); } - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/Document.java b/src/java/org/apache/fop/render/afp/modca/Document.java index 3d2d40a3a..72c65e8a7 100644 --- a/src/java/org/apache/fop/render/afp/modca/Document.java +++ b/src/java/org/apache/fop/render/afp/modca/Document.java @@ -18,10 +18,9 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; -import java.util.Iterator; -import java.util.List; /** * The document is the highest level of the MO:DCA data-stream document @@ -48,23 +47,13 @@ import java.util.List; * document to be presented. * */ -public final class Document extends AbstractNamedAFPObject { +public final class Document extends AbstractResourceEnvironmentGroupContainer { /** - * Ststic default name reference + * Static default generated name reference */ private static final String DEFAULT_NAME = "DOC00001"; - - /** - * A list of the objects in the document - */ - private List objects = new java.util.ArrayList(); - - /** - * The document started state - */ - private boolean started = false; - + /** * The document completion state */ @@ -82,36 +71,14 @@ public final class Document extends AbstractNamedAFPObject { * @param name The name of the document */ public Document(String name) { - super(name); - - } - - /** - * Adds a page to the document. - * @param page - the Page object - */ - public void addPage(PageObject page) { - if (!objects.contains(page)) { - objects.add(page); - } - } - - /** - * Adds a PageGroup to the document. - * @param pageGroup the PageGroup object - */ - public void addPageGroup(PageGroup pageGroup) { - objects.add(pageGroup); } /** * Method to mark the end of the page group. */ public void endDocument() { - complete = true; - } /** @@ -127,40 +94,17 @@ public final class Document extends AbstractNamedAFPObject { * @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 { - - if (!started) { - writeStart(os); - started = true; - } - - for (Iterator it = objects.iterator(); it.hasNext();) { - AbstractAFPObject ao = (AbstractAFPObject)it.next(); - if (ao instanceof PageObject && ((PageObject)ao).isComplete() - || ao instanceof PageGroup && ((PageGroup)ao).isComplete()) { - ao.writeDataStream(os); - it.remove(); - } else { - break; - } + public void writeDataStream(OutputStream os) throws IOException { + if (isComplete()) { + super.writeDataStream(os); } - - if (complete) { - writeEnd(os); - } - } /** - * Helper method to write the start of the Document - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(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 @@ -170,26 +114,17 @@ public final class Document extends AbstractNamedAFPObject { 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); - } /** - * Helper method to write the end of the Document. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(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 @@ -199,15 +134,16 @@ public final class Document extends AbstractNamedAFPObject { 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); - } - + + /** + * {@inheritDoc} + */ + public String toString() { + return this.name; + } } \ No newline at end of file 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 065ca6626..7e5f12877 100644 --- a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java @@ -23,22 +23,22 @@ import java.awt.Color; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.modca.goca.GraphicsBox; -import org.apache.fop.render.afp.modca.goca.GraphicsData; -import org.apache.fop.render.afp.modca.goca.GraphicsFillet; -import org.apache.fop.render.afp.modca.goca.GraphicsFullArc; -import org.apache.fop.render.afp.modca.goca.GraphicsImageBegin; -import org.apache.fop.render.afp.modca.goca.GraphicsImageData; -import org.apache.fop.render.afp.modca.goca.GraphicsImageEnd; -import org.apache.fop.render.afp.modca.goca.GraphicsLine; -import org.apache.fop.render.afp.modca.goca.GraphicsSetArcParameters; -import org.apache.fop.render.afp.modca.goca.GraphicsSetCharacterSet; -import org.apache.fop.render.afp.modca.goca.GraphicsSetCurrentPosition; -import org.apache.fop.render.afp.modca.goca.GraphicsSetLineType; -import org.apache.fop.render.afp.modca.goca.GraphicsSetLineWidth; -import org.apache.fop.render.afp.modca.goca.GraphicsSetPatternSymbol; -import org.apache.fop.render.afp.modca.goca.GraphicsSetProcessColor; -import org.apache.fop.render.afp.modca.goca.GraphicsString; +import org.apache.fop.render.afp.goca.GraphicsBox; +import org.apache.fop.render.afp.goca.GraphicsData; +import org.apache.fop.render.afp.goca.GraphicsFillet; +import org.apache.fop.render.afp.goca.GraphicsFullArc; +import org.apache.fop.render.afp.goca.GraphicsImageBegin; +import org.apache.fop.render.afp.goca.GraphicsImageData; +import org.apache.fop.render.afp.goca.GraphicsImageEnd; +import org.apache.fop.render.afp.goca.GraphicsLine; +import org.apache.fop.render.afp.goca.GraphicsSetArcParameters; +import org.apache.fop.render.afp.goca.GraphicsSetCharacterSet; +import org.apache.fop.render.afp.goca.GraphicsSetCurrentPosition; +import org.apache.fop.render.afp.goca.GraphicsSetLineType; +import org.apache.fop.render.afp.goca.GraphicsSetLineWidth; +import org.apache.fop.render.afp.goca.GraphicsSetPatternSymbol; +import org.apache.fop.render.afp.goca.GraphicsSetProcessColor; +import org.apache.fop.render.afp.goca.GraphicsString; /** * Top-level GOCA graphics object. @@ -309,7 +309,7 @@ public class GraphicsObject extends AbstractDataObject { * {@inheritDoc} */ public String toString() { - return "GraphicsObject"; + return "GraphicsObject: " + getName(); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java b/src/java/org/apache/fop/render/afp/modca/IMImageObject.java index bb43950dd..2afd3fa49 100644 --- a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IMImageObject.java @@ -63,9 +63,7 @@ public class IMImageObject extends AbstractNamedAFPObject { * @param name The name of the image. */ public IMImageObject(String name) { - super(name); - } /** @@ -101,44 +99,29 @@ public class IMImageObject extends AbstractNamedAFPObject { } /** - * Accessor method to write the AFP datastream for the IM Image Objetc - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); if (imageOutputControl != null) { imageOutputControl.writeDataStream(os); } - if (imageInputDescriptor != null) { imageInputDescriptor.writeDataStream(os); } - if (imageCellPosition != null) { imageCellPosition.writeDataStream(os); } - if (imageRasterData != null) { imageRasterData.writeDataStream(os); } - - writeEnd(os); - } /** - * Helper method to write the start of the IM Image Object. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(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 @@ -148,26 +131,17 @@ public class IMImageObject extends AbstractNamedAFPObject { 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); - } /** - * Helper method to write the end of the IM Image Object. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(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 @@ -177,15 +151,9 @@ public class IMImageObject extends AbstractNamedAFPObject { 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); - } - } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java index e7fd538e1..4aea02901 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageContent.java @@ -26,7 +26,31 @@ import org.apache.fop.render.afp.tools.BinaryUtils; /** * Image content IOCA object */ -public class ImageContent extends AbstractAFPObject { +public class ImageContent extends AbstractStructuredAFPObject { + + /** + * The CCITT T.4 Group 3 Coding Standard (G3 MH-Modified Huffman) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * one-dimensional compression. + */ + public static final byte COMPID_G3_MH = (byte)0x80; + + /** + * The CCITT T.4 Group 3 Coding Option (G3 MR-Modified READ) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * two-dimensional compression. + */ + public static final byte COMPID_G3_MR = (byte)0x81; + + /** + * The CCITT T.6 Group 4 Coding Standard (G4 MMR-Modified Modified READ) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * two-dimensional compression. + */ + public static final byte COMPID_G3_MMR = (byte)0x82; /** * The image size parameter @@ -56,13 +80,12 @@ public class ImageContent extends AbstractAFPObject { /** * The image data */ - private byte[] data = null; + private byte[] imageData = null; /** * Constructor for the image content */ public ImageContent() { - } /** @@ -111,70 +134,55 @@ public class ImageContent extends AbstractAFPObject { /** * Set the data of the image. - * @param dat the image data + * @param data the image data */ - public void setImageData(byte[] dat) { - this.data = dat; + public void setImageData(byte[] data) { + this.imageData = data; } /** - * Accessor method to write the AFP datastream for the Image Content - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurs + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { - - writeStart(os); - + protected void writeContent(OutputStream os) throws IOException { if (imageSizeParam != null) { imageSizeParam.writeDataStream(os); } - os.write(getImageEncodingParameter()); - os.write(getImageIDESizeParameter()); - os.write(getIDEStructureParameter()); - os.write(getExternalAlgorithmParameter()); - - if (data != null) { + if (imageData != null) { int off = 0; - while (off < data.length) { - int len = Math.min(30000, data.length - off); + while (off < imageData.length) { + int len = Math.min(30000, imageData.length - off); os.write(getImageDataStart(len)); - os.write(data, off, len); + os.write(imageData, off, len); off += len; } } - - writeEnd(os); - } /** - * Helper method to write the start of the Image Content. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) throws IOException { - byte[] startData = new byte[] { + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[] { (byte)0x91, // ID 0x01, // Length (byte)0xff, // Object Type = IOCA Image Object }; - os.write(startData); + os.write(data); } /** - * Helper method to write the end of the Image Content. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) throws IOException { - byte[] endData = new byte[] { + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[] { (byte)0x93, // ID 0x00, // Length }; - os.write(endData); + os.write(data); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java index 5f8454fa8..2876e8348 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java @@ -21,7 +21,6 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import java.io.UnsupportedEncodingException; /** * An Image Segment is represented by a set of self-defining fields, fields @@ -33,23 +32,13 @@ import java.io.UnsupportedEncodingException; * * Only one Image Content can exist within a single IOCA Image Segment. */ -public class ImageSegment extends AbstractAFPObject { +public class ImageSegment extends AbstractNamedAFPObject { /** * Default name for the object environment group */ private static final String DEFAULT_NAME = "IS01"; - /** - * The name of the image segment - */ - private String name; - - /** - * The name of the image segment as EBCIDIC bytes - */ - private byte[] nameBytes; - /** * The ImageContent for the image segment */ @@ -68,20 +57,14 @@ public class ImageSegment extends AbstractAFPObject { * @param name The name of the image. */ public ImageSegment(String name) { - if (name.length() != 4) { - String msg = "Image segment name must be 4 characters long " + name; - log.error("Constructor:: " + msg); - throw new IllegalArgumentException(msg); - } - this.name = name; - try { - this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException usee) { - this.nameBytes = name.getBytes(); - log.warn( - "Constructor:: UnsupportedEncodingException translating the name " - + name); - } + super(name); + } + + /** + * {@inheritDoc} + */ + protected int getNameLength() { + return 4; } /** @@ -155,43 +138,33 @@ public class ImageSegment extends AbstractAFPObject { } /** - * Accessor method to write the AFP datastream for the Image Segment - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { - writeStart(os); + public void writeContent(OutputStream os) throws IOException { if (imageContent != null) { imageContent.writeDataStream(os); } - writeEnd(os); } /** - * Helper method to write the start of the Image Segment. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) throws IOException { + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[] { 0x70, // ID 0x04, // Length - 0x00, // Name byte 1 - 0x00, // Name byte 2 - 0x00, // Name byte 3 - 0x00, // Name byte 4 + nameBytes[0], // Name byte 1 + nameBytes[1], // Name byte 2 + nameBytes[2], // Name byte 3 + nameBytes[3], // Name byte 4 }; - for (int i = 0; i < nameBytes.length; i++) { - data[2 + i] = nameBytes[i]; - } os.write(data); - } /** - * Helper method to write the end of the Image Segment. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) throws IOException { + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[] { 0x71, // ID 0x00, // Length diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java index 890fdcd9d..0fceff893 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java @@ -40,28 +40,92 @@ import org.apache.fop.render.afp.tools.BinaryUtils; public class IncludeObject extends AbstractNamedAFPObject { /** - * The object type + * the include object is of type page segment */ - private byte objectType = (byte) 0x92; + protected static final byte TYPE_PAGE_SEGMENT = (byte)0x5F; + + /** + * the include object is of type other + */ + protected static final byte TYPE_OTHER = (byte)0x92; + + /** + * the include object is of type graphic + */ + protected static final byte TYPE_GRAPHIC = (byte)0xBB; + + /** + * the included object is of type barcode + */ + protected static final byte TYPE_BARCODE = (byte)0xEB; + + /** + * the included object is of type image + */ + protected static final byte TYPE_IMAGE = (byte)0xFB; + + /** + * The object type (default is other) + */ + private byte objectType = TYPE_OTHER; /** * The orientation on the include object */ - private int orientation = 0; + private int orientation = -1; + + /** + * The X-axis origin of the object area + */ + private int xOffset = -1; + + /** + * The Y-axis origin of the object area + */ + private int yOffset = -1; + + /** + * The X-axis origin defined in the object + */ + private int xContentOffset = -1; + /** + * The Y-axis origin defined in the object + */ + private int yContentOffset = -1; + + /** + * The object referenced by this include object + */ + private AbstractStructuredAFPObject referencedObject = null; + /** * Constructor for the include object with the specified name, the name must * be a fixed length of eight characters and is the name of the referenced * object. * - * @param name - * the name of the image + * @param resourceObj + * the resource object wrapper */ - public IncludeObject(String name) { - - super(name); - objectType = (byte) 0xFB; + public IncludeObject(ResourceObject resourceObj) { + super(resourceObj.getResource().getName()); + this.referencedObject = resourceObj.getResource(); + if (referencedObject instanceof ImageObject) { + this.objectType = TYPE_IMAGE; + } else if (referencedObject instanceof GraphicsObject) { + this.objectType = TYPE_GRAPHIC; + } else if (referencedObject instanceof PageSegment) { + this.objectType = TYPE_PAGE_SEGMENT; + } else { + this.objectType = TYPE_OTHER; + } + } + /** + * @return the object referenced by this include object + */ + public AbstractStructuredAFPObject getReferencedObject() { + return referencedObject; } /** @@ -71,7 +135,6 @@ public class IncludeObject 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; @@ -79,25 +142,39 @@ public class IncludeObject extends AbstractNamedAFPObject { throw new IllegalArgumentException( "The orientation must be one of the values 0, 90, 180, 270"); } - } /** - * Accessor method to write the AFP datastream for the Include Object - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * Sets the x and y offset to the origin in the object area + * @param x the X-axis origin of the object area + * @param y the Y-axis origin of the object area */ - public void writeDataStream(OutputStream os) - throws IOException { - - byte[] data = new byte[37]; - + public void setObjectArea(int x, int y) { + this.xOffset = x; + this.yOffset = y; + } + + /** + * Sets the x and y offset of the content area to the object area + * @param x the X-axis origin defined in the object + * @param y the Y-axis origin defined in the object + */ + public void setContentArea(int x, int y) { + this.xContentOffset = x; + this.yContentOffset = y; + } + + /** + * {@inheritDoc} + */ + public void writeDataStream(OutputStream os) throws IOException { + byte[] data = new byte[36]; data[0] = 0x5A; // Set the total record length - byte[] rl1 = BinaryUtils.convert(36, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; + byte[] len = BinaryUtils.convert(35, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; // Structured field ID for a IOB data[3] = (byte) 0xD3; @@ -112,60 +189,91 @@ public class IncludeObject extends AbstractNamedAFPObject { data[9 + i] = nameBytes[i]; } - data[17] = 0x00; + data[17] = 0x00; // reserved data[18] = objectType; - // XoaOset - data[20] = (byte) 0xFF; - data[21] = (byte) 0xFF; - data[22] = (byte) 0xFF; + //XoaOset (object area) + if (xOffset > 0) { + byte[] x = BinaryUtils.convert(xOffset, 3); + data[19] = x[0]; + data[20] = x[1]; + data[21] = x[2]; + } else { + data[19] = (byte)0xFF; + data[20] = (byte)0xFF; + data[21] = (byte)0xFF; + } - // YoaOset - data[23] = (byte) 0xFF; - data[24] = (byte) 0xFF; - data[25] = (byte) 0xFF; + // YoaOset (object area) + if (yOffset > 0) { + byte[] y = BinaryUtils.convert(yOffset, 3); + data[22] = y[0]; + data[23] = y[1]; + data[24] = y[2]; + } else { + data[22] = (byte)0xFF; + data[23] = (byte)0xFF; + data[24] = (byte)0xFF; + } switch (orientation) { + case -1: // use x/y axis orientation defined in object + data[25] = (byte)0xFF; // x axis rotation + data[26] = (byte)0xFF; // + data[27] = (byte)0xFF; // y axis rotation + data[28] = (byte)0xFF; + break; case 90: - data[26] = 0x2D; - data[27] = 0x00; - data[28] = 0x5A; - data[29] = 0x00; + data[25] = 0x2D; + data[26] = 0x00; + data[27] = 0x5A; + data[28] = 0x00; break; case 180: - data[26] = 0x5A; - data[27] = 0x00; - data[28] = (byte) 0x87; - data[29] = 0x00; + data[25] = 0x5A; + data[25] = 0x00; + data[27] = (byte)0x87; + data[28] = 0x00; break; case 270: - data[26] = (byte) 0x87; + data[25] = (byte)0x87; + data[26] = 0x00; data[27] = 0x00; data[28] = 0x00; - data[29] = 0x00; break; default: + data[25] = 0x00; data[26] = 0x00; - data[27] = 0x00; - data[28] = 0x2D; - data[29] = 0x00; + data[27] = 0x2D; + data[28] = 0x00; break; } - // XocaOset - data[30] = (byte) 0xFF; - data[31] = (byte) 0xFF; - data[32] = (byte) 0xFF; - - // YocaOset - data[33] = (byte) 0xFF; - data[34] = (byte) 0xFF; - data[35] = (byte) 0xFF; + // XocaOset (object content) + if (xContentOffset > 0) { + byte[] y = BinaryUtils.convert(xContentOffset, 3); + data[29] = y[0]; + data[30] = y[1]; + data[31] = y[2]; + } else { + data[29] = (byte)0xFF; + data[30] = (byte)0xFF; + data[31] = (byte)0xFF; + } - data[36] = 0x01; + // YocaOset (object content) + if (yContentOffset > 0) { + byte[] y = BinaryUtils.convert(yContentOffset, 3); + data[32] = y[0]; + data[33] = y[1]; + data[34] = y[2]; + } else { + data[32] = (byte)0xFF; + data[33] = (byte)0xFF; + data[34] = (byte)0xFF; + } + data[35] = 0x01; os.write(data); - } - } \ No newline at end of file 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 7c52fe0a2..8a7d4720a 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java @@ -69,7 +69,7 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { } /** - * Sets the orienation to use for the overlay. + * Sets the orientation to use for the overlay. * * @param orientation * The orientation (0,90, 180, 270) @@ -85,15 +85,10 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { } /** - * Accessor method to write the AFP datastream for the Include Page Overlay - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - + public void writeDataStream(OutputStream os) throws IOException { byte[] data = new byte[25]; //(9 +16) - data[0] = 0x5A; // Set the total record length 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 7792a7162..b87222c00 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java @@ -59,35 +59,29 @@ public class IncludePageSegment extends AbstractNamedAFPObject { * @param y The y position */ public IncludePageSegment(String name, int x, int y) { - super(name); this.x = BinaryUtils.convert(x, 3); this.y = BinaryUtils.convert(y, 3); - } /** - * Accessor method to write the AFP datastream for the Include Page Segment - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { + public void writeDataStream(OutputStream os) throws IOException { byte[] data = new byte[23]; //(9 +14) data[0] = 0x5A; // Set the total record length - byte[] rl1 = BinaryUtils.convert(22, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; + byte[] len = BinaryUtils.convert(22, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; // Structured field ID for a IPS data[3] = (byte) 0xD3; data[4] = (byte) 0xAF; data[5] = (byte) 0x5F; - data[6] = 0x00; // Reserved data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved @@ -95,11 +89,9 @@ public class IncludePageSegment extends AbstractNamedAFPObject { for (int i = 0; i < nameBytes.length; i++) { data[9 + i] = nameBytes[i]; } - data[17] = x[0]; // x coordinate data[18] = x[1]; data[19] = x[2]; - data[20] = y[0]; // y coordinate data[21] = y[1]; data[22] = y[2]; diff --git a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java b/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java index f38096ade..f67ee8268 100644 --- a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java +++ b/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java @@ -34,30 +34,25 @@ public class InvokeMediumMap extends AbstractNamedAFPObject { /** * Constructor for the Invoke Medium Map - * @param mediumMapName Name of the medium map + * @param name the name of the medium map */ - public InvokeMediumMap(String mediumMapName) { - - super(mediumMapName); - + public InvokeMediumMap(String name) { + super(name); } /** - * Accessor method to write the AFP datastream for the Invoke Medium Map - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { + public void writeDataStream(OutputStream os) throws IOException { byte[] data = new byte[17]; data[0] = 0x5A; // Set the total record length - byte[] rl1 = BinaryUtils.convert(16, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; + byte[] len = BinaryUtils.convert(16, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; // Structured field ID for a IPO data[3] = (byte) 0xD3; @@ -69,13 +64,8 @@ public class InvokeMediumMap extends AbstractNamedAFPObject { data[8] = 0x00; // Reserved for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java b/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java index 05d45dc2f..e83f04b78 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java +++ b/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java @@ -138,7 +138,6 @@ public class MapCodedFont extends AbstractAFPObject { baos.write(0x5D); baos.write(BinaryUtils.convert(fd.scale, 2)); } - } byte[] data = baos.toByteArray(); @@ -149,7 +148,6 @@ public class MapCodedFont extends AbstractAFPObject { data[2] = rl1[1]; os.write(data); - } /** diff --git a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java new file mode 100644 index 000000000..66ae57d75 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java @@ -0,0 +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.render.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * The Map Data Resource structured field specifies resources that are + * required for presentation. + */ +public class MapDataResource extends AbstractStructuredAFPObject { + /** + * Static default generated name reference + */ + private static final String DEFAULT_NAME = "MDR00001"; + + /** + * Main constructor + * @param obj a map data resource for a given structured AFP object + */ + public MapDataResource(AbstractStructuredAFPObject obj) { + String fqName = obj.getFullyQualifiedName(); + if (fqName != null) { + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); + } + } + + /** + * {@inheritDoc} + */ + public void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + // RGLength + byte[] len = BinaryUtils.convert(8 + getTripletDataLength(), 2); + byte[] data = new byte[] { + 0x5A, // Structured field identifier + len[0], // Length byte 1 + len[1], // Length byte 2 + (byte) 0xD3, // Structured field id byte 1 + (byte) 0xAB, // Structured field id byte 2 + (byte) 0xC3, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00 // Reserved + }; + os.write(data); + } +} 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 129a3f5a1..65f90aa2b 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java @@ -36,15 +36,21 @@ public class MapPageOverlay extends AbstractAFPObject { /** * The collection of overlays (maximum of 254 stored as byte[]) */ - private List overLays = new java.util.ArrayList(); + private List overLays = null; /** * Constructor for the Map Page Overlay */ public MapPageOverlay() { - } + private List getOverlays() { + if (overLays == null) { + this.overLays = new java.util.ArrayList(); + } + return this.overLays; + } + /** * Add an overlay to to the map page overlay object. * @@ -53,23 +59,19 @@ public class MapPageOverlay extends AbstractAFPObject { * @throws MaximumSizeExceededException if the maximum size is reached */ public void addOverlay(String name) throws MaximumSizeExceededException { - - if (overLays.size() > 253) { + if (getOverlays().size() > 253) { throw new MaximumSizeExceededException(); } - if (name.length() != 8) { throw new IllegalArgumentException("The name of overlay " + name + " must be 8 characters"); } - if (log.isDebugEnabled()) { log.debug("addOverlay():: adding overlay " + name); } - try { byte[] data = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - overLays.add(data); + getOverlays().add(data); } catch (UnsupportedEncodingException usee) { log.error("addOverlay():: UnsupportedEncodingException translating the name " + name); @@ -82,7 +84,7 @@ public class MapPageOverlay extends AbstractAFPObject { * @throws java.io.IOException if an I/O exception occurred */ public void writeDataStream(OutputStream os) throws IOException { - int oLayCount = overLays.size(); + int oLayCount = getOverlays().size(); int recordlength = oLayCount * 18; byte[] data = new byte[recordlength + 9]; diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java index 688288063..6ff3f03f8 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java @@ -55,7 +55,6 @@ public class ObjectAreaPosition extends AbstractAFPObject { byte[] len = BinaryUtils.convert(32, 2); byte[] xcoord = BinaryUtils.convert(x, 3); byte[] ycoord = BinaryUtils.convert(y, 3); - byte[] data = new byte[] { 0x5A, len[0], // Length @@ -91,9 +90,6 @@ public class ObjectAreaPosition extends AbstractAFPObject { 0x00, 0x00, // RefCSys }; - os.write(data); - } - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java index 27fe7c270..b2108d0d7 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java @@ -34,7 +34,7 @@ import java.io.OutputStream; * normally contained in the object environment group, or it may specify that one or * more default values are to be used. */ -public final class ObjectEnvironmentGroup extends AbstractStructuredAFPObject { +public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject { /** * Default name for the object environment group @@ -150,7 +150,9 @@ public final class ObjectEnvironmentGroup extends AbstractStructuredAFPObject { /** * {@inheritDoc} */ - public void writeContent(OutputStream os) throws IOException { + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + objectAreaDescriptor.writeDataStream(os); objectAreaPosition.writeDataStream(os); diff --git a/src/java/org/apache/fop/render/afp/modca/Overlay.java b/src/java/org/apache/fop/render/afp/modca/Overlay.java index 628ef5516..e7d3b87d0 100644 --- a/src/java/org/apache/fop/render/afp/modca/Overlay.java +++ b/src/java/org/apache/fop/render/afp/modca/Overlay.java @@ -50,43 +50,14 @@ public class Overlay extends AbstractPageObject { */ public Overlay(String name, int width, int height, int rotation, int widthResolution, int heightResolution) { - super(name, width, height, rotation, widthResolution, heightResolution); - } /** - * Accessor method to write the AFP datastream for the overlay. - * - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - activeEnvironmentGroup.writeDataStream(os); - - writeObjectList(segments, os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the overlay. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(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 @@ -96,26 +67,17 @@ public class Overlay extends AbstractPageObject { 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); - } /** - * Helper method to write the end of the overlay. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(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 @@ -125,15 +87,9 @@ public class Overlay extends AbstractPageObject { 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); - } - } diff --git a/src/java/org/apache/fop/render/afp/modca/PageGroup.java b/src/java/org/apache/fop/render/afp/modca/PageGroup.java index 0b40a83c5..39d7920e6 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/PageGroup.java @@ -18,9 +18,9 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; import java.util.List; /** @@ -34,17 +34,12 @@ import java.util.List; * * @author Pete Townsend */ -public class PageGroup extends AbstractNamedAFPObject { - - /** - * The pages contained within this group - */ - private List objects = new ArrayList(); +public class PageGroup extends AbstractResourceEnvironmentGroupContainer { /** * The tag logical elements contained within this group */ - private List tagLogicalElements = new ArrayList(); + private List tagLogicalElements = null; /** * The page state @@ -58,32 +53,16 @@ public class PageGroup extends AbstractNamedAFPObject { * the name of the page group */ public PageGroup(String name) { - super(name); - } - /** - * Adds a page object to the group. - * - * @param page - * the page object to add - */ - public void addPage(PageObject page) { - - if (!objects.contains(page)) { - objects.add(page); + private List getTagLogicalElements() { + if (tagLogicalElements == null) { + this.tagLogicalElements = new java.util.ArrayList(); } - + return this.tagLogicalElements; } - - /** - * @return the name of the page group - */ - public String getName() { - return name; - } - + /** * Creates a TagLogicalElement on the page. * @@ -93,32 +72,17 @@ public class PageGroup extends AbstractNamedAFPObject { * the value of the tag */ public void createTagLogicalElement(String name, String value) { - TagLogicalElement tle = new TagLogicalElement(name, value); - tagLogicalElements.add(tle); - - } - - /** - * Creates an InvokeMediaMap on the page. - * - * @param name - * the name of the media map - */ - public void createInvokeMediumMap(String name) { - - InvokeMediumMap imm = new InvokeMediumMap(name); - objects.add(imm); - + if (!getTagLogicalElements().contains(tle)) { + getTagLogicalElements().add(tle); + } } /** * Method to mark the end of the page group. */ - public void endPageGroup() { - + protected void endPageGroup() { complete = true; - } /** @@ -129,33 +93,19 @@ public class PageGroup extends AbstractNamedAFPObject { return complete; } - /** - * Accessor method to write the AFP datastream for the page group. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + /** + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - + protected void writeContent(OutputStream os) throws IOException { + writeObjects(tagLogicalElements, os); + super.writeContent(os); } /** - * Helper method to write the start of the page group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(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 @@ -165,26 +115,17 @@ public class PageGroup extends AbstractNamedAFPObject { 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); - } /** - * Helper method to write the end of the page group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(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 @@ -194,15 +135,9 @@ public class PageGroup extends AbstractNamedAFPObject { 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); - } - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java index a9a4581e7..bad80bcc1 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PageObject.java @@ -18,11 +18,10 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; - - /** * Pages contain the data objects that comprise a presentation document. Each * page has a set of data objects associated with it. Each page within a @@ -45,11 +44,6 @@ import java.io.OutputStream; */ public class PageObject extends AbstractPageObject { - /** - * The resource group object - */ - private ResourceGroup resourceGroup = null; - /** * Construct a new page object for the specified name argument, the page * name should be an 8 character identifier. @@ -69,20 +63,7 @@ public class PageObject extends AbstractPageObject { */ public PageObject(String name, int width, int height, int rotation, int widthRes, int heightRes) { - super(name, width, height, rotation, widthRes, heightRes); - - } - - /** - * Adds an overlay to the page resources - * @param overlay the overlay to add - */ - public void addOverlay(Overlay overlay) { - if (resourceGroup == null) { - resourceGroup = new ResourceGroup(); - } - resourceGroup.addOverlay(overlay); } /** @@ -98,47 +79,14 @@ public class PageObject extends AbstractPageObject { * the orientation required for the overlay */ public void createIncludePageOverlay(String name, int x, int y, int orientation) { - - IncludePageOverlay ipo = new IncludePageOverlay(name, x, y, orientation); - objects.add(ipo); - + addObject(new IncludePageOverlay(name, x, y, orientation)); } /** - * Accessor method to write the AFP datastream for the page. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - if (resourceGroup != null) { - resourceGroup.writeDataStream(os); - } - - activeEnvironmentGroup.writeDataStream(os); - - writeObjectList(segments, os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the page. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(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 @@ -148,26 +96,17 @@ public class PageObject extends AbstractPageObject { 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); - } /** - * Helper method to write the end of the page. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(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 @@ -177,15 +116,9 @@ public class PageObject extends AbstractPageObject { 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); - } - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageSegment.java b/src/java/org/apache/fop/render/afp/modca/PageSegment.java new file mode 100644 index 000000000..f88e3cc55 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/PageSegment.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; +import java.util.List; + +/** + * A page segment is a MO:DCA-P resource object. It may be stored in an + * external resource library or it may be carried in a resource group. + * Page segments contain any combination of IOCA image objects and + * GOCA graphics objects. + */ +public class PageSegment extends AbstractNamedAFPObject { + + private List objects = null; + + /** + * Main constructor + * @param name the name of this object + */ + public PageSegment(String name) { + super(name); + } + + /** + * Adds a resource object (image/graphic) to this page segment + * @param object the resource objec to add to this page segment + */ + public void addObject(AbstractAFPObject object) { + if (objects == null) { + objects = new java.util.ArrayList(); + } + objects.add(object); + } + + /** + * {@inheritDoc} + */ + protected void writeStart(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) 0xA8; // Structured field id byte 2 + data[5] = (byte) 0x5F; // 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); + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(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) 0x5F; // 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); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + writeObjects(objects, os); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java b/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java new file mode 100644 index 000000000..33e6407ee --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; + +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * The Preprocess Presentation Object structured field specifies presentation + * parameters for a data object that has been mapped as a resource. + */ +public class PreprocessPresentationObject extends AbstractStructuredAFPObject { + private static final byte TYPE_OTHER = (byte)0x92; + private static final byte TYPE_OVERLAY = (byte)0xDF; + private static final byte TYPE_IMAGE = (byte)0xFB; + + private byte objType = TYPE_OTHER; + private byte objOrent = 0; // object always processed at 0 degree orientation + private int objXOffset = -1; + private int objYOffset = -1; + + /** + * Main constructor + * @param prePresObj the presentation object to be preprocessed + */ + public PreprocessPresentationObject(AbstractStructuredAFPObject prePresObj) { + if (prePresObj instanceof ImageObject || prePresObj instanceof Overlay) { + if (prePresObj instanceof ImageObject) { + this.objType = TYPE_IMAGE; + } else { + this.objType = TYPE_OVERLAY; + } + setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, + prePresObj.getFullyQualifiedName()); + } else { + this.objType = TYPE_OTHER; +// Registry registry = Registry.getInstance(); +// Registry.Entry entry = registry.getEntry(compontentId); +// entry. +// setObjectClassification(objectClass, componentId) + } + } + + public static final byte ORIENTATION_ZERO_DEGREES = 1; + public static final byte ORIENTATION_90_DEGREES = 2; + public static final byte ORIENTATION_180_DEGREES = 4; + public static final byte ORIENTATION_270_DEGREES = 8; + + /** + * Sets the object orientations relative to media leading edge + * @param orientation the object orientations relative to media leading edge + */ + public void setOrientation(byte orientation) { + objOrent = (byte)orientation; + } + + /** + * Sets the X axis origin for object content + * @param xOffset the X axis origin for object content + */ + public void setXOffset(int xOffset) { + this.objXOffset = xOffset; + } + + /** + * Sets the Y axis origin for object content + * @param yOffset the Y axis origin for object content + */ + public void setYOffset(int yOffset) { + this.objYOffset = yOffset; + } + + /** + * {@inheritDoc} + */ + public void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + byte[] l = BinaryUtils.convert(19 + getTripletDataLength(), 2); + byte[] data = new byte[9]; + data[0] = 0x5A; // Structured field identifier + data[1] = l[0]; // Length byte 1 + data[2] = l[1]; // Length byte 1 + data[3] = (byte)0xD3; // Structured field id byte 1 + data[4] = (byte)0xAD; // Structured field id byte 2 + data[5] = (byte)0xC3; // Structured field id byte 3 + data[6] = 0x00; // Flags + data[7] = 0x00; // Reserved + data[8] = 0x00; // Reserved + + os.write(data); + } + + /** + * {@inheritDoc} + */ + public void writeContent(OutputStream os) throws IOException { + byte[] data = new byte[12]; + byte[] l = BinaryUtils.convert(12 + getTripletDataLength(), 2); + data[0] = l[0]; // RGLength + data[1] = l[1]; // RGLength + data[2] = objType; // ObjType + data[3] = 0x00; // Reserved + data[4] = 0x00; // Reserved + data[5] = objOrent; // ObjOrent + if (objXOffset > 0) { + byte[] xOff = BinaryUtils.convert(objYOffset, 3); + data[6] = xOff[0]; // XocaOset (not specified) + data[7] = xOff[1]; // XocaOset + data[8] = xOff[2]; // XocaOset + } else { + data[6] = (byte)0xFF; // XocaOset (not specified) + data[7] = (byte)0xFF; // XocaOset + data[8] = (byte)0xFF; // XocaOset + } + if (objYOffset > 0) { + byte[] yOff = BinaryUtils.convert(objYOffset, 3); + data[9] = yOff[0]; // YocaOset (not specified) + data[10] = yOff[1]; // YocaOset + data[11] = yOff[2]; // YocaOset + } else { + data[9] = (byte)0xFF; // YocaOset (not specified) + data[10] = (byte)0xFF; // YocaOset + data[11] = (byte)0xFF; // YocaOset + } + os.write(data); + + // Triplets + super.writeContent(os); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java index 901f24bb1..49f7c81a8 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java @@ -22,7 +22,7 @@ package org.apache.fop.render.afp.modca; import java.awt.Color; import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; +import java.util.List; /** * The Presentation Text object is the data object used in document processing @@ -47,17 +47,15 @@ public class PresentationTextObject extends AbstractNamedAFPObject { */ private static final String DEFAULT_NAME = "PTO00001"; - private PresentationTextData currentPresentationTextData = null; + private PresentationTextData currentPresentationTextData; - private ArrayList presentationTextData = new ArrayList(); + private List presentationTextData; /** * Default constructor for the PresentationTextObject */ public PresentationTextObject() { - this(DEFAULT_NAME); - } /** @@ -66,15 +64,13 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @param name the name of this presentation object */ public PresentationTextObject(String name) { - super(name); - } /** * Create the presentation text data for the byte array of data. * - * @param fontNumber + * @param fontNum * The font resource identifier. * @param x * The x coordinate for the text data. @@ -89,18 +85,16 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @param data * The text data to be created. */ - public void createTextData(int fontNumber, int x, int y, Color col, + public void createTextData(int fontNum, int x, int y, Color col, int vsci, int ica, byte[] data) { - // Use a default orientation of zero - createTextData(fontNumber, x, y, 0, col, vsci, ica, data); - + createTextData(fontNum, x, y, 0, col, vsci, ica, data); } /** * Create the presentation text data for the byte array of data. * - * @param fontReference + * @param fontRef * The font resource identifier. * @param x * The x coordinate for the text data. @@ -117,25 +111,19 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @param data * The text data to be created. */ - public void createTextData(int fontReference, int x, int y, int orientation, + public void createTextData(int fontRef, int x, int y, int orientation, Color col, int vsci, int ica, byte[] data) { - if (currentPresentationTextData == null) { startPresentationTextData(); } - try { - currentPresentationTextData.createTextData(fontReference, x, y, + currentPresentationTextData.createTextData(fontRef, x, y, orientation, col, vsci, ica, data); - } catch (MaximumSizeExceededException msee) { - endPresentationTextData(); - createTextData(fontReference, x, y, orientation, col, vsci, ica, data); - + createTextData(fontRef, x, y, orientation, col, vsci, ica, data); } - } /** @@ -180,47 +168,38 @@ public class PresentationTextObject extends AbstractNamedAFPObject { */ public void createLineData(int x1, int y1, int x2, int y2, int thickness, int orientation, Color col) { - if (currentPresentationTextData == null) { startPresentationTextData(); } - try { - currentPresentationTextData.createLineData(x1, y1, x2, y2, thickness, orientation, col); - } catch (MaximumSizeExceededException msee) { - endPresentationTextData(); createLineData(x1, y1, x2, y2, thickness, orientation, col); - } - } /** * Helper method to mark the start of the presentation text data */ private void startPresentationTextData() { - + if (presentationTextData == null) { + presentationTextData = new java.util.ArrayList(); + } if (presentationTextData.size() == 0) { currentPresentationTextData = new PresentationTextData(true); } else { currentPresentationTextData = new PresentationTextData(); } - presentationTextData.add(currentPresentationTextData); - } /** * Helper method to mark the end of the presentation text data */ private void endPresentationTextData() { - currentPresentationTextData = null; - } /** @@ -228,15 +207,10 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @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 { - + public void writeDataStream(OutputStream os) throws IOException { writeStart(os); - - writeObjectList(presentationTextData, os); - + writeObjects(presentationTextData, os); writeEnd(os); - } /** @@ -244,20 +218,14 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @return the name of this presentation text object */ public String getName() { - return name; - } /** - * Helper method to write the start of the presenation text object. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(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 @@ -267,27 +235,17 @@ public class PresentationTextObject extends AbstractNamedAFPObject { 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); - } /** - * Helper method to write the end of the presenation text object. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - - + protected void writeEnd(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 @@ -297,15 +255,10 @@ public class PresentationTextObject extends AbstractNamedAFPObject { 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); - } /** @@ -316,22 +269,14 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * method terminates the control sequence. */ public void endControlSequence() { - if (currentPresentationTextData == null) { startPresentationTextData(); } - try { - currentPresentationTextData.endControlSequence(); - } catch (MaximumSizeExceededException msee) { - endPresentationTextData(); endControlSequence(); - } - } - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/Registry.java b/src/java/org/apache/fop/render/afp/modca/Registry.java new file mode 100644 index 000000000..b643cd2d2 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/Registry.java @@ -0,0 +1,353 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.UnsupportedEncodingException; + +import org.apache.commons.logging.LogFactory; + +/** + * MOD:CA object type registry + */ +public final class Registry { + + /** IOB supported object types */ + public static final byte IOCA_FS10 = 5; + public static final byte IOCA_FS11 = 11; + public static final byte IOCA_FS45 = 12; + public static final byte DIB_WIN = 17; //device independent bitmap + public static final byte DIB_OS2 = 18; + public static final byte PCX = 19; + public static final byte GIF = 22; + public static final byte JFIF = 23; // jpeg file interchange format + public static final byte PDF_SINGLE_PAGE = 25; + public static final byte PCL_PAGE_OBJECT = 34; + public static final byte EPS_TRANS = 48; + public static final byte PDF_SINGLE_PAGE_TRANS = 49; + public static final byte JPEG2000 = 58; + + /** IOB unsupported object types */ + public static final byte EPS = 13; + public static final byte TIFF = 14; + public static final byte COM_SETUP_FILE = 15; + public static final byte TAPE_LABEL_SETUP_FILE = 16; + public static final byte CMT = 20; // color mapping table + public static final byte ANACOMP_CONTROL_RECORD = 24; + public static final byte PDF_RESOURCE_OBJECT = 26; + public static final byte IOCA_FS42 = 45; + public static final byte RESIDENT_COLOR_PROFILE = 46; + public static final byte IOCA_FS45_TILE_RESOURCE = 47; + public static final byte FONT = 51; + public static final byte FONT_COLLECTION = 53; + public static final byte RESOURCE_ACCESS_TABLE = 54; + public static final byte IOCA_FS40 = 55; + public static final byte UP3I_PRINT_DATA = 56; + public static final byte COLOR_MANAGEMENT_RESOURCE = 57; + + + /** internal mapping array references */ + private static final int COMPONENT_ID = 0; + private static final int OBJECT_TYPE_NAME = 1; + private static final int OBJECT_ID = 2; + private static final int CAN_BE_INCLUDED = 3; + + private byte[][][] componentIdMap; + + private static Registry instance = null; + + /** + * @return a single instance of Registry + */ + public static Registry getInstance() { + synchronized (instance) { + if (instance == null) { + instance = new Registry(); + } + } + return instance; + } + + private Registry() { + init(); + } + + private void init() { + try { + componentIdMap = new byte[][][] { + /* object type id (OID), object type name, compontent Id, can be included with IOB?, */ + { + {IOCA_FS10}, + "IOCA FS10".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x05}, + {1} + }, + { + {IOCA_FS11}, + "IOCA FS11".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0B}, + {1} + }, + { + {IOCA_FS45}, + "IOCA FS45".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0C}, + {1} + }, + { + {EPS}, + "Encapsulated Postscript".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D}, + {0} + }, + { + {TIFF}, + "TIFF".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E}, + {0} + }, + { + {COM_SETUP_FILE}, + "COM setup".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0F}, + {0} + }, + { + {TAPE_LABEL_SETUP_FILE}, + "Tape Label setup".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x10}, + {0} + }, + { + {DIB_WIN}, + "DIB, Windows Version".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x11}, + {1} + }, + { + {DIB_OS2}, + "DIB, OS/2 PM Version".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x12}, + {1} + }, + { + {PCX}, + "PCX".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x13}, + {1} + }, + { + {CMT}, + "Color Mapping Table (CMT)".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x14}, + {0} + }, + { + {GIF}, + "GIF".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16}, + {1} + }, + { + {JFIF}, + "JFIF".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17}, + {1} + }, + { + {ANACOMP_CONTROL_RECORD}, + "AnaStak Control Record".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x18}, + {0} + }, + { + {PDF_SINGLE_PAGE}, + "PDF Single-page Object".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19}, + {1} + }, + { + {PDF_RESOURCE_OBJECT}, + "PDF Resource Object".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x1A}, + {0} + }, + { + {PCL_PAGE_OBJECT}, + "PCL Page Object".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22}, + {1} + }, + { + {IOCA_FS42}, + "IOCA FS42".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2D}, + {0} + }, + { + {RESIDENT_COLOR_PROFILE}, + "Resident Color Profile".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2E}, + {0} + }, + { + {IOCA_FS45_TILE_RESOURCE}, + "IOCA FS45".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2E}, + {0} + }, + { + {EPS_TRANS}, + "EPS with Transparency".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x30}, + {1} + }, + { + {PDF_SINGLE_PAGE_TRANS}, + "PDF with Transparency".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x31}, + {1} + }, + { + {FONT}, + "TrueType/OpenType Font".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x33}, + {0} + }, + { + {FONT_COLLECTION}, + "TrueType/OpenType Font Collection".getBytes( + AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x35}, + {0} + }, + { + {RESOURCE_ACCESS_TABLE}, + "Resource Access Table".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x36}, + {0} + }, + { + {IOCA_FS40}, + "IOCA FS40".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x37}, + {0} + }, + { + {UP3I_PRINT_DATA}, + "IP3i Print Data".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x38}, + {0} + }, + { + {COLOR_MANAGEMENT_RESOURCE}, + "Color Management Resource (CMR)".getBytes( + AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x39}, + {0} + }, + { + {JPEG2000}, + "JPEG2000 (JP2) File Format".getBytes( + AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x3A}, + {1} + } + }; + } catch (UnsupportedEncodingException e) { + // should never happen! + LogFactory.getLog("org.apache.fop.render.afp.modca.Registry").error(e.getMessage()); + } + } + + private byte[][][] getComponentIdMap() { + if (componentIdMap == null) { + init(); + } + return componentIdMap; + } + + private byte[][] getMapData(byte compontentId) { + getComponentIdMap(); + for (int i = 0; i < componentIdMap.length; i++) { + if (compontentId == componentIdMap[i][0][0]) { + return componentIdMap[i]; + } + } + return null; + } + + /** + * Returns a registry Entry for a given componentId + * @param compontentId a compontent id + * @return the registry entry for a give componentId + */ + public Entry getEntry(byte compontentId) { + byte[][] data = getMapData(compontentId); + if (data != null) { + return new Registry.Entry(data); + } + return null; + } + + /** + * Encapsulates a MOD:CA Registry Entry + */ + public final class Entry { + private byte[][] data; + + /** + * Main constructor + * @param the map data structure array + */ + private Entry(byte[][] data) { + this.data = data; + } + + /** + * Returns a MOD:CA object type OID from a given a componentId + * @return the corresponding object type id for a given component id + * or null if the component id is unknown and the object type OID was not found. + */ + public byte[] getOID() { + return data[OBJECT_ID]; + } + + /** + * @return the object type name for the given componentId + */ + public byte[] getObjectTypeName() { + return data[OBJECT_TYPE_NAME]; + } + + /** + * @return the compontentId for this entry + */ + public byte[] getComponentId() { + return data[COMPONENT_ID]; + } + + /** + * @return true if this component can be included with an IOB structured field + */ + public boolean canBeIncluded() { + return data[CAN_BE_INCLUDED][0] == 1; + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java new file mode 100644 index 000000000..080226e9f --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; +import java.util.List; + +/** + * A Resource Environment Group contains a set of resources for a document + * or for a group of pages in a document. + */ +public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup { + /** + * Default name for the resource group + */ + private static final String DEFAULT_NAME = "REG00001"; + + /** + * The maps data resources contained in this resource environment group + */ + private List mapDataResources = null; + + /** + * The maps page overlays contained in this resource environment group + */ + private List mapPageOverlays = null; + + /** + * The pre-process presentation objects contained in this resource environment group + */ + private List preProcessPresentationObjects = null; + + /** + * The resource environment group state + */ + private boolean complete = false; + + /** + * Default constructor + */ + public ResourceEnvironmentGroup() { + this(DEFAULT_NAME); + } + + private List getMapDataResources() { + if (mapDataResources == null) { + this.mapDataResources = new java.util.ArrayList(); + } + return this.mapDataResources; + } + + private List getMapPageOverlays() { + if (mapPageOverlays == null) { + this.mapPageOverlays = new java.util.ArrayList(); + } + return this.mapPageOverlays; + } + + private List getPreprocessPresentationObjects() { + if (preProcessPresentationObjects == null) { + this.preProcessPresentationObjects = new java.util.ArrayList(); + } + return this.preProcessPresentationObjects; + } + + /** + * Constructor for the ResourceEnvironmentGroup, this takes a + * name parameter which must be 8 characters long. + * @param name the resource environment group name + */ + public ResourceEnvironmentGroup(String name) { + super(name); + } + + /** + * Adds an AFP object mapping reference to this resource environment group + * @param obj the object to add + */ + public void addObject(AbstractStructuredAFPObject obj) { + getMapDataResources().add(new MapDataResource(obj)); + getPreprocessPresentationObjects().add(new PreprocessPresentationObject(obj)); + } + + /** + * Returns an indication if the resource environment group is complete + * @return whether or not this resource environment group is complete or not + */ + public boolean isComplete() { + return complete; + } + + /** + * {@inheritDoc} + */ + protected void writeStart(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) 0xA8; // Structured field id byte 2 + data[5] = (byte) 0xD9; // 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); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + writeObjects(mapDataResources, os); + writeObjects(mapPageOverlays, os); + writeObjects(preProcessPresentationObjects, os); + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(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) 0xD9; // 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); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java index 07043dcf1..48f4f0eeb 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java @@ -21,32 +21,34 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; +import java.util.Map; + +import org.apache.fop.render.afp.DataObjectParameters; +import org.apache.fop.render.afp.ImageObjectParameters; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.tools.StringUtils; +import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; /** * A Resource Group contains a set of overlays. */ public final class ResourceGroup extends AbstractNamedAFPObject { - + /** * Default name for the resource group */ private static final String DEFAULT_NAME = "RG000001"; - /** - * The overlays contained in this resource group + * Mapping of resource uri to data resource object (image/graphic) */ - private List overlays = new ArrayList(); + private Map/**/ resourceMap = null; /** * Default constructor */ public ResourceGroup() { - this(DEFAULT_NAME); - } /** @@ -55,53 +57,208 @@ public final class ResourceGroup extends AbstractNamedAFPObject { * @param name the resource group name */ public ResourceGroup(String name) { - super(name); - } + private static final String IMAGE_NAME_PREFIX = "IMG"; + private static final String GRAPHIC_NAME_PREFIX = "GRA"; + private static final String PAGE_SEGMENT_NAME_PREFIX = "PAG"; + private static final String BARCODE_NAME_PREFIX = "BAR"; + private static final String OTHER_NAME_PREFIX = "OTH"; + /** - * Adds an overlay to the resource group - * @param overlay the overlay to add + * Converts a byte array containing 24 bit RGB image data to a grayscale + * image. + * + * @param io + * the target image object + * @param raw + * the buffer containing the RGB image data + * @param width + * the width of the image in pixels + * @param height + * the height of the image in pixels + * @param bitsPerPixel + * the number of bits to use per pixel */ - public void addOverlay(Overlay overlay) { - overlays.add(overlay); + private static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, + int height, int bitsPerPixel) { + int pixelsPerByte = 8 / bitsPerPixel; + int bytewidth = (width / pixelsPerByte); + if ((width % pixelsPerByte) != 0) { + bytewidth++; + } + byte[] bw = new byte[height * bytewidth]; + byte ib; + for (int y = 0; y < height; y++) { + ib = 0; + int i = 3 * y * width; + for (int x = 0; x < width; x++, i += 3) { + + // see http://www.jguru.com/faq/view.jsp?EID=221919 + double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d + * ((int) raw[i + 1] & 0xff) + 0.072169d + * ((int) raw[i + 2] & 0xff); + switch (bitsPerPixel) { + case 1: + if (greyVal < 128) { + ib |= (byte) (1 << (7 - (x % 8))); + } + break; + case 4: + greyVal /= 16; + ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4)); + break; + case 8: + ib = (byte) greyVal; + break; + default: + throw new UnsupportedOperationException( + "Unsupported bits per pixel: " + bitsPerPixel); + } + + if ((x % pixelsPerByte) == (pixelsPerByte - 1) + || ((x + 1) == width)) { + bw[(y * bytewidth) + (x / pixelsPerByte)] = ib; + ib = 0; + } + } + } + io.setImageIDESize((byte) bitsPerPixel); + io.setImageData(bw); } /** - * Returns the list of overlays - * @return the list of overlays + * Helper method to create an image on the current container and to return + * the object. + * @param params the set of image object parameters + * @return a newly created image object */ - public List getOverlays() { - return overlays; + private ImageObject createImage(ImageObjectParameters params) { + String name = IMAGE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); + ImageObject imageObj = new ImageObject(name); + if (params.hasCompression()) { + int compression = params.getCompression(); + switch (compression) { + case TIFFImage.COMP_FAX_G3_1D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MH); + break; + case TIFFImage.COMP_FAX_G3_2D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MR); + break; + case TIFFImage.COMP_FAX_G4_2D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MMR); + break; + default: + throw new IllegalStateException( + "Invalid compression scheme: " + compression); + } + } + imageObj.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_URL, params.getUri()); + imageObj.setImageParameters(params.getWidthRes(), params.getHeightRes(), + params.getImageDataWidth(), params.getImageDataHeight()); + if (params.isColor()) { + imageObj.setImageIDESize((byte)24); + imageObj.setImageData(params.getData()); + } else { + convertToGrayScaleImage(imageObj, params.getData(), + params.getImageDataWidth(), params.getImageDataHeight(), + params.getBitsPerPixel()); + } + return imageObj; } - + /** - * Accessor method to obtain write the AFP datastream for - * the resource group. - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception of some sort has occurred + * Helper method to create a graphic in the current container and to return + * the object. + * @param params the data object parameters + * @return a newly created graphics object */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(overlays, os); - - writeEnd(os); + private GraphicsObject createGraphic(DataObjectParameters params) { + String name = GRAPHIC_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); + GraphicsObject graphicsObj = new GraphicsObject(name); + return graphicsObj; + } + /** + * Adds a data object to this resource group + * @param params the data object parameters + * @return an include object reference + */ + public IncludeObject addObject(DataObjectParameters params) { + ResourceObject resourceObj = (ResourceObject)getResourceMap().get(params.getUri()); + if (resourceObj == null) { + AbstractDataObject dataObj; + if (params instanceof ImageObjectParameters) { + dataObj = createImage((ImageObjectParameters)params); + } else { + dataObj = createGraphic(params); + } + // TODO: AC - rotation? + int rotation = 0; + dataObj.setViewport(params.getX(), params.getY(), + params.getWidth(), params.getHeight(), + params.getWidthRes(), params.getHeightRes(), rotation); + + // Wrap the data object in a resource object + resourceObj = new ResourceObject(dataObj.getName(), dataObj); + getResourceMap().put(params.getUri(), resourceObj); + } + IncludeObject includeObj = new IncludeObject(resourceObj); + //includeObj.setObjectAreaSize(params.getX(), params.getY()); + return includeObj; + } + + /** + * @return the number of resources contained in this resource group + */ + public int getResourceCount() { + if (resourceMap != null) { + return resourceMap.size(); + } + return 0; + } + + /** + * Returns true if the resource exists within this resource group, + * false otherwise. + * + * @param uri the uri of the resource + * @return true if the resource exists within this resource group + */ + public boolean resourceExists(String uri) { + return getResourceMap().containsKey(uri); + } + + /** + * Returns the list of resources + * @return the list of resources + */ + public Map/**/ getResourceMap() { + if (resourceMap == null) { + resourceMap = new java.util.HashMap/**/(); + } + return resourceMap; } /** - * Helper method to write the start of the resource group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { + public void writeContent(OutputStream os) throws IOException { + if (resourceMap != null) { + super.writeObjects(resourceMap.values(), os); + } + } + /** + * {@inheritDoc} + */ + protected void writeStart(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 @@ -111,26 +268,17 @@ public final class ResourceGroup extends AbstractNamedAFPObject { 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); - } /** - * Helper method to write the end of the resource group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(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 @@ -140,15 +288,16 @@ public final class ResourceGroup extends AbstractNamedAFPObject { 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); - } - -} \ No newline at end of file + + /** + * {@inheritDoc} + */ + public String toString() { + return this.name + " " + this.resourceMap; + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java new file mode 100644 index 000000000..ff660a208 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; + +import org.apache.fop.render.afp.modca.triplets.Triplet; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * This resource structured field begins an envelope that is used to carry + * resource objects in print-file-level (external) resource groups. + */ +public class ResourceObject extends AbstractPreparedAFPObject { + + /** + * Resource object types + */ + private static final byte GRAPHICS_OBJECT = 0x03; + private static final byte BARCODE_OBJECT = 0x05; + private static final byte IMAGE_OBJECT = 0x06; + private static final byte FONT_CHARACTER_SET_OBJECT = 0x40; + private static final byte CODE_PAGE_OBJECT = 0x41; + private static final byte CODED_FONT_OBJECT = 0x42; + private static final byte OBJECT_CONTAINER = (byte) 0x92; + private static final byte DOCUMENT_OBJECT = (byte) 0xA8; + private static final byte PAGE_SEGMENT_OBJECT = (byte) 0xFB; + private static final byte OVERLAY_OBJECT = (byte) 0xFC; + private static final byte PAGEDEF_OBJECT = (byte) 0xFD; + private static final byte FORMDEF_OBJECT = (byte) 0xFE; + + /** + * the resource object + */ + private AbstractNamedAFPObject resourceObj = null; + + /** + * Default constructor + * + * @param name the name of this resource (reference id) + * @param resourceObj the resource object to be added + */ + public ResourceObject(String name, AbstractNamedAFPObject resourceObj) { + super(name); + this.resourceObj = resourceObj; + byte type; + if (resourceObj instanceof ImageObject) { + type = IMAGE_OBJECT; + } else if (resourceObj instanceof GraphicsObject) { + type = GRAPHICS_OBJECT; + } else if (resourceObj instanceof Document) { + type = DOCUMENT_OBJECT; + } else if (resourceObj instanceof PageSegment) { + type = PAGE_SEGMENT_OBJECT; + } else if (resourceObj instanceof Overlay) { + type = OVERLAY_OBJECT; + } else { + throw new UnsupportedOperationException( + "Unsupported resource object type " + resourceObj); + } + setResourceObjectType(type); + } + + private void setResourceObjectType(byte type) { + getTriplets().add(new ResourceObjectTypeTriplet(type)); + } + + /** + * @return the resource object contained in this envelope + */ + public AbstractNamedAFPObject getResource() { + return this.resourceObj; + } + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + // Set the total record length + byte[] len = BinaryUtils.convert(18 + getTripletDataLength(), 2); + byte[] data = new byte[] { + 0x5A, // Structured field identifier + len[0], // Length byte 1 + len[1], // Length byte 2 + (byte)0xD3, // Structured field id byte 1 + (byte)0xA8, // Structured field id byte 2 + (byte)0xCE, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00, // Reserved + nameBytes[0], + nameBytes[1], + nameBytes[2], + nameBytes[3], + nameBytes[4], + nameBytes[5], + nameBytes[6], + nameBytes[7], + 0x00, // Reserved + 0x00, // Reserved + }; + os.write(data); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); // write triplets + if (resourceObj != null) { + resourceObj.writeDataStream(os); + } + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[] { + 0x5A, // Structured field identifier + 0x00, // Length byte 1 + 0x10, // Length byte 2 + (byte)0xD3, // Structured field id byte 1 + (byte)0xA9, // Structured field id byte 2 + (byte)0xCE, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00, // Reserved + nameBytes[0], + nameBytes[1], + nameBytes[2], + nameBytes[3], + nameBytes[4], + nameBytes[5], + nameBytes[6], + nameBytes[7], + }; + os.write(data); + } + + private class ResourceObjectTypeTriplet extends Triplet { + + private static final byte RESOURCE_OBJECT = 0x21; + + /** + * Main constructor + * + * @param type + * the resource type + */ + public ResourceObjectTypeTriplet(byte type) { + super(RESOURCE_OBJECT, + new byte[] { + type, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } + ); + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java new file mode 100644 index 000000000..23c0d7e6b --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id: $ */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.triplets; + + +/** + * A Fully Qualified Name triplet enable the identification and referencing of + * objects using Gloabl Identifiers (GIDs). + */ +public class FullyQualifiedNameTriplet extends Triplet { + // Specifies how the GID will be used + public static final byte TYPE_REPLACE_FIRST_GID_NAME = 0x01; + public static final byte TYPE_FONT_FAMILY_NAME = 0x07; + public static final byte TYPE_FONT_TYPEFACE_NAME = 0x08; + public static final byte TYPE_MODCA_RESOURCE_HIERARCHY_REF = 0x09; + public static final byte TYPE_BEGIN_RESOURCE_GROUP_REF = 0x0A; + public static final byte TYPE_ATTRIBUTE_GID = 0x0B; + public static final byte TYPE_PROCESS_ELEMENT_GID = 0x0C; + public static final byte TYPE_BEGIN_PAGE_GROUP_REF = 0x0D; + public static final byte TYPE_MEDIA_TYPE_REF = 0x11; + public static final byte TYPE_COLOR_MANAGEMENT_RESOURCE_REF = 0x41; + public static final byte TYPE_DATA_OBJECT_FONT_BASE_FONT_ID = 0x6E; + public static final byte TYPE_DATA_OBJECT_FONT_LINKED_FONT_ID = 0x7E; + public static final byte TYPE_BEGIN_DOCUMENT_REF = (byte)0x83; + public static final byte TYPE_BEGIN_RESOURCE_OBJECT_REF = (byte)0x84; + public static final byte TYPE_CODE_PAGE_NAME_REF = (byte)0x85; + public static final byte TYPE_FONT_CHARSET_NAME_REF = (byte)0x86; + public static final byte TYPE_BEGIN_PAGE_REF = (byte)0x87; + public static final byte TYPE_BEGIN_MEDIUM_MAP_REF = (byte)0x8D; + public static final byte TYPE_CODED_FONT_NAME_REF = (byte)0x8E; + public static final byte TYPE_BEGIN_DOCUMENT_INDEX_REF = (byte)0x98; + public static final byte TYPE_BEGIN_OVERLAY_REF = (byte)0xB0; + public static final byte TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF = (byte)0xBE; + public static final byte TYPE_INDEX_ELEMENT_GID = (byte)0xCA; + public static final byte TYPE_OTHER_OBJECT_DATA_REF = (byte)0xCE; + public static final byte TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF = (byte)0xDE; + + // GID Format + public static final byte FORMAT_CHARSTR = (byte)0x00; + public static final byte FORMAT_OID = (byte)0x10; + public static final byte FORMAT_URL = (byte)0x20; + + private byte[] fqName; + + /** + * @return the actual fully qualified name of this triplet + */ + public byte[] getFullyQualifiedName() { + return fqName; + } + + /** + * Main constructor + * @param fqnType the fully qualified name type + * @param fqnFmt the fully qualified name format + * @param fqName the fully qualified name + */ + public FullyQualifiedNameTriplet(byte fqnType, byte fqnFmt, byte[] fqName) { + super(FULLY_QUALIFIED_NAME); + this.fqName = fqName; + super.data = new byte[2 + fqName.length]; + data[0] = fqnType; + data[1] = fqnFmt; + // FQName + System.arraycopy(fqName, 0, data, 2, fqName.length); + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java new file mode 100644 index 000000000..e99045292 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.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.render.afp.modca.triplets; + +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * The Measurement Units triplet is used to specify the units of measure + * for a presentation space + */ +public class MeasurementUnitsTriplet extends Triplet { + + private static final byte TEN_INCHES = 0x00; + private static final byte TEN_CM = 0x01; + + /** + * Main constructor + */ + public MeasurementUnitsTriplet() { + super(MEASUREMENT_UNITS); + //TODO: units correct? + byte[] xUnits = BinaryUtils.convert(1, 2); + byte[] yUnits = BinaryUtils.convert(1, 2); + super.data = new byte[] { + TEN_INCHES, // XoaBase + TEN_INCHES, // YoaBase + xUnits[0], // XoaUnits (x units per unit base) + xUnits[1], + yUnits[0], // YoaUnits (y units per unit base) + yUnits[1] + }; + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java new file mode 100644 index 000000000..bd026763d --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.triplets; + +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * The Object Area Size triplet is used to specify the extent of an object area + * in the X and Y directions + */ +public class ObjectAreaSizeTriplet extends Triplet { + + /** + * Main constructor + * @param x the object area extent for the X axis + * @param y the object area extent for the Y axis + */ + public ObjectAreaSizeTriplet(int x, int y) { + super(Triplet.OBJECT_AREA_SIZE); + byte[] xOASize = BinaryUtils.convert(x, 3); + byte[] yOASize = BinaryUtils.convert(y, 3); + super.data = new byte[] { + 0x02, // SizeType + xOASize[0], // XoaSize - Object area extent for X axis + xOASize[1], + xOASize[2], + yOASize[0], // YoaSize - Object area extent for Y axis + yOASize[1], + yOASize[2] + }; + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java new file mode 100644 index 000000000..4d5f41359 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.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.render.afp.modca.triplets; + +import org.apache.fop.render.afp.modca.Registry; + +/** + * The Object Classification is used to classify and identify object data. + * The object data may or may not be defined by an IBM presentation architecture + */ +public class ObjectClassificationTriplet extends Triplet { + public static final byte CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT = 0x01; + public static final byte CLASS_TIME_VARIANT_PRESENTATION_OBJECT = 0x10; + public static final byte CLASS_EXECUTABLE_PROGRAM = 0x20; + public static final byte CLASS_SETUP_FILE = 0x30; + public static final byte CLASS_SECONDARY_RESOURCE = 0x40; + public static final byte CLASS_DATA_OBJECT_FONT = 0x41; + + /** + * Main constructor + * + * @param objectClass + * the object class type + * @param componentId + * the object componentId + */ + public ObjectClassificationTriplet(byte objectClass, byte componentId) { + super(OBJECT_CLASSIFICATION); + byte[] data = new byte[93]; + data[0] = 0x00; // reserved (must be zero) + data[1] = objectClass; // ObjClass + data[2] = 0x00; // reserved (must be zero) + data[3] = 0x00; // reserved (must be zero) + data[4] = 0x00; // StrucFlgs - Information on the structure of the object container + data[5] = 0x00; // StrucFlgs + + Registry.Entry entry = Registry.getInstance().getEntry(componentId); + + if (entry == null) { + throw new UnsupportedOperationException("unknown registry entry " + componentId); + } + // RegObjId - MOD:CA-registered ASN.1 OID for object type (8-23) + System.arraycopy(entry.getOID(), 0, data, 6, entry.getOID().length); + + // ObjTpName - name of object type (24-55) + System.arraycopy(entry.getObjectTypeName(), 0, data, 22, + entry.getObjectTypeName().length); + + // ObjLev (not specified) - Release level or version number of object type (56-63) + + // CompName (not specified) - Name of company or org that owns object definition (64-95) + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ResourceObjectTypeTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ResourceObjectTypeTriplet.java new file mode 100644 index 000000000..c157659d6 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ResourceObjectTypeTriplet.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.triplets; + diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java new file mode 100644 index 000000000..bcf6f22c3 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.triplets; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import org.apache.fop.render.afp.modca.AFPConstants; +import org.apache.fop.render.afp.modca.AbstractAFPObject; + +/** + * A simple implementation of a MOD:CA triplet + */ +public class Triplet extends AbstractAFPObject { + public static final byte CODED_GRAPHIC_CHARACTER_SET_GLOBAL_IDENTIFIER = 0x01; + public static final byte FULLY_QUALIFIED_NAME = 0x02; + public static final byte MAPPING_OPTION = 0x04; + public static final byte OBJECT_CLASSIFICATION = 0x10; + public static final byte MODCA_INTERCHANGE_SET = 0x18; + public static final byte FONT_DESCRIPTOR_SPECIFICATION = 0x1F; + public static final byte OBJECT_FUNCTION_SET_SPECIFICATION = 0x21; + public static final byte EXTENDED_RESOURCE_LOCAL_IDENTIFIER = 0x22; + public static final byte RESOURCE_LOCAL_IDENTIFIER = 0x24; + public static final byte RESOURCE_SECTION_NUMBER = 0x25; + public static final byte CHARACTER_ROTATION = 0x26; + public static final byte OBJECT_BYTE_OFFSET = 0x2D; + public static final byte ATTRIBUTE_VALUE = 0x36; + public static final byte DESCRIPTOR_POSITION = 0x43; + public static final byte MEDIA_EJECT_CONTROL = 0x45; + public static final byte PAGE_OVERLAY_CONDITIONAL_PROCESSING = 0x46; + public static final byte RESOURCE_USAGE_ATTRIBUTE = 0x47; + public static final byte MEASUREMENT_UNITS = 0x4B; + public static final byte OBJECT_AREA_SIZE = 0x4C; + public static final byte AREA_DEFINITION = 0x4D; + public static final byte COLOR_SPECIFICATION = 0x4E; + public static final byte ENCODING_SCHEME_ID = 0x50; + public static final byte MEDIUM_MAP_PAGE_NUMBER = 0x56; + public static final byte OBJECT_BYTE_EXTENT = 0x57; + public static final byte OBJECT_STRUCTURED_FIELD_OFFSET = 0x58; + public static final byte OBJECT_STRUCTURED_FIELD_EXTENT = 0x59; + public static final byte OBJECT_OFFSET = 0x5A; + public static final byte FONT_HORIZONTAL_SCALE_FACTOR = 0x5D; + public static final byte OBJECT_COUNT = 0x5E; + public static final byte OBJECT_DATE_AND_TIMESTAMP = 0x62; + public static final byte COMMENT = 0x65; + public static final byte MEDIUM_ORIENTATION = 0x68; + public static final byte RESOURCE_OBJECT_INCLUDE = 0x6C; + public static final byte PRESENTATION_SPACE_RESET_MIXING = 0x70; + public static final byte PRESENTATION_SPACE_MIXING_RULE = 0x71; + public static final byte UNIVERSAL_DATE_AND_TIMESTAMP = 0x72; + public static final byte TONER_SAVER = 0x74; + public static final byte COLOR_FIDELITY = 0x75; + public static final byte FONT_FIDELITY = 0x78; + public static final byte ATTRIBUTE_QUALIFIER = (byte)0x80; + public static final byte PAGE_POSITION_INFORMATION = (byte)0x81; + public static final byte PARAMETER_VALUE = (byte)0x82; + public static final byte PRESENTATION_CONTROL = (byte)0x83; + public static final byte FONT_RESOLUTION_AND_METRIC_TECHNOLOGY = (byte)0x84; + public static final byte FINISHING_OPERATION = (byte)0x85; + public static final byte TEXT_FIDELITY = (byte)0x86; + public static final byte MEDIA_FIDELITY = (byte)0x87; + public static final byte FINISHING_FIDELITY = (byte)0x88; + public static final byte DATA_OBJECT_FONT_DESCRIPTOR = (byte)0x8B; + public static final byte LOCALE_SELECTOR = (byte)0x8C; + public static final byte UP3I_FINISHING_OPERATION = (byte)0x8E; + public static final byte COLOR_MANAGEMENT_RESOURCE_DESCRIPTOR = (byte)0x91; + public static final byte RENDERING_INTENT = (byte)0x95; + public static final byte CMR_TAG_FIDELITY = (byte)0x96; + public static final byte DEVICE_APPEARANCE = (byte)0x97; + + /** + * the triplet identifier + */ + protected byte id; + + /** + * the triplet's data contents + */ + protected byte[] data; + + /** + * Main constructor + * @param id the triplet identifier (see static definitions above) + * @param contents the data item contained in this triplet + */ + public Triplet(byte id, byte[] contents) { + this(id); + this.data = contents; + } + + /** + * Constructor + * @param id the triplet identifier (see static definitions above) + */ + public Triplet(byte id) { + this.id = id; + } + + /** + * Constructor + * @param id the triplet identifier (see static definitions above) + * @param content the content byte data + */ + public Triplet(byte id, byte content) { + this(id, new byte[] {content}); + } + + /** + * Constructor + * @param id the triplet identifier (see static definitions above) + * @param data the data item (in String form) contained in this triplet + * @throws UnsupportedEncodingException EBCIDIC encoding is not supported + */ + public Triplet(byte id, String data) throws UnsupportedEncodingException { + this(id, data.getBytes(AFPConstants.EBCIDIC_ENCODING)); + } + + /** + * {@inheritDoc} + */ + public void writeDataStream(OutputStream os) throws IOException { + os.write((byte)data.length + 2); + os.write(id); + os.write(data); + } + + /** + * @return the triplet identifier + */ + public byte getId() { + return this.id; + } + + /** + * @return the contents of the triplet + */ + public byte[] getData() { + return this.data; + } +} diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 5b7dd840e..19f274902 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -1086,10 +1086,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** * {@inheritDoc} */ - protected void fillRect(float x, float y, float w, float h) { - if (w != 0 && h != 0) { + protected void fillRect(float x, float y, float width, float height) { + if (width > 0 && height > 0) { currentStream.add(format(x) + " " + format(y) + " " - + format(w) + " " + format(h) + " re f\n"); + + format(width) + " " + format(height) + " re f\n"); } } @@ -1684,7 +1684,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { endTextObject(); putImage(url, pos, foreignAttributes); } - + /** * Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced. * @param uri URL of the bitmap @@ -1767,6 +1767,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { this.pdfDoc.output(ostream); } catch (IOException ioe) { // ioexception will be caught later + log.error(ioe.getMessage()); } } 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..4bbfa0c73 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java @@ -27,8 +27,6 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; */ public class PSCommentAfterElement extends AbstractPSCommentElement { - protected static final String ELEMENT = "ps-comment-after"; - /** * Main constructor * @param parent node @@ -42,7 +40,7 @@ public class PSCommentAfterElement extends AbstractPSCommentElement { * @see org.apache.fop.fo.FONode#getLocalName() */ public String getLocalName() { - return ELEMENT; + return PSCommentAfter.ELEMENT; } /** 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..f05e7c7fe 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java @@ -27,8 +27,6 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; */ public class PSCommentBeforeElement extends AbstractPSCommentElement { - protected static final String ELEMENT = "ps-comment-before"; - /** * Main constructor * @param parent parent node @@ -42,7 +40,7 @@ public class PSCommentBeforeElement extends AbstractPSCommentElement { * @see org.apache.fop.fo.FONode#getLocalName() */ public String getLocalName() { - return ELEMENT; + return PSCommentBefore.ELEMENT; } /** diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java index 45ace5f80..b23ff54da 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java @@ -42,8 +42,8 @@ public class PSExtensionElementMapping extends ElementMapping { foObjs.put(PSSetupCodeElement.ELEMENT, new PSSetupCodeMaker()); foObjs.put(PSPageSetupCodeElement.ELEMENT, new PSPageSetupCodeMaker()); foObjs.put(PSSetPageDeviceElement.ELEMENT, new PSSetPageDeviceMaker()); - foObjs.put(PSCommentBeforeElement.ELEMENT, new PSCommentBeforeMaker()); - foObjs.put(PSCommentAfterElement.ELEMENT, new PSCommentAfterMaker()); + foObjs.put(PSCommentBefore.ELEMENT, new PSCommentBeforeMaker()); + foObjs.put(PSCommentAfter.ELEMENT, new PSCommentAfterMaker()); } } -- cgit v1.2.3 From 8aea6dca9c87eceacace44a78534f23f45096162 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 27 Mar 2008 16:19:39 +0000 Subject: Forgot to remove this. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@641874 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/afp/extensions/AFPExtensionHandler.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/java') 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 72d7639bd..7fdf7cd11 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java @@ -54,9 +54,7 @@ public class AFPExtensionHandler extends DefaultHandler || localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) || localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) || localName.equals(AFPElementMapping.PAGE) - || localName.equals(AFPElementMapping.PAGE_GROUP) - || localName.equals(AFPElementMapping.PAGE_GROUP) - || localName.equals(AFPResource.ELEMENT)) { + || localName.equals(AFPElementMapping.PAGE_GROUP)) { //handled in endElement } else { handled = false; -- cgit v1.2.3 From 068f78cf23e72c8f596c982eda4f295e7e7d5aed Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 1 Apr 2008 15:08:24 +0000 Subject: Merged revisions 611142,611175,611278,611285,611766-611768,612560,612785,612815-612816,612825,613144,613185,613828,613831,613835,613896,614156,614169-614170,614191,614201-614202,614566,614845,614920,614924,614964,614966,614993,615144,615164,615197,615251,615598,615604,615845,615906,615917,616080,616191,616260,616334,616485,616691,616694,616798,617126,617473,617512,617531,617550,617708,617716,617765,617812,617907,617909,617976,617989,618239,618470,618626-618627,618992,619417,619461,619670,619674,619790,619854,619856,619870,619923,619979,620272,620276-620278,620283,620285,620558-620559,620565,620567,620570,620723,620750,620761,627318,627324,627367,627495,627497,627553,627576,627679,627698,627702,627712,627719,627721,628140,628280,628652,628668,628775,628804,628816,628826,628829,629048,629093,629103,629129,629131,629169,629769,629902,630215,630772,630814,631178,631226,631276,631575,631609,631984,632121-632122,632321,632558,632716,632784,632938,632972,633389-633391,633396-633397,633437,633460,633470,633473,633525,633557,633559,633561,633961,634187,635508,635686,635701,635741,635884,635961,635967,636276,636293,636295,636405,636409,636471,637057,637076,638396,640089,640242,641742,641764,641827 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ................ r611142 | jeremias | 2008-01-11 11:13:42 +0000 (Fri, 11 Jan 2008) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-594557" from https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImagePackageRedesign ................ r611175 | jeremias | 2008-01-11 13:41:54 +0000 (Fri, 11 Jan 2008) | 4 lines Removed merge tracking for "svnmerge" for https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImagePackageRedesign (I'm not happy with the result) ................ r611278 | jeremias | 2008-01-11 19:50:53 +0000 (Fri, 11 Jan 2008) | 925 lines 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. ------------------------------------------------------------------------ ................ r611285 | jeremias | 2008-01-11 20:03:36 +0000 (Fri, 11 Jan 2008) | 1 line Removed stray reference to ImageFactory. ................ r611766 | jeremias | 2008-01-14 11:01:11 +0000 (Mon, 14 Jan 2008) | 1 line 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. ................ r611767 | jeremias | 2008-01-14 11:02:34 +0000 (Mon, 14 Jan 2008) | 1 line Restore default constructor for PDFArray. ................ r611768 | jeremias | 2008-01-14 11:02:54 +0000 (Mon, 14 Jan 2008) | 1 line Clear parent if later on an object number is assigned to a PDFObject which means it is a top-level object. ................ r612560 | jeremias | 2008-01-16 20:14:56 +0000 (Wed, 16 Jan 2008) | 1 line Fixed dead link. ................ r612785 | acumiskey | 2008-01-17 10:36:36 +0000 (Thu, 17 Jan 2008) | 1 line added serial version id ................ r612815 | jeremias | 2008-01-17 13:37:04 +0000 (Thu, 17 Jan 2008) | 6 lines 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. ................ r612816 | jeremias | 2008-01-17 13:43:33 +0000 (Thu, 17 Jan 2008) | 1 line Slight performance improvement on multi-core CPUs using a cheap trick. ................ r612825 | jeremias | 2008-01-17 14:23:13 +0000 (Thu, 17 Jan 2008) | 2 lines Fixed layout problem in two of the changes. Categorized the individual changes a bit. ................ r613144 | jeremias | 2008-01-18 12:44:56 +0000 (Fri, 18 Jan 2008) | 1 line Forgot to adjust the JAR name when updating to Batik 1.7 ................ r613185 | jeremias | 2008-01-18 15:25:26 +0000 (Fri, 18 Jan 2008) | 1 line Copy/Paste problem with TTF has long been fixed. ................ r613828 | jeremias | 2008-01-21 10:21:25 +0000 (Mon, 21 Jan 2008) | 1 line Removed stray System.out ................ r613831 | jeremias | 2008-01-21 10:33:10 +0000 (Mon, 21 Jan 2008) | 1 line 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. ................ r613835 | jeremias | 2008-01-21 10:40:38 +0000 (Mon, 21 Jan 2008) | 1 line Correct inline writing when object has an object number. ................ r613896 | jeremias | 2008-01-21 14:13:29 +0000 (Mon, 21 Jan 2008) | 1 line A note about the internal coordinate system when using fox:transform. ................ r614156 | jeremias | 2008-01-22 09:26:05 +0000 (Tue, 22 Jan 2008) | 2 lines 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. ................ r614169 | vhennebert | 2008-01-22 10:48:43 +0000 (Tue, 22 Jan 2008) | 2 lines Fixed minor typos ................ r614170 | vhennebert | 2008-01-22 10:50:24 +0000 (Tue, 22 Jan 2008) | 2 lines Updated text to reflect the upgrading of the minimum Java requirement to 1.4 ................ r614191 | jeremias | 2008-01-22 12:31:11 +0000 (Tue, 22 Jan 2008) | 1 line A note on the difference between JAI Image I/O Tools, the codec package, and JAI, the image library. ................ r614201 | jeremias | 2008-01-22 14:02:27 +0000 (Tue, 22 Jan 2008) | 2 lines 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. ................ r614202 | jeremias | 2008-01-22 14:13:22 +0000 (Tue, 22 Jan 2008) | 1 line We need JAI Image I/O Tools now rather than Jimi or JAI. ................ r614566 | vhennebert | 2008-01-23 15:22:05 +0000 (Wed, 23 Jan 2008) | 3 lines 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 ................ r614845 | vhennebert | 2008-01-24 11:32:07 +0000 (Thu, 24 Jan 2008) | 2 lines Removed the no longer needed maxColumnCount parameter ................ r614920 | vhennebert | 2008-01-24 16:40:46 +0000 (Thu, 24 Jan 2008) | 6 lines 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 ................ r614924 | vhennebert | 2008-01-24 16:51:53 +0000 (Thu, 24 Jan 2008) | 2 lines Removed no longer needed reference to TableColumn in GridUnit ................ r614964 | vhennebert | 2008-01-24 19:56:05 +0000 (Thu, 24 Jan 2008) | 2 lines Replaced 'non-lead' with 'normal' ................ r614966 | vhennebert | 2008-01-24 19:59:20 +0000 (Thu, 24 Jan 2008) | 2 lines Added license header ................ r614993 | vhennebert | 2008-01-24 21:10:22 +0000 (Thu, 24 Jan 2008) | 2 lines Bugzilla #44289: Wrong border resolution when header/footer omitted at break ................ r615144 | jeremias | 2008-01-25 08:26:54 +0000 (Fri, 25 Jan 2008) | 1 line Added support for DOMSource to Preloader SVG so a URI Resolver can be written that provides the SVG as a W3C SVG DOM. ................ r615164 | jeremias | 2008-01-25 09:59:29 +0000 (Fri, 25 Jan 2008) | 1 line Fix exception when closing Source that doesn't have any streams. ................ r615197 | jeremias | 2008-01-25 12:14:52 +0000 (Fri, 25 Jan 2008) | 1 line Improved error tolerance: an enum property value with leading or trailing spaces is still recognized. Example: content-width="scale-to-fit " ................ r615251 | vhennebert | 2008-01-25 15:52:53 +0000 (Fri, 25 Jan 2008) | 2 lines Fixed a bug in computeContentLength when there are empty cells ................ r615598 | adelmelle | 2008-01-27 13:35:39 +0000 (Sun, 27 Jan 2008) | 4 lines Bugzilla #44286: Fixed a memory-leak in XMLWhiteSpaceHandler. Submitted by: Stefan Ziel ................ r615604 | vhennebert | 2008-01-27 14:09:12 +0000 (Sun, 27 Jan 2008) | 2 lines Of course startIndex == endIndex means there is one element whose length must be computed... Changed >= into > ................ r615845 | jeremias | 2008-01-28 10:32:46 +0000 (Mon, 28 Jan 2008) | 1 line 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. ................ r615906 | jeremias | 2008-01-28 15:04:39 +0000 (Mon, 28 Jan 2008) | 2 lines 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. ................ r615917 | jeremias | 2008-01-28 15:45:10 +0000 (Mon, 28 Jan 2008) | 1 line A note on country/language. ................ r616080 | jeremias | 2008-01-28 22:05:39 +0000 (Mon, 28 Jan 2008) | 1 line Bugfix for invalid numTables entry in subset TrueType fonts if there was no "fpgm" table (Example: FreeSerif). ................ r616191 | jeremias | 2008-01-29 07:30:08 +0000 (Tue, 29 Jan 2008) | 1 line A more detailed comment on RTF output explaining that RTF has limitations besides the incomplete implementation on the FOP side. ................ r616260 | vhennebert | 2008-01-29 11:15:29 +0000 (Tue, 29 Jan 2008) | 2 lines Added more tests to ensure no weird things occurs when keep-with-previous/next is set on table. Runs ok ................ r616334 | vhennebert | 2008-01-29 14:15:52 +0000 (Tue, 29 Jan 2008) | 2 lines Renamed testcase for clarity ................ r616485 | vhennebert | 2008-01-29 19:12:58 +0000 (Tue, 29 Jan 2008) | 2 lines Replaced testcases for forced break on table-row with more complete ones. Tests failing because of bug #44320 have been commented out and will need to be re-enabled once the bug is fixed ................ r616691 | jeremias | 2008-01-30 08:53:48 +0000 (Wed, 30 Jan 2008) | 1 line "cvt ", "fpgm" and "prep" are all optional tables in TrueType. Some PDF viewers fail because FOP didn't handle those correctly. ................ r616694 | jeremias | 2008-01-30 09:05:30 +0000 (Wed, 30 Jan 2008) | 1 line Removing the previous entry because the new one basically covers the other, too. ................ r616798 | jeremias | 2008-01-30 16:03:00 +0000 (Wed, 30 Jan 2008) | 1 line Removed the Dijkstra stuff as it was moved to Commons. ................ r617126 | jeremias | 2008-01-31 13:44:46 +0000 (Thu, 31 Jan 2008) | 1 line Update lib README based on recent findings. ................ r617473 | jeremias | 2008-02-01 11:11:02 +0000 (Fri, 01 Feb 2008) | 1 line Implemented drawRenderedImage() which fixes painting of PNG images embedded inside SVG images. ................ r617512 | jeremias | 2008-02-01 14:58:30 +0000 (Fri, 01 Feb 2008) | 4 lines 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. ................ r617531 | jeremias | 2008-02-01 16:02:33 +0000 (Fri, 01 Feb 2008) | 2 lines 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. ................ r617550 | jeremias | 2008-02-01 16:31:24 +0000 (Fri, 01 Feb 2008) | 1 line Add a note about color space overrides which currently aren't supported for natively handled images, yet. ................ r617708 | adelmelle | 2008-02-01 23:30:13 +0000 (Fri, 01 Feb 2008) | 5 lines 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." ................ r617716 | adelmelle | 2008-02-02 00:06:29 +0000 (Sat, 02 Feb 2008) | 4 lines Minor cleanup/improvement: - FontSizePropertyMaker: remove redundant casts (FixedLength already casts the doubles internally) - FixedLength: reduce visibility of 'fishy' convert() method (not used anywhere else) ................ r617765 | jeremias | 2008-02-02 06:45:39 +0000 (Sat, 02 Feb 2008) | 1 line Fixed transcoder test after yesterday's changes. ................ r617812 | adelmelle | 2008-02-02 15:13:40 +0000 (Sat, 02 Feb 2008) | 6 lines 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) ................ r617907 | adelmelle | 2008-02-02 22:11:12 +0000 (Sat, 02 Feb 2008) | 4 lines Further improvement in FixedLength: * added a special ZERO_FIXED_LENGTH instance * store only non-zero values in the PropertyCache ................ r617909 | adelmelle | 2008-02-02 22:18:30 +0000 (Sat, 02 Feb 2008) | 2 lines Slight correction for pixel-values: pass the ratio of pixels-per-point into FixedLength.getInstance() ................ r617976 | adelmelle | 2008-02-03 12:05:49 +0000 (Sun, 03 Feb 2008) | 5 lines 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. ................ r617989 | adelmelle | 2008-02-03 14:11:40 +0000 (Sun, 03 Feb 2008) | 5 lines 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. ................ r618239 | vhennebert | 2008-02-04 11:25:13 +0000 (Mon, 04 Feb 2008) | 2 lines Fixed minor typo I stumbled upon while doing something completely unrelated ................ r618470 | adelmelle | 2008-02-04 22:26:53 +0000 (Mon, 04 Feb 2008) | 1 line Added testcase for Bugzilla 44343 ................ r618626 | jeremias | 2008-02-05 12:34:56 +0000 (Tue, 05 Feb 2008) | 1 line Change PDFPage to use PDFDictionary in order to make it possible to better set MediaBox/TrimBox/BleedBox. ................ r618627 | jeremias | 2008-02-05 12:35:42 +0000 (Tue, 05 Feb 2008) | 1 line FOX_TRANSFORM constant should be static. ................ r618992 | jeremias | 2008-02-06 14:07:03 +0000 (Wed, 06 Feb 2008) | 4 lines 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. ................ r619417 | jeremias | 2008-02-07 14:02:44 +0000 (Thu, 07 Feb 2008) | 1 line 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! ................ r619461 | jeremias | 2008-02-07 15:42:03 +0000 (Thu, 07 Feb 2008) | 2 lines 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. ................ r619670 | adelmelle | 2008-02-07 22:32:27 +0000 (Thu, 07 Feb 2008) | 1 line 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. ................ r619674 | adelmelle | 2008-02-07 22:41:26 +0000 (Thu, 07 Feb 2008) | 3 lines 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. ................ r619790 | jeremias | 2008-02-08 07:27:06 +0000 (Fri, 08 Feb 2008) | 1 line Added a clarification that this bug affected PDF/A compliance. ................ r619854 | vhennebert | 2008-02-08 12:11:04 +0000 (Fri, 08 Feb 2008) | 3 lines 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" ................ r619856 | vhennebert | 2008-02-08 12:14:01 +0000 (Fri, 08 Feb 2008) | 2 lines Also display the column index in the toString method ................ r619870 | jeremias | 2008-02-08 13:23:47 +0000 (Fri, 08 Feb 2008) | 1 line Added missing width for Euro glyph. ................ r619923 | vhennebert | 2008-02-08 15:59:21 +0000 (Fri, 08 Feb 2008) | 2 lines Testcase for bug #43676, which is now fixed ................ r619979 | spepping | 2008-02-08 19:20:27 +0000 (Fri, 08 Feb 2008) | 5 lines 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. ................ r620272 | adelmelle | 2008-02-10 12:31:46 +0000 (Sun, 10 Feb 2008) | 5 lines 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 ................ r620276 | adelmelle | 2008-02-10 12:50:47 +0000 (Sun, 10 Feb 2008) | 3 lines Revisit background-position shorthand implementation: always convert to percentages (more possibilities/precision). ................ r620277 | adelmelle | 2008-02-10 13:01:07 +0000 (Sun, 10 Feb 2008) | 2 lines Tweak: wrap numeric values internally in Integers or Longs if possible, Doubles only if necessary. ................ r620278 | adelmelle | 2008-02-10 13:07:34 +0000 (Sun, 10 Feb 2008) | 2 lines Missing file from r620272 ................ r620283 | adelmelle | 2008-02-10 13:17:20 +0000 (Sun, 10 Feb 2008) | 5 lines 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 ................ r620285 | adelmelle | 2008-02-10 13:42:39 +0000 (Sun, 10 Feb 2008) | 3 lines Bugzilla 41631: Percentage resolution for arguments to proportional-column-width() ................ r620558 | vhennebert | 2008-02-11 18:10:09 +0000 (Mon, 11 Feb 2008) | 2 lines Added full support for breaks inside table-cell elements ................ r620559 | vhennebert | 2008-02-11 18:11:09 +0000 (Mon, 11 Feb 2008) | 2 lines Fixed illegal character in the file ................ r620565 | vhennebert | 2008-02-11 18:18:13 +0000 (Mon, 11 Feb 2008) | 2 lines Better javadoc for break class ................ r620567 | vhennebert | 2008-02-11 18:24:00 +0000 (Mon, 11 Feb 2008) | 2 lines Disabled region-body_column-count_bug#37468 testcase because of bug 44393 ................ r620570 | adelmelle | 2008-02-11 18:36:14 +0000 (Mon, 11 Feb 2008) | 1 line Missing file from r620283 ................ r620723 | jeremias | 2008-02-12 08:23:04 +0000 (Tue, 12 Feb 2008) | 2 lines Bugzilla #44393: Recognize the newly used EN_AUTO constant for break values. Other LMs generate a -1 value for this case. ................ r620750 | jeremias | 2008-02-12 10:45:50 +0000 (Tue, 12 Feb 2008) | 1 line Simplification. ................ r620761 | vhennebert | 2008-02-12 11:12:25 +0000 (Tue, 12 Feb 2008) | 2 lines Fixed wrong numbering of cells ................ r627318 | maxberger | 2008-02-13 09:12:25 +0000 (Wed, 13 Feb 2008) | 1 line Added *.xml to svn:ignore ................ r627324 | maxberger | 2008-02-13 09:35:01 +0000 (Wed, 13 Feb 2008) | 1 line Ensured all SVN properties are set equally ................ r627367 | maxberger | 2008-02-13 12:03:30 +0000 (Wed, 13 Feb 2008) | 1 line Ensured all SVN properties are set equally ................ r627495 | jeremias | 2008-02-13 15:55:34 +0000 (Wed, 13 Feb 2008) | 1 line Replace useless javadoc comment. ................ r627497 | jeremias | 2008-02-13 15:57:01 +0000 (Wed, 13 Feb 2008) | 1 line Easy way to force the discarding of the user's font cache file (especially after the recent changes). ................ r627553 | vhennebert | 2008-02-13 18:11:06 +0000 (Wed, 13 Feb 2008) | 2 lines Added support for breaks before and after table cells ................ r627576 | vhennebert | 2008-02-13 20:10:01 +0000 (Wed, 13 Feb 2008) | 2 lines 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 ................ r627679 | jeremias | 2008-02-14 08:12:34 +0000 (Thu, 14 Feb 2008) | 10 lines 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. ................ r627698 | acumiskey | 2008-02-14 10:12:48 +0000 (Thu, 14 Feb 2008) | 3 lines 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. ................ r627702 | jeremias | 2008-02-14 10:41:26 +0000 (Thu, 14 Feb 2008) | 2 lines 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. ................ r627712 | vhennebert | 2008-02-14 11:36:01 +0000 (Thu, 14 Feb 2008) | 2 lines Simplified the detection of double as integer ................ r627719 | maxberger | 2008-02-14 11:57:05 +0000 (Thu, 14 Feb 2008) | 1 line Created Constants for unit descriptions ................ r627721 | vhennebert | 2008-02-14 12:09:05 +0000 (Thu, 14 Feb 2008) | 2 lines break-after set on the last child of a row-spanning cell must apply to the last row spanned by the cell ................ r628140 | vhennebert | 2008-02-15 18:33:12 +0000 (Fri, 15 Feb 2008) | 2 lines 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. ................ r628280 | jeremias | 2008-02-16 12:28:48 +0000 (Sat, 16 Feb 2008) | 7 lines 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. ................ r628652 | jeremias | 2008-02-18 09:00:08 +0000 (Mon, 18 Feb 2008) | 1 line No stack traces with missing images. ................ r628668 | jeremias | 2008-02-18 09:41:03 +0000 (Mon, 18 Feb 2008) | 2 lines 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. ................ r628775 | jeremias | 2008-02-18 15:02:39 +0000 (Mon, 18 Feb 2008) | 2 lines 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. ................ r628804 | jeremias | 2008-02-18 16:45:18 +0000 (Mon, 18 Feb 2008) | 1 line Reducing noise. Better messages. ................ r628816 | jeremias | 2008-02-18 17:06:39 +0000 (Mon, 18 Feb 2008) | 1 line It currently doesn't work properly without a layout-master-set. ................ r628826 | jeremias | 2008-02-18 17:24:23 +0000 (Mon, 18 Feb 2008) | 1 line Made the necessary changes to remove the long-standing deprecations in the apps package as discussed. ................ r628829 | jeremias | 2008-02-18 17:30:15 +0000 (Mon, 18 Feb 2008) | 1 line Makes sense to mention the removal of deprecated methods. ................ r629048 | vhennebert | 2008-02-19 09:36:23 +0000 (Tue, 19 Feb 2008) | 2 lines Style only: removed spurious ^M characters at the end of lines ................ r629093 | jeremias | 2008-02-19 13:08:39 +0000 (Tue, 19 Feb 2008) | 9 lines 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 ................ r629103 | jeremias | 2008-02-19 14:16:08 +0000 (Tue, 19 Feb 2008) | 1 line 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. ................ r629129 | jeremias | 2008-02-19 15:43:31 +0000 (Tue, 19 Feb 2008) | 1 line Fixed NPE when no AFM is available and the PFM didn't provide a xHeight. ................ r629131 | jeremias | 2008-02-19 15:47:48 +0000 (Tue, 19 Feb 2008) | 2 lines 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. ................ r629169 | vhennebert | 2008-02-19 17:32:18 +0000 (Tue, 19 Feb 2008) | 2 lines 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 ................ r629769 | maxberger | 2008-02-21 12:52:33 +0000 (Thu, 21 Feb 2008) | 1 line Moved me to commiters :) ................ r629902 | maxberger | 2008-02-21 18:22:22 +0000 (Thu, 21 Feb 2008) | 1 line Turned on XInclude processing for the main source given on the command line. ................ r630215 | maxberger | 2008-02-22 14:17:20 +0000 (Fri, 22 Feb 2008) | 2 lines Fixed backward compatiblity with 1.4 ................ r630772 | jeremias | 2008-02-25 09:17:43 +0000 (Mon, 25 Feb 2008) | 1 line Bugfix: When scale-up/down-to-fit was used, the image scaling rule was not always respected. ................ r630814 | vhennebert | 2008-02-25 11:30:43 +0000 (Mon, 25 Feb 2008) | 5 lines - added full support for keep-with-previous on table-row and in table-cell - added more testcases for keeps in tables - assign the right table-row element to grid units that are not on the first row spanned - slightly re-worked the RowGroupBuilder interface to make it more SAX-like ................ r631178 | jeremias | 2008-02-26 11:07:20 +0000 (Tue, 26 Feb 2008) | 3 lines Reverted revision 603590 which broke the AFP renderer. The other changes after revision 603590 should be preserved as well as possible, including the switch to the new image library. Adjustments for change in behaviour of the block viewport CTM. Bugfix: SVG painting is now always done on a color canvas (like for PCL) because Batik cannot handle gradients on a grayscale canvas. ................ r631226 | jeremias | 2008-02-26 14:30:50 +0000 (Tue, 26 Feb 2008) | 1 line GOCA support temporarily removed. ................ r631276 | vhennebert | 2008-02-26 16:23:15 +0000 (Tue, 26 Feb 2008) | 2 lines Moved the getBody method into PrimaryGridUnit, since it's only needed there and that allows to simplify EmptyGridUnit ................ r631575 | jeremias | 2008-02-27 13:00:54 +0000 (Wed, 27 Feb 2008) | 2 lines Bugzilla #44497: AFP Renderer: Bugfix for broken reference orientation on absolutely positioned block-containers. ................ r631609 | vhennebert | 2008-02-27 15:09:06 +0000 (Wed, 27 Feb 2008) | 2 lines bpBeforeNormal and bpAfterNormal already include border-separation, no need to re-substract it from the box height ................ r631984 | jeremias | 2008-02-28 14:30:46 +0000 (Thu, 28 Feb 2008) | 2 lines Slight improvement for thin lines in Java2D/AWT output. Submitted by: Gordon Cooke ................ r632121 | adelmelle | 2008-02-28 21:29:04 +0000 (Thu, 28 Feb 2008) | 6 lines Minor tweaks/updates: - change toString() to getLocalizedMessage() for exceptions passed to warning() - removed deprecated method isLocatorDisabled() - removed superfluous try-catch block - some javadoc changes ................ r632122 | adelmelle | 2008-02-28 21:33:11 +0000 (Thu, 28 Feb 2008) | 2 lines Minor tweak: switch from toString() to getLocalizedMessage() for Exceptions passed into warning() ................ r632321 | jeremias | 2008-02-29 14:03:01 +0000 (Fri, 29 Feb 2008) | 1 line Bugfix: Disabled setting widths from AFM since we're using WinAnsiEncoding internally but the AFM delivers the character widths using the font's native encoding which causes problems with some characters. ................ r632558 | clay | 2008-03-01 07:10:03 +0000 (Sat, 01 Mar 2008) | 1 line Preparing for FOP 0.95 release. ................ r632716 | clay | 2008-03-02 06:42:02 +0000 (Sun, 02 Mar 2008) | 1 line Adding Quick Start Guide. ................ r632784 | jeremias | 2008-03-02 16:53:24 +0000 (Sun, 02 Mar 2008) | 1 line Further preparations for the 0.95 release. This was tested with the latest Forrest Trunk (which uses FOP 0.94 for the PDFs). ................ r632938 | clay | 2008-03-03 04:44:28 +0000 (Mon, 03 Mar 2008) | 2 lines Updated the Apache FOP Quick Start to include a 'Hello World' document and make it more geared toward newbies (thanks Jeremias!). ................ r632972 | jeremias | 2008-03-03 07:51:14 +0000 (Mon, 03 Mar 2008) | 1 line Tried to make font configuration easier to understand by splitting the basics from the advanced stuff. Otherwise, people will believe for the next 100 years that generating XML font metrics file is still always necessary. ................ r633389 | jeremias | 2008-03-04 08:37:05 +0000 (Tue, 04 Mar 2008) | 1 line 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. ................ r633390 | jeremias | 2008-03-04 08:38:36 +0000 (Tue, 04 Mar 2008) | 1 line Switched to Commons 1.3 being released. ................ r633391 | jeremias | 2008-03-04 08:39:12 +0000 (Tue, 04 Mar 2008) | 1 line Added ApacheCon US 2008. ................ r633396 | jeremias | 2008-03-04 09:06:03 +0000 (Tue, 04 Mar 2008) | 1 line Various updates. ................ r633397 | jeremias | 2008-03-04 09:15:50 +0000 (Tue, 04 Mar 2008) | 1 line 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. ................ r633437 | jeremias | 2008-03-04 11:50:34 +0000 (Tue, 04 Mar 2008) | 3 lines 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. ................ r633460 | jeremias | 2008-03-04 12:59:57 +0000 (Tue, 04 Mar 2008) | 1 line Copyright year ................ r633470 | jeremias | 2008-03-04 13:25:12 +0000 (Tue, 04 Mar 2008) | 1 line Noted some of the major change areas in this release. ................ r633473 | jeremias | 2008-03-04 13:40:11 +0000 (Tue, 04 Mar 2008) | 2 lines Ha! Almost forgot the most important change: Java 1.4! Plus a note on image libraries. ................ r633525 | jeremias | 2008-03-04 16:13:17 +0000 (Tue, 04 Mar 2008) | 1 line Bugfix: Without the system ID (base URI), the XSLT processor cannot resolve document(, .) function calls correctly. ................ r633557 | jeremias | 2008-03-04 17:30:40 +0000 (Tue, 04 Mar 2008) | 1 line 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. ................ r633559 | jeremias | 2008-03-04 17:35:52 +0000 (Tue, 04 Mar 2008) | 2 lines 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). ................ r633561 | jeremias | 2008-03-04 17:39:08 +0000 (Tue, 04 Mar 2008) | 1 line Update README. ................ r633961 | vhennebert | 2008-03-05 18:22:06 +0000 (Wed, 05 Mar 2008) | 5 lines - 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 ................ r634187 | jeremias | 2008-03-06 08:21:06 +0000 (Thu, 06 Mar 2008) | 1 line Added some notes on getting the same output for PDF/PS and Java2D-based renderers. ................ r635508 | jeremias | 2008-03-10 10:06:37 +0000 (Mon, 10 Mar 2008) | 4 lines 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). ................ r635686 | vhennebert | 2008-03-10 20:52:43 +0000 (Mon, 10 Mar 2008) | 2 lines Bugfix: forced break ignored when the minimum height of a table-row isn't reached ................ r635701 | jeremias | 2008-03-10 21:28:08 +0000 (Mon, 10 Mar 2008) | 1 line Need to clean up after myself. ................ r635741 | jeremias | 2008-03-10 22:39:38 +0000 (Mon, 10 Mar 2008) | 1 line Bugfix for row/body/col background painting when padding is used in the table-cells. ................ r635884 | vhennebert | 2008-03-11 11:02:27 +0000 (Tue, 11 Mar 2008) | 2 lines Fixed a copy-paste error (getPaddingStart instead of getPaddingEnd) ................ r635961 | vhennebert | 2008-03-11 15:05:27 +0000 (Tue, 11 Mar 2008) | 2 lines Forgot to add the testcase for forced break vs explicit row height in revision 635686 ................ r635967 | vhennebert | 2008-03-11 15:13:51 +0000 (Tue, 11 Mar 2008) | 2 lines Updated the disabled-testcases.xml file: re-enabled testcases which could easily be updated, removed the other ones which anyway were superseded by more complete ones ................ r636276 | vhennebert | 2008-03-12 10:51:09 +0000 (Wed, 12 Mar 2008) | 2 lines 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. ................ r636293 | vhennebert | 2008-03-12 12:14:51 +0000 (Wed, 12 Mar 2008) | 2 lines Updated the compliance page. Re-added the 0.94 column since there are some noteworthy changes between the 0.94 and 0.95 versions ................ r636295 | vhennebert | 2008-03-12 12:19:15 +0000 (Wed, 12 Mar 2008) | 3 lines Update of the documentation before the release. Added notes about improved checks and conformance in tables. ................ r636405 | vhennebert | 2008-03-12 16:25:52 +0000 (Wed, 12 Mar 2008) | 2 lines Initialized merge tracking via "svnmerge" from the 0.95 branch ................ r636409 | vhennebert | 2008-03-12 16:36:29 +0000 (Wed, 12 Mar 2008) | 8 lines Blocked revisions 636406 via svnmerge ........ r636406 | vhennebert | 2008-03-12 16:28:00 +0000 (Wed, 12 Mar 2008) | 2 lines Set the version to 0.95beta ........ ................ r636471 | vhennebert | 2008-03-12 19:24:05 +0000 (Wed, 12 Mar 2008) | 2 lines Removed no longer used borderAndPaddingBPD field ................ r637057 | jeremias | 2008-03-14 11:15:24 +0000 (Fri, 14 Mar 2008) | 2 lines Bugzilla #44412: Bugfix: When there was a forced break after a block with (conditional) borders the border-after wasn't painted. ................ r637076 | vhennebert | 2008-03-14 12:22:44 +0000 (Fri, 14 Mar 2008) | 2 lines 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 ................ r638396 | vhennebert | 2008-03-18 15:01:43 +0000 (Tue, 18 Mar 2008) | 53 lines 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 ........ ................ r640089 | clay | 2008-03-22 21:54:27 +0000 (Sat, 22 Mar 2008) | 1 line updates to Forrest web site (expand menu structure). ................ r640242 | adelmelle | 2008-03-23 19:36:36 +0000 (Sun, 23 Mar 2008) | 11 lines 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... ................ r641742 | jeremias | 2008-03-27 08:49:41 +0000 (Thu, 27 Mar 2008) | 6 lines 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). ................ r641764 | maxberger | 2008-03-27 10:02:25 +0000 (Thu, 27 Mar 2008) | 1 line Added my key ................ r641827 | jeremias | 2008-03-27 14:29:44 +0000 (Thu, 27 Mar 2008) | 2 lines 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/branches/Temp_AFPGOCAResources@643433 13f79535-47bb-0310-9956-ffa450edef68 --- KEYS | 24 +- README | 40 + build.properties | 4 +- build.xml | 80 +- fop.bat | 2 +- forrest.properties | 7 +- forrest.properties.xml | 22 + lib/README.txt | 14 +- lib/xmlgraphics-commons-1.3svn.jar | Bin 510302 -> 0 bytes lib/xmlgraphics-commons-1.4svn.jar | Bin 0 -> 511830 bytes src/codegen/fonts/font-file.xsl | 6 +- src/documentation/content/.htaccess | 4 +- src/documentation/content/doap.rdf | 8 +- src/documentation/content/xdocs/0.93/anttask.xml | 197 - src/documentation/content/xdocs/0.93/compiling.xml | 140 - .../content/xdocs/0.93/configuration.xml | 335 - src/documentation/content/xdocs/0.93/embedding.xml | 682 - .../content/xdocs/0.93/extensions.xml | 125 - src/documentation/content/xdocs/0.93/fonts.xml | 298 - .../xdocs/0.93/fotree/disabled-testcases.xml | 31 - src/documentation/content/xdocs/0.93/graphics.xml | 338 - .../content/xdocs/0.93/hyphenation.xml | 237 - src/documentation/content/xdocs/0.93/index.xml | 54 - .../content/xdocs/0.93/intermediate.xml | 146 - .../content/xdocs/0.93/known-issues.xml | 102 - .../content/xdocs/0.93/knownissues_overview.xml | 72 - .../xdocs/0.93/layoutengine/disabled-testcases.xml | 328 - src/documentation/content/xdocs/0.93/output.xml | 772 -- src/documentation/content/xdocs/0.93/pdfa.xml | 133 - .../content/xdocs/0.93/pdfencryption.xml | 234 - src/documentation/content/xdocs/0.93/pdfx.xml | 136 - src/documentation/content/xdocs/0.93/running.xml | 349 - src/documentation/content/xdocs/0.93/servlets.xml | 260 - src/documentation/content/xdocs/0.93/upgrading.xml | 136 - src/documentation/content/xdocs/0.94/index.xml | 2 +- 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 | 410 + .../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 | 70 + .../content/xdocs/0.95/knownissues_overview.xml | 70 + .../xdocs/0.95/layoutengine/disabled-testcases.xml | 260 + src/documentation/content/xdocs/0.95/output.xml | 888 ++ src/documentation/content/xdocs/0.95/pdfa.xml | 159 + .../content/xdocs/0.95/pdfencryption.xml | 225 + 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/compliance.ihtml | 12770 +++++++++++-------- src/documentation/content/xdocs/dev/doc.xml | 4 +- src/documentation/content/xdocs/dev/release.xml | 2 +- src/documentation/content/xdocs/download.xml | 21 +- src/documentation/content/xdocs/faq.xml | 15 + src/documentation/content/xdocs/index.xml | 7 +- .../content/xdocs/quickstartguide.xml | 124 + src/documentation/content/xdocs/site.xml | 25 +- src/documentation/content/xdocs/status.xml | 8 +- src/documentation/content/xdocs/tabs.xml | 8 +- src/documentation/content/xdocs/team.xml | 32 +- .../content/xdocs/trunk/compiling.xml | 4 +- src/documentation/content/xdocs/trunk/fonts.xml | 210 +- src/documentation/content/xdocs/trunk/output.xml | 29 + .../content/xdocs/trunk/pdfencryption.xml | 6 +- src/documentation/content/xdocs/trunk/running.xml | 2 +- src/documentation/poster/README.txt | 5 +- src/documentation/poster/cfg/README.txt | 7 - 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 +- src/documentation/sitemap.xmap | 43 +- src/documentation/skinconf.xml | 20 +- .../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/cli/InputHandler.java | 8 +- src/java/org/apache/fop/fo/ElementMapping.java | 6 +- src/java/org/apache/fop/fo/FOPropertyMapping.java | 6 + src/java/org/apache/fop/fo/FOTreeBuilder.java | 104 +- .../apache/fop/fo/flow/table/EmptyGridUnit.java | 7 - .../org/apache/fop/fo/flow/table/GridUnit.java | 9 - .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 26 +- .../fop/fo/properties/CommonHyphenation.java | 5 +- .../fop/fo/properties/XMLLangShorthandParser.java | 2 +- .../apache/fop/fonts/AbstractCodePointMapping.java | 23 +- src/java/org/apache/fop/fonts/Base14Font.java | 27 + src/java/org/apache/fop/fonts/CIDFont.java | 33 +- 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 +- .../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 +- .../org/apache/fop/layoutmgr/AbstractBreaker.java | 4 +- .../fop/layoutmgr/AbstractLayoutManager.java | 16 +- .../org/apache/fop/layoutmgr/AreaAdditionUtil.java | 2 +- .../fop/layoutmgr/BlockContainerLayoutManager.java | 54 +- .../apache/fop/layoutmgr/BlockLayoutManager.java | 11 +- .../fop/layoutmgr/BlockStackingLayoutManager.java | 21 +- .../apache/fop/layoutmgr/FlowLayoutManager.java | 2 +- .../org/apache/fop/layoutmgr/LayoutContext.java | 108 +- .../org/apache/fop/layoutmgr/MinOptMaxUtil.java | 13 +- src/java/org/apache/fop/layoutmgr/PageBreaker.java | 2 +- .../fop/layoutmgr/PageBreakingAlgorithm.java | 8 +- .../fop/layoutmgr/StaticContentLayoutManager.java | 8 +- src/java/org/apache/fop/layoutmgr/TraitSetter.java | 87 +- .../inline/AbstractGraphicsLayoutManager.java | 7 - .../AbstractPageNumberCitationLayoutManager.java | 17 +- .../layoutmgr/inline/CharacterLayoutManager.java | 23 +- .../fop/layoutmgr/inline/ContentLayoutManager.java | 24 +- .../fop/layoutmgr/inline/ICLayoutManager.java | 5 - .../fop/layoutmgr/inline/InlineLayoutManager.java | 18 +- .../inline/InlineStackingLayoutManager.java | 26 +- .../fop/layoutmgr/inline/LeaderLayoutManager.java | 5 - .../layoutmgr/inline/LeafNodeLayoutManager.java | 10 - .../fop/layoutmgr/inline/LineLayoutManager.java | 14 +- .../layoutmgr/inline/PageNumberLayoutManager.java | 6 +- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 36 +- .../list/ListItemContentLayoutManager.java | 30 +- .../fop/layoutmgr/list/ListItemLayoutManager.java | 58 +- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 144 +- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 220 +- .../org/apache/fop/layoutmgr/table/RowPainter.java | 116 +- .../table/TableAndCaptionLayoutManager.java | 7 +- .../layoutmgr/table/TableCaptionLayoutManager.java | 5 +- .../layoutmgr/table/TableCellLayoutManager.java | 123 +- .../layoutmgr/table/TableContentLayoutManager.java | 164 +- .../fop/layoutmgr/table/TableContentPosition.java | 7 + .../layoutmgr/table/TableHFPenaltyPosition.java | 5 + .../layoutmgr/table/TableHeaderFooterPosition.java | 5 + .../fop/layoutmgr/table/TableLayoutManager.java | 75 +- 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 + .../fop/render/AbstractGenericSVGHandler.java | 2 +- .../org/apache/fop/render/afp/AFPRenderer.java | 22 +- .../fop/render/afp/AFPRendererConfigurator.java | 3 +- .../org/apache/fop/render/afp/AFPSVGHandler.java | 10 +- .../fop/render/afp/extensions/AFPElement.java | 7 +- .../render/afp/extensions/AFPElementMapping.java | 18 +- .../render/afp/extensions/AFPExtensionHandler.java | 2 +- .../apache/fop/render/afp/fonts/OutlineFont.java | 7 +- .../apache/fop/render/afp/fonts/RasterFont.java | 7 +- .../fop/render/afp/modca/AbstractAFPObject.java | 10 +- .../fop/render/afp/modca/AbstractDescriptor.java | 14 +- .../render/afp/modca/AbstractNamedAFPObject.java | 23 +- .../fop/render/afp/modca/AbstractPageObject.java | 2 +- .../apache/fop/render/afp/modca/ImageContent.java | 98 +- .../fop/render/afp/modca/ImageDataDescriptor.java | 81 +- .../apache/fop/render/afp/modca/ImageSegment.java | 2 +- .../fop/render/afp/modca/ObjectAreaDescriptor.java | 21 +- .../fop/render/afp/modca/PageDescriptor.java | 12 +- .../apache/fop/render/afp/modca/PageObject.java | 8 +- .../fop/render/afp/modca/PresentationTextData.java | 122 +- .../afp/modca/PresentationTextDescriptor.java | 13 +- .../render/afp/modca/PresentationTextObject.java | 3 +- .../render/afp/modca/TagLogicalElementBean.java | 4 +- .../fop/render/java2d/CustomFontMetricsMapper.java | 2 +- .../apache/fop/render/java2d/Java2DRenderer.java | 2 + .../fop/render/java2d/SystemFontMetricsMapper.java | 2 +- .../fop/render/pdf/AbstractImageAdapter.java | 10 +- .../apache/fop/render/pdf/ImageRawJPEGAdapter.java | 101 +- .../fop/render/pdf/PDFGraphics2DAdapter.java | 4 +- .../org/apache/fop/render/pdf/PDFRenderer.java | 258 +- src/java/org/apache/fop/render/ps/PSFontUtils.java | 128 +- .../org/apache/fop/render/ps/PSImageUtils.java | 73 - src/java/org/apache/fop/render/ps/PSRenderer.java | 91 +- .../org/apache/fop/render/rtf/SVGConverter.java | 70 - .../org/apache/fop/svg/GraphicsConfiguration.java | 51 + 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 | 259 +- .../java/org/apache/fop/URIResolutionTestCase.java | 11 +- .../apache/fop/render/pdf/PDFEncodingTestCase.java | 6 +- test/layoutengine/disabled-testcases.xml | 48 - ...ock-container_absolute-position_no-height_3.xml | 63 + .../block-level_break-after_bug44412.xml | 112 + .../block_break-before_bug44412.xml | 64 + .../inline_block-level_nested_1.xml | 104 + .../table-body_background-image.xml | 110 - .../table-cell_block_keep-with-previous.xml | 85 - .../table-cell_conditional-spaces_2.xml | 64 +- .../table-footer_omit-footer-at-break.xml | 38 +- .../table-header_background-image.xml | 101 - .../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 +- .../table-row_keep-with-previous.xml | 250 +- .../standard-testcases/table_backgrounds.xml | 392 + .../standard-testcases/table_backgrounds_2.xml | 113 + .../table_border-collapse_collapse_1.xml | 130 - .../table_border-collapse_collapse_2.xml | 70 - .../table_border-collapse_separate_1.xml | 2 +- .../standard-testcases/table_border_padding.xml | 28 +- .../standard-testcases/table_bug44621.xml | 105 + .../table_row-delay_fixed-row-height.xml | 6 +- .../standard-testcases/table_row-height_break.xml | 87 + 262 files changed, 18053 insertions(+), 23274 deletions(-) create mode 100644 forrest.properties.xml delete mode 100644 lib/xmlgraphics-commons-1.3svn.jar create mode 100644 lib/xmlgraphics-commons-1.4svn.jar delete mode 100644 src/documentation/content/xdocs/0.93/anttask.xml delete mode 100644 src/documentation/content/xdocs/0.93/compiling.xml delete mode 100644 src/documentation/content/xdocs/0.93/configuration.xml delete mode 100644 src/documentation/content/xdocs/0.93/embedding.xml delete mode 100644 src/documentation/content/xdocs/0.93/extensions.xml delete mode 100644 src/documentation/content/xdocs/0.93/fonts.xml delete mode 100644 src/documentation/content/xdocs/0.93/fotree/disabled-testcases.xml delete mode 100644 src/documentation/content/xdocs/0.93/graphics.xml delete mode 100644 src/documentation/content/xdocs/0.93/hyphenation.xml delete mode 100644 src/documentation/content/xdocs/0.93/index.xml delete mode 100644 src/documentation/content/xdocs/0.93/intermediate.xml delete mode 100644 src/documentation/content/xdocs/0.93/known-issues.xml delete mode 100644 src/documentation/content/xdocs/0.93/knownissues_overview.xml delete mode 100644 src/documentation/content/xdocs/0.93/layoutengine/disabled-testcases.xml delete mode 100644 src/documentation/content/xdocs/0.93/output.xml delete mode 100644 src/documentation/content/xdocs/0.93/pdfa.xml delete mode 100644 src/documentation/content/xdocs/0.93/pdfencryption.xml delete mode 100644 src/documentation/content/xdocs/0.93/pdfx.xml delete mode 100644 src/documentation/content/xdocs/0.93/running.xml delete mode 100644 src/documentation/content/xdocs/0.93/servlets.xml delete mode 100644 src/documentation/content/xdocs/0.93/upgrading.xml 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 create mode 100644 src/documentation/content/xdocs/quickstartguide.xml delete mode 100644 src/documentation/poster/cfg/README.txt 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 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 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 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 create mode 100644 src/java/org/apache/fop/pdf/PDFTextUtil.java 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-container_absolute-position_no-height_3.xml 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/inline_block-level_nested_1.xml delete mode 100644 test/layoutengine/standard-testcases/table-body_background-image.xml delete mode 100644 test/layoutengine/standard-testcases/table-cell_block_keep-with-previous.xml delete mode 100644 test/layoutengine/standard-testcases/table-header_background-image.xml create mode 100644 test/layoutengine/standard-testcases/table_backgrounds.xml create mode 100644 test/layoutengine/standard-testcases/table_backgrounds_2.xml delete mode 100644 test/layoutengine/standard-testcases/table_border-collapse_collapse_1.xml delete mode 100644 test/layoutengine/standard-testcases/table_border-collapse_collapse_2.xml create mode 100644 test/layoutengine/standard-testcases/table_bug44621.xml create mode 100644 test/layoutengine/standard-testcases/table_row-height_break.xml (limited to 'src/java') diff --git a/KEYS b/KEYS index f49f8d6be..c11ca63c3 100644 --- a/KEYS +++ b/KEYS @@ -19,7 +19,8 @@ pub 1024D/5F298824 2006-09-30 Simon Pepping sub 2048g/40F32100 2006-09-30 pub 1024D/4358C584 2006-12-08 Vincent Hennebert sub 2048g/0BD6AC9B 2006-12-08 - +pub 1024D/CC31AE97 2008-03-27 [expires: 2011-01-01] +uid Maximilian Berger -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.0.6 (GNU/Linux) @@ -167,3 +168,24 @@ SQQYEQIACQUCRXmZwgIbDAAKCRCgctTQQ1jFhBc3AKCQ1X7oIVR8g7GvSGEUw6DE HgEaUgCgkl30lcl9gGa9hqk4cuGYn1OTyks= =XphF -----END PGP PUBLIC KEY BLOCK----- + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.7 (OpenBSD) + +mQGiBEfrX/ARBADulGs9V7StbfK8CFfClihdh4lRpw2tktMuYiQJ/rIsNq4zghkT +UGxFU0eUC2ZVPYvwG6sXgZ5SSm6i8Ii79YdIIxUG7oNwXaY/e9rK+xX193xqmDgl +Vh5vm4LUtncHi9TZDSF+g1YU1DVHbSjTd2oQEHxbBppL0CLfaLv3U1qr2wCgxeGw +ZIwb6KD6yesRLx6vGDkDzAMEAL99p0m4sNnjZdKC25Rrt6NZ7CROXWs89/+dkewg +JCZiVEoAcdSa0z5d8+XaSzmqR8BJWM1PBPjG48eEdqOevwypd0F/U1mwZ42MvQEw +oBayUY+7/pptW7C5L3Fjk18drE0a8lIzt9VBGX5fe3GoXtZKuOzDv0hEuHyzR9q9 +JLXsA/sELFfrHf0tBfXAdE7pj/Mahalu17/GAyb0RHSvuOfoUvXSXZA91cFg8ycB +4x265NtYZk52M32wi5ePrYeSJIZ6vWRvPuWVAXDg5S6HCMjcXc6ElkgLcUt1NoPI +DmRXe4FIDZkGSYSXdLTUByu7+8fCuWQHCFG2sALdOyVlucij2LQoTWF4aW1pbGlh +biBCZXJnZXIgPG1heGJlcmdlckBhcGFjaGUub3JnPohmBBMRAgAmBQJH61/wAhsD +BQkFM4sABgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQ4+RAT8wxrpcs1wCeIAoI +B0MwZfWLV+wD3pt1wDkPXbsAnjuOsyZ7EeNOcpoqSteB17aPRGeLiEYEEBECAAYF +Akfrb00ACgkQByq3OugVkrx76ACgqJ8W64IhBYgBvp3dTDLS825gCQQAnjB6X5+4 +eW/0pQUpJcvolxbT9xvF +=bbQO +-----END PGP PUBLIC KEY BLOCK----- + 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/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/fop.bat b/fop.bat index 774e2a8b6..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.3svn.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/forrest.properties b/forrest.properties index 537cb15e3..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 @@ -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= @@ -106,4 +107,4 @@ forrest.validate.skins.stylesheets=${forrest.validate.skins} # 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.output.pdf-0.1 +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/lib/README.txt b/lib/README.txt index 46c716b77..db0c2cdcf 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) @@ -182,4 +190,4 @@ Additional development-time dependencies (not bundled, to be added to your Apache Ant installation) http://xmlunit.sourceforge.net/ - BSD style license \ No newline at end of file + BSD style license diff --git a/lib/xmlgraphics-commons-1.3svn.jar b/lib/xmlgraphics-commons-1.3svn.jar deleted file mode 100644 index 55b9d9b2a..000000000 Binary files a/lib/xmlgraphics-commons-1.3svn.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/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/doap.rdf b/src/documentation/content/doap.rdf index 82be83e32..1c4253cea 100644 --- a/src/documentation/content/doap.rdf +++ b/src/documentation/content/doap.rdf @@ -77,15 +77,15 @@ Previous release - 2003-07-16 - 0.20.5 + 2007-01-02 + 0.93 Latest stable release - 2007-01-02 - 0.93 + 2007-08-23 + 0.94 diff --git a/src/documentation/content/xdocs/0.93/anttask.xml b/src/documentation/content/xdocs/0.93/anttask.xml deleted file mode 100644 index 44550c3d7..000000000 --- a/src/documentation/content/xdocs/0.93/anttask.xml +++ /dev/null @@ -1,197 +0,0 @@ - - - - - -

- 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.93/compiling.xml b/src/documentation/content/xdocs/0.93/compiling.xml deleted file mode 100644 index 76d7b214f..000000000 --- a/src/documentation/content/xdocs/0.93/compiling.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - - -
- 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.2 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: Generates javadocs. This creates the FOP API documentation. -
  • -
-

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.93/configuration.xml b/src/documentation/content/xdocs/0.93/configuration.xml deleted file mode 100644 index ed96c3eb7..000000000 --- a/src/documentation/content/xdocs/0.93/configuration.xml +++ /dev/null @@ -1,335 +0,0 @@ - - - - - -
- 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)Default Value
baseURL or directorySpecifies the base URL based on which relative URL will be resolved.
font-baseURL or directorySpecifies the base URL based on which relative font URLs will be resolved. - If not specified defaults to the base URL 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. -
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. -
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. -
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.
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.
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.
renderers(see text below)Contains the configuration for each renderer. See below.
-

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

- - - - ./ - - - ./ - - - 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 - - ]]> -
-
- 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 who 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.93/embedding.xml b/src/documentation/content/xdocs/0.93/embedding.xml deleted file mode 100644 index 00d57c75e..000000000 --- a/src/documentation/content/xdocs/0.93/embedding.xml +++ /dev/null @@ -1,682 +0,0 @@ - - - - - - -
- 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"); -
  • -
  • -

    - 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.93/extensions.xml b/src/documentation/content/xdocs/0.93/extensions.xml deleted file mode 100644 index 0c22ca123..000000000 --- a/src/documentation/content/xdocs/0.93/extensions.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - -
- 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 required 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: -

- ]]> - - Currently, no extension elements are implemented in FOP Trunk which use the - FOP extension namespace. - -
-
- 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 -

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

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

-
-
- -
- diff --git a/src/documentation/content/xdocs/0.93/fonts.xml b/src/documentation/content/xdocs/0.93/fonts.xml deleted file mode 100644 index 53d4bd97f..000000000 --- a/src/documentation/content/xdocs/0.93/fonts.xml +++ /dev/null @@ -1,298 +0,0 @@ - - - - - -
- 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.

-
-
- 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:

- - -]]> - 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 "kerning" and "embed-url" attributes are optional. Kerning is currently not used at all. 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.
  • -
  • - 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. -
  • -
- -
-
- 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. -Currently, this embedded font contains only the minimum data needed to be embedded in a pdf document, and does not contain any codepage information. -The PDF document contains indexes to the glyphs in the font instead of to encoded characters. -While the document will be displayed correctly, the net effect of this is that searching, indexing, and cut-and-paste will not work properly.

-

One workaround for this behavior is to use the "-enc ansi" option when generating metrics with TTFReader. -This will cause the whole font to be embedded in the pdf document. -Characters will be WinAnsi encoded (as specified in the PDF spec), so you lose the ability to use characters from other character sets. -See Table of TTF Encoding Options for more details.

-
-
- Explicitely 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.93/fotree/disabled-testcases.xml b/src/documentation/content/xdocs/0.93/fotree/disabled-testcases.xml deleted file mode 100644 index 196eafcc4..000000000 --- a/src/documentation/content/xdocs/0.93/fotree/disabled-testcases.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - demo test failure - demo-test-failure.fo - - - - 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.93/graphics.xml b/src/documentation/content/xdocs/0.93/graphics.xml deleted file mode 100644 index beb860223..000000000 --- a/src/documentation/content/xdocs/0.93/graphics.xml +++ /dev/null @@ -1,338 +0,0 @@ - - - - - -
- Apache FOP: Graphics Formats - $Revision$ -
- -
- 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. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FormatTypeFOP native supportBatik SVGBatik codecsImage I/OJAIJIMI
BMP (Microsoft Windows Bitmap)bitmapX
EPS (Encapsulated PostScript)metafile (both bitmap and vector), probably most frequently used for vector drawings(X)
GIF (Graphics Interchange Format)bitmapXXXX
JPEG (Joint Photographic Experts Group)bitmap(X)
PNG (Portable Network Graphic)bitmapX
SVG (Scalable Vector Graphics)vector (with embedded bitmaps)X
TIFF (Tag Image Format File)bitmap(X)XX
- "(X)" means restricted support. Please see the details below. -
-
- Graphics Packages -
- FOP Native -

- FOP has native ability to handle some graphic file formats. -

-
-
- Batik codecs -

- Apache Batik contains codecs for PNG and TIFF access. FOP can use these. -

-
-
- Image I/O (JDK 1.4 or higher) -

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

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

-
-
- JAI (Java Advanced Imaging API) - JAI support is available for Release 0.20.5 and later. The comments in this section do not apply to releases earlier than 0.20.5. -

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

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

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

-
-
- SVG -
- Introduction -

FOP uses 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. -

-

-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 this graphic may not -be ideal depending on the FOP dpi (72dpi) and the scaling for that graphic. -We hope to improve this in the future.

-

-Currently transparency is not supported in PDF so many svg images that -contain effects or graphics with transparent areas will not be displayed -correctly. -

-
-
- Placing SVG Text into PDF -

If possible, Batik will use normal PDF 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 pdf files large and when the pdf is viewed the -viewer does not normally draw those fine curves very well (turning on -Smooth Line Art in the Acrobat preferences will fix this). -If the text is inserted into the PDF using the inbuilt text commands -for PDF 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. -FOP will probably implement a scaling mechanism in the future.

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

JAI: Supports RGB and RGBA only for FOP rendering.

-
-
- Graphics Resolution -

Some bitmapped image file formats store a dots-per-inch (dpi) or other resolution value. Since PDF and most output formats do not have a concept of resolution, but only of absolute image units (i.e. pixels) FOP ignores the resolution values as well. Instead, FOP uses the dimensions of the image as specified in the fo:external-graphic element to render the image:

-
    -
  • If no dimensions are given, FOP uses a default value of 72 dpi to compute the graphic's dimensions. For example, suppose a graphic 300 pixels wide and 400 pixels high. FOP will render the graphic at 4.167 inches wide, 5.555 inches high, with an apparent resolution of 72 dpi.
  • -
  • If only one dimension is given, FOP by default uses the same aspect ratio to compute the other dimension (to avoid the appearance of stretching). For example, suppose a graphic 300 pixels wide and 400 pixels high, for which content-width = ".5in". FOP will compute the content-height = .667 inches, and will render the graphic at that size, with an apparent resolution of 600 dpi.
  • -
  • If both dimensions are given, FOP simply renders the image in that space. For example, suppose a graphic 300 pixels wide and 400 pixels high, for which content-width = "3in" and content-height = "4in". FOP will render the graphic at that size, with an apparent resolution of 100 dpi.
  • -
-

If you need a higher apparent output resolution for bitmapped images, first make sure that at least one dimension of the image is defined in your XSL-FO input. Apart from that, resolution problems are in the image file itself, and must be corrected there: use or create a higher-resolution image file.

- The explanation above describes only the basic default behavior. There are other attributes of the fo:external-graphic element that can affect the behavior described above. -
-
- Image caching -

- FOP caches images between runs. The URL is used as a key to identify images which means that when - a particular URL 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. -

-

- The image cache has been improved considerably in the redesigned code. Therefore, a resetCache() method - has become unnecessary. If you still experience OutOfMemoryErrors, please notify us. -

-
- -
diff --git a/src/documentation/content/xdocs/0.93/hyphenation.xml b/src/documentation/content/xdocs/0.93/hyphenation.xml deleted file mode 100644 index ed97c6868..000000000 --- a/src/documentation/content/xdocs/0.93/hyphenation.xml +++ /dev/null @@ -1,237 +0,0 @@ - - - - - -
- 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.93/index.xml b/src/documentation/content/xdocs/0.93/index.xml deleted file mode 100644 index 3542e1d5f..000000000 --- a/src/documentation/content/xdocs/0.93/index.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - -
- Apache FOP Version 0.93 - $Revision$ -
- -
- Introduction -

- The Apache FOP team is proud to present to you this production quality release. It has taken - over three years to get this far and over two years without a new release from the FOP - project. 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 fourth release contains many bug fix release and new features compared - to 0.92beta. 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.93/intermediate.xml b/src/documentation/content/xdocs/0.93/intermediate.xml deleted file mode 100644 index 4744185aa..000000000 --- a/src/documentation/content/xdocs/0.93/intermediate.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - - -
- 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.93/known-issues.xml b/src/documentation/content/xdocs/0.93/known-issues.xml deleted file mode 100644 index 25af2a217..000000000 --- a/src/documentation/content/xdocs/0.93/known-issues.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - MIF and SVG output support have not been restored, yet. - - - Java2D/AWT support has been improved, but some problems remain, - for example with block-containers. - - - Auto table layout is not implemented, yet. - - - The collapsing border model on tables is not implemented, yet. Please - use border-collapse="separate" for now. - - - 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. - - - Images currently don't shrink so they fit on a page when they are - too big and shrinking is allowed to happen. - - - inline-container may not work as expected. - - - letter-spacing and word-spacing properties may not work as expected. - - - leaders with leader-pattern="use-content" may not work as expected. - - - keep-with-previous doesn't work inside tables and lists, yet. - - - 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. - - - Border and padding conditionality are not supported on table-cells, yet. - - - Column balancing in multi-column documents may not work as expected - (Bugzilla #36356) - - - Internal basic-links don't point to the exact location on a page, yet, as they - did in 0.20.5. Currently you land in the upper left corner of the page. - - diff --git a/src/documentation/content/xdocs/0.93/knownissues_overview.xml b/src/documentation/content/xdocs/0.93/knownissues_overview.xml deleted file mode 100644 index 0f91bb482..000000000 --- a/src/documentation/content/xdocs/0.93/knownissues_overview.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - -
- 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 currently disabled test cases in the test suite for the FO tree tests. - The data for this section comes from - test/fotree/disabled-testcases.xml. -

- -
-
- Layout Engine -

- This section lists currently disabled test cases in the test suite for the layout engine tests. - The data for this section comes from - test/layoutengine/disabled-testcases.xml. -

- -
-
- Other known issues -

This section lists other known issues.

- -
-
- -
- diff --git a/src/documentation/content/xdocs/0.93/layoutengine/disabled-testcases.xml b/src/documentation/content/xdocs/0.93/layoutengine/disabled-testcases.xml deleted file mode 100644 index cdaaaa741..000000000 --- a/src/documentation/content/xdocs/0.93/layoutengine/disabled-testcases.xml +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - - 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. - - - 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 - 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 linefeeds - are painted as '#' and 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 hyphenated fo:inlines - footnote_in_inline.xml - getChangedKnuthElements probably loses the footnote - layout manager somewhere along the way. - - - 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 - - - keeps on inlines NYI - inline_keep-together.xml - Keeps are not implemented in inline-level elements, yet. - - - 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 - wrapper_block.xml - A ClassCastException occurs when fo:wrapper directly surrounds a - block-level element because its layout manager is written to handle only - inline content. - - - Bugzilla #40230: invalid extra page break - block_break-after_bug40230.xml - Currently an extra page is created even if there is nothing - after a block with break-after="page" - http://issues.apache.org/bugzilla/show_bug.cgi?id=40230 - - diff --git a/src/documentation/content/xdocs/0.93/output.xml b/src/documentation/content/xdocs/0.93/output.xml deleted file mode 100644 index fdc37931d..000000000 --- a/src/documentation/content/xdocs/0.93/output.xml +++ /dev/null @@ -1,772 +0,0 @@ - - - - - - -
- 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: XMP metadata and watermarks. - 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 feature used is FlateDecode, everything else is Level 2. -

-
- 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 -]]> -

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

-

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

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ]]> -
-
- 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: - 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. -

-
-
-
-
- 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 fo document as - possible. The RTF output follows Microsoft's RTF specifications - and produces best results on Microsoft Word. -

-
-
- 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 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.93/pdfa.xml b/src/documentation/content/xdocs/0.93/pdfa.xml deleted file mode 100644 index 64bd5dc91..000000000 --- a/src/documentation/content/xdocs/0.93/pdfa.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - - - -
- 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. -

-
- -
diff --git a/src/documentation/content/xdocs/0.93/pdfencryption.xml b/src/documentation/content/xdocs/0.93/pdfencryption.xml deleted file mode 100644 index f68eae437..000000000 --- a/src/documentation/content/xdocs/0.93/pdfencryption.xml +++ /dev/null @@ -1,234 +0,0 @@ - - - - - -
- PDF encryption. - $Revision$ - - - - -
- -
- Overview - - PDF Encryption is available in Release 0.20.5 and later. The comments on this page do - not apply to releases earlier than 0.20.5. - -

- 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.93/pdfx.xml b/src/documentation/content/xdocs/0.93/pdfx.xml deleted file mode 100644 index cf796c74d..000000000 --- a/src/documentation/content/xdocs/0.93/pdfx.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - - -
- 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.93/running.xml b/src/documentation/content/xdocs/0.93/running.xml deleted file mode 100644 index 3e852ea98..000000000 --- a/src/documentation/content/xdocs/0.93/running.xml +++ /dev/null @@ -1,349 +0,0 @@ - - - - - -
- Running Apache FOP - $Revision$ -
- - -
- System Requirements -

The following software must be installed:

- -

The following software is optional, depending on your needs:

- -

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 availabe 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. FOP uses the current working - directory as the base directory for its search. 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. -
  • -
-

- One of FOP's stated design goals is to be able to process input of arbitrary size. - Addressing this goal is one of the prime motivations behind the - FOP Redesign. -

-
-
- Problems -

If you have problems running FOP, please see the "How to get Help" page.

-
- -
diff --git a/src/documentation/content/xdocs/0.93/servlets.xml b/src/documentation/content/xdocs/0.93/servlets.xml deleted file mode 100644 index cecbcaa60..000000000 --- a/src/documentation/content/xdocs/0.93/servlets.xml +++ /dev/null @@ -1,260 +0,0 @@ - - - - - -
- 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. -

-
-
-
- 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.93/upgrading.xml b/src/documentation/content/xdocs/0.93/upgrading.xml deleted file mode 100644 index 0f04e63b2..000000000 --- a/src/documentation/content/xdocs/0.93/upgrading.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - - -
- 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 three years. With version 0.93 the code has reached production level. -
  • -
  • - 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. -
  • -
  • - If you are using font metrics files for version 0.20.5 or - 0.92 or earlier, you have to regenerate them in the new - format. The new format is characterized by a version - attribute on the top-level font-metrics element, whose value - is 2.0. The absence of a version attribute will be - interpreted as version 1.0, and such metrics files will no - longer be parsed. -
  • -
  • -

    - 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 will be available in - January 2007. -
  • -
  • - The PCL 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. -
  • -
  • - By looking at the Compliance page you might get the impression - that the new code is much more advanced than version 0.20.5. That's true but there may still - be a few things that may not be handled as gracefully by the new code as by version 0.20.5. -
  • -
-
-
- 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. -

-
    -
  • - Check the Compliance page for the feature causing - trouble. It may contain the necessary information to understand and resolve the problem. -
  • -
  • - Not all 0.20.5 output formats are supported. PDF and Postscript should be fully supported. - See Output Targets for a more complete description. -
  • -
  • - 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. -
  • -
  • - The fox:destination extension is also not implemented in this version - although it may be added in the future. See also - Bug 37157. -
  • -
-
- -
diff --git a/src/documentation/content/xdocs/0.94/index.xml b/src/documentation/content/xdocs/0.94/index.xml index ba5b1af15..9bf46ccf5 100644 --- a/src/documentation/content/xdocs/0.94/index.xml +++ b/src/documentation/content/xdocs/0.94/index.xml @@ -32,7 +32,7 @@

This fifth release contains many bug fix release and new features compared - to 0.92beta. To see what has changed since the last release, please visit the + to 0.93. To see what has changed since the last release, please visit the Changes Page and the Release Notes.

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..57761429f --- /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.4 + (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.4 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..423eaad11 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/fonts.xml @@ -0,0 +1,410 @@ + + + + + +
+ Apache FOP: Fonts + $Revision$ + + + + + + +
+ +
+ Summary +

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

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RendererBase-14AWT/OSCustomCustom Embedding
PDFyesnoyesyes
PostScriptyesnoyesyes
PCLyes (modified)yes (painted as bitmaps)yes (painted as bitmaps)no
AFPnonoyesyes
Java2D/AWT/Bitmapif available from OSyesyesn/a (display only)
Printif available from OSyesyescontrolled by OS printer driver
RTFn/a (font metrics not needed)n/an/an/a
TXTyes (used for layout but not for output)noyes (used for layout but not for output)no
XMLyesnoyesn/a
+
+
+ Base-14 Fonts +

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

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

+

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 +

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 +

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

+
+ +
+ +
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..6e28e3fb7 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/known-issues.xml @@ -0,0 +1,70 @@ + + + + + + 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. + + + 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..b4de16ef4 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/layoutengine/disabled-testcases.xml @@ -0,0 +1,260 @@ + + + + + + + + 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. + + + 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..628df1248 --- /dev/null +++ b/src/documentation/content/xdocs/0.95/output.xml @@ -0,0 +1,888 @@ + + + + + + +
+ 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. +

+

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

+ 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..cda301aab --- /dev/null +++ b/src/documentation/content/xdocs/0.95/pdfencryption.xml @@ -0,0 +1,225 @@ + + + + + +
+ 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. + 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. +
  2. +
  3. + 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. +
  4. +
+

+ 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..38e31cc6c --- /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/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 27ca74a63..2b25b89d7 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.

+ - - - - - + + + + + + + + + + - - - - + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - - - - - +
  • [0.94 and later] The page width may not change among pages of the same page-sequence + unless a forced break is inserted.
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - +
  • [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.94 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.93 (stable) - 0.94 (stable) - develop- ment 0.20.5 (ancient)0.94 (stable)0.95 (beta)develop- ment
    - Declarations and Pagination and Layout Formatting Objects (§6.4) Declarations and Pagination and Layout Formatting Objects + (§6.4)
    - root - Basic - §6.4.2 - yes yes - yes - yes  
    - declarations - Basic - §6.4.3 - no no - no - no  
    - color-profile - Extended - §6.4.4 - no no - no - no  
    - page-sequence - Basic - §6.4.5 - yes yes - yes - yes  
    - layout-master-set - Basic - §6.4.6 - yes yes - yes - yes  
    - page-sequence-master - Basic - §6.4.7 - yes yes - yes - yes  
    - single-page-master-reference - Basic - §6.4.8 - yes yes - yes - yes  
    - repeatable-page-master-reference - Basic - §6.4.9 - yes yes - yes - yes  
    - repeatable-page-master-alternatives - Extended - §6.4.10 - yes yes - yes - yes  
    - conditional-page-master-reference - Extended - §6.4.11 - yes yes - yes - yes  
    - simple-page-master - Basic - §6.4.12 - yes partial - 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.
    • -
    rootBasic§6.4.2yesyesyesyes 
    - region-body - Basic - §6.4.13 - yes yes - yes - yes
    - region-before - Extended - §6.4.14 - yes yes - yes - yes  
    - region-after - Extended - §6.4.15 - yes yes - yes - yes  
    - region-start - Extended - §6.4.16 - yes yes - yes - yes  
    - region-end - Extended - §6.4.17 - yes yes - yes - yes  
    - flow - Basic - §6.4.18 - yes yes - yes - yes  
    - static-content - Extended - §6.4.19 - yes yes - yes - yes  
    - title - Extended - §6.4.20 - no no - no - no   declarationsBasic§6.4.3nononono 
    - Block Formatting Objects (§6.5) color-profileExtended§6.4.4nononono 
    - block - Basic - §6.5.2 - yes yes - yes - yes  
    - block-container - Extended - §6.5.3 - partial 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.
    • -
    page-sequenceBasic§6.4.5yesyesyesyes 
    - Inline Formatting Objects (§6.6) layout-master-setBasic§6.4.6yesyesyesyes 
    - bidi-override - Extended - §6.6.2 - no no - no - no  
    - character - Basic - §6.6.3 - yes yes - yes - yes  
    - initial-property-set - Extended - §6.6.4 - no no - no - no  
    - external-graphic - Basic - §6.6.5 - yes yes - yes - yes  
    - instream-foreign-object - Extended - §6.6.6 - yes yes - yes - yes -
      -
    • Built-in support for SVG only, additional namespaces through optional extensions.
    • -
    page-sequence-masterBasic§6.4.7yesyesyesyes 
    - inline - Basic - §6.6.7 - yes yes - yes - yes  
    - inline-container - Extended - §6.6.8 - no no - no - no  
    - leader - Basic - §6.6.9 - partial yes - yes - yes  
    - page-number - Basic - §6.6.10 - yes yes - yes - yes  
    - page-number-citation - Extended - §6.6.11 - partial 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.
    • -
    single-page-master-referenceBasic§6.4.8yesyesyesyes 
    repeatable-page-master-referenceBasic§6.4.9yesyesyesyes 
    - Table Formatting Objects (§6.7) repeatable-page-master-alternativesExtended + §6.4.10yesyesyesyes 
    - table-and-caption - Basic - §6.7.2 - no no - no - no  
    - table - Basic - §6.7.3 - partial partial - partial - partial -
      -
    • [0.20.5–0.93] Only border-collapse="separate"
    • -
    • [All] No support for auto layout yet
    • -
    -
    conditional-page-master-referenceExtended + §6.4.11yesyesyesyes 
    - table-column - Basic simple-page-masterBasic§6.4.12yespartialpartialpartial - §6.7.4 - partial yes - yes - yes
      -
    • - [0.20.5] You must explicitly specify column widths.
    • -
    - table-caption - Extended - §6.7.5 - no no - no - no  
    - table-header - Basic - §6.7.6 - yes yes - yes - yes  
    - table-footer - Extended - §6.7.7 - yes yes - yes - yes  
    - table-body - Basic - §6.7.8 - yes yes - yes - yes  
    - table-row - Basic - §6.7.9 - yes yes - yes - yes  
    - table-cell - Basic - §6.7.10 - partial yes - yes - yes  
    - List Formatting Objects (§6.8) region-bodyBasic§6.4.13yesyesyesyes
    - list-block - Basic - §6.8.2 - yes yes - yes - yes  
    - list-item - Basic - §6.8.3 - yes yes - yes - yes  
    - list-item-body - Basic - §6.8.4 - yes yes - yes - yes  
    - list-item-label - Extended - §6.8.5 - yes yes - yes - yes   region-beforeExtended§6.4.14yesyesyesyes 
    - Link and Multi Formatting Objects (§6.9) region-afterExtended§6.4.15yesyesyesyes 
    - basic-link - Extended - §6.9.2 - yes yes - yes - yes -
      -
    • - both internal and external supported
    • -
    region-startExtended§6.4.16yesyesyesyes 
    - multi-switch - Extended - §6.9.3 - no no - no - no  
    - multi-case - Basic - §6.9.4 - no no - no - no  
    - multi-toggle - Extended - §6.9.5 - no no - no - no  
    - multi-properties - Extended - §6.9.6 - no no - no - no  
    - multi-property-set - Extended - §6.9.7 - no no - no - no   region-endExtended§6.4.17yesyesyesyes 
    - Formatting Objects for Bookmarks (§6.11 in XSL 1.1 WD) flowBasic§6.4.18yesyesyesyes 
    - bookmark-tree (since XSL 1.1) - Extended - §6.11.1 in XSL 1.1 WD - no yes - yes - yes -
      -
    • [0.20.5] Uses the proprietary fox:outline extension.
    • -
    static-contentExtended§6.4.19yesyesyesyes 
    - bookmark (since XSL 1.1) - Extended - §6.11.2 in XSL 1.1 WD - no yes - yes - yes -
      -
    • [0.20.5] Uses the proprietary fox:outline extension.
    • -
    titleExtended§6.4.20nononono 
    - bookmark-title (since XSL 1.1) - Extended - §6.11.3 in XSL 1.1 WD - no partial - 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.
    • -
    Block Formatting Objects (§6.5)
    - Out-of-line Formatting Objects (§6.10) blockBasic§6.5.2yesyesyesyes 
    - float - Extended - §6.10.2 - no no - no - no  
    - footnote - Extended - §6.10.3 - yes partial - partial - partial block-containerExtended§6.5.3partialpartialpartialpartial
      -
    • [0.20.5] Footnotes sometimes overlap with the main content
    • -
    • [0.93 and later] Restrictions with multi-column documents.
    • -
    - footnote-body - Extended - §6.10.4 - yes yes - yes - yes  
    - Other Formatting Objects (§6.11)
    - wrapper - Basic - §6.11.2 - yes partial - partial - partial -
      -
    • [0.93 and later] Only works as expected with inline-level content.
    • -
    Inline Formatting Objects (§6.6)
    - marker - Extended - §6.11.3 - yes yes - yes - yes bidi-overrideExtended§6.6.2nononono 
    - retrieve-marker - Extended - §6.11.4 - yes yes - yes - yes  
    -

    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] 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.94 and later] After the page number is known, no relayout is performed. The + appearance may be suboptimal depending on the use case.
  • + + + - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +
  • [0.20.5] 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] Uses the proprietary fox:outline extension.
  • + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  • [0.20.5] Uses the proprietary fox:outline extension.
  • + +
  • [0.94 and later] color, font-style and font-weight are not supported, yet.
  • + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  • [0.20.5] Footnotes sometimes overlap with the main content
  • + +
  • [0.94 and later] Restrictions with multi-column documents.
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    - Property Name - XSL-FO Conformance Level - Citation - Support in FOP - Comments
    - 0.20.5 (previous) 0.93 (stable) - 0.94 (stable) - develop- ment
    - Common Accessibility Properties (§7.4) characterBasic§6.6.3yesyesyesyes 
    - source-document - Basic - §7.4.1 - na na - na - na  
    - role - Basic - §7.4.2 - na na - na - na   initial-property-setExtended§6.6.4nononono 
    - Common Absolute Position Properties (§7.5) external-graphicBasic§6.6.5yesyesyesyes 
    - absolute-position - Complete instream-foreign-objectExtended§6.6.6yesyesyesyes - §7.5.1 - no yes - 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.
    • -
    - top - Extended - §7.5.2 - yes yes - yes - yes  
    - right - Extended - §7.5.3 - yes yes - yes - yes  
    - bottom - Extended - §7.5.4 - yes yes - yes - yes  
    - left - Extended - §7.5.5 - yes yes - yes - yes   inlineBasic§6.6.7yesyesyesyes 
    - Common Aural Properties (§7.6) inline-containerExtended§6.6.8nononono 
    - azimuth - Basic - §7.6.1 - na na - na - na  
    - cue-after - Basic - §7.6.2 - na na - na - na  
    - cue-before - Basic - §7.6.3 - na na - na - na  
    - elevation - Basic - §7.6.4 - na na - na - na  
    - pause-after - Basic - §7.6.5 - na na - na - na  
    - pause-before - Basic - §7.6.6 - na na - na - na  
    - pitch - Basic - §7.6.7 - na na - na - na  
    - pitch-range - Basic - §7.6.8 - na na - na - na  
    - play-during - Basic - §7.6.9 - na na - na - na  
    - richness - Basic - §7.6.10 - na na - na - na  
    - speak - Basic - §7.6.11 - na na - na - na  
    - speak-header - Basic - §7.6.12 - na na - na - na  
    - speak-numeral - Basic - §7.6.13 - na na - na - na  
    - speak-punctuation - Basic - §7.6.14 - na na - na - na  
    - speech-rate - Basic - §7.6.15 - na na - na - na  
    - stress - Basic - §7.6.16 - na na - na - na  
    - voice-family - Basic - §7.6.17 - na na - na - na  
    - volume - Basic - §7.6.18 - na na - na - na   leaderBasic§6.6.9partialyesyesyes 
    - Common Border, Padding, and Background Properties (§7.7) page-numberBasic§6.6.10yesyesyesyes 
    - background-attachment - Extended - §7.7.1 - no no - no - no  
    - background-color - Basic - §7.7.2 - yes partial - partial - partial page-number-citationExtended§6.6.11partialpartialpartialpartial
      -
    • - [0.93 and later] not yet implemented for table-column, table-body, table-header and table-footer.
    • -
    - background-image - Extended - §7.7.3 - yes partial - partial - partial -
      -
    • - [0.93 and later] not yet implemented for table-column, table-body, table-header and table-footer.
    • -
    Table Formatting Objects (§6.7)
    - background-repeat - Extended - §7.7.4 - no yes - yes - yes  
    - background-position-horizontal - Extended - §7.7.5 - no yes - yes - yes  
    - background-position-vertical - Extended - §7.7.6 - no yes - yes - yes  
    - border-before-color - Basic - §7.7.7 - yes yes - yes - yes  
    - border-before-style - Basic - §7.7.8 - partial yes - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-and-captionBasic§6.7.2nononono 
    - border-before-width - Basic - §7.7.9 - yes yes - yes - yes  
    - border-after-color - Basic - §7.7.10 - yes yes - yes - yes  
    - border-after-style - Basic - §7.7.11 - partial yes - yes - yes tableBasic§6.7.3partialpartialpartialpartial
      -
    • - [0.20.5] only "solid" works
    • -
    - border-after-width - Basic - §7.7.12 - yes yes - yes - yes  
    - border-start-color - Basic - §7.7.13 - yes yes - yes - yes  
    - border-start-style - Basic - §7.7.14 - partial yes - yes - yes table-columnBasic§6.7.4partialyesyesyes
      -
    • - [0.20.5] only "solid" works
    • -
    - border-start-width - Basic - §7.7.15 - yes yes - yes - yes  
    - border-end-color - Basic - §7.7.16 - yes yes - yes - yes  
    - border-end-style - Basic - §7.7.17 - partial yes - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-captionExtended§6.7.5nononono 
    - border-end-width - Basic - §7.7.18 - yes yes - yes - yes  
    - border-top-color - Basic - §7.7.19 - yes yes - yes - yes  
    - border-top-style - Basic - §7.7.20 - partial yes - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-headerBasic§6.7.6yesyesyesyes 
    - border-top-width - Basic - §7.7.21 - yes yes - yes - yes  
    - border-bottom-color - Basic - §7.7.22 - yes yes - yes - yes  
    - border-bottom-style - Basic - §7.7.23 - partial yes - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-footerExtended§6.7.7yesyesyesyes 
    - border-bottom-width - Basic - §7.7.24 - yes yes - yes - yes  
    - border-left-color - Basic - §7.7.25 - yes yes - yes - yes  
    - border-left-style - Basic - §7.7.26 - partial yes - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-bodyBasic§6.7.8yesyesyesyes 
    - border-left-width - Basic - §7.7.27 - yes yes - yes - yes  
    - border-right-color - Basic - §7.7.28 - yes yes - yes - yes  
    - border-right-style - Basic - §7.7.29 - partial yes - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    table-rowBasic§6.7.9yesyesyesyes 
    - border-right-width - Basic - §7.7.30 - yes yes - yes - yes  
    - padding-before - Basic - §7.7.31 - partial yes - 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 - yes -
      -
    • - [0.20.5] same limitations as padding-before
    • -
    table-cellBasic§6.7.10partialyesyesyes 
    - padding-start - Basic - §7.7.33 - partial yes - yes - yes List Formatting Objects (§6.8)
    list-blockBasic§6.8.2yesyesyesyes 
    list-itemBasic§6.8.3yesyesyesyes 
    list-item-bodyBasic§6.8.4yesyesyesyes 
    list-item-labelExtended§6.8.5yesyesyesyes 
    Link and Multi Formatting Objects (§6.9)
    basic-linkExtended§6.9.2yesyesyesyes
      -
    • - [0.20.5] same limitations as padding-before
    • -
    - padding-end - Basic - §7.7.34 - partial yes - yes - yes multi-switchExtended§6.9.3nononono 
    multi-caseBasic§6.9.4nononono 
    multi-toggleExtended§6.9.5nononono 
    multi-propertiesExtended§6.9.6nononono 
    multi-property-setExtended§6.9.7nononono 
    Formatting Objects for Bookmarks (§6.11 in XSL 1.1 WD)
    bookmark-tree (since + XSL 1.1)Extended§6.11.1 in XSL + 1.1 WDnoyesyesyes
      -
    • - [0.20.5] same limitations as padding-before
    • -
    - padding-top - Basic - §7.7.35 - partial yes - yes - yes bookmark (since XSL 1.1)Extended§6.11.2 in XSL 1.1 + WDnoyesyesyes +
      +
    • [0.20.5] Uses the proprietary fox:outline extension.
    • +
    +
    bookmark-title + (since XSL 1.1)Extended§6.11.3 in + XSL 1.1 WDnopartialpartialpartial
      -
    • - [0.20.5] same limitations as padding-before
    • -
    Out-of-line Formatting Objects (§6.10)
    - padding-bottom - Basic - §7.7.36 - partial yes - yes - yes floatExtended§6.10.2nononono 
    footnoteExtended§6.10.3yespartialpartialpartial
      -
    • - [0.20.5] same limitations as padding-before
    • -
    footnote-bodyExtended§6.10.4yesyesyesyes 
    Other Formatting Objects (§6.11)
    wrapperBasic§6.11.2yespartialpartialpartial +
      +
    • [0.94 and later] Only works as expected with inline-level content.
    • +
    +
    markerExtended§6.11.3yesyesyesyes 
    retrieve-markerExtended§6.11.4yesyesyesyes 
    + +

    XSL-FO Property Support Table + (§7)

    + +

    The following is a summary of FOP's current support for the standard XSL-FO properties.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + +
  • [0.94 and later] Some small limitations
  • + + + - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +
  • [0.20.5] "percentage" not implemented. Workaround is to use the XSL-FO + "proportional-column-width" function.
  • + + + - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - + + + + + + - - - + + + + + + + + + - - - - + + + + + + + + + + + + - - - + + + - + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + - - - + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  • [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.
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +
  • [0.20.5] only "solid" works
  • + + + - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  • [0.94 and later] Enum values other than "inherit" not yet supported.
  • + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  • [0.20.5] only on pages and regions
  • + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  • [0.20.5] "inherit" not handled
  • + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + +
    Property NameXSL-FO Conformance LevelCitationSupport in FOPComments
    0.20.5 (ancient)0.94 (stable)0.95 (beta)develop- ment
    Common Accessibility Properties (§7.4)
    source-documentBasic§7.4.1nananana 
    roleBasic§7.4.2nananana 
    Common Absolute Position Properties (§7.5)
    absolute-positionComplete§7.5.1noyesyesyes +
      +
    • [0.20.5] Use shorthand position="absolute" as a workaround.
    • + +
    • [0.94 and later] No restrictions. The 0.20.5 work-around is not supported.
    • +
    +
    topExtended§7.5.2yesyesyesyes 
    rightExtended§7.5.3yesyesyesyes 
    bottomExtended§7.5.4yesyesyesyes 
    leftExtended§7.5.5yesyesyesyes 
    Common Aural Properties (§7.6)
    azimuthBasic§7.6.1nananana 
    cue-afterBasic§7.6.2nananana 
    cue-beforeBasic§7.6.3nananana 
    elevationBasic§7.6.4nananana 
    pause-afterBasic§7.6.5nananana 
    pause-beforeBasic§7.6.6nananana 
    pitchBasic§7.6.7nananana 
    pitch-rangeBasic§7.6.8nananana 
    play-duringBasic§7.6.9nananana 
    richnessBasic§7.6.10nananana 
    speakBasic§7.6.11nananana 
    speak-headerBasic§7.6.12nananana 
    speak-numeralBasic§7.6.13nananana 
    speak-punctuationBasic§7.6.14nananana 
    speech-rateBasic§7.6.15nananana 
    stressBasic§7.6.16nananana 
    voice-familyBasic§7.6.17nananana 
    volumeBasic§7.6.18nananana 
    Common Border, Padding, and Background Properties + (§7.7)
    background-attachmentExtended§7.7.1nononono 
    background-colorBasic§7.7.2yespartialyesyes +
      +
    • [0.94] not yet implemented for table-column, table-body, table-header and + table-footer.
    • +
    +
    background-imageExtended§7.7.3yespartialyesyes +
      +
    • [0.94] not yet implemented for table-column, table-body, table-header and + table-footer.
    • +
    +
    background-repeatExtended§7.7.4noyesyesyes 
    background-position-horizontalExtended§7.7.5nopartialpartialpartial[0.94 and later] Ignored when background-repeat set to + "repeat" or "repeat-x"
    background-position-verticalExtended§7.7.6nopartialpartialpartial[0.94 and later] Ignored when background-repeat set to + "repeat" or "repeat-y"
    border-before-colorBasic§7.7.7yesyesyesyes 
    border-before-styleBasic§7.7.8partialyesyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-before-widthBasic§7.7.9yespartialyesyes +
      +
    • [0.94] .conditionality not supported on fo:table-cell
    • +
    +
    border-after-colorBasic§7.7.10yesyesyesyes 
    border-after-styleBasic§7.7.11partialyesyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-after-widthBasic§7.7.12yespartialyesyes +
      +
    • [0.94] .conditionality not supported on fo:table-cell
    • +
    +
    border-start-colorBasic§7.7.13yesyesyesyes 
    border-start-styleBasic§7.7.14partialyesyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-start-widthBasic§7.7.15yesyesyesyes 
    border-end-colorBasic§7.7.16yesyesyesyes 
    border-end-styleBasic§7.7.17partialyesyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-end-widthBasic§7.7.18yesyesyesyes 
    border-top-colorBasic§7.7.19yesyesyesyes 
    border-top-styleBasic§7.7.20partialyesyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-top-widthBasic§7.7.21yesyesyesyes 
    border-bottom-colorBasic§7.7.22yesyesyesyes 
    border-bottom-styleBasic§7.7.23partialyesyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-bottom-widthBasic§7.7.24yesyesyesyes 
    border-left-colorBasic§7.7.25yesyesyesyes 
    border-left-styleBasic§7.7.26partialyesyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-left-widthBasic§7.7.27yesyesyesyes 
    border-right-colorBasic§7.7.28yesyesyesyes 
    border-right-styleBasic§7.7.29partialyesyesyes +
      +
    • [0.20.5] only "solid" works
    • +
    +
    border-right-widthBasic§7.7.30yesyesyesyes 
    padding-beforeBasic§7.7.31partialyesyesyes +
      +
    • [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-afterBasic§7.7.32partialyesyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-startBasic§7.7.33partialyesyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-endBasic§7.7.34partialyesyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-topBasic§7.7.35partialyesyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-bottomBasic§7.7.36partialyesyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-leftBasic§7.7.37partialyesyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    padding-rightBasic§7.7.38partialyesyesyes +
      +
    • [0.20.5] same limitations as padding-before
    • +
    +
    Common Font Properties (§7.8)
    font-familyBasic§7.8.2partialpartialpartialpartial +
      +
    • [0.20.5] font-family lists are not supported, use a single font-family name
    • + +
    • [0.94 and later] font-family lists are allowed but glyph based font selection is not + supported
    • +
    +
    font-selection-strategyComplete§7.8.3nononono 
    font-sizeBasic§7.8.4partialyesyesyes +
      +
    • [0.20.5] "smaller" and "larger" not implemented
    • +
    +
    font-stretchExtended§7.8.5nononono 
    font-size-adjustExtended§7.8.6nononono 
    font-styleBasic§7.8.7partialyesyesyes +
      +
    • [0.20.5] "normal" is not supported
    • +
    +
    font-variantBasic§7.8.8yesnonono 
    font-weightBasic§7.8.9partialpartialpartialpartial +
      +
    • [0.20.5] "normal", "bolder" and "lighter" are not supported
    • + +
    • [0.94 and later] TODO <relative> font weights
    • +
    +
    Common Hyphenation Properties (§7.9)
    countryExtended§7.9.1yesyesyesyes +
      +
    • [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.2yesyesyesyes +
      +
    • [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.3nononono 
    hyphenateExtended§7.9.4yesyesyesyes 
    hyphenation-characterExtended§7.9.5yesyesyesyes 
    hyphenation-push-character-countExtended§7.9.6yesyesyesyes 
    hyphenation-remain-character-countExtended§7.9.7yesyesyesyes 
    Common Margin Properties - Block (§7.10)
    margin-topBasic§7.10.1partialyesyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    margin-bottomBasic§7.10.2partialyesyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    margin-leftBasic§7.10.3partialyesyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    margin-rightBasic§7.10.4partialyesyesyes +
      +
    • [0.20.5] only on pages and regions
    • +
    +
    space-beforeBasic§7.10.5partialpartialpartialpartial +
      +
    • [0.20.5] space-before.optimum supported
    • + +
    • [0.94 and later] Space adjustment may not fully work everywhere, yet.
    • +
    +
    space-afterBasic§7.10.6partialpartialpartialpartial +
      +
    • [0.20.5] space-after.optimum supported
    • + +
    • [0.94 and later] Space adjustment may not fully work everywhere, yet.
    • +
    +
    start-indentBasic§7.10.7yesyesyesyes 
    end-indentBasic§7.10.8yesyesyesyes 
    Common Margin Properties - Inline (§7.11)
    space-endBasic§7.11.1nononono 
    space-startBasic§7.11.2nononono 
    Common Relative Position Properties (§7.12)
    relative-positionExtended§7.12.1nononono 
    Area Alignment Properties (§7.13)
    alignment-adjustBasic§7.13.1noyesyesyes 
    alignment-baselineBasic§7.13.2noyesyesyes 
    baseline-shiftBasic§7.13.3partialyesyesyes +
      +
    • [0.20.5] Only values "super" and "sub" have been implemented.
    • +
    +
    display-alignExtended§7.13.4partialpartialpartialpartial +
      +
    • [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.94 and later] TODO Check e-g, i-f-o.
    • +
    +
    dominant-baselineBasic§7.13.5noyesyesyes 
    relative-alignExtended§7.13.6nononono 
    Area Dimension Properties (§7.14)
    block-progression-dimensionBasic§7.14.1noyesyesyes 
    content-heightExtended§7.14.2noyesyesyes 
    content-widthExtended§7.14.3noyesyesyes 
    heightBasic§7.14.4yesyesyesyes 
    inline-progression-dimensionBasic§7.14.5noyesyesyes 
    max-heightComplete§7.14.6nononono 
    max-widthComplete§7.14.7nononono 
    min-heightComplete§7.14.8nononono 
    min-widthComplete§7.14.9nononono 
    scalingExtended§7.14.10noyesyesyes 
    scaling-methodExtended§7.14.11nononono 
    widthBasic§7.14.12yesyesyesyes 
    Block and Line-related Properties (§7.15)
    hyphenation-keepExtended§7.15.1nononono 
    hyphenation-ladder-countExtended§7.15.2noyesyesyes 
    last-line-end-indentExtended§7.15.3noyesyesyes 
    line-heightBasic§7.15.4yesyesyesyes 
    line-height-shift-adjustmentExtended§7.15.5noyesyesyes 
    line-stacking-strategyBasic§7.15.6nopartialpartialpartial +
      +
    • [0.94 and later] value "line-height" not supported
    • +
    +
    linefeed-treatmentExtended§7.15.7noyesyesyes 
    white-space-treatmentExtended§7.15.8nopartialpartialpartial +
      +
    • [0.94 and later] inline elements may interfere with correct handling of this property + in some cases
    • +
    +
    text-alignBasic§7.15.9partialpartialpartialpartial +
      +
    • Only start, end, center and justify are supported
    • +
    +
    text-align-lastExtended§7.15.10partialpartialpartialpartial +
      +
    • Only start, end, center and justify are supported
    • +
    +
    text-indentBasic§7.15.11yesyesyesyes 
    white-space-collapseExtended§7.15.12yesyesyesyes 
    wrap-optionBasic§7.15.13yespartialpartialpartial +
      +
    • [0.94 and later] Only supported on fo:block.
    • +
    +
    Character Properties (§7.16)
    characterBasic§7.16.1yesyesyesyes 
    letter-spacingExtended§7.16.2yesyesyesyes 
    suppress-at-line-breakExtended§7.16.3nononono 
    text-decorationExtended§7.16.4yesyesyesyes 
    text-shadowExtended§7.16.5nononono 
    text-transformExtended§7.16.6noyesyesyes 
    treat-as-word-spaceExtended§7.16.7nononono 
    word-spacingExtended§7.16.8noyesyesyes 
    Color-related Properties (§7.17)
    colorBasic§7.17.1yesyesyesyes 
    color-profile-nameExtended§7.17.2nononono 
    rendering-intentExtended§7.17.3nononono 
    Float-related Properties (§7.18)
    clearExtended§7.18.1nononono 
    floatExtended§7.18.2nononono 
    intrusion-displaceExtended§7.18.3nononono 
    Keeps and Breaks Properties (§7.19)
    break-afterBasic§7.19.1yespartialyesyes +
      +
    • [0.94] Doesn't work on the last row of a table
    • +
    +
    break-beforeBasic§7.19.2yespartialyesyes +
      +
    • [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
    • +
    +
    keep-togetherExtended§7.19.3partialpartialpartialpartial +
      +
    • [0.20.5] works only in table rows
    • + +
    • [0.94 and later] <integer> values are not supported.
    • +
    +
    keep-with-nextBasic§7.19.4partialpartialpartialpartial +
      +
    • [0.20.5] works only in table rows
    • + +
    • [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.
    • +
    +
    keep-with-previousBasic§7.19.5partialpartialpartialpartial +
      +
    • [0.20.5] works only in table rows
    • + +
    • [0.94] works on all implemented FOs, except list- and table-related and + inline-level FOs.
    • + +
    • [0.95] works on all implemented FOs, except list- and inline-level + FOs.
    • + +
    • [0.94 and later] <integer> values are not supported.
    • +
    +
    orphansBasic§7.19.6noyesyesyes 
    widowsBasic§7.19.7noyesyesyes 
    Layout-related Properties (§7.20)
    clipExtended§7.20.1nononono 
    overflowBasic§7.20.2noyesyesyes 
    reference-orientationExtended§7.20.3noyesyesyes +
      +
    • [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.4yesyesyesyes 
    Leader and Rule Properties (§7.21)
    leader-alignmentExtended§7.21.1partialnonono +
      +
    • [0.20.5] not value "page"
    • + +
    • [0.94 and later] Not supported
    • +
    +
    leader-patternBasic§7.21.2partialyesyesyes +
      +
    • [0.20.5] not value "use-content"
    • + +
    • [0.94 and later] Value "use-content" does not work in all circumstances.
    • +
    +
    leader-pattern-widthExtended§7.21.3yesyesyesyes 
    leader-lengthBasic§7.21.4partialyesyesyes +
      +
    • [0.20.5] leader-length.minimum is not used at all
    • +
    +
    rule-styleBasic§7.21.5yesyesyesyes 
    rule-thicknessBasic§7.21.6yesyesyesyes 
    Properties for Dynamic Effects Formatting Objects + (§7.22)
    active-stateExtended§7.22.1nononono 
    auto-restoreExtended§7.22.2nononono 
    case-nameExtended§7.22.3nononono 
    case-titleExtended§7.22.4nononono 
    destination-placement-offsetExtended§7.22.5nononono 
    external-destinationBasic§7.22.6yesyesyesyes 
    indicate-destinationExtended§7.22.7nononono 
    internal-destinationExtended§7.22.8yesyesyesyes 
    show-destinationExtended§7.22.9nononono 
    starting-stateExtended§7.22.10nopartialpartialpartial +
      +
    • [0.94 and later] support for starting-state on fo:bookmark
    • +
    +
    switch-toExtended§7.22.11nononono 
    target-presentation-contextExtended§7.22.12nononono 
    target-processing-contextExtended§7.22.13nononono 
    target-stylesheetExtended§7.22.14nononono 
    Properties for Markers (§7.23)
    marker-class-nameExtended§7.23.1noyesyesyes 
    retrieve-class-nameExtended§7.23.2noyesyesyes 
    retrieve-positionExtended§7.23.3noyesyesyes 
    retrieve-boundaryExtended§7.23.4noyesyesyes 
    Properties for Number to String Conversion (§7.24)
    formatBasic§7.24.1noyesyesyes 
    grouping-separatorExtended§7.24.2nononono 
    grouping-sizeExtended§7.24.3nononono 
    letter-valueBasic§7.24.4nononono 
    Pagination and Layout Properties (§7.25)
    blank-or-not-blankExtended§7.25.1yesyesyesyes 
    column-countExtended§7.25.2yesyesyesyes 
    column-gapExtended§7.25.3yesyesyesyes 
    extentExtended§7.25.4yesyesyesyes 
    flow-nameBasic§7.25.5yesyesyesyes 
    force-page-countExtended§7.25.6noyesyesyes 
    initial-page-numberBasic§7.25.7yesyesyesyes 
    master-nameBasic§7.25.8yesyesyesyes 
    master-referenceBasic§7.25.9yesyesyesyes 
    maximum-repeatsExtended§7.25.10yesyesyesyes 
    media-usageExtended§7.25.11nononono 
    odd-or-evenExtended§7.25.12yesyesyesyes 
    page-heightBasic§7.25.13yesyesyesyes 
    page-positionExtended§7.25.14partialyesyesyes +
      +
    • [0.20.5] "last" isn't implemented!
    • +
    +
    page-widthBasic§7.25.15yesyesyesyes 
    precedenceExtended§7.25.16noyesyesyes 
    region-nameBasic§7.25.17yesyesyesyes 
    Table Properties (§7.26)
    border-after-precedenceBasic§7.26.1nononono 
    border-before-precedenceBasic§7.26.2nononono 
    - padding-left - Basic - §7.7.37 - partial yes - yes - yes border-collapseExtended§7.26.3partialyesyesyes
      -
    • - [0.20.5] same limitations as padding-before
    • -
    - padding-right - Basic - §7.7.38 - partial yes - yes - yes -
      -
    • - [0.20.5] same limitations as padding-before
    • -
    border-end-precedenceBasic§7.26.4nononono 
    - Common Font Properties (§7.8) border-separationExtended§7.26.5noyesyesyes 
    - font-family - Basic - §7.8.2 - partial 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
    • -
    border-start-precedenceBasic§7.26.6nononono 
    - font-selection-strategy - Complete - §7.8.3 - no no - no - no  
    - font-size - Basic - §7.8.4 - partial yes - yes - yes -
      -
    • - [0.20.5] "smaller" and "larger" not implemented
    • -
    caption-sideComplete§7.26.7nononono 
    - font-stretch - Extended - §7.8.5 - no no - no - no  
    - font-size-adjust - Extended - §7.8.6 - no no - no - no  
    - font-style - Basic - §7.8.7 - partial yes - yes - yes -
      -
    • - [0.20.5] "normal" is not supported
    • -
    column-numberBasic§7.26.8noyesyesyes 
    - font-variant - Basic - §7.8.8 - yes no - no - no  
    - font-weight - Basic - §7.8.9 - partial partial - partial - partial column-widthBasic§7.26.9partialyesyesyes
      -
    • - [0.20.5] "normal", "bolder" and "lighter" are not supported
    • -
    • - [0.93 and later] TODO <relative> font weights
    • -
    - Common Hyphenation Properties (§7.9) empty-cellsExtended§7.26.10nononono 
    - country - Extended - §7.9.1 - yes yes - 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!
    • -
    -
    ends-rowExtended§7.26.11noyesyesyes 
    - language - Extended - §7.9.2 - yes yes - 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!
    • -
    -
    number-columns-repeatedBasic§7.26.12noyesyesyes 
    - script - Extended - §7.9.3 - no no - no - no  
    - hyphenate - Extended - §7.9.4 - yes yes - yes - yes  
    - hyphenation-character - Extended - §7.9.5 - yes yes - yes - yes  
    - hyphenation-push-character-count - Extended - §7.9.6 - yes yes - yes - yes  
    - hyphenation-remain-character-count - Extended - §7.9.7 - yes yes - yes - yes   number-columns-spannedBasic§7.26.13yesyesyesyes 
    - Common Margin Properties - Block (§7.10) number-rows-spannedBasic§7.26.14yesyesyesyes 
    - margin-top - Basic - §7.10.1 - partial yes - yes - yes -
      -
    • - [0.20.5] only on pages and regions
    • -
    starts-rowExtended§7.26.15noyesyesyes 
    - margin-bottom - Basic - §7.10.2 - partial yes - yes - yes -
      -
    • - [0.20.5] only on pages and regions
    • -
    table-layoutExtended§7.26.16nononono 
    - margin-left - Basic - §7.10.3 - partial yes - yes - yes -
      -
    • - [0.20.5] only on pages and regions
    • -
    table-omit-footer-at-breakExtended§7.26.17yesyesyesyes 
    - margin-right - Basic - §7.10.4 - partial yes - yes - yes -
      -
    • - [0.20.5] only on pages and regions
    • -
    table-omit-header-at-breakExtended§7.26.18yesyesyesyes 
    - space-before - Basic - §7.10.5 - partial partial - partial - partial -
      -
    • - [0.20.5] space-before.optimum supported
    • -
    • - [0.93 and later] Space adjustment may not fully work everywhere, yet.
    • -
    Writing-mode-related Properties (§7.27)
    - space-after - Basic - §7.10.6 - partial partial - partial - partial -
      -
    • - [0.20.5] space-after.optimum supported
    • -
    • - [0.93 and later] Space adjustment may not fully work everywhere, yet.
    • -
    directionBasic§7.27.1nononono 
    - start-indent - Basic - §7.10.7 - yes yes - yes - yes  
    - end-indent - Basic - §7.10.8 - yes yes - yes - yes   glyph-orientation-horizontalExtended§7.27.2nononono 
    - Common Margin Properties - Inline (§7.11) glyph-orientation-verticalExtended§7.27.3nononono 
    - space-end - Basic - §7.11.1 - no text-altitudeExtended§7.27.4no - no - no   nonono 
    - space-start - Basic - §7.11.2 - no text-depthExtended§7.27.5nononono - no - no    
    - Common Relative Position Properties (§7.12) unicode-bidiExtended§7.27.6nononono 
    - relative-position - Extended - §7.12.1 - no writing-modeBasic§7.27.7nononono - no - no    
    - Area Alignment Properties (§7.13) Miscellaneous Properties (§7.28)
    - alignment-adjust - Basic - §7.13.1 - no yes - yes - yes  
    - alignment-baseline - Basic - §7.13.2 - no yes - yes - yes  
    - baseline-shift - Basic - §7.13.3 - partial yes - yes - yes -
      -
    • - [0.20.5] Only values "super" and "sub" have been implemented.
    • -
    content-typeExtended§7.28.1nononono 
    - display-align - Extended - §7.13.4 - partial partial - partial - partial idBasic§7.28.2yespartialpartialpartial
      -
    • - [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 - yes  
    - relative-align - Extended - §7.13.6 - no no - no - no  
    - Area Dimension Properties (§7.14)
    - block-progression-dimension - Basic - §7.14.1 - no yes - yes - yes  
    - content-height - Extended - §7.14.2 - no yes - yes - yes  
    - content-width - Extended - §7.14.3 - no yes - yes - yes  
    - height - Basic - §7.14.4 - yes yes - yes - yes  
    - inline-progression-dimension - Basic - §7.14.5 - no yes - yes - yes  
    - max-height - Complete - §7.14.6 - no no - no - no  
    - max-width - Complete - §7.14.7 - no no - no - no  
    - min-height - Complete - §7.14.8 - no no - no - no  
    - min-width - Complete - §7.14.9 - no no - no - no  
    - scaling - Extended - §7.14.10 - no yes - yes - yes  
    - scaling-method - Extended - §7.14.11 - no no - no - no  
    - width - Basic - §7.14.12 - yes yes - yes - yes  
    - Block and Line-related Properties (§7.15)
    - hyphenation-keep - Extended - §7.15.1 - no no - no - no  
    - hyphenation-ladder-count - Extended - §7.15.2 - no yes - yes - yes  
    - last-line-end-indent - Extended - §7.15.3 - no yes - yes - yes  
    - line-height - Basic - §7.15.4 - yes yes - yes - yes  
    - line-height-shift-adjustment - Extended - §7.15.5 - no no - no - yes  
    - line-stacking-strategy - Basic - §7.15.6 - no partial - partial - partial -
      -
    • - [0.93 and later] value "line-height" not supported
    • -
    provisional-label-separationBasic§7.28.3yesyesyesyes 
    - linefeed-treatment - Extended - §7.15.7 - no yes - yes - yes  
    - white-space-treatment - Extended - §7.15.8 - no partial - partial - partial -
      -
    • - [0.93 and later] inline elements may interfere with correct handling of this property - in some cases
    • -
    provisional-distance-between-startsBasic§7.28.4yesyesyesyes 
    - text-align - Basic - §7.15.9 - partial partial - partial - partial -
      -
    • - Only start, end, center and justify are supported
    • -
    ref-idExtended§7.28.5yesyesyesyes 
    - text-align-last - Extended - §7.15.10 - partial partial - partial - partial -
      -
    • - Only start, end, center and justify are supported
    • -
    score-spacesExtended§7.28.6nononono 
    - text-indent - Basic - §7.15.11 - yes yes - yes - yes  
    - white-space-collapse - Extended - §7.15.12 - yes yes - yes - yes  
    - wrap-option - Basic - §7.15.13 - yes partial - partial - partial -
      -
    • - [0.93 and later] Only supported on fo:block.
    • -
    srcBasic§7.28.7yesyesyesyes 
    - Character Properties (§7.16) visibilityExtended§7.28.8nononono 
    - character - Basic - §7.16.1 - yes yes - yes - yes  
    - letter-spacing - Extended - §7.16.2 - yes yes - yes - yes  
    - suppress-at-line-break - Extended - §7.16.3 - no no - no - no  
    - text-decoration - Extended - §7.16.4 - yes yes - yes - yes  
    - text-shadow - Extended - §7.16.5 - no no - no - no  
    - text-transform - Extended - §7.16.6 - no yes - yes - yes  
    - treat-as-word-space - Extended - §7.16.7 - no no - no - no  
    - word-spacing - Extended - §7.16.8 - no yes - yes - yes   z-indexExtended§7.28.9nononono 
    - Color-related Properties (§7.17) Shorthand Properties (§7.29)
    - color - Basic - §7.17.1 - yes yes - yes - yes  
    - color-profile-name - Extended - §7.17.2 - no no - no - no  
    - rendering-intent - Extended - §7.17.3 - no no - no - no   backgroundComplete§7.29.1nononono 
    - Float-related Properties (§7.18) background-positionComplete§7.29.2noyesyesyes 
    - clear - Extended - §7.18.1 - no no - no - no  
    - float - Extended - §7.18.2 - no no - no - no  
    - intrusion-displace - Extended - §7.18.3 - no no - no - no   borderComplete§7.29.3noyesyesyes 
    - Keeps and Breaks Properties (§7.19) border-bottomComplete§7.29.4yesyesyesyes 
    - break-after - Basic - §7.19.1 - yes yes - yes - yes  
    - break-before - Basic - §7.19.2 - yes yes - yes - yes  
    - keep-together - Extended - §7.19.3 - partial partial - partial - partial border-colorComplete§7.29.5partialyesyesyes
      -
    • - [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.20.5] only one value allowed
    - keep-with-next - Basic - §7.19.4 - partial 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 - 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.
    • -
    - orphans - Basic - §7.19.6 - no yes - yes - yes  
    - widows - Basic - §7.19.7 - no yes - yes - yes   border-leftComplete§7.29.6yesyesyesyes 
    - Layout-related Properties (§7.20) border-rightComplete§7.29.7yesyesyesyes 
    - clip - Extended - §7.20.1 - no no - no - no  
    - overflow - Basic - §7.20.2 - no yes - yes - yes  
    - reference-orientation - Extended - §7.20.3 - no yes - yes - yes border-styleComplete§7.29.8partialyesyesyes
      -
    • - [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.
    • -
    - span - Extended - §7.20.4 - yes yes - yes - yes   border-spacingComplete§7.29.9noyesyesyes 
    - Leader and Rule Properties (§7.21) border-topComplete§7.29.10yesyesyesyes 
    - leader-alignment - Extended - §7.21.1 - partial no - no - no -
      -
    • - [0.20.5] not value "page"
    • -
    • - [0.93 and later] Not supported
    • -
    border-widthComplete§7.29.11yesyesyesyes 
    - leader-pattern - Basic - §7.21.2 - partial yes - yes - yes -
      -
    • - [0.20.5] not value "use-content"
    • -
    • - [0.93 and later] Value "use-content" does not work in all circumstances.
    • -
    cueComplete§7.29.12nananana 
    - leader-pattern-width - Extended - §7.21.3 - yes yes - yes - yes  
    - leader-length - Basic fontComplete§7.29.13nopartialpartialpartial - §7.21.4 - partial yes - yes - yes
      -
    • - [0.20.5] leader-length.minimum is not used at all
    • -
    - rule-style - Basic - §7.21.5 - yes yes - yes - yes  
    - rule-thickness - Basic - §7.21.6 - yes yes - yes - yes  
    - Properties for Dynamic Effects Formatting Objects (§7.22)
    - active-state - Extended - §7.22.1 - no no - no - no  
    - auto-restore - Extended - §7.22.2 - no no - no - no  
    - case-name - Extended - §7.22.3 - no no - no - no  
    - case-title - Extended - §7.22.4 - no no - no - no  
    - destination-placement-offset - Extended - §7.22.5 - no no - no - no  
    - external-destination - Basic - §7.22.6 - yes yes - yes - yes  
    - indicate-destination - Extended - §7.22.7 - no no - no - no  
    - internal-destination - Extended - §7.22.8 - yes yes - yes - yes  
    - show-destination - Extended - §7.22.9 - no no - no - no  
    - starting-state - Extended - §7.22.10 - no partial - partial - partial marginComplete§7.29.14partialyesyesyes
      -
    • [0.93 and later] support for starting-state on fo:bookmark
    • -
    - switch-to - Extended - §7.22.11 - no no - no - no  
    - target-presentation-context - Extended - §7.22.12 - no no - no - no  
    - target-processing-context - Extended - §7.22.13 - no no - no - no  
    - target-stylesheet - Extended - §7.22.14 - no no - no - no  
    - Properties for Markers (§7.23) paddingComplete§7.29.15partialyesyesyes +
      +
    • [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
    • +
    +
    - marker-class-name - Extended - §7.23.1 - no yes - yes - yes  
    - retrieve-class-name - Extended - §7.23.2 - no yes - yes - yes  
    - retrieve-position - Extended - §7.23.3 - no yes - yes - yes  
    - retrieve-boundary - Extended - §7.23.4 - no yes - yes - yes   page-break-afterComplete§7.29.16noyesyesyes 
    - Properties for Number to String Conversion (§7.24) page-break-beforeComplete§7.29.17noyesyesyes 
    - format - Basic - §7.24.1 - no yes - yes - yes  
    - grouping-separator - Extended - §7.24.2 - no no - no - no  
    - grouping-size - Extended - §7.24.3 - no no - no - no  
    - letter-value - Basic - §7.24.4 - no no - no - no   page-break-insideComplete§7.29.18noyesyesyes 
    - Pagination and Layout Properties (§7.25) pauseComplete§7.29.19nananana 
    - blank-or-not-blank - Extended - §7.25.1 - yes yes - yes - yes  
    - column-count - Extended - §7.25.2 - yes yes - yes - yes  
    - column-gap - Extended - §7.25.3 - yes yes - yes - yes  
    - extent - Extended - §7.25.4 - yes yes - yes - yes  
    - flow-name - Basic - §7.25.5 - yes yes - yes - yes  
    - force-page-count - Extended - §7.25.6 - no yes - yes - yes  
    - initial-page-number - Basic - §7.25.7 - yes yes - yes - yes  
    - master-name - Basic - §7.25.8 - yes yes - yes - yes  
    - master-reference - Basic - §7.25.9 - yes yes - yes - yes  
    - maximum-repeats - Extended - §7.25.10 - yes yes - yes - yes  
    - media-usage - Extended - §7.25.11 - no no - no - no  
    - odd-or-even - Extended - §7.25.12 - yes yes - yes - yes  
    - page-height - Basic - §7.25.13 - yes yes - yes - yes  
    - page-position - Extended - §7.25.14 - partial yes - yes - yes positionComplete§7.29.20partialyesyesyes
      -
    • - [0.20.5] "last" isn't implemented!
    • -
    - page-width - Basic - §7.25.15 - yes yes - yes - yes  
    - precedence - Extended - §7.25.16 - no yes - yes - yes  
    - region-name - Basic - §7.25.17 - yes yes - yes - yes  
    - Table Properties (§7.26) sizeComplete§7.29.21nononono 
    - border-after-precedence - Basic - §7.26.1 - no no - no - no  
    - border-before-precedence - Basic - §7.26.2 - no no - no - no  
    - border-collapse - Extended - §7.26.3 vertical-alignComplete§7.29.22partialnoyesyespartialpartialpartial
      -
    • [0.94 and later] Some small limitations
    • +
    • [0.20.5] Only works as a shorthand for baseline-shift property.
    • + +
    • [0.94 and later] Percentages are not supported, yet.
    - border-end-precedence - Basic - §7.26.4 - no no - no - no  
    - border-separation - Extended - §7.26.5 - no yes - yes - yes  
    - border-start-precedence - Basic - §7.26.6 - no no - no - no  
    - caption-side - Complete - §7.26.7 - no no - no - no  
    - column-number - Basic - §7.26.8 - no yes - yes - yes  
    - column-width - Basic - §7.26.9 - partial yes - yes - yes -
      -
    • - [0.20.5] "percentage" not implemented. Workaround is to use the XSL-FO "proportional-column-width" function.
    • -
    white-spaceComplete§7.29.23noyesyesyes 
    - empty-cells - Extended - §7.26.10 - no yes - yes - yes  
    - ends-row - Extended - §7.26.11 - no yes - yes - yes  
    - number-columns-repeated - Basic - §7.26.12 - no yes - yes - yes  
    - number-columns-spanned - Basic - §7.26.13 - yes yes - yes - yes  
    - number-rows-spanned - Basic - §7.26.14 - yes yes - yes - yes  
    - starts-row - Extended - §7.26.15 - no yes - yes - yes  
    - table-layout - Extended - §7.26.16 - no no - no - no  
    - table-omit-footer-at-break - Extended - §7.26.17 - yes yes - yes - yes  
    - table-omit-header-at-break - Extended - §7.26.18 - yes yes - yes - yes   xml:langComplete§7.29.24noyesyesyes[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
    - Writing-mode-related Properties (§7.27) 0.20.5 (ancient)0.94 (stable)0.95 (beta)develop- ment
    - direction - Basic - §7.27.1 - no no - no - no  
    - glyph-orientation-horizontal - Extended - §7.27.2 - no no - no - no  
    - glyph-orientation-vertical - Extended - §7.27.3 - no no - no - no  
    - text-altitude - Extended - §7.27.4 - no no - no - no  
    - text-depth - Extended - §7.27.5 - no no - no - no  
    - unicode-bidi - Extended - §7.27.6 - no no - no - no  
    - writing-mode - Basic - §7.27.7 - no no - no - no   Number Functions (§5.10.1)
    - Miscellaneous Properties (§7.28) floorBasic§5.10.1yesyesyesyes 
    - content-type - Extended - §7.28.1 - no no - no - no  
    - id - Basic - §7.28.2 - yes partial - partial - partial -
      -
    • [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.
    • -
    ceilingBasic§5.10.1yesyesyesyes 
    - provisional-label-separation - Basic - §7.28.3 - yes yes - yes - yes  
    - provisional-distance-between-starts - Basic - §7.28.4 - yes yes - yes - yes  
    - ref-id - Extended - §7.28.5 - yes yes - yes - yes  
    - score-spaces - Extended - §7.28.6 - no no - no - no  
    - src - Basic - §7.28.7 - yes yes - yes - yes  
    - visibility - Extended - §7.28.8 - no no - no - no  
    - z-index - Extended - §7.28.9 - no no - no - no   roundBasic§5.10.1yesyesyesyes 
    - Shorthand Properties (§7.29) minBasic§5.10.1yesyesyesyes 
    - background - Complete - §7.29.1 - no no - no - no  
    - background-position - Complete - §7.29.2 - no yes - yes - yes  
    - border - Complete - §7.29.3 - no yes - yes - yes  
    - border-bottom - Complete - §7.29.4 - yes yes - yes - yes  
    - border-color - Complete - §7.29.5 - partial yes - yes - yes -
      -
    • - [0.20.5] only one value allowed
    • -
    maxBasic§5.10.1yesyesyesyes 
    - border-left - Complete - §7.29.6 - yes yes - yes - yes  
    - border-right - Complete - §7.29.7 - yes yes - yes - yes  
    - border-style - Complete - §7.29.8 - partial yes - yes - yes -
      -
    • - [0.20.5] only "solid" works
    • -
    absBasic§5.10.1yesyesyesyes 
    - border-spacing - Complete - §7.29.9 - no yes - yes - yes  
    - border-top - Complete - §7.29.10 - yes yes - yes - yes  
    - border-width - Complete - §7.29.11 - yes yes - yes - yes  
    - cue - Complete - §7.29.12 - na na - na - na  
    - font - Complete - §7.29.13 - no partial - partial - partial -
      -
    • - [0.93 and later] Enum values other than "inherit" not yet supported.
    • -
    Color Functions (§5.10.2)
    - margin - Complete - §7.29.14 - partial yes - yes - yes -
      -
    • - [0.20.5] only on pages and regions
    • -
    rgbBasic§5.10.2yesyesyesyes 
    - padding - Complete - §7.29.15 - partial yes - 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 - yes  
    - page-break-before - Complete - §7.29.17 - no yes - yes - yes  
    - page-break-inside - Complete - §7.29.18 - no yes - yes - yes  
    - pause - Complete - §7.29.19 - na na - na - na  
    - position - Complete - §7.29.20 - partial yes - yes - yes -
      -
    • - [0.20.5] "inherit" not handled
    • -
    rgb-iccBasic§5.10.2noyesyesyes 
    - size - Complete - §7.29.21 - no no - no - no  
    - vertical-align - Complete - §7.29.22 - partial partial - partial - partial -
      -
    • - [0.20.5] Only works as a shorthand for baseline-shift property.
    • -
    • - [0.93 and later] Percentages are not supported, yet.
    • -
    system-colorBasic§5.10.2noyesyesyes 
    - white-space - Complete - §7.29.23 - no yes - yes - yes  
    - xml:lang - Complete - §7.29.24 - no no - no - yes [dev] Very basic parsing; no validation of the specified value.Font Functions (§5.10.3)
    -

    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 system-fontBasic§5.10.3nononono 
    - 0.20.5 (previous) - 0.93 (stable) 0.94 (stable) - develop- ment Property Value Functions (§5.10.4)
    - Number Functions (§5.10.1) inherited-property-valueBasic + §5.10.4yesyesyesyes 
    - floor - Basic - §5.10.1 - yes - yes yes - yes  
    - ceiling - Basic - §5.10.1 - yes - yes yes - yes  
    - round - Basic - §5.10.1 - yes - yes yes - yes  
    - min - Basic - §5.10.1 - yes - yes yes - yes  
    - max - Basic - §5.10.1 - yes - yes yes - yes  
    - abs - Basic - §5.10.1 - yes - yes yes - yes   label-endBasic + §5.10.4yesyesyesyes 
    - Color Functions (§5.10.2) body-startBasic + §5.10.4yesyesyesyes 
    - rgb - Basic - §5.10.2 - yes - yes yes - yes  
    - rgb-icc - Basic - §5.10.2 - no - yes yes - yes  
    - system-color - Basic - §5.10.2 - no - yes yes - yes   from-parentBasic + §5.10.4yesyesyesyes 
    - Font Functions (§5.10.3) from-nearest-specified-valueBasic + §5.10.4yesyesyesyes 
    - system-font - Basic - §5.10.3 - no - no from-table-columnBasic + §5.10.4no - no   yesyesyes 
    - Property Value Functions (§5.10.4) proportional-column-widthBasic + §5.10.4yesyesyesyes 
    - inherited-property-value - Basic - §5.10.4 - yes - yes yes - yes  
    - label-end - Basic - §5.10.4 - yes - yes yes - yes  
    - body-start - Basic - §5.10.4 - yes - yes yes - yes  
    - from-parent - Basic - §5.10.4 - yes - yes yes - yes  
    - from-nearest-specified-value - Basic - §5.10.4 - yes - yes yes - yes  
    - from-table-column - Basic - §5.10.4 - no - yes yes - yes  
    - proportional-column-width - Basic - §5.10.4 - yes - yes yes - yes  
    - merge-property-values - Basic - §5.10.4 - no - no no - no   merge-property-valuesBasic + §5.10.4nononono 
    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").
    • 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/download.xml b/src/documentation/content/xdocs/download.xml index 40e42236b..f0a2a0a61 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/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/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/src/documentation/content/xdocs/quickstartguide.xml b/src/documentation/content/xdocs/quickstartguide.xml new file mode 100644 index 000000000..ca205f5a2 --- /dev/null +++ b/src/documentation/content/xdocs/quickstartguide.xml @@ -0,0 +1,124 @@ + + + + + +
      + FOP: Quick Start Guide + Everything you need to start using and appreciating Apache FOP quickly. + $Revision: 627324 $ +
      + +
      + FOP Essentials +

      The goal of this 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 (you can skip this step if you download the binary distribution!)
      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:

      +
        +
      • Calling FOP from a Java Application
      • +
      • Using FOP in Servlets
      • +
      • Using FOP in an 'Ant' Build Script
      • +
      • XSL-FO Compliance (what FOP supports and what it doesn't)
      • +
      • FAQs
      • +
      • Getting Help
      • +
      • Mailing Lists
      • +
      +

      + Once you've familiarized yourself with the basics, you can get more detailed information, + in the detailed FOP product documentation. +

      +
      + +
      + Hello World with FOP +

      + This section walks you through a "Hello World!" page with Apache FOP. We're assuming you + download the binary distribution and that you have a Java Runtime Environment (version 1.4 + or later) installed. +

      +
        +
      1. + Unpack the downloaded binary distribution to a directory of your choice (for example, + C:\FOP if you're on Windows). Let's call that + directory <fop-home>. +
      2. +
      3. + Get a command prompt in the <fop-home> directory and write:
        + Windows: fop -fo examples/fo/basic/readme.fo -awt
        + Unix: ./fop.sh -fo examples/fo/basic/readme.fo -awt
        +
      4. +
      5. + If all went well, this should open a window showing you a "readme"-style document. + This is just to verify that FOP runs correctly. +
      6. +
      7. + Now, take your favorite XML editor and create a small XML file like the following. Replace + "Frank" with your own first name to make it a bit more personal and save it as + name.xml:
        + Frank]]> +
      8. +
      9. + To produce a PDF file from this XML file, we need an XSLT stylesheet that converts the + XML to XSL-FO. This is the first step in the processing chain. The second step will be + done by FOP when it reads the generated XSL-FO document and formats it to a PDF document. + You can copy the following minimal XSLT stylesheet, which takes your first name and + produces a "Hello World!"-style document (save it as name2fo.xsl):
        + + + + + + + + + + + + + + Hello, ! + + + + + +]]> + +
      10. +
      11. + Finally, let's put the previous two steps together: Go back to the command prompt and + enter the following command:
        + Windows: fop -xml name.xml -xsl name2fo.xsl -pdf name.pdf
        + Unix: ./fop.sh -xml name.xml -xsl name2fo.xsl -pdf name.pdf
        +
      12. +
      13. + You've produced your first PDF with Apache FOP! Please open name.pdf + in your favorite PDF viewer. +
      14. +
      +
      + +
      diff --git a/src/documentation/content/xdocs/site.xml b/src/documentation/content/xdocs/site.xml index 7914d5ef2..18716903c 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. --> + - @@ -57,12 +58,12 @@ --> - + - - + + @@ -89,16 +90,16 @@ - + - - + + @@ -125,9 +126,9 @@ - + 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 bb2fd7e72..a42fc9bd7 100644 --- a/src/documentation/content/xdocs/tabs.xml +++ b/src/documentation/content/xdocs/tabs.xml @@ -21,14 +21,8 @@ - + - - diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index 23cb87708..bd9f72fde 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,11 @@ 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 + conforming to given style-guides. See his home + page for more information.
      • 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 +108,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 +126,7 @@
        • Jordan Naftolin
        • Arved Sandstrom
        • Eric Schaeffer
        • +
        • Oleg Tkachenko (OT)
        • Art Welch
        • Peter B. West
        @@ -264,7 +269,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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..300d54234 --- /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 + + + + + + + + + + + + + + + + + + + + + + + + +
      diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_1.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_1.xml deleted file mode 100644 index 052eaa1c9..000000000 --- a/test/layoutengine/standard-testcases/table_border-collapse_collapse_1.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - - -

      - This test checks tables with collapse border model. Simple cell borders to start with. -

      -
      - - - - - - - - - - - block before table - - normal border here - - - - - - - - - - - - - cell1 cell1 cell1 cell1 cell1 cell1 cell1 - - - cell2 cell2 cell2 cell2 cell2 cell2 cell2 - - - - - cell3 - - - cell4 - - - - - block after table - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      diff --git a/test/layoutengine/standard-testcases/table_border-collapse_collapse_2.xml b/test/layoutengine/standard-testcases/table_border-collapse_collapse_2.xml deleted file mode 100644 index cd2575822..000000000 --- a/test/layoutengine/standard-testcases/table_border-collapse_collapse_2.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - -

      - This test checks tables with collapse border model. Simple cell borders to start with. -

      -
      - - - - - - - - - - block before table - - - - - - - cell1 - - - cell2 - - - - - spanned - - - - - cell4 - - - cell5 - - - - - block after table - - - - - - - -
      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_border_padding.xml b/test/layoutengine/standard-testcases/table_border_padding.xml index 7099d5dd1..385242903 100644 --- a/test/layoutengine/standard-testcases/table_border_padding.xml +++ b/test/layoutengine/standard-testcases/table_border_padding.xml @@ -66,8 +66,8 @@ - - + + @@ -95,7 +95,7 @@ - + @@ -106,7 +106,7 @@ - + @@ -121,19 +121,27 @@ - + + + - + - + + - + + + - + + + + 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 70990de62..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 @@ -144,9 +144,9 @@ 3 - - - + + + diff --git a/test/layoutengine/standard-testcases/table_row-height_break.xml b/test/layoutengine/standard-testcases/table_row-height_break.xml new file mode 100644 index 000000000..b6c7d8d37 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_row-height_break.xml @@ -0,0 +1,87 @@ + + + + + +

      + This test checks that a forced break is still taken into account when the minimal height of a + row is not reached yet. +

      +
      + + + + + + + + + + The first row of the following table has a fixed height, and a forced break + occurs before this height is reached. + + + + + Cell 1 + Should be on a new page + + + Cell 2 + + + + + Cell 3 + + + Cell 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      -- cgit v1.2.3 From cfa5ebf3a6e05964b07c7adc06f68d80c2c911bc Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 1 Apr 2008 15:23:19 +0000 Subject: Merged revisions 642923-642924,642927 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r642923 | jeremias | 2008-03-31 09:39:49 +0100 (Mon, 31 Mar 2008) | 1 line Fixed possible NullPointerException in AFM kerning table build code. ........ r642924 | jeremias | 2008-03-31 09:40:48 +0100 (Mon, 31 Mar 2008) | 1 line 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. ........ r642927 | jeremias | 2008-03-31 09:48:34 +0100 (Mon, 31 Mar 2008) | 1 line Updated XG Commons for revision: http://svn.apache.org/viewvc?rev=642925&view=rev ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@643443 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.4svn.jar | Bin 511830 -> 512165 bytes src/java/org/apache/fop/fonts/type1/AFMFile.java | 4 +-- .../apache/fop/fonts/type1/Type1FontLoader.java | 27 +++++++++++++++------ 3 files changed, 22 insertions(+), 9 deletions(-) (limited to 'src/java') diff --git a/lib/xmlgraphics-commons-1.4svn.jar b/lib/xmlgraphics-commons-1.4svn.jar index cb386bd59..d7f9092ea 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/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) { 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 918928b5b464c3ce55af20b608f78a5a70da1b95 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 3 Apr 2008 09:40:10 +0000 Subject: Merged revisions 644208,644213 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r644208 | jeremias | 2008-04-03 09:05:14 +0100 (Thu, 03 Apr 2008) | 11 lines 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. ........ r644213 | jeremias | 2008-04-03 09:13:50 +0100 (Thu, 03 Apr 2008) | 1 line Oops. Fixed a last-minute change that broke the build. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@644243 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/java') 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..ccff3baa1 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, 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 a008177c1..c3cbb0103 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,10 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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 c95c1382d5062b466dd876e3152886705a56b724 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 4 Apr 2008 12:57:47 +0000 Subject: Merged revisions 644691,644697 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r644691 | jeremias | 2008-04-04 13:19:50 +0100 (Fri, 04 Apr 2008) | 3 lines Bugzilla #44743: Added a public accessor for reference to the current page to PDFGraphics2D. Submitted by: Yegor Kozlov ........ r644697 | jeremias | 2008-04-04 13:40:22 +0100 (Fri, 04 Apr 2008) | 2 lines 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/branches/Temp_AFPGOCAResources@644700 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/svg/PDFGraphics2D.java | 20 +++++++++++++------- status.xml | 3 +++ 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index f6a7cbc3b..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; @@ -304,7 +302,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 +396,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 +964,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(); @@ -1512,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(); @@ -1577,7 +1583,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { } currentStream.write("ET\n"); - } + }*/ /** * Fills the interior of a Shape using the settings of the diff --git a/status.xml b/status.xml index c3cbb0103..1d2f91e60 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,9 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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 7045f7e0124c6a6f00736b0d1d81f89824fd1271 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 11 Apr 2008 17:17:14 +0000 Subject: Some fixes to apply but committed in preparation for http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback merge into trunk. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@647228 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/render/afp/AFPGraphics2DAdapter.java | 10 +- .../org/apache/fop/render/afp/AFPRenderer.java | 74 +++-- .../fop/render/afp/AFPRendererConfigurator.java | 45 +-- .../org/apache/fop/render/afp/AFPSVGHandler.java | 22 +- .../org/apache/fop/render/afp/DataObjectInfo.java | 245 ++++++++++++++ .../fop/render/afp/DataObjectParameters.java | 173 ---------- .../org/apache/fop/render/afp/ImageObjectInfo.java | 163 ++++++++++ .../fop/render/afp/ImageObjectParameters.java | 138 -------- .../org/apache/fop/render/afp/ResourceInfo.java | 164 ++++++++++ .../org/apache/fop/render/afp/ResourceLevel.java | 123 ------- .../fop/render/afp/extensions/AFPElement.java | 7 +- .../render/afp/extensions/AFPElementMapping.java | 10 +- .../apache/fop/render/afp/modca/AFPDataStream.java | 291 ++++++++++------- .../fop/render/afp/modca/AbstractAFPObject.java | 8 +- .../render/afp/modca/AbstractNamedAFPObject.java | 1 - .../fop/render/afp/modca/AbstractPageObject.java | 5 +- .../afp/modca/AbstractResourceGroupContainer.java | 163 +++++++++- .../afp/modca/AbstractStructuredAFPObject.java | 78 +++-- .../render/afp/modca/ActiveEnvironmentGroup.java | 5 +- .../apache/fop/render/afp/modca/IncludeObject.java | 84 ++++- .../fop/render/afp/modca/MapDataResource.java | 57 +++- .../fop/render/afp/modca/ObjectContainer.java | 171 ++++++++++ .../fop/render/afp/modca/ObjectTypeRegistry.java | 204 ++++++++++++ .../apache/fop/render/afp/modca/PageSegment.java | 35 +- .../fop/render/afp/modca/PresentationTextData.java | 163 ++++------ .../org/apache/fop/render/afp/modca/Registry.java | 353 --------------------- .../render/afp/modca/ResourceEnvironmentGroup.java | 3 +- .../apache/fop/render/afp/modca/ResourceGroup.java | 222 +++++-------- .../fop/render/afp/modca/ResourceObject.java | 53 ++-- .../modca/triplets/FullyQualifiedNameTriplet.java | 37 ++- .../triplets/ObjectClassificationTriplet.java | 59 +++- .../fop/render/afp/modca/triplets/StrucFlgs.java | 80 +++++ 32 files changed, 1888 insertions(+), 1358 deletions(-) create mode 100644 src/java/org/apache/fop/render/afp/DataObjectInfo.java delete mode 100644 src/java/org/apache/fop/render/afp/DataObjectParameters.java create mode 100644 src/java/org/apache/fop/render/afp/ImageObjectInfo.java delete mode 100644 src/java/org/apache/fop/render/afp/ImageObjectParameters.java create mode 100644 src/java/org/apache/fop/render/afp/ResourceInfo.java delete mode 100644 src/java/org/apache/fop/render/afp/ResourceLevel.java create mode 100644 src/java/org/apache/fop/render/afp/modca/ObjectContainer.java create mode 100644 src/java/org/apache/fop/render/afp/modca/ObjectTypeRegistry.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/Registry.java create mode 100644 src/java/org/apache/fop/render/afp/modca/triplets/StrucFlgs.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index 1abe7c0d1..af8c7fedf 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -52,10 +52,12 @@ public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter { int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, gray, false); - //TODO: uri - String uri = null; - java.util.Map foreignAttributes = null; - afp.drawBufferedImage(uri, bi, resolution, x, y, width, height, foreignAttributes); + + //TODO: AC - fix +// String uri = null; +// java.util.Map foreignAttributes = null; +// ImageInfo imageInfo = new ImageInfo(); +// afp.drawBufferedImage(uri, bi, resolution, x, y, width, height, foreignAttributes); } } diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index cb3d3a433..e50e77830 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -26,6 +26,7 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; 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; @@ -87,6 +88,7 @@ import org.apache.fop.render.afp.fonts.FopCharacterSet; import org.apache.fop.render.afp.fonts.OutlineFont; import org.apache.fop.render.afp.modca.AFPConstants; import org.apache.fop.render.afp.modca.AFPDataStream; +import org.apache.fop.render.afp.modca.AbstractNamedAFPObject; import org.apache.fop.render.afp.modca.ImageObject; import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.fop.render.afp.modca.PageObject; @@ -969,7 +971,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } else if (img instanceof ImageRendered) { ImageRendered imgRend = (ImageRendered)img; RenderedImage ri = imgRend.getRenderedImage(); - drawBufferedImage(uri, ri, getResolution(), + drawBufferedImage(info, ri, getResolution(), posInt.x + currentIPPosition, posInt.y + currentBPPosition, posInt.width, @@ -983,17 +985,26 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int afpw = mpts2units(posInt.getWidth()); int afph = mpts2units(posInt.getHeight()); int afpres = getResolution(); - ImageObjectParameters params = new ImageObjectParameters( - uri, afpx, afpy, afpw, afph, afpres, afpres, - buf, - ccitt.getSize().getWidthPx(), - ccitt.getSize().getHeightPx(), - colorImages, bitsPerPixel - ); - params.setCompression(ccitt.getCompression()); - params.setResourceLevelFromForeignAttributes(foreignAttributes); -// params.setData(buf); - afpDataStream.createImageObject(params); + + // create image object parameters + ImageObjectInfo imageObjectInfo = new ImageObjectInfo(); + imageObjectInfo.setUri(uri); + imageObjectInfo.setMimeType(info.getMimeType()); + imageObjectInfo.setX(afpx); + imageObjectInfo.setY(afpy); + imageObjectInfo.setWidth(afpw); + imageObjectInfo.setHeight(afph); + imageObjectInfo.setWidthRes(afpres); + imageObjectInfo.setHeightRes(afpres); + imageObjectInfo.setData(buf); + imageObjectInfo.setDataHeight(ccitt.getSize().getHeightPx()); + imageObjectInfo.setDataWidth(ccitt.getSize().getWidthPx()); + imageObjectInfo.setColor(colorImages); + imageObjectInfo.setBitsPerPixel(bitsPerPixel); + imageObjectInfo.setCompression(ccitt.getCompression()); + imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); + + afpDataStream.createObject(imageObjectInfo); // ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph, @@ -1193,7 +1204,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @param h * the height of the viewport (in mpt) */ - public void drawBufferedImage(String uri, RenderedImage image, int imageRes, int x, + public void drawBufferedImage(ImageInfo info, RenderedImage image, int imageRes, int x, int y, int w, int h, Map foreignAttributes) { // int afpx = mpts2units(x); // int afpy = mpts2units(y); @@ -1213,19 +1224,25 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // String uri = null;// = image.getProperty(name); // String uri = image.getProperty(name); // Generate image - ImageObjectParameters params = new ImageObjectParameters( - uri, - mpts2units(x), mpts2units(y), - mpts2units(w), mpts2units(h), - imageRes, imageRes, - baout.toByteArray(), - image.getWidth(), - image.getHeight(), - colorImages, - bitsPerPixel); - - params.setResourceLevelFromForeignAttributes(foreignAttributes); - IncludeObject io = afpDataStream.createImageObject(params); + + // create image object parameters + ImageObjectInfo imageObjectInfo = new ImageObjectInfo(); + imageObjectInfo.setUri(info.getOriginalURI()); + imageObjectInfo.setMimeType(info.getMimeType()); + imageObjectInfo.setX(mpts2units(x)); + imageObjectInfo.setY(mpts2units(y)); + imageObjectInfo.setWidth(mpts2units(w)); + imageObjectInfo.setHeight(mpts2units(h)); + imageObjectInfo.setWidthRes(imageRes); + imageObjectInfo.setHeightRes(imageRes); + imageObjectInfo.setData(baout.toByteArray()); + imageObjectInfo.setDataHeight(image.getHeight()); + imageObjectInfo.setDataWidth(image.getWidth()); + imageObjectInfo.setColor(colorImages); + imageObjectInfo.setBitsPerPixel(bitsPerPixel); + imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); + + AbstractNamedAFPObject obj = afpDataStream.createObject(imageObjectInfo); // ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, // afph, afpres, afpres); // io.setImageParameters(imageResolution, imageResolution, @@ -1586,9 +1603,10 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (content != null) { afpDataStream.createNoOperation(content); } - } else if (AFPElementMapping.RESOURCE.equals(element)) { - log.info("resource: " + attachment); } +// else if (AFPElementMapping.RESOURCE.equals(element)) { +// log.info("resource: " + attachment); +// } } } } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index cde464ba5..f83aaf9f6 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -19,6 +19,7 @@ package org.apache.fop.render.afp; +import java.io.File; import java.util.List; import org.apache.avalon.framework.configuration.Configuration; @@ -224,7 +225,8 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { LogUtil.handleException(log, e, userAgent.getFactory().validateUserConfigStrictly()); } - + + // image information Configuration imagesCfg = cfg.getChild("images"); if (!"color".equalsIgnoreCase(imagesCfg.getAttribute("mode", "b+w"))) { afpRenderer.setBitsPerPixel(imagesCfg.getAttributeAsInteger("bits-per-pixel", 8)); @@ -232,35 +234,36 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { afpRenderer.setColorImages(true); } + // renderer resolution Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false); if (rendererResolutionCfg != null) { afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240)); } + // a default external resource group file setting + Configuration resourceGroupFileCfg = cfg.getChild("resource-group-file", false); + if (resourceGroupFileCfg != null) { + String resourceGroupDest = null; + try { + resourceGroupDest = resourceGroupFileCfg.getValue(); + } catch (ConfigurationException e) { + LogUtil.handleException(log, e, + userAgent.getFactory().validateUserConfigStrictly()); + } + File resourceGroupFile = new File(resourceGroupDest); + if (resourceGroupFile.canWrite()) { + afpRenderer.getAFPDataStream().setDefaultResourceGroupFile(resourceGroupFile); + } else { + log.warn("Unable to write to default external resource group file '" + + resourceGroupDest); + } + } + + // goca enabled Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false); if (gocaSupportCfg != null) { afpRenderer.setGOCAEnabled(true); } - -// Configuration resourceGroupsCfg = cfg.getChild("resource-groups", false); -// if (resourceGroupsCfg != null) { -// resourceGroupsCfg.getValue("print-file-level"); -// } -// if (externalCfg != null) { -// Configuration[] resourceGroups = externalCfg.getChildren("resource-groups"); -// for (int i = 0; i < resourceGroups.length; i++) { -// String resourceresourceGroups[i].getAttribute("url", null); -// Configuration resourceGroup = externalCfg.getChild("resource-group", false); -// } -// } -// Configuration externalResourceGroupCfg = cfg.getChild("external-resource-group", false); -// if (externalResourceGroupCfg != null) { -//// afpRenderer.setExternalResources(true); -// String resourceLibraryUrl = externalResourceGroupCfg.getAttribute("url", null); -// if (resourceLibraryUrl != null) { -// afpRenderer.setExternalResourceLibraryUrl(resourceLibraryUrl); -// } -// } } } } diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 1d469ea94..0d3b864b0 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -159,20 +159,26 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { int width = (int)Math.round((afpInfo.getWidth() * res) / 72000f); int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f); - DataObjectParameters params = new DataObjectParameters( - uri, x, y, width, height, res, res); - + // set the data object parameters + DataObjectInfo info = new DataObjectInfo(); + info.setUri(uri); + info.setX(x); + info.setY(y); + info.setWidth(width); + info.setHeight(height); + info.setWidthRes(res); + info.setHeightRes(res); Map/**/ foreignAttributes = (Map/**/)context.getProperty( RendererContextConstants.FOREIGN_ATTRIBUTES); - if (foreignAttributes != null) { - params.setResourceLevelFromForeignAttributes(foreignAttributes); + info.setResourceInfoFromForeignAttributes(foreignAttributes); } - IncludeObject includeObj = afpInfo.getAFPDataStream().createGraphicsObject(params); - GraphicsObject graphicsObj = (GraphicsObject)includeObj.getReferencedObject(); - graphics.setGraphicsObject(graphicsObj); + //TODO: AC - fix +// IncludeObject includeObj = afpInfo.getAFPDataStream().createObject(info); +// GraphicsObject graphicsObj = (GraphicsObject)includeObj.getReferencedObject(); +// graphics.setGraphicsObject(graphicsObj); try { root.paint(graphics); diff --git a/src/java/org/apache/fop/render/afp/DataObjectInfo.java b/src/java/org/apache/fop/render/afp/DataObjectInfo.java new file mode 100644 index 000000000..d363dd5ea --- /dev/null +++ b/src/java/org/apache/fop/render/afp/DataObjectInfo.java @@ -0,0 +1,245 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.File; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.render.afp.extensions.AFPElementMapping; +import org.apache.fop.render.afp.modca.ObjectTypeRegistry; +import org.apache.fop.render.afp.modca.ObjectTypeRegistry.ObjectType; +import org.apache.fop.util.QName; + +/** + * A list of parameters associated with an AFP data objects + */ +public class DataObjectInfo { + private static final ResourceInfo DEFAULT_RESOURCE_INFO = new ResourceInfo(); + + private String uri; + private int x; + private int y; + private int width; + private int height; + private int widthRes; + private int heightRes; + + // object type entry + private ObjectType objectTypeEntry; + private ResourceInfo resourceInfo = DEFAULT_RESOURCE_INFO; + + /** + * Sets the data object uri + * @param uri the data object uri + */ + protected void setUri(String uri) { + this.uri = uri; + } + + /** + * Sets the x position of the data object + * @param x the x position of the data object + */ + protected void setX(int x) { + this.x = x; + } + + /** + * Sets the y position of the data object + * @param y the y position of the data object + */ + protected void setY(int y) { + this.y = y; + } + + /** + * Sets the data object width + * @param width the width of the data object + */ + protected void setWidth(int width) { + this.width = width; + } + + /** + * Sets the data object height + * @param height the height of the data object + */ + protected void setHeight(int height) { + this.height = height; + } + + /** + * Sets the width resolution + * @param widthRes the width resolution + */ + protected void setWidthRes(int widthRes) { + this.widthRes = widthRes; + } + + /** + * Sets the height resolution + * @param heightRes the height resolution + */ + protected void setHeightRes(int heightRes) { + this.heightRes = heightRes; + } + + /** + * Default constructor + */ + public DataObjectInfo() { + } + + /** + * @return the uri of this data object + */ + public String getUri() { + return uri; + } + + /** + * @return the x coordinate of this data object + */ + public int getX() { + return x; + } + + /** + * @return the y coordinate of this data object + */ + public int getY() { + return y; + } + + /** + * @return the width of this data object + */ + public int getWidth() { + return width; + } + + /** + * @return the height of this data object + */ + public int getHeight() { + return height; + } + + /** + * @return the width resolution of this data object + */ + public int getWidthRes() { + return widthRes; + } + + /** + * @return the height resolution of this data object + */ + public int getHeightRes() { + return heightRes; + } + + /** + * Sets the object type entry + * @param entry the object type entry + */ + public void setObjectType(ObjectTypeRegistry.ObjectType entry) { + this.objectTypeEntry = entry; + } + + /** + * @return the object type entry + */ + protected ObjectType getObjectTypeEntry() { + return objectTypeEntry; + } + + /** + * @return returns the resource level at which this data object should reside + */ + public ResourceInfo getResourceInfo() { + return resourceInfo; + } + + /** + * Sets the resource level at which this object should reside + * @param resourceInfo the resource level at which this data object should reside + */ + public void setResourceInfo(ResourceInfo resourceInfo) { + this.resourceInfo = resourceInfo; + } + + + private static final String RESOURCE_NAME = "afp:resource-name"; + private static final String RESOURCE_LEVEL = "afp:resource-level"; + private static final String RESOURCE_GROUP_FILE = "afp:resource-group-file"; + + /** + * Sets the resource group settings using the given foreign attributes + * @param foreignAttributes a mapping of element attributes names to values + */ + public void setResourceInfoFromForeignAttributes(Map/**/ foreignAttributes) { + if (foreignAttributes != null) { + this.resourceInfo = new ResourceInfo(); + QName resourceNameKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_NAME); + String resourceName = (String)foreignAttributes.get(resourceNameKey); + if (resourceName != null) { + resourceInfo.setName(resourceName); + } + QName resourceLevelKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_LEVEL); + if (foreignAttributes.containsKey(resourceLevelKey)) { + String level = (String)foreignAttributes.get(resourceLevelKey); + if (resourceInfo.setLevel(level)) { + if (resourceInfo.isExternal()) { + QName resourceGroupFileKey = new QName(AFPElementMapping.NAMESPACE, + RESOURCE_GROUP_FILE); + String resourceExternalDest + = (String)foreignAttributes.get(resourceGroupFileKey); + File resourceExternalGroupFile = new File(resourceExternalDest); + if (resourceExternalGroupFile.canWrite()) { + resourceInfo.setExternalResourceGroupFile(resourceExternalGroupFile); + } + } + } else { + Log log = LogFactory.getLog("org.apache.fop.afp"); + log.warn("invalid resource level '" + level + + "', using default document level"); + } + } + } + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "uri=" + uri + + ", x=" + x + + ", y=" + y + + ", width=" + width + + ", height=" + height + + ", widthRes=" + widthRes + + ", heightRes=" + heightRes + + (resourceInfo != null ? ", resourceInfo=" + resourceInfo : "") + + (objectTypeEntry != null ? ", objectTypeEntry=" + objectTypeEntry : ""); + } +} diff --git a/src/java/org/apache/fop/render/afp/DataObjectParameters.java b/src/java/org/apache/fop/render/afp/DataObjectParameters.java deleted file mode 100644 index 2ec56a4e3..000000000 --- a/src/java/org/apache/fop/render/afp/DataObjectParameters.java +++ /dev/null @@ -1,173 +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; - -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.extensions.AFPElementMapping; -import org.apache.fop.util.QName; - -/** - * A list of parameters associated with an AFP data objects - */ -public class DataObjectParameters { - private static final ResourceLevel DEFAULT_RESOURCE_LEVEL = new ResourceLevel(); - - private String uri; - private int x; - private int y; - private int width; - private int height; - private int widthRes; - private int heightRes; - private ResourceLevel resourceLevel = DEFAULT_RESOURCE_LEVEL; - - /** - * Main constructor - * - * @param uri the data object uri - * @param x the data object x coordinate - * @param y the data object y coordinate - * @param width the data object width - * @param height the data object height - * @param widthRes the data object width resolution - * @param heightRes the data object height resolution - */ - public DataObjectParameters(String uri, int x, int y, int width, int height, - int widthRes, int heightRes) { - this.uri = uri; - this.x = x; - this.y = y; - this.width = width; - this.height = height; - this.widthRes = widthRes; - this.heightRes = heightRes; - } - - /** - * @return the uri of this data object - */ - public String getUri() { - return uri; - } - - /** - * @return the x coordinate of this data object - */ - public int getX() { - return x; - } - - /** - * @return the y coordinate of this data object - */ - public int getY() { - return y; - } - - /** - * @return the width of this data object - */ - public int getWidth() { - return width; - } - - /** - * @return the height of this data object - */ - public int getHeight() { - return height; - } - - /** - * @return the width resolution of this data object - */ - public int getWidthRes() { - return widthRes; - } - - /** - * @return the height resolution of this data object - */ - public int getHeightRes() { - return heightRes; - } - - /** - * @return returns the resource level at which this data object should reside - */ - public ResourceLevel getResourceLevel() { - return resourceLevel; - } - - /** - * Sets the resource level at which this object should reside - * @param resourceLevel the resource level at which this data object should reside - */ - public void setResourceLevel(ResourceLevel resourceLevel) { - this.resourceLevel = resourceLevel; - } - - /** - * Sets the resource level using the given foreign attributes - * @param foreignAttributes a mapping of element attributes names to values - */ - public void setResourceLevelFromForeignAttributes(Map/**/ foreignAttributes) { - if (foreignAttributes != null) { - QName resourceLevelKey = new QName( - AFPElementMapping.NAMESPACE, - "afp:resource-level"); - if (foreignAttributes.containsKey(resourceLevelKey)) { - String level = (String)foreignAttributes.get(resourceLevelKey); - this.resourceLevel = new ResourceLevel(); - if (resourceLevel.setLevel(level)) { - if (resourceLevel.isExternal()) { - QName resourceDestKey = new QName( - AFPElementMapping.NAMESPACE, - "afp:resource-dest"); - String resourceExternalDest - = (String)foreignAttributes.get(resourceDestKey); - resourceLevel.setExternalDest(resourceExternalDest); - } - } else { - Log log = LogFactory.getLog("org.apache.fop.afp"); - log.warn("invalid resource level '" + level - + "', using default document level"); - } - } - } - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "uri=" + uri - + ", x=" + x - + ", y=" + y - + ", width=" + width - + ", height=" + height - + ", widthRes=" + widthRes - + ", heightRes=" + heightRes - + (resourceLevel != null ? ", resourceLevel=" + resourceLevel : ""); - } -} diff --git a/src/java/org/apache/fop/render/afp/ImageObjectInfo.java b/src/java/org/apache/fop/render/afp/ImageObjectInfo.java new file mode 100644 index 000000000..16f9d1103 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/ImageObjectInfo.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; + +/** + * A list of parameters associated with an image + */ +public class ImageObjectInfo extends DataObjectInfo { + private int bitsPerPixel; + private boolean color; + private int compression = -1; + private byte[] data; + private int dataWidth; + private int dataHeight; + private String mimeType; + + /** + * Default constructor + */ + public ImageObjectInfo() { + } + + /** + * Sets the number of bits per pixel + * @param bitsPerPixel the number of bits per pixel + */ + public void setBitsPerPixel(int bitsPerPixel) { + this.bitsPerPixel = bitsPerPixel; + } + + /** + * Sets if this image is color + * @param color true if this is a color image + */ + public void setColor(boolean color) { + this.color = color; + } + + /** + * Sets the image data + * @param data the image data + */ + public void setData(byte[] data) { + this.data = data; + } + + /** + * Sets the image mime type + * @param mimeType the image mime type + */ + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + /** + * @return the number of bits used per pixel + */ + public int getBitsPerPixel() { + return bitsPerPixel; + } + + /** + * @return true if this is a color image + */ + public boolean isColor() { + return color; + } + + /** + * @return the image data + */ + public byte[] getData() { + return data; + } + + /** + * @return true of this image uses compression + */ + public boolean hasCompression() { + return compression > -1; + } + + /** + * @return the compression type + */ + public int getCompression() { + return compression; + } + + /** + * Sets the compression used with this image + * @param compression the type of compression used with this image + */ + public void setCompression(int compression) { + this.compression = compression; + } + + /** + * @return the image data width + */ + public int getDataWidth() { + return dataWidth; + } + + /** + * Sets the image data width + * @param imageDataWidth the image data width + */ + public void setDataWidth(int imageDataWidth) { + this.dataWidth = imageDataWidth; + } + + /** + * @return the image data height + */ + public int getDataHeight() { + return dataHeight; + } + + /** + * Sets the image data height + * @param imageDataHeight the image data height + */ + public void setDataHeight(int imageDataHeight) { + this.dataHeight = imageDataHeight; + } + + /** + * @return the mime type of this image + */ + public String getMimeType() { + return mimeType; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return super.toString() + + ", mimeType=" + mimeType + + ", dataWidth=" + dataWidth + + ", dataHeight=" + dataHeight + + ", color=" + color + + ", bitPerPixel=" + bitsPerPixel; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/ImageObjectParameters.java b/src/java/org/apache/fop/render/afp/ImageObjectParameters.java deleted file mode 100644 index 8b430f042..000000000 --- a/src/java/org/apache/fop/render/afp/ImageObjectParameters.java +++ /dev/null @@ -1,138 +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; - -/** - * A list of parameters associated with an image - */ -public class ImageObjectParameters extends DataObjectParameters { - private int bitsPerPixel; - private boolean color; - private int compression = -1; - private byte[] imageData; - private int imageDataWidth; - private int imageDataHeight; - - /** - * Main constructor - * - * @param uri the image uri - * @param x the image x coordinate - * @param y the image y coordinate - * @param width the image width - * @param height the image height - * @param widthRes the image width resolution - * @param heightRes the image height resolution - */ - public ImageObjectParameters(String uri, int x, int y, int width, int height, - int widthRes, int heightRes, byte[] imageData, - int imageDataWidth, int imageDataHeight, boolean color, int bitsPerPixel) { - super(uri, x, y, width, height, widthRes, heightRes); - this.imageData = imageData; - this.imageDataWidth = imageDataWidth; - this.imageDataHeight = imageDataHeight; - this.color = color; - this.bitsPerPixel = bitsPerPixel; - } - - /** - * @return the numner of bits used per pixel - */ - public int getBitsPerPixel() { - return bitsPerPixel; - } - - /** - * @return true if this is a color image - */ - public boolean isColor() { - return color; - } - - /** - * @return the image data - */ - public byte[] getData() { - return imageData; - } - - /** - * @return true of this image uses compression - */ - public boolean hasCompression() { - return compression > -1; - } - - /** - * @return the compression type - */ - public int getCompression() { - return compression; - } - - /** - * Sets the compression used with this image - * @param compression the type of compression used with this image - */ - public void setCompression(int compression) { - this.compression = compression; - } - - /** - * @return the image data width - */ - public int getImageDataWidth() { - return imageDataWidth; - } - - /** - * Sets the image data width - * @param imageDataWidth the image data width - */ - protected void setImageDataWidth(int imageDataWidth) { - this.imageDataWidth = imageDataWidth; - } - - /** - * @return the image data height - */ - public int getImageDataHeight() { - return imageDataHeight; - } - - /** - * Sets the image data height - * @param imageDataHeight the image data height - */ - protected void setImageDataHeight(int imageDataHeight) { - this.imageDataHeight = imageDataHeight; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return super.toString() - + ", imageDataWidth=" + imageDataWidth - + ", imageDataHeight=" + imageDataHeight - + ", color=" + color - + ", bitPerPixel=" + bitsPerPixel; - } -} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/ResourceInfo.java b/src/java/org/apache/fop/render/afp/ResourceInfo.java new file mode 100644 index 000000000..5c39d48b0 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/ResourceInfo.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 java.io.File; + +/** + * The level at which a resource is to reside in the AFP output + */ +public class ResourceInfo { + private static final String LEVEL_EXTERNAL = "external"; + + private static final String LEVEL_PRINT_FILE = "print-file"; + + private static final String LEVEL_DOCUMENT = "document"; + + private static final String LEVEL_PAGE_GROUP = "page-group"; + + private static final String LEVEL_PAGE = "page"; + + /** + * the reference name of this resource + */ + private String name = null; + + /** + * where the resource will reside in the AFP output + */ + private String level = LEVEL_PAGE; // default is page level + + /** + * the external resource group file + */ + private File externalResourceGroupFile = null; + + /** + * @return true if this is a page level resource group + */ + public boolean isPage() { + return level.equals(LEVEL_PAGE); + } + + /** + * @return true if this is a page group level resource group + */ + public boolean isPageGroup() { + return level.equals(LEVEL_PAGE_GROUP); + } + + /** + * @return true if this is a document level resource group + */ + public boolean isDocument() { + return level.equals(LEVEL_DOCUMENT); + } + + /** + * @return true if this is an external level resource group + */ + public boolean isExternal() { + return level.equals(LEVEL_EXTERNAL); + } + + /** + * @return true if this is a print-file level resource group + */ + public boolean isPrintFile() { + return level.equals(LEVEL_PRINT_FILE); + } + + private boolean isValid(String lvl) { + return lvl.equals(LEVEL_EXTERNAL) + || lvl.equals(LEVEL_PRINT_FILE) + || lvl.equals(LEVEL_DOCUMENT) + || lvl.equals(LEVEL_PAGE_GROUP) + || lvl.equals(LEVEL_PAGE); + } + + /** + * Sets the resource placement level within the AFP output + * @param lvl the resource level (page, page-group, document, print-file or external) + * @return true if the resource level was successfully set + */ + public boolean setLevel(String lvl) { + if (isValid(lvl)) { + this.level = lvl; + return true; + } + return false; + } + + /** + * @return the external resource group file of this resource + */ + public File getExternalResourceGroupFile() { + return this.externalResourceGroupFile; + } + + /** + * @return the destination file path of the external resource group file + */ + public String getExternalResourceGroupDest() { + if (externalResourceGroupFile != null) { + return externalResourceGroupFile.getAbsolutePath(); + } + return null; + } + + /** + * @return true if this resource has a defined external resource group file destination + */ + public boolean hasExternalResourceGroupFile() { + return getExternalResourceGroupFile() != null; + } + + /** + * Sets the external destination of the resource + * @param file the external resource group file + */ + public void setExternalResourceGroupFile(File file) { + this.externalResourceGroupFile = file; + } + + /** + * Sets the resource reference name + * @param resourceName the resource reference name + */ + public void setName(String resourceName) { + this.name = resourceName; + } + + /** + * @return the resource reference name + */ + public String getName() { + return this.name; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "ResourceInfo(name=" + name + ", level=" + level + + (isExternal() ? ", externalResourceGroupFile=" + externalResourceGroupFile : "") + + ")"; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/ResourceLevel.java b/src/java/org/apache/fop/render/afp/ResourceLevel.java deleted file mode 100644 index f397edb04..000000000 --- a/src/java/org/apache/fop/render/afp/ResourceLevel.java +++ /dev/null @@ -1,123 +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; - -/** - * The level at which a resource is to reside in the AFP output - */ -public class ResourceLevel { - private static final String EXTERNAL = "external"; - - private static final String PRINT_FILE = "print-file"; - - private static final String DOCUMENT = "document"; - - private static final String PAGE_GROUP = "page-group"; - - private static final String PAGE = "page"; - - /** - * where the resource will reside in the AFP output - */ - private String level = PAGE; // default is page level - - /** - * the destination location of the resource - */ - private String dest = null; - - /** - * @return true if this is a page level resource group - */ - public boolean isPage() { - return level.equals(PAGE); - } - - /** - * @return true if this is a page group level resource group - */ - public boolean isPageGroup() { - return level.equals(PAGE_GROUP); - } - - /** - * @return true if this is a document level resource group - */ - public boolean isDocument() { - return level.equals(DOCUMENT); - } - - /** - * @return true if this is an external level resource group - */ - public boolean isExternal() { - return level.equals(EXTERNAL); - } - - /** - * @return true if this is a print-file level resource group - */ - public boolean isPrintFile() { - return level.equals(PRINT_FILE); - } - - private boolean isValid(String lvl) { - return lvl.equals(EXTERNAL) - || lvl.equals(PRINT_FILE) - || lvl.equals(DOCUMENT) - || lvl.equals(PAGE_GROUP) - || lvl.equals(PAGE); - } - - /** - * Sets the resource placement level within the AFP output - * @param level the resource level (page, page-group, document, print-file or external) - * @return true if the resource level was successfully set - */ - public boolean setLevel(String level) { - if (isValid(level)) { - this.level = level; - return true; - } - return false; - } - - /** - * @return the external destination of the resource - */ - public String getExternalDest() { - return dest; - } - - /** - * Sets the external destination of the resource - * @param dest the external destination of the resource - */ - public void setExternalDest(String dest) { - this.dest = dest; - } - - /** - * {@inheritDoc} - */ - public String toString() { - return "level=" + level + (isExternal() ? ", dest=" + dest : ""); - } -} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java index 659c79a8e..7d32c90d7 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java @@ -55,8 +55,7 @@ public class AFPElement extends AbstractAFPExtensionObject { } } - protected ExtensionAttachment instantiateExtensionAttachment() { - return new AFPPageSetup(getName()); - } - + protected ExtensionAttachment instantiateExtensionAttachment() { + return new AFPPageSetup(getName()); + } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java index ad80399e3..44ba63aca 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java @@ -48,8 +48,8 @@ public class AFPElementMapping extends ElementMapping { /** include page segment element */ public static final String INCLUDE_PAGE_SEGMENT = "include-page-segment"; - /** include resource element (external) */ - public static final String RESOURCE = "resource"; +// /** include resource element (external) */ +// public static final String RESOURCE = "resource"; /** NOP */ public static final String NO_OPERATION = "no-operation"; @@ -70,7 +70,7 @@ public class AFPElementMapping extends ElementMapping { } /** - * Private static synchronized method to set up the element and atribute + * Private static synchronized method to set up the element and attribute * HashMaps, this defines what elements and attributes are extracted. */ protected void initialize() { @@ -79,8 +79,8 @@ public class AFPElementMapping extends ElementMapping { super.foObjs = new java.util.HashMap(); foObjs.put(PAGE, new AFPPageSetupMaker()); // foObjs.put( -// PAGE_GROUP, -// new AFPPageGroupMaker() +// PAGE_GROUP, +// new AFPPageGroupMaker() // ); foObjs.put( TAG_LOGICAL_ELEMENT, diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java index bf534e3c7..e6790e91c 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java @@ -20,6 +20,7 @@ package org.apache.fop.render.afp.modca; import java.awt.Color; +import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; @@ -29,9 +30,8 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.render.afp.AFPFontAttributes; -import org.apache.fop.render.afp.DataObjectParameters; -import org.apache.fop.render.afp.ImageObjectParameters; -import org.apache.fop.render.afp.ResourceLevel; +import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.ResourceInfo; import org.apache.fop.render.afp.fonts.AFPFont; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.tools.StringUtils; @@ -146,9 +146,9 @@ public class AFPDataStream extends AbstractResourceGroupContainer { private OutputStream outputStream = null; /** - * A mapping of external resource destinations to resource groups + * The external resource group manager */ - private Map/**/ externalResourceGroups = null; + private ExternalResourceGroupManager externalResourceGroupManager = null; /** * Default constructor for the AFPDataStream. @@ -226,9 +226,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { } // Write out any external resource groups - if (externalResourceGroups != null) { - writeExternalResources(); - } + getExternalResourceGroupManager().writeExternalResources(); // Write out any print-file level resources if (hasResources()) { @@ -405,7 +403,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * the point size of the font */ public void createFont(int fontReference, AFPFont font, int size) { - currentPage.createFont(fontReference, font, size); + getCurrentPage().createFont(fontReference, font, size); } /** @@ -429,51 +427,37 @@ public class AFPDataStream extends AbstractResourceGroupContainer { */ public void createText(int fontReference, int x, int y, Color col, int vsci, int ica, byte[] data) { - currentPage.createText(fontReference, x + xOffset, y + yOffset, rotation, + getCurrentPage().createText(fontReference, x + xOffset, y + yOffset, rotation, col, vsci, ica, data); } - - /** - * Returns true if the resource exists within this resource group, - * false otherwise. - * - * @param uri the uri of the resource - * @return true if the resource exists within this resource group - */ - public boolean resourceExists(String uri) { - return getResourceGroup().resourceExists(uri); - } - - /** - * Returns an IncludeObject referencing an image in the datastream. - * - * @param params - * the unique uri of the image - * @return - * a new include object referencing an image object - */ - public IncludeObject createImageObject(ImageObjectParameters params) { - ResourceLevel resourceLevel = params.getResourceLevel(); - IncludeObject includeObj = getResourceGroup(resourceLevel).addObject(params); - currentPage.addObject(includeObj); - return includeObj; - } /** - * Returns an IncludeObject referencing a graphic in the datastream. - * - * @param params - * the data object parameters + * Creates a data object in the datastream. The data object resides according + * to its type, info and MO:DCA-L (resource) support. + * + * @param dataObjectInfo + * the data object info * @return - * a new include object referencing the graphics object - */ - public IncludeObject createGraphicsObject(DataObjectParameters params) { - ResourceLevel resourceLevel = params.getResourceLevel(); - IncludeObject includeObj = getResourceGroup(resourceLevel).addObject(params); - currentPage.addObject(includeObj); - return includeObj; + * a data object + */ + public AbstractNamedAFPObject createObject(DataObjectInfo dataObjectInfo) { + ObjectTypeRegistry registry = ObjectTypeRegistry.getInstance(); + ObjectTypeRegistry.ObjectType objectType = registry.getObjectType(dataObjectInfo); + if (objectType != null) { + dataObjectInfo.setObjectType(objectType); + } + AbstractNamedAFPObject dataObj; + // can this data object use the include object (IOB) mechanism? + if (objectType.canBeIncluded()) { + ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + ResourceGroup resourceGroup = getResourceGroup(resourceInfo); + dataObj = resourceGroup.createObject(dataObjectInfo); + } else { + dataObj = getCurrentPage().createObject(dataObjectInfo); + } + return dataObj; } - + /** * Sets the object view port taking into account rotation. * @@ -502,7 +486,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { int heightRes; switch (this.rotation) { case 90: - xOrigin = currentPage.getWidth() - y - yOffset; + xOrigin = getCurrentPage().getWidth() - y - yOffset; yOrigin = x + xOffset; width = h; height = w; @@ -510,8 +494,8 @@ public class AFPDataStream extends AbstractResourceGroupContainer { heightRes = wr; break; case 180: - xOrigin = currentPage.getWidth() - x - xOffset; - yOrigin = currentPage.getHeight() - y - yOffset; + xOrigin = getCurrentPage().getWidth() - x - xOffset; + yOrigin = getCurrentPage().getHeight() - y - yOffset; width = w; height = h; widthRes = wr; @@ -519,7 +503,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { break; case 270: xOrigin = y + yOffset; - yOrigin = currentPage.getHeight() - x - xOffset; + yOrigin = getCurrentPage().getHeight() - x - xOffset; width = h; height = w; widthRes = hr; @@ -555,7 +539,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { */ public void createLine(int x1, int y1, int x2, int y2, int thickness, Color col) { - currentPage.createLine(x1 + xOffset, y1 + yOffset, x2 + xOffset, y2 + getCurrentPage().createLine(x1 + xOffset, y1 + yOffset, x2 + xOffset, y2 + yOffset, thickness, rotation, col); } @@ -581,7 +565,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { */ public void createShading(int x, int y, int w, int h, int red, int green, int blue) { - currentPage.createShading(x + xOffset, y + xOffset, w, h, red, green, + getCurrentPage().createShading(x + xOffset, y + xOffset, w, h, red, green, blue); } @@ -622,23 +606,23 @@ public class AFPDataStream extends AbstractResourceGroupContainer { int yOrigin; switch (rotation) { case 90: - xOrigin = currentPage.getWidth() - y - yOffset; + xOrigin = getCurrentPage().getWidth() - y - yOffset; yOrigin = x + xOffset; break; case 180: - xOrigin = currentPage.getWidth() - x - xOffset; - yOrigin = currentPage.getHeight() - y - yOffset; + xOrigin = getCurrentPage().getWidth() - x - xOffset; + yOrigin = getCurrentPage().getHeight() - y - yOffset; break; case 270: xOrigin = y + yOffset; - yOrigin = currentPage.getHeight() - x - xOffset; + yOrigin = getCurrentPage().getHeight() - x - xOffset; break; default: xOrigin = x + xOffset; yOrigin = y + yOffset; break; } - currentPage.createIncludePageSegment(name, xOrigin, yOrigin); + getCurrentPage().createIncludePageSegment(name, xOrigin, yOrigin); } /** @@ -681,7 +665,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { if (currentPageGroup != null) { currentPageGroup.createTagLogicalElement(name, value); } else { - currentPage.createTagLogicalElement(name, value); + getCurrentPage().createTagLogicalElement(name, value); } } @@ -692,7 +676,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * byte data */ public void createNoOperation(String content) { - currentPage.createNoOperation(content); + getCurrentPage().createNoOperation(content); } private PageGroup getCurrentPageGroup() { @@ -719,7 +703,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { public void endPageGroup() { if (currentPageGroup != null) { currentPageGroup.endPageGroup(); - document.addPageGroup(currentPageGroup); + getDocument().addPageGroup(currentPageGroup); currentPageGroup = null; } } @@ -758,70 +742,143 @@ public class AFPDataStream extends AbstractResourceGroupContainer { } } + /** - * Writes out external AFP resources - */ - private void writeExternalResources() { - // write any external resources - Iterator it = getExternalResourceGroups().keySet().iterator(); - while (it.hasNext()) { - String externalDest = (String)it.next(); - ResourceGroup resourceGroup - = (ResourceGroup)getExternalResourceGroups().get(externalDest); - OutputStream os = null; - try { - log.debug("Writing external AFP resource file " + externalDest); - os = new java.io.FileOutputStream(externalDest); - resourceGroup.writeDataStream(os); - } catch (FileNotFoundException e) { - log.error("Failed to open external AFP resource file " - + externalDest); - } catch (IOException e) { - log.error("An error occurred when attempting to write external AFP resource file " - + externalDest); - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - log.error("Failed to close outputstream for external AFP resource file " - + externalDest); - } - } - } - } - } - - /** - * Returns the resource group for a given resource level - * @param resourceLevel a resource level - * @return a resource group container for the given level + * Returns the resource group for a given resource into + * @param resourceInfo resource info + * @return a resource group container for the given resource info */ - private ResourceGroup getResourceGroup(ResourceLevel resourceLevel) { + private ResourceGroup getResourceGroup(ResourceInfo resourceInfo) { ResourceGroup resourceGroup = null; - if (resourceLevel.isPrintFile()) { - resourceGroup = this.getResourceGroup(); - } else if (resourceLevel.isDocument()) { - resourceGroup = document.getResourceGroup(); - } else if (resourceLevel.isPageGroup()) { + if (resourceInfo.isPrintFile()) { + resourceGroup = getResourceGroup(); + } else if (resourceInfo.isDocument()) { + resourceGroup = getDocument().getResourceGroup(); + } else if (resourceInfo.isPageGroup()) { resourceGroup = getCurrentPageGroup().getResourceGroup(); - } else if (resourceLevel.isPage()) { + } else if (resourceInfo.isPage()) { resourceGroup = getCurrentPage().getResourceGroup(); - } else if (resourceLevel.isExternal()) { - String externalDest = resourceLevel.getExternalDest(); - resourceGroup = (ResourceGroup)getExternalResourceGroups().get(externalDest); - if (resourceGroup == null) { - resourceGroup = new ResourceGroup(); - externalResourceGroups.put(externalDest, resourceGroup); - } + } else if (resourceInfo.isExternal()) { + resourceGroup = getExternalResourceGroupManager().getExternalResourceGroup( + resourceInfo); } return resourceGroup; } + + /** + * Sets the default resource group file + * @param resourceGroupFile the default resource group file + */ + public void setDefaultResourceGroupFile(File resourceGroupFile) { + getExternalResourceGroupManager().setDefaultResourceGroupFile(resourceGroupFile); + } + + /** + * @return the resource group manager + */ + protected ExternalResourceGroupManager getExternalResourceGroupManager() { + if (externalResourceGroupManager == null) { + this.externalResourceGroupManager = new ExternalResourceGroupManager(this); + } + return this.externalResourceGroupManager; + } + - private Map/**/ getExternalResourceGroups() { - if (externalResourceGroups == null) { - externalResourceGroups = new java.util.HashMap(); + /** + * Manages the use of resource groups (external and internal) + */ + private final class ExternalResourceGroupManager { + /** + * A mapping of external resource destinations to resource groups + */ + private Map/**/ externalResourceGroups = null; + + /** sets the default resource group file */ + private File defaultResourceGroupFile; + + /** the container of this manager */ + private AbstractResourceGroupContainer container; + + /** + * Main constructor + * @param container the container of this manager + */ + private ExternalResourceGroupManager(AbstractResourceGroupContainer container) { + this.container = container; } - return externalResourceGroups; + + /** + * Sets the default resource group file + * @param resourceGroupFile the default resource group file + */ + private void setDefaultResourceGroupFile(File resourceGroupFile) { + this.defaultResourceGroupFile = resourceGroupFile; + } + + /** + * Writes out external AFP resources + */ + private void writeExternalResources() { + // write any external resources + Iterator it = getExternalResourceGroups().keySet().iterator(); + while (it.hasNext()) { + String externalDest = (String)it.next(); + ResourceGroup resourceGroup + = (ResourceGroup)getExternalResourceGroups().get(externalDest); + OutputStream os = null; + try { + log.debug("Writing external AFP resource file " + externalDest); + os = new java.io.FileOutputStream(externalDest); + resourceGroup.writeDataStream(os); + } catch (FileNotFoundException e) { + log.error("Failed to open external AFP resource file " + + externalDest); + } catch (IOException e) { + log.error( + "An error occurred when attempting to write external AFP resource file " + + externalDest); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + log.error("Failed to close outputstream for external AFP resource file " + + externalDest); + } + } + } + } + } + + private ResourceGroup getExternalResourceGroup(ResourceInfo resourceInfo) { + ResourceGroup resourceGroup; + // this resource info does not have a an external resource group file definition + if (!resourceInfo.hasExternalResourceGroupFile()) { + if (defaultResourceGroupFile != null) { + // fallback to default resource group file + resourceInfo.setExternalResourceGroupFile(defaultResourceGroupFile); + resourceGroup = getExternalResourceGroup(resourceInfo); + } else { + // use print-file level resource group in the absence + // of an external resource group file definition + resourceGroup = container.getResourceGroup(); + } + } else { + File resourceGroupFile = resourceInfo.getExternalResourceGroupFile(); + resourceGroup = (ResourceGroup)getExternalResourceGroups().get(resourceGroupFile); + if (resourceGroup == null) { + resourceGroup = new ResourceGroup(container); + externalResourceGroups.put(resourceGroupFile, resourceGroup); + } + } + return resourceGroup; + } + + private Map/**/ getExternalResourceGroups() { + if (externalResourceGroups == null) { + externalResourceGroups = new java.util.HashMap/**/(); + } + return externalResourceGroups; + } } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java index 106454ad6..60cfeb623 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java @@ -44,7 +44,7 @@ public abstract class AbstractAFPObject { * DataStream objects must implement the writeDataStream() * method to write its data to the given OutputStream * @param os The outputsteam stream - * @throws java.io.IOException + * @throws java.io.IOException an I/O exception of some sort has occurred. */ public abstract void writeDataStream(OutputStream os) throws IOException; @@ -52,18 +52,16 @@ public abstract class AbstractAFPObject { * Help method to write a set of AFPObjects to the AFP datastream. * @param objects a list of AFPObjects * @param os The stream to write to - * @throws java.io.IOException + * @throws java.io.IOException an I/O exception of some sort has occurred. */ protected void writeObjects(Collection/**/ objects, OutputStream os) throws IOException { if (objects != null) { for (Iterator it = objects.iterator(); it.hasNext();) { - Object obj1 = it.next(); - AbstractAFPObject obj = (AbstractAFPObject)obj1; + AbstractAFPObject obj = (AbstractAFPObject)it.next(); obj.writeDataStream(os); } } - } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java index 09fa33f8f..8e6127b8a 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java @@ -81,5 +81,4 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject public String getName() { return name; } - } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java index 984aa44c9..95dd303b2 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java @@ -432,10 +432,7 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer protected void addObject(AbstractStructuredAFPObject obj) { if (obj instanceof IncludeObject) { IncludeObject includeObj = (IncludeObject)obj; - AbstractStructuredAFPObject refObj = includeObj.getReferencedObject(); - if (refObj instanceof ImageObject || refObj instanceof GraphicsObject) { - getActiveEnvironmentGroup().createResource(refObj); - } + getActiveEnvironmentGroup().createResource(includeObj); } endPresentationObject(); super.addObject(obj); diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java index e8e25b6b8..896771cd7 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java @@ -23,8 +23,11 @@ import java.io.IOException; import java.io.OutputStream; import java.util.Set; -import org.apache.fop.render.afp.DataObjectParameters; -import org.apache.fop.render.afp.ImageObjectParameters; +import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.ImageObjectInfo; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.tools.StringUtils; +import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; /** * An abstract container of resource objects @@ -87,31 +90,165 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj */ protected ResourceGroup getResourceGroup() { if (resourceGroup == null) { - resourceGroup = new ResourceGroup(); + resourceGroup = new ResourceGroup(this); } return resourceGroup; } + + /** + * Converts a byte array containing 24 bit RGB image data to a grayscale + * image. + * + * @param io + * the target image object + * @param raw + * the buffer containing the RGB image data + * @param width + * the width of the image in pixels + * @param height + * the height of the image in pixels + * @param bitsPerPixel + * the number of bits to use per pixel + * + * TODO: move this method somewhere appropriate in commons + */ + private static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, + int height, int bitsPerPixel) { + int pixelsPerByte = 8 / bitsPerPixel; + int bytewidth = (width / pixelsPerByte); + if ((width % pixelsPerByte) != 0) { + bytewidth++; + } + byte[] bw = new byte[height * bytewidth]; + byte ib; + for (int y = 0; y < height; y++) { + ib = 0; + int i = 3 * y * width; + for (int x = 0; x < width; x++, i += 3) { + + // see http://www.jguru.com/faq/view.jsp?EID=221919 + double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d + * ((int) raw[i + 1] & 0xff) + 0.072169d + * ((int) raw[i + 2] & 0xff); + switch (bitsPerPixel) { + case 1: + if (greyVal < 128) { + ib |= (byte) (1 << (7 - (x % 8))); + } + break; + case 4: + greyVal /= 16; + ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4)); + break; + case 8: + ib = (byte) greyVal; + break; + default: + throw new UnsupportedOperationException( + "Unsupported bits per pixel: " + bitsPerPixel); + } + + if ((x % pixelsPerByte) == (pixelsPerByte - 1) + || ((x + 1) == width)) { + bw[(y * bytewidth) + (x / pixelsPerByte)] = ib; + ib = 0; + } + } + } + io.setImageIDESize((byte) bitsPerPixel); + io.setImageData(bw); + } + + private static final String IMAGE_NAME_PREFIX = "IMG"; + private static final String GRAPHIC_NAME_PREFIX = "GRA"; + private static final String PAGE_SEGMENT_NAME_PREFIX = "PSG"; + // not currently used/implemented + private static final String BARCODE_NAME_PREFIX = "BAR"; + private static final String OTHER_NAME_PREFIX = "OTH"; + /** * Helper method to create an image on the current container and to return * the object. - * @param params the image object parameters - * @return the image object + * @param info the image object info + * @return a newly created image object */ - public IncludeObject createImageObject(ImageObjectParameters params) { - return getResourceGroup().addObject(params); + protected ImageObject createImage(ImageObjectInfo info) { + String name = IMAGE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); + ImageObject imageObj = new ImageObject(name); + if (info.hasCompression()) { + int compression = info.getCompression(); + switch (compression) { + case TIFFImage.COMP_FAX_G3_1D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MH); + break; + case TIFFImage.COMP_FAX_G3_2D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MR); + break; + case TIFFImage.COMP_FAX_G4_2D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MMR); + break; + default: + throw new IllegalStateException( + "Invalid compression scheme: " + compression); + } + } + imageObj.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_URL, info.getUri()); + imageObj.setImageParameters(info.getWidthRes(), info.getHeightRes(), + info.getDataWidth(), info.getDataHeight()); + if (info.isColor()) { + imageObj.setImageIDESize((byte)24); + imageObj.setImageData(info.getData()); + } else { + convertToGrayScaleImage(imageObj, info.getData(), + info.getDataWidth(), info.getDataHeight(), + info.getBitsPerPixel()); + } + return imageObj; } - + /** * Helper method to create a graphic in the current container and to return * the object. - * @param params the data object parameters - * @return the graphics object + * @return a newly created graphics object */ - public IncludeObject createGraphicsObject(DataObjectParameters params) { - return getResourceGroup().addObject(params); + protected GraphicsObject createGraphic() { + String name = GRAPHIC_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); + GraphicsObject graphicsObj = new GraphicsObject(name); + return graphicsObj; } - + + /** + * Helper method to create a page segment in the current container and to return + * the object. + * @return a newly created page segment + */ + protected PageSegment createPageSegment() { + String name = PAGE_SEGMENT_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); + PageSegment pageSegment = new PageSegment(name); + return pageSegment; + } + + /** + * Creates and returns a new data object + * @param info the data object parameters + * @return a newly created data object + */ + public AbstractNamedAFPObject createObject(DataObjectInfo info) { + AbstractNamedAFPObject dataObject; + if (info instanceof ImageObjectInfo) { + dataObject = createImage((ImageObjectInfo)info); + } else { + dataObject = createGraphic(); + } + return dataObject; + } + /** * {@inheritDoc} */ 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 3c448b2ab..6ec3a6d63 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java @@ -31,6 +31,7 @@ import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.modca.triplets.MeasurementUnitsTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectAreaSizeTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; +import org.apache.fop.render.afp.modca.triplets.StrucFlgs; import org.apache.fop.render.afp.modca.triplets.Triplet; /** @@ -58,6 +59,12 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { * @return the triplet data length */ protected int getTripletDataLength() { + if (tripletData == null) { + try { + getTripletData(); + } catch (IOException e) { + } + } if (tripletData != null) { return tripletData.length; } @@ -65,27 +72,18 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { } /** - * Helper method to write the start of the Object. - * @param os The stream to write to - * @throws IOException an I/O exception if one occurred + * @return the triplet data + * @throws IOException throws an I/O exception if one occurred */ - protected void writeStart(OutputStream os) throws IOException { - if (triplets != null) { + protected byte[] getTripletData() throws IOException { + if (tripletData == null && triplets != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeObjects(triplets, baos); this.tripletData = baos.toByteArray(); } + return this.tripletData; } - - /** - * Helper method to write the contents of the Object. - * @param os The stream to write to - * @throws IOException The stream to write to - */ - protected void writeContent(OutputStream os) throws IOException { - writeTriplets(os); - } - + /** * Writes any triplet data * @param os The stream to write to @@ -98,6 +96,24 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { writeObjects(triplets, os); } } + + /** + * Helper method to write the start of the Object. + * @param os The stream to write to + * @throws IOException throws an I/O exception if one occurred + */ + protected void writeStart(OutputStream os) throws IOException { + getTripletData(); + } + + /** + * Helper method to write the contents of the Object. + * @param os The stream to write to + * @throws IOException throws an I/O exception if one occurred + */ + protected void writeContent(OutputStream os) throws IOException { + writeTriplets(os); + } /** * Helper method to write the end of the Object. @@ -176,9 +192,8 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { * @param fqName the fully qualified name of this resource */ public void setFullyQualifiedName(byte fqnType, byte fqnFormat, String fqName) { - byte[] fqNameBytes; try { - fqNameBytes = fqName.getBytes(AFPConstants.EBCIDIC_ENCODING); + byte[] fqNameBytes = fqName.getBytes(AFPConstants.EBCIDIC_ENCODING); addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqNameBytes)); } catch (UnsupportedEncodingException e) { log.error(e.getMessage()); @@ -191,15 +206,17 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { public String getFullyQualifiedName() { FullyQualifiedNameTriplet fqNameTriplet = (FullyQualifiedNameTriplet)getTriplet(Triplet.FULLY_QUALIFIED_NAME); - byte[] nameBytes = fqNameTriplet.getFullyQualifiedName(); - if (nameBytes != null) { - try { - return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException e) { - log.error(e.getMessage()); + if (fqNameTriplet != null) { + byte[] nameBytes = fqNameTriplet.getFullyQualifiedName(); + if (nameBytes != null) { + try { + return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage()); + } + } else { + log.warn(this + " has no fully qualified name"); } - } else { - log.warn(this + " has no fully qualified name"); } return null; } @@ -207,12 +224,15 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { /** * Sets the objects classification * @param objectClass the classification of the object - * @param componentId the component Id of the object + * @param objectType the MOD:CA registry object type entry for the given + * object/component type of the object + * @param strucFlgs information on the structure of the object and its container */ - public void setObjectClassification(byte objectClass, byte componentId) { - addTriplet(new ObjectClassificationTriplet(objectClass, componentId)); + public void setObjectClassification(byte objectClass, ObjectTypeRegistry.ObjectType objectType, + StrucFlgs strucFlgs) { + addTriplet(new ObjectClassificationTriplet(objectClass, objectType, strucFlgs)); } - + /** * Specifies the extent of an object area in the X and Y directions * @param x the x direction extent diff --git a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java index 845af4dfc..df4975e59 100644 --- a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java @@ -146,8 +146,8 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { super.writeTriplets(os); writeObjects(mapCodedFonts, os); - writeObjects(mapPageOverlays, os); writeObjects(mapDataResources, os); + writeObjects(mapPageOverlays, os); if (pageDescriptor != null) { pageDescriptor.writeDataStream(os); @@ -258,12 +258,11 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { } } - /** * Method to create a map data resource object * @param obj creates a map data resource entry for a given AFP data resource object */ - public void createResource(AbstractStructuredAFPObject obj) { + public void createResource(IncludeObject obj) { getMapDataResources().add(new MapDataResource(obj)); } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java index 0fceff893..799578966 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java @@ -19,9 +19,12 @@ package org.apache.fop.render.afp.modca; +import java.io.File; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.ResourceInfo; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.tools.BinaryUtils; /** @@ -94,38 +97,84 @@ public class IncludeObject extends AbstractNamedAFPObject { */ private int yContentOffset = -1; +// /** +// * The object referenced by this include object +// */ +// private Resource resourceObj = null; + /** - * The object referenced by this include object + * the level at which this resource object resides */ - private AbstractStructuredAFPObject referencedObject = null; + private ResourceInfo level = null; + + /** + * the referenced data object + */ + private AbstractNamedAFPObject dataObj = null; /** * Constructor for the include object with the specified name, the name must * be a fixed length of eight characters and is the name of the referenced * object. * - * @param resourceObj - * the resource object wrapper + * @param resourceObj the resource object wrapper */ - public IncludeObject(ResourceObject resourceObj) { - super(resourceObj.getResource().getName()); - this.referencedObject = resourceObj.getResource(); - if (referencedObject instanceof ImageObject) { + public IncludeObject(AbstractNamedAFPObject dataObj) { + super(dataObj.getName()); + this.dataObj = dataObj; +// AbstractStructuredAFPObject referencedObject = resourceObj.getReferencedObject(); + if (dataObj instanceof ImageObject) { this.objectType = TYPE_IMAGE; - } else if (referencedObject instanceof GraphicsObject) { + } else if (dataObj instanceof GraphicsObject) { this.objectType = TYPE_GRAPHIC; - } else if (referencedObject instanceof PageSegment) { + } else if (dataObj instanceof PageSegment) { this.objectType = TYPE_PAGE_SEGMENT; } else { this.objectType = TYPE_OTHER; } + + // set data object reference triplet + ResourceInfo resourceInfo = getResourceInfo(); + if (resourceInfo != null && resourceInfo.isExternal()) { + String dest = resourceInfo.getExternalResourceGroupDest(); + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, + FullyQualifiedNameTriplet.FORMAT_URL, dest); + } else { + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, dataObj.getName()); + } + } + + /** + * Sets the resource level for this resource object + * @param level the resource level + */ + public void setResourceInfo(ResourceInfo level) { + this.level = level; + } + + /** + * @return the resource info of this resource object + */ + public ResourceInfo getResourceInfo() { + return this.level; } +// /** +// * @return the resource container object referenced by this include object +// */ +// public Resource getResource() { +// return this.resourceObj; +// } + /** - * @return the object referenced by this include object + * @return the actual resource data object referenced by this include object */ public AbstractStructuredAFPObject getReferencedObject() { - return referencedObject; + return this.dataObj; + //getResource().getReferencedObject(); } /** @@ -167,12 +216,12 @@ public class IncludeObject extends AbstractNamedAFPObject { /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { + public void writeDataStream(OutputStream os) throws IOException { byte[] data = new byte[36]; data[0] = 0x5A; // Set the total record length - byte[] len = BinaryUtils.convert(35, 2); //Ignore first byte + byte[] len = BinaryUtils.convert(35 + getTripletDataLength(), 2); //Ignore first byte data[1] = len[0]; data[2] = len[1]; @@ -272,8 +321,13 @@ public class IncludeObject extends AbstractNamedAFPObject { data[33] = (byte)0xFF; data[34] = (byte)0xFF; } - data[35] = 0x01; + + // Write structured field data os.write(data); + + // Write triplet for FQN internal/external object reference + byte[] tripletData = super.getTripletData(); + os.write(tripletData); } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java index 66ae57d75..3ccfd450a 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java +++ b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java @@ -22,7 +22,11 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +//import org.apache.fop.render.afp.ResourceLevel; +import org.apache.fop.render.afp.ResourceInfo; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; +import org.apache.fop.render.afp.modca.triplets.StrucFlgs; import org.apache.fop.render.afp.tools.BinaryUtils; /** @@ -39,13 +43,42 @@ public class MapDataResource extends AbstractStructuredAFPObject { * Main constructor * @param obj a map data resource for a given structured AFP object */ - public MapDataResource(AbstractStructuredAFPObject obj) { - String fqName = obj.getFullyQualifiedName(); + public MapDataResource(IncludeObject includeObj) { + AbstractStructuredAFPObject refObj = includeObj.getReferencedObject(); +// ResourceObject resObj = includeObj.getResource(); + String fqName = refObj.getFullyQualifiedName(); + ResourceInfo resourceInfo = includeObj.getResourceInfo(); if (fqName != null) { - super.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, - FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); + if (resourceInfo.isExternal()) { + String dest = resourceInfo.getExternalResourceGroupDest(); + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, dest); + } else { +// super.setFullyQualifiedName( +// FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, +// FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); + } } +// if (fqName != null) { +// super.setFullyQualifiedName( +// FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, +// FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); +// } + final boolean dataInContainer = true; + final boolean containerHasOEG = false; + final boolean dataInOCD = true; + StrucFlgs strucFlgs = new StrucFlgs( + dataInContainer, containerHasOEG, dataInOCD + ); + + //TODO: AC - fix +// super.setObjectClassification( +// ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, +// objectType, strucFlgs); } /** @@ -54,8 +87,7 @@ public class MapDataResource extends AbstractStructuredAFPObject { public void writeStart(OutputStream os) throws IOException { super.writeStart(os); - // RGLength - byte[] len = BinaryUtils.convert(8 + getTripletDataLength(), 2); + byte[] len = BinaryUtils.convert(10 + getTripletDataLength(), 2); byte[] data = new byte[] { 0x5A, // Structured field identifier len[0], // Length byte 1 @@ -69,4 +101,15 @@ public class MapDataResource extends AbstractStructuredAFPObject { }; os.write(data); } + + /** + * {@inheritDoc} + */ + public void writeContent(OutputStream os) throws IOException { + // RGLength + byte[] len = BinaryUtils.convert(2 + getTripletDataLength(), 2); + os.write(len); + + super.writeTriplets(os); + } } diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java new file mode 100644 index 000000000..59e770d6d --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; +import org.apache.fop.render.afp.modca.triplets.StrucFlgs; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * Object containers are MO:DCA objects that envelop and carry object data. + */ +public class ObjectContainer extends AbstractNamedAFPObject { + + /** + * the object container data + */ + private ObjectContainerData objectContainerData; + + /** + * Main constructor + * @param name the name of this object container + * @param dataObj the data object to reside within this object container + * @param info the data object info about the data object + */ + public ObjectContainer(String name, AbstractDataObject dataObj, DataObjectInfo info) { + super(name); + + final boolean dataInContainer = true; + final boolean containerHasOEG = false; + final boolean dataInOCD = true; + StrucFlgs strucFlgs = new StrucFlgs( + dataInContainer, containerHasOEG, dataInOCD + ); + ObjectTypeRegistry registry = ObjectTypeRegistry.getInstance(); + ObjectTypeRegistry.ObjectType entry = registry.getObjectType(info); + super.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, + entry, strucFlgs + ); + + // write data object to object container data + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + // TODO: AC - fix +// dataObj.writeDataStream(bos); + this.objectContainerData = new ObjectContainerData(bos.toByteArray()); + } + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + // Set the total record length + byte[] len = BinaryUtils.convert(18 + getTripletDataLength(), 2); + byte[] data = new byte[] { + 0x5A, // Structured field identifier + len[0], // Length byte 1 + len[1], // Length byte 2 + (byte)0xD3, // Structured field id byte 1 + (byte)0xA8, // Structured field id byte 2 + (byte)0x92, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00, // Reserved + nameBytes[0], + nameBytes[1], + nameBytes[2], + nameBytes[3], + nameBytes[4], + nameBytes[5], + nameBytes[6], + nameBytes[7], + 0x00, // Reserved + 0x00, // Reserved + }; + os.write(data); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); // write triplets + if (objectContainerData != null) { + objectContainerData.writeDataStream(os); + } + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[] { + 0x5A, // Structured field identifier + 0x00, // Length byte 1 + 0x10, // Length byte 2 + (byte)0xD3, // Structured field id byte 1 + (byte)0xA9, // Structured field id byte 2 + (byte)0x92, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00, // Reserved + nameBytes[0], + nameBytes[1], + nameBytes[2], + nameBytes[3], + nameBytes[4], + nameBytes[5], + nameBytes[6], + nameBytes[7], + }; + os.write(data); + } + + private class ObjectContainerData extends AbstractStructuredAFPObject { + /** the object data */ + private byte[] objData = null; + + /** + * Main constructor + * @param objData the object data + */ + public ObjectContainerData(byte[] objData) { + this.objData = objData; + } + + /** + * {@inheritDoc} + */ + public void writeDataStream(OutputStream os) throws IOException { + // Set the total record length + byte[] len = BinaryUtils.convert(8 + objData.length, 2); + byte[] data = new byte[] { + 0x5A, // Structured field identifier + len[0], // Length byte 1 + len[1], // Length byte 2 + (byte)0xD3, // Structured field id byte 1 + (byte)0xEE, // Structured field id byte 2 + (byte)0x92, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00, // Reserved + }; + + os.write(data); + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectTypeRegistry.java b/src/java/org/apache/fop/render/afp/modca/ObjectTypeRegistry.java new file mode 100644 index 000000000..278a56732 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/ObjectTypeRegistry.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.render.afp.modca; + +import java.io.UnsupportedEncodingException; +import java.util.Collections; + +import org.apache.commons.logging.LogFactory; +import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.ImageObjectInfo; +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * MOD:CA object type registry + */ +public final class ObjectTypeRegistry { + /** IOB supported object types */ + private static final byte COMPID_GIF = 22; + private static final byte COMPID_JFIF = 23; // jpeg file interchange format + private static final byte COMPID_PDF_SINGLE_PAGE = 25; + private static final byte COMPID_PCL_PAGE_OBJECT = 34; + + /** IOB unsupported object types */ + private static final byte COMPID_EPS = 13; + private static final byte COMPID_TIFF = 14; + + /** mime type entry mapping */ + private java.util.Map/**/ mimeEntryMap + = Collections.synchronizedMap( + Collections.unmodifiableMap( + new java.util.HashMap/**/())); + + private static ObjectTypeRegistry instance = null; + + /** + * @return a single instance of Registry + */ + public static ObjectTypeRegistry getInstance() { + synchronized (instance) { + if (instance == null) { + instance = new ObjectTypeRegistry(); + } + } + return instance; + } + + private ObjectTypeRegistry() { + init(); + } + + private void init() { + mimeEntryMap.put( + MimeConstants.MIME_EPS, + new ObjectType( + COMPID_EPS, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D}, + "Encapsulated Postscript", + false + ) + ); + mimeEntryMap.put( + MimeConstants.MIME_TIFF, + new ObjectType( + COMPID_TIFF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E}, + "TIFF", + false + ) + ); + mimeEntryMap.put( + MimeConstants.MIME_GIF, + new ObjectType( + COMPID_GIF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16}, + "GIF", + true + ) + ); + mimeEntryMap.put( + MimeConstants.MIME_JPEG, + new ObjectType( + COMPID_JFIF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17}, + "JFIF", + true + ) + ); + mimeEntryMap.put(MimeConstants.MIME_PDF, + new ObjectType( + COMPID_PDF_SINGLE_PAGE, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19}, + "PDF Single-page Object", + true + ) + ); + mimeEntryMap.put( + MimeConstants.MIME_PCL, + new ObjectType( + COMPID_PCL_PAGE_OBJECT, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22}, + "PCL Page Object", + true + ) + ); + } + + /** + * Returns the registry Entry for a given data object info + * + * @param info + * the data object info + * @return the registry Entry for a given data object info + */ + public ObjectType getObjectType(DataObjectInfo info) { + ObjectType entry = null; + if (info instanceof ImageObjectInfo) { + ImageObjectInfo imageInfo = (ImageObjectInfo)info; + String mimeType = imageInfo.getMimeType(); + entry = (ObjectType)mimeEntryMap.get(mimeType); + } + return entry; + } + + /** + * Encapsulates a MOD:CA Registry Object Type entry + */ + public class ObjectType { + private byte componentId; + private byte[] oid; + private byte[] name; + private boolean canBeIncluded; + + /** + * Main constructor + * @param componentId the component id of this object type + * @param oid the object id of this object type + * @param objectTypeName the object type name + * @param canBeIncluded true if this object can be included with an IOB structured field + */ + public ObjectType(byte componentId, byte[] oid, String objectTypeName, + boolean canBeIncluded) { + this.componentId = componentId; + this.oid = oid; + try { + this.name = objectTypeName.getBytes(AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException e) { + // should never happen! + LogFactory.getLog("org.apache.fop.render.afp.modca.Registry.Entry").error( + "character encoding error occurred on componentId " + + componentId + + " : " + + e.getMessage()); + } + this.canBeIncluded = canBeIncluded; + } + + /** + * Returns a MOD:CA object type OID from a given a componentId + * @return the corresponding object type id for a given component id + * or null if the component id is unknown and the object type OID was not found. + */ + public byte[] getOID() { + return this.oid; + } + + /** + * @return the object type name for the given componentId + */ + public byte[] getName() { + return this.name; + } + + /** + * @return the compontentId for this entry + */ + public byte getComponentId() { + return this.componentId; + } + + /** + * @return true if this component can be included with an IOB structured field + */ + public boolean canBeIncluded() { + return this.canBeIncluded; + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/PageSegment.java b/src/java/org/apache/fop/render/afp/modca/PageSegment.java index f88e3cc55..1ff4b8e5f 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/PageSegment.java @@ -31,7 +31,7 @@ import java.util.List; */ public class PageSegment extends AbstractNamedAFPObject { - private List objects = null; + private List/**/ objects = null; /** * Main constructor @@ -42,14 +42,21 @@ public class PageSegment extends AbstractNamedAFPObject { } /** - * Adds a resource object (image/graphic) to this page segment - * @param object the resource objec to add to this page segment + * @return a list of objects contained within this page segment */ - public void addObject(AbstractAFPObject object) { + public List/**/ getObjects() { if (objects == null) { objects = new java.util.ArrayList(); } - objects.add(object); + return objects; + } + + /** + * Adds a resource object (image/graphic) to this page segment + * @param object the resource objec to add to this page segment + */ + public void addObject(AbstractAFPObject object) { + getObjects().add(object); } /** @@ -72,6 +79,14 @@ public class PageSegment extends AbstractNamedAFPObject { os.write(data); } + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + writeObjects(objects, os); + } + /** * {@inheritDoc} */ @@ -90,13 +105,5 @@ public class PageSegment extends AbstractNamedAFPObject { data[9 + i] = nameBytes[i]; } os.write(data); - } - - /** - * {@inheritDoc} - */ - protected void writeContent(OutputStream os) throws IOException { - super.writeContent(os); - writeObjects(objects, os); - } + } } diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java index 98beb96f7..ec93ebebd 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java @@ -54,52 +54,50 @@ public class PresentationTextData extends AbstractAFPObject { private static final int MAX_SIZE = 8192; /** - * The afp data relating to this presentaion text data. + * The afp data relating to this presentation text data. */ - private ByteArrayOutputStream _baos = new ByteArrayOutputStream(1024); + private ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); /** * The current x coordinate. */ - private int _currentXCoordinate = -1; + private int currentXCoordinate = -1; /** * The current y cooridnate */ - private int _currentYCoordinate = -1; + private int currentYCoordinate = -1; /** * The current font */ - private String _currentFont = ""; + private String currentFont = ""; /** * The current orientation */ - private int _currentOrientation = 0; + private int currentOrientation = 0; /** * The current color */ - private Color _currentColor = new Color(0, 0, 0); + private Color currentColor = new Color(0, 0, 0); /** * The current variable space increment */ - private int _currentVariableSpaceCharacterIncrement = 0; + private int currentVariableSpaceCharacterIncrement = 0; /** * The current inter character adjustment */ - private int _currentInterCharacterAdjustment = 0; + private int currentInterCharacterAdjustment = 0; /** * Default constructor for the PresentationTextData. */ public PresentationTextData() { - this(false); - } /** @@ -111,8 +109,7 @@ public class PresentationTextData extends AbstractAFPObject { * The control sequence indicator. */ public PresentationTextData(boolean controlInd) { - - _baos.write(new byte[] { 0x5A, // Structured field identifier + baos.write(new byte[] { 0x5A, // Structured field identifier 0x00, // Record length byte 1 0x00, // Record length byte 2 (byte) 0xD3, // PresentationTextData identifier byte 1 @@ -124,9 +121,8 @@ public class PresentationTextData extends AbstractAFPObject { }, 0, 9); if (controlInd) { - _baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2); + baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2); } - } /** @@ -140,16 +136,14 @@ public class PresentationTextData extends AbstractAFPObject { * The output stream to which data should be written. */ private void setCodedFont(byte font, ByteArrayOutputStream afpdata) { - // Avoid unnecessary specification of the font - if (String.valueOf(font).equals(_currentFont)) { + if (String.valueOf(font).equals(currentFont)) { return; } else { - _currentFont = String.valueOf(font); + currentFont = String.valueOf(font); } afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3); - } /** @@ -162,15 +156,10 @@ public class PresentationTextData extends AbstractAFPObject { * @param afpdata * The output stream to which data should be written. */ - private void absoluteMoveInline(int coordinate, - ByteArrayOutputStream afpdata) { - + private void absoluteMoveInline(int coordinate, ByteArrayOutputStream afpdata) { byte[] b = BinaryUtils.convert(coordinate, 2); - afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4); - - _currentXCoordinate = coordinate; - + currentXCoordinate = coordinate; } /** @@ -183,15 +172,10 @@ public class PresentationTextData extends AbstractAFPObject { * @param afpdata * The output stream to which data should be written. */ - private void absoluteMoveBaseline(int coordinate, - ByteArrayOutputStream afpdata) { - + private void absoluteMoveBaseline(int coordinate, ByteArrayOutputStream afpdata) { byte[] b = BinaryUtils.convert(coordinate, 2); - afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4); - - _currentYCoordinate = coordinate; - + currentYCoordinate = coordinate; } /** @@ -204,21 +188,16 @@ public class PresentationTextData extends AbstractAFPObject { * The output stream to which data should be written. */ private void addTransparentData(byte[] data, ByteArrayOutputStream afpdata) { - // Calculate the length int l = data.length + 2; - if (l > 255) { // Check that we are not exceeding the maximum length throw new IllegalArgumentException( "Transparent data is longer than 253 bytes: " + data); } - afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, }, 0, 2); - afpdata.write(data, 0, data.length); - } /** @@ -233,13 +212,10 @@ public class PresentationTextData extends AbstractAFPObject { * @param afpdata * The output stream to which data should be written. */ - private void drawBaxisRule(int length, int width, - ByteArrayOutputStream afpdata) { - + private void drawBaxisRule(int length, int width, ByteArrayOutputStream afpdata) { afpdata.write(new byte[] { 0x07, // Length (byte) 0xE7, // Type }, 0, 2); - // Rule length byte[] data1 = BinaryUtils.shortToByteArray((short) length); afpdata.write(data1, 0, data1.length); @@ -248,7 +224,6 @@ public class PresentationTextData extends AbstractAFPObject { afpdata.write(data2, 0, data2.length); // Rule width fraction afpdata.write(0x00); - } /** @@ -263,13 +238,10 @@ public class PresentationTextData extends AbstractAFPObject { * @param afpdata * The output stream to which data should be written. */ - private void drawIaxisRule(int length, int width, - ByteArrayOutputStream afpdata) { - + private void drawIaxisRule(int length, int width, ByteArrayOutputStream afpdata) { afpdata.write(new byte[] { 0x07, // Length (byte) 0xE5, // Type }, 0, 2); - // Rule length byte[] data1 = BinaryUtils.shortToByteArray((short) length); afpdata.write(data1, 0, data1.length); @@ -278,7 +250,6 @@ public class PresentationTextData extends AbstractAFPObject { afpdata.write(data2, 0, data2.length); // Rule width fraction afpdata.write(0x00); - } /** @@ -303,62 +274,60 @@ public class PresentationTextData extends AbstractAFPObject { * @throws MaximumSizeExceededException */ public void createTextData(int fontNumber, int x, int y, int orientation, - Color col, int vsci, int ica, byte[] data) - throws MaximumSizeExceededException { + Color col, int vsci, int ica, byte[] data) throws MaximumSizeExceededException { ByteArrayOutputStream afpdata = new ByteArrayOutputStream(); - if (_currentOrientation != orientation) { + if (currentOrientation != orientation) { setTextOrientation(orientation, afpdata); - _currentOrientation = orientation; - _currentXCoordinate = -1; - _currentYCoordinate = -1; + currentOrientation = orientation; + currentXCoordinate = -1; + currentYCoordinate = -1; } // Avoid unnecessary specification of the Y co-ordinate - if (y != _currentYCoordinate) { + if (y != currentYCoordinate) { absoluteMoveBaseline(y, afpdata); - _currentXCoordinate = -1; + currentXCoordinate = -1; } // Avoid unnecessary specification of the X co-ordinate - if (x != _currentXCoordinate) { + if (x != currentXCoordinate) { absoluteMoveInline(x, afpdata); } // Avoid unnecessary specification of the variable space increment - if (vsci != _currentVariableSpaceCharacterIncrement) { + if (vsci != currentVariableSpaceCharacterIncrement) { setVariableSpaceCharacterIncrement(vsci, afpdata); - _currentVariableSpaceCharacterIncrement = vsci; + currentVariableSpaceCharacterIncrement = vsci; } // Avoid unnecessary specification of the inter character adjustment - if (ica != _currentInterCharacterAdjustment) { + if (ica != currentInterCharacterAdjustment) { setInterCharacterAdjustment(ica, afpdata); - _currentInterCharacterAdjustment = ica; + currentInterCharacterAdjustment = ica; } // Avoid unnecessary specification of the text color - if (!col.equals(_currentColor)) { + if (!col.equals(currentColor)) { setExtendedTextColor(col, afpdata); - _currentColor = col; + currentColor = col; } setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata); addTransparentData(data, afpdata); - _currentXCoordinate = -1; + currentXCoordinate = -1; int s = afpdata.size(); - if (_baos.size() + s > MAX_SIZE) { - _currentXCoordinate = -1; - _currentYCoordinate = -1; + if (baos.size() + s > MAX_SIZE) { + currentXCoordinate = -1; + currentYCoordinate = -1; throw new MaximumSizeExceededException(); } byte[] outputdata = afpdata.toByteArray(); - _baos.write(outputdata, 0, outputdata.length); - + baos.write(outputdata, 0, outputdata.length); } /** @@ -385,24 +354,24 @@ public class PresentationTextData extends AbstractAFPObject { ByteArrayOutputStream afpdata = new ByteArrayOutputStream(); - if (_currentOrientation != orientation) { + if (currentOrientation != orientation) { setTextOrientation(orientation, afpdata); - _currentOrientation = orientation; + currentOrientation = orientation; } // Avoid unnecessary specification of the Y coordinate - if (y1 != _currentYCoordinate) { + if (y1 != currentYCoordinate) { absoluteMoveBaseline(y1, afpdata); } // Avoid unnecessary specification of the X coordinate - if (x1 != _currentXCoordinate) { + if (x1 != currentXCoordinate) { absoluteMoveInline(x1, afpdata); } - if (!col.equals(_currentColor)) { + if (!col.equals(currentColor)) { setExtendedTextColor(col, afpdata); - _currentColor = col; + currentColor = col; } if (y1 == y2) { @@ -415,15 +384,14 @@ public class PresentationTextData extends AbstractAFPObject { int s = afpdata.size(); - if (_baos.size() + s > MAX_SIZE) { - _currentXCoordinate = -1; - _currentYCoordinate = -1; + if (baos.size() + s > MAX_SIZE) { + currentXCoordinate = -1; + currentYCoordinate = -1; throw new MaximumSizeExceededException(); } byte[] outputdata = afpdata.toByteArray(); - _baos.write(outputdata, 0, outputdata.length); - + baos.write(outputdata, 0, outputdata.length); } /** @@ -440,11 +408,8 @@ public class PresentationTextData extends AbstractAFPObject { * @param afpdata * The output stream to which data should be written. */ - private void setTextOrientation(int orientation, - ByteArrayOutputStream afpdata) { - + private void setTextOrientation(int orientation, ByteArrayOutputStream afpdata) { afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2); - switch (orientation) { case 90: afpdata.write(0x2D); @@ -471,7 +436,6 @@ public class PresentationTextData extends AbstractAFPObject { afpdata.write(0x00); break; } - } /** @@ -528,7 +492,6 @@ public class PresentationTextData extends AbstractAFPObject { , b[0] , b[1] }, 0, 4); - } /** @@ -540,11 +503,8 @@ public class PresentationTextData extends AbstractAFPObject { * @param afpdata * The output stream to which data should be written. */ - private void setInterCharacterAdjustment(int incr, - ByteArrayOutputStream afpdata) { - + private void setInterCharacterAdjustment(int incr, ByteArrayOutputStream afpdata) { byte[] b = BinaryUtils.convert(Math.abs(incr), 2); - afpdata.write(new byte[] { 5 // Control sequence length , (byte)0xC3 // Control sequence function type @@ -552,25 +512,17 @@ public class PresentationTextData extends AbstractAFPObject { , b[1] , (byte)(incr >= 0 ? 0 : 1) // Direction }, 0, 5); - } /** - * Accessor method to write the AFP datastream for - * the text data. - * @param os The stream to write to - * @throws java.io.IOException + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - byte[] data = _baos.toByteArray(); + public void writeDataStream(OutputStream os) throws IOException { + byte[] data = baos.toByteArray(); byte[] size = BinaryUtils.convert(data.length - 1, 2); data[1] = size[0]; data[2] = size[1]; - os.write(data); - } /** @@ -583,17 +535,12 @@ public class PresentationTextData extends AbstractAFPObject { * @throws MaximumSizeExceededException */ public void endControlSequence() throws MaximumSizeExceededException { - byte[] data = new byte[2]; data[0] = 0x02; data[1] = (byte) 0xF8; - - if (data.length + _baos.size() > MAX_SIZE) { + if (data.length + baos.size() > MAX_SIZE) { throw new MaximumSizeExceededException(); } - - _baos.write(data, 0, data.length); - + baos.write(data, 0, data.length); } - } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/Registry.java b/src/java/org/apache/fop/render/afp/modca/Registry.java deleted file mode 100644 index b643cd2d2..000000000 --- a/src/java/org/apache/fop/render/afp/modca/Registry.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.afp.modca; - -import java.io.UnsupportedEncodingException; - -import org.apache.commons.logging.LogFactory; - -/** - * MOD:CA object type registry - */ -public final class Registry { - - /** IOB supported object types */ - public static final byte IOCA_FS10 = 5; - public static final byte IOCA_FS11 = 11; - public static final byte IOCA_FS45 = 12; - public static final byte DIB_WIN = 17; //device independent bitmap - public static final byte DIB_OS2 = 18; - public static final byte PCX = 19; - public static final byte GIF = 22; - public static final byte JFIF = 23; // jpeg file interchange format - public static final byte PDF_SINGLE_PAGE = 25; - public static final byte PCL_PAGE_OBJECT = 34; - public static final byte EPS_TRANS = 48; - public static final byte PDF_SINGLE_PAGE_TRANS = 49; - public static final byte JPEG2000 = 58; - - /** IOB unsupported object types */ - public static final byte EPS = 13; - public static final byte TIFF = 14; - public static final byte COM_SETUP_FILE = 15; - public static final byte TAPE_LABEL_SETUP_FILE = 16; - public static final byte CMT = 20; // color mapping table - public static final byte ANACOMP_CONTROL_RECORD = 24; - public static final byte PDF_RESOURCE_OBJECT = 26; - public static final byte IOCA_FS42 = 45; - public static final byte RESIDENT_COLOR_PROFILE = 46; - public static final byte IOCA_FS45_TILE_RESOURCE = 47; - public static final byte FONT = 51; - public static final byte FONT_COLLECTION = 53; - public static final byte RESOURCE_ACCESS_TABLE = 54; - public static final byte IOCA_FS40 = 55; - public static final byte UP3I_PRINT_DATA = 56; - public static final byte COLOR_MANAGEMENT_RESOURCE = 57; - - - /** internal mapping array references */ - private static final int COMPONENT_ID = 0; - private static final int OBJECT_TYPE_NAME = 1; - private static final int OBJECT_ID = 2; - private static final int CAN_BE_INCLUDED = 3; - - private byte[][][] componentIdMap; - - private static Registry instance = null; - - /** - * @return a single instance of Registry - */ - public static Registry getInstance() { - synchronized (instance) { - if (instance == null) { - instance = new Registry(); - } - } - return instance; - } - - private Registry() { - init(); - } - - private void init() { - try { - componentIdMap = new byte[][][] { - /* object type id (OID), object type name, compontent Id, can be included with IOB?, */ - { - {IOCA_FS10}, - "IOCA FS10".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x05}, - {1} - }, - { - {IOCA_FS11}, - "IOCA FS11".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0B}, - {1} - }, - { - {IOCA_FS45}, - "IOCA FS45".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0C}, - {1} - }, - { - {EPS}, - "Encapsulated Postscript".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D}, - {0} - }, - { - {TIFF}, - "TIFF".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E}, - {0} - }, - { - {COM_SETUP_FILE}, - "COM setup".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0F}, - {0} - }, - { - {TAPE_LABEL_SETUP_FILE}, - "Tape Label setup".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x10}, - {0} - }, - { - {DIB_WIN}, - "DIB, Windows Version".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x11}, - {1} - }, - { - {DIB_OS2}, - "DIB, OS/2 PM Version".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x12}, - {1} - }, - { - {PCX}, - "PCX".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x13}, - {1} - }, - { - {CMT}, - "Color Mapping Table (CMT)".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x14}, - {0} - }, - { - {GIF}, - "GIF".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16}, - {1} - }, - { - {JFIF}, - "JFIF".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17}, - {1} - }, - { - {ANACOMP_CONTROL_RECORD}, - "AnaStak Control Record".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x18}, - {0} - }, - { - {PDF_SINGLE_PAGE}, - "PDF Single-page Object".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19}, - {1} - }, - { - {PDF_RESOURCE_OBJECT}, - "PDF Resource Object".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x1A}, - {0} - }, - { - {PCL_PAGE_OBJECT}, - "PCL Page Object".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22}, - {1} - }, - { - {IOCA_FS42}, - "IOCA FS42".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2D}, - {0} - }, - { - {RESIDENT_COLOR_PROFILE}, - "Resident Color Profile".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2E}, - {0} - }, - { - {IOCA_FS45_TILE_RESOURCE}, - "IOCA FS45".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2E}, - {0} - }, - { - {EPS_TRANS}, - "EPS with Transparency".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x30}, - {1} - }, - { - {PDF_SINGLE_PAGE_TRANS}, - "PDF with Transparency".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x31}, - {1} - }, - { - {FONT}, - "TrueType/OpenType Font".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x33}, - {0} - }, - { - {FONT_COLLECTION}, - "TrueType/OpenType Font Collection".getBytes( - AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x35}, - {0} - }, - { - {RESOURCE_ACCESS_TABLE}, - "Resource Access Table".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x36}, - {0} - }, - { - {IOCA_FS40}, - "IOCA FS40".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x37}, - {0} - }, - { - {UP3I_PRINT_DATA}, - "IP3i Print Data".getBytes(AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x38}, - {0} - }, - { - {COLOR_MANAGEMENT_RESOURCE}, - "Color Management Resource (CMR)".getBytes( - AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x39}, - {0} - }, - { - {JPEG2000}, - "JPEG2000 (JP2) File Format".getBytes( - AFPConstants.EBCIDIC_ENCODING), - {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x3A}, - {1} - } - }; - } catch (UnsupportedEncodingException e) { - // should never happen! - LogFactory.getLog("org.apache.fop.render.afp.modca.Registry").error(e.getMessage()); - } - } - - private byte[][][] getComponentIdMap() { - if (componentIdMap == null) { - init(); - } - return componentIdMap; - } - - private byte[][] getMapData(byte compontentId) { - getComponentIdMap(); - for (int i = 0; i < componentIdMap.length; i++) { - if (compontentId == componentIdMap[i][0][0]) { - return componentIdMap[i]; - } - } - return null; - } - - /** - * Returns a registry Entry for a given componentId - * @param compontentId a compontent id - * @return the registry entry for a give componentId - */ - public Entry getEntry(byte compontentId) { - byte[][] data = getMapData(compontentId); - if (data != null) { - return new Registry.Entry(data); - } - return null; - } - - /** - * Encapsulates a MOD:CA Registry Entry - */ - public final class Entry { - private byte[][] data; - - /** - * Main constructor - * @param the map data structure array - */ - private Entry(byte[][] data) { - this.data = data; - } - - /** - * Returns a MOD:CA object type OID from a given a componentId - * @return the corresponding object type id for a given component id - * or null if the component id is unknown and the object type OID was not found. - */ - public byte[] getOID() { - return data[OBJECT_ID]; - } - - /** - * @return the object type name for the given componentId - */ - public byte[] getObjectTypeName() { - return data[OBJECT_TYPE_NAME]; - } - - /** - * @return the compontentId for this entry - */ - public byte[] getComponentId() { - return data[COMPONENT_ID]; - } - - /** - * @return true if this component can be included with an IOB structured field - */ - public boolean canBeIncluded() { - return data[CAN_BE_INCLUDED][0] == 1; - } - } -} diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java index 080226e9f..09d4fabb6 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java @@ -95,7 +95,8 @@ public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup { * @param obj the object to add */ public void addObject(AbstractStructuredAFPObject obj) { - getMapDataResources().add(new MapDataResource(obj)); + // TODO: AC - fix +// getMapDataResources().add(new MapDataResource(obj)); getPreprocessPresentationObjects().add(new PreprocessPresentationObject(obj)); } diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java index 48f4f0eeb..38b9524e6 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java @@ -21,10 +21,13 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +import java.util.Collection; +import java.util.Iterator; import java.util.Map; -import org.apache.fop.render.afp.DataObjectParameters; -import org.apache.fop.render.afp.ImageObjectParameters; +import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.ImageObjectInfo; +import org.apache.fop.render.afp.ResourceInfo; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.tools.StringUtils; import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; @@ -42,13 +45,19 @@ public final class ResourceGroup extends AbstractNamedAFPObject { /** * Mapping of resource uri to data resource object (image/graphic) */ - private Map/**/ resourceMap = null; + private Map/**/ resourceMap = null; + + /** + * This resource groups container + */ + private AbstractResourceGroupContainer container = null; /** * Default constructor + * @param container the resource group container */ - public ResourceGroup() { - this(DEFAULT_NAME); + public ResourceGroup(AbstractResourceGroupContainer container) { + this(DEFAULT_NAME, container); } /** @@ -56,159 +65,86 @@ public final class ResourceGroup extends AbstractNamedAFPObject { * name parameter which must be 8 characters long. * @param name the resource group name */ - public ResourceGroup(String name) { + public ResourceGroup(String name, AbstractResourceGroupContainer container) { super(name); + this.container = container; } - private static final String IMAGE_NAME_PREFIX = "IMG"; - private static final String GRAPHIC_NAME_PREFIX = "GRA"; - private static final String PAGE_SEGMENT_NAME_PREFIX = "PAG"; - private static final String BARCODE_NAME_PREFIX = "BAR"; - private static final String OTHER_NAME_PREFIX = "OTH"; + private static final String RESOURCE_NAME_PREFIX = "RES"; + private static final String INCLUDE_NAME_PREFIX = "INC"; /** - * Converts a byte array containing 24 bit RGB image data to a grayscale - * image. - * - * @param io - * the target image object - * @param raw - * the buffer containing the RGB image data - * @param width - * the width of the image in pixels - * @param height - * the height of the image in pixels - * @param bitsPerPixel - * the number of bits to use per pixel - */ - private static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, - int height, int bitsPerPixel) { - int pixelsPerByte = 8 / bitsPerPixel; - int bytewidth = (width / pixelsPerByte); - if ((width % pixelsPerByte) != 0) { - bytewidth++; - } - byte[] bw = new byte[height * bytewidth]; - byte ib; - for (int y = 0; y < height; y++) { - ib = 0; - int i = 3 * y * width; - for (int x = 0; x < width; x++, i += 3) { - - // see http://www.jguru.com/faq/view.jsp?EID=221919 - double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d - * ((int) raw[i + 1] & 0xff) + 0.072169d - * ((int) raw[i + 2] & 0xff); - switch (bitsPerPixel) { - case 1: - if (greyVal < 128) { - ib |= (byte) (1 << (7 - (x % 8))); - } - break; - case 4: - greyVal /= 16; - ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4)); - break; - case 8: - ib = (byte) greyVal; - break; - default: - throw new UnsupportedOperationException( - "Unsupported bits per pixel: " + bitsPerPixel); - } - - if ((x % pixelsPerByte) == (pixelsPerByte - 1) - || ((x + 1) == width)) { - bw[(y * bytewidth) + (x / pixelsPerByte)] = ib; - ib = 0; - } - } - } - io.setImageIDESize((byte) bitsPerPixel); - io.setImageData(bw); - } - - /** - * Helper method to create an image on the current container and to return + * Helper method to create a new resource object in the current container and to return * the object. - * @param params the set of image object parameters - * @return a newly created image object + * @return a newly created resource object */ - private ImageObject createImage(ImageObjectParameters params) { - String name = IMAGE_NAME_PREFIX - + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); - ImageObject imageObj = new ImageObject(name); - if (params.hasCompression()) { - int compression = params.getCompression(); - switch (compression) { - case TIFFImage.COMP_FAX_G3_1D: - imageObj.setImageEncoding(ImageContent.COMPID_G3_MH); - break; - case TIFFImage.COMP_FAX_G3_2D: - imageObj.setImageEncoding(ImageContent.COMPID_G3_MR); - break; - case TIFFImage.COMP_FAX_G4_2D: - imageObj.setImageEncoding(ImageContent.COMPID_G3_MMR); - break; - default: - throw new IllegalStateException( - "Invalid compression scheme: " + compression); - } - } - imageObj.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, - FullyQualifiedNameTriplet.FORMAT_URL, params.getUri()); - imageObj.setImageParameters(params.getWidthRes(), params.getHeightRes(), - params.getImageDataWidth(), params.getImageDataHeight()); - if (params.isColor()) { - imageObj.setImageIDESize((byte)24); - imageObj.setImageData(params.getData()); - } else { - convertToGrayScaleImage(imageObj, params.getData(), - params.getImageDataWidth(), params.getImageDataHeight(), - params.getBitsPerPixel()); - } - return imageObj; + private ResourceObject createResourceObject() { + String name = RESOURCE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); + ResourceObject resource = new ResourceObject(name); + return resource; } - /** - * Helper method to create a graphic in the current container and to return - * the object. - * @param params the data object parameters - * @return a newly created graphics object - */ - private GraphicsObject createGraphic(DataObjectParameters params) { - String name = GRAPHIC_NAME_PREFIX - + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); - GraphicsObject graphicsObj = new GraphicsObject(name); - return graphicsObj; - } +// /** +// * Helper method to create a new resource object in the current container and to return +// * the object. +// * @return a newly created resource object +// */ +// private IncludeObject createIncludeObject() { +// String name = INCLUDE_NAME_PREFIX +// + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); +// IncludeObject includeObj = new IncludeObject(name); +// return includeObj; +// } /** - * Adds a data object to this resource group - * @param params the data object parameters + * Creates a data object in this resource group + * @param info the data object info * @return an include object reference */ - public IncludeObject addObject(DataObjectParameters params) { - ResourceObject resourceObj = (ResourceObject)getResourceMap().get(params.getUri()); - if (resourceObj == null) { + public IncludeObject createObject(DataObjectInfo info) { + IncludeObject includeObj = (IncludeObject)getResourceMap().get(info.getUri()); + if (includeObj == null) { AbstractDataObject dataObj; - if (params instanceof ImageObjectParameters) { - dataObj = createImage((ImageObjectParameters)params); + if (info instanceof ImageObjectInfo) { + dataObj = container.createImage((ImageObjectInfo)info); + } else { + dataObj = container.createGraphic(); + } + + ResourceInfo resourceInfo = info.getResourceInfo(); + String resourceName = resourceInfo.getName(); + if (resourceInfo.isExternal()) { + ObjectContainer objectContainer = new ObjectContainer(resourceName, dataObj, info); } else { - dataObj = createGraphic(params); + } + + // Wrap the data object in a page segment + PageSegment pageSegment = container.createPageSegment(); + pageSegment.addObject(dataObj); + + // TODO: AC - rotation? int rotation = 0; - dataObj.setViewport(params.getX(), params.getY(), - params.getWidth(), params.getHeight(), - params.getWidthRes(), params.getHeightRes(), rotation); + dataObj.setViewport(info.getX(), info.getY(), + info.getWidth(), info.getHeight(), + info.getWidthRes(), info.getHeightRes(), rotation); - // Wrap the data object in a resource object - resourceObj = new ResourceObject(dataObj.getName(), dataObj); - getResourceMap().put(params.getUri(), resourceObj); + includeObj.setResourceInfo(resourceInfo); + + // If resource is to be stored externally, + // wrap the page segment in a resource object + if (resourceInfo.isExternal()) { + ResourceObject resource = createResourceObject(); + resource.setReferencedObject(pageSegment); + includeObj = new IncludeObject(resource); + } else { + includeObj = new IncludeObject(pageSegment); + } + // Add include object to resource map + getResourceMap().put(info.getUri(), includeObj); } - IncludeObject includeObj = new IncludeObject(resourceObj); //includeObj.setObjectAreaSize(params.getX(), params.getY()); return includeObj; } @@ -218,7 +154,7 @@ public final class ResourceGroup extends AbstractNamedAFPObject { */ public int getResourceCount() { if (resourceMap != null) { - return resourceMap.size(); + return resourceMap.size(); } return 0; } @@ -250,7 +186,13 @@ public final class ResourceGroup extends AbstractNamedAFPObject { */ public void writeContent(OutputStream os) throws IOException { if (resourceMap != null) { - super.writeObjects(resourceMap.values(), os); + Collection includes = resourceMap.values(); + Iterator it = includes.iterator(); + while (it.hasNext()) { + IncludeObject includeObj = (IncludeObject)it.next(); + AbstractStructuredAFPObject obj = includeObj.getReferencedObject(); + obj.writeDataStream(os); + } } } diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java index ff660a208..c0d4d88df 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java @@ -22,6 +22,7 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.ResourceInfo; import org.apache.fop.render.afp.modca.triplets.Triplet; import org.apache.fop.render.afp.tools.BinaryUtils; @@ -48,19 +49,37 @@ public class ResourceObject extends AbstractPreparedAFPObject { private static final byte FORMDEF_OBJECT = (byte) 0xFE; /** - * the resource object + * the referenced data object */ - private AbstractNamedAFPObject resourceObj = null; - + private AbstractNamedAFPObject dataObj = null; + /** * Default constructor * * @param name the name of this resource (reference id) - * @param resourceObj the resource object to be added + * @param dataObj the resource object to be added */ - public ResourceObject(String name, AbstractNamedAFPObject resourceObj) { + public ResourceObject(String name) { super(name); - this.resourceObj = resourceObj; + } + + /** + * Sets the data object referenced by this resource object + * @param dataObj the data object + */ + public void setReferencedObject(AbstractNamedAFPObject dataObj) { + this.dataObj = dataObj; + setResourceObjectType(dataObj); + } + + /** + * @return the resource object contained in this envelope + */ + public AbstractNamedAFPObject getReferencedObject() { + return this.dataObj; + } + + private void setResourceObjectType(AbstractNamedAFPObject resourceObj) { byte type; if (resourceObj instanceof ImageObject) { type = IMAGE_OBJECT; @@ -76,19 +95,8 @@ public class ResourceObject extends AbstractPreparedAFPObject { throw new UnsupportedOperationException( "Unsupported resource object type " + resourceObj); } - setResourceObjectType(type); - } - - private void setResourceObjectType(byte type) { getTriplets().add(new ResourceObjectTypeTriplet(type)); } - - /** - * @return the resource object contained in this envelope - */ - public AbstractNamedAFPObject getResource() { - return this.resourceObj; - } /** * {@inheritDoc} @@ -127,8 +135,8 @@ public class ResourceObject extends AbstractPreparedAFPObject { */ protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); // write triplets - if (resourceObj != null) { - resourceObj.writeDataStream(os); + if (dataObj != null) { + dataObj.writeDataStream(os); } } @@ -158,6 +166,13 @@ public class ResourceObject extends AbstractPreparedAFPObject { os.write(data); } + /** + * {@inheritDoc} + */ + public String toString() { + return this.getName(); + } + private class ResourceObjectTypeTriplet extends Triplet { private static final byte RESOURCE_OBJECT = 0x21; diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java index 23c0d7e6b..e1a36b4da 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java @@ -37,6 +37,10 @@ /* $Id: $ */ package org.apache.fop.render.afp.modca.triplets; +import java.io.UnsupportedEncodingException; + +import org.apache.fop.render.afp.modca.AFPConstants; + /** * A Fully Qualified Name triplet enable the identification and referencing of @@ -75,28 +79,39 @@ public class FullyQualifiedNameTriplet extends Triplet { public static final byte FORMAT_OID = (byte)0x10; public static final byte FORMAT_URL = (byte)0x20; - private byte[] fqName; + private byte[] nameBytes; /** * @return the actual fully qualified name of this triplet */ public byte[] getFullyQualifiedName() { - return fqName; + return nameBytes; } /** * Main constructor - * @param fqnType the fully qualified name type - * @param fqnFmt the fully qualified name format - * @param fqName the fully qualified name + * @param type the fully qualified name type + * @param format the fully qualified name format + * @param name the fully qualified name */ - public FullyQualifiedNameTriplet(byte fqnType, byte fqnFmt, byte[] fqName) { + public FullyQualifiedNameTriplet(byte type, byte format, byte[] name) { super(FULLY_QUALIFIED_NAME); - this.fqName = fqName; - super.data = new byte[2 + fqName.length]; - data[0] = fqnType; - data[1] = fqnFmt; + this.nameBytes = name; + super.data = new byte[2 + name.length]; + data[0] = type; + data[1] = format; // FQName - System.arraycopy(fqName, 0, data, 2, fqName.length); + System.arraycopy(name, 0, data, 2, name.length); + } + + /** + * {@inheritDoc} + */ + public String toString() { + try { + return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException e) { + } + return null; } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java index 4d5f41359..28c3dca4e 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java @@ -19,52 +19,83 @@ package org.apache.fop.render.afp.modca.triplets; -import org.apache.fop.render.afp.modca.Registry; +import org.apache.fop.render.afp.modca.ObjectTypeRegistry; /** * The Object Classification is used to classify and identify object data. * The object data may or may not be defined by an IBM presentation architecture */ -public class ObjectClassificationTriplet extends Triplet { +public class ObjectClassificationTriplet extends Triplet { + + /** + * The scope of this object is the including page or overlay + */ public static final byte CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT = 0x01; + + /** + * The scope of this object is not defined + */ public static final byte CLASS_TIME_VARIANT_PRESENTATION_OBJECT = 0x10; + + /** + * This is not a presentation object, the scope of this object is not defined + */ public static final byte CLASS_EXECUTABLE_PROGRAM = 0x20; + + /** + * Setup information file, document level. This is not a presentation object, + */ public static final byte CLASS_SETUP_FILE = 0x30; + + /** + * This is a resource used by a presentation object that may itself be a resource. + * The scope of the resource is the object that uses the resource. + */ public static final byte CLASS_SECONDARY_RESOURCE = 0x40; + + /** + * Data object font. This is a non-FOCA font resource used to present + * text in a data object. The scope of the resource is the object that + * uses the resource. + */ public static final byte CLASS_DATA_OBJECT_FONT = 0x41; - + /** * Main constructor * * @param objectClass * the object class type - * @param componentId - * the object componentId + * @param entry + * the object type registry entry + * @param strucFlgs + * the structured flags pertaining to this object classification triplet */ - public ObjectClassificationTriplet(byte objectClass, byte componentId) { + public ObjectClassificationTriplet(byte objectClass, ObjectTypeRegistry.ObjectType entry, + StrucFlgs strucFlgs) { super(OBJECT_CLASSIFICATION); byte[] data = new byte[93]; data[0] = 0x00; // reserved (must be zero) data[1] = objectClass; // ObjClass data[2] = 0x00; // reserved (must be zero) data[3] = 0x00; // reserved (must be zero) - data[4] = 0x00; // StrucFlgs - Information on the structure of the object container + // StrucFlgs - Information on the structure of the object container + data[4] = strucFlgs.getValue(); data[5] = 0x00; // StrucFlgs - Registry.Entry entry = Registry.getInstance().getEntry(componentId); - if (entry == null) { - throw new UnsupportedOperationException("unknown registry entry " + componentId); + throw new UnsupportedOperationException("Unknown registry entry"); } + + byte[] oid = entry.getOID(); // RegObjId - MOD:CA-registered ASN.1 OID for object type (8-23) - System.arraycopy(entry.getOID(), 0, data, 6, entry.getOID().length); + System.arraycopy(oid, 0, data, 6, oid.length); + byte[] objectTypeName = entry.getName(); // ObjTpName - name of object type (24-55) - System.arraycopy(entry.getObjectTypeName(), 0, data, 22, - entry.getObjectTypeName().length); + System.arraycopy(objectTypeName, 0, data, 22, objectTypeName.length); // ObjLev (not specified) - Release level or version number of object type (56-63) // CompName (not specified) - Name of company or org that owns object definition (64-95) - } + } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/StrucFlgs.java b/src/java/org/apache/fop/render/afp/modca/triplets/StrucFlgs.java new file mode 100644 index 000000000..87601c435 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/StrucFlgs.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.afp.modca.triplets; + +/** + * Used by ObjectClassificationTriplet to provide + * information on the structure of the object and its container + */ +public class StrucFlgs { + private static final int OBJECT_DATA_NOT_CARRIED_IN_OBJECT_CONTAINER = 1; + private static final int OBJECT_DATA_OBJECT_CONTAINER_STRUCTURE_UNKNOWN = 2; + private static final int OBJECT_DATA_CARRIED_IN_OBJECT_CONTAINER = 3; + + private static final int OBJECT_CONTAINER_NOT_INCLUDE_OBJECT_ENVIRONMENT_GROUP = 4; + private static final int OBJECT_CONTAINER_OBJECT_ENVIRONMENT_GROUP_CONTAINMENT_UNKNOWN = 8; + private static final int OBJECT_CONTAINER_INCLUDES_OBJECT_ENVIRONMENT_GROUP = 12; + + private static final int OBJECT_CONTAINER_DATA_NOT_CARRIED_IN_OBJECT_DATA = 16; + private static final int OBJECT_CONTAINER_DATA_OBJECT_DATA_CONTAINMENT_UNKNOWN = 32; + private static final int OBJECT_CONTAINER_DATA_CARRIES_OBJECT_DATA = 48; + + private byte value = 0; + + /** + * Main constructor + * @param dataInContainer true if the object data in carried in the object container + * @param containerHasOEG true if the object container has an object environment group + * @param dataInOCD true if the object container data carries the object data + */ + public StrucFlgs(boolean dataInContainer, boolean containerHasOEG, boolean dataInOCD) { + if (dataInContainer) { + this.value += OBJECT_DATA_CARRIED_IN_OBJECT_CONTAINER; + } else { + this.value += OBJECT_DATA_NOT_CARRIED_IN_OBJECT_CONTAINER; + } + if (containerHasOEG) { + this.value += OBJECT_CONTAINER_INCLUDES_OBJECT_ENVIRONMENT_GROUP; + } else { + this.value += OBJECT_CONTAINER_NOT_INCLUDE_OBJECT_ENVIRONMENT_GROUP; + } + if (dataInOCD) { + this.value += OBJECT_CONTAINER_DATA_CARRIES_OBJECT_DATA; + } else { + this.value += OBJECT_CONTAINER_DATA_NOT_CARRIED_IN_OBJECT_DATA; + } + } + + /** + * Default constructor + */ + public StrucFlgs() { + this.value = OBJECT_DATA_OBJECT_CONTAINER_STRUCTURE_UNKNOWN + + OBJECT_CONTAINER_OBJECT_ENVIRONMENT_GROUP_CONTAINMENT_UNKNOWN + + OBJECT_CONTAINER_DATA_OBJECT_DATA_CONTAINMENT_UNKNOWN; + } + + /** + * @return the value of structure flags value + */ + public byte getValue() { + return this.value; + } +} \ No newline at end of file -- cgit v1.2.3 From 309f4e2998c676913e64070adda8dca5e3768fad Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 14 Apr 2008 13:05:52 +0000 Subject: Merged revisions 647692,647742,647745 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ................ r647692 | jeremias | 2008-04-14 09:25:22 +0100 (Mon, 14 Apr 2008) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-615152" from https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ProcessingFeedback ................ r647742 | jeremias | 2008-04-14 12:53:29 +0100 (Mon, 14 Apr 2008) | 298 lines 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). ........ ................ r647745 | jeremias | 2008-04-14 13:01:06 +0100 (Mon, 14 Apr 2008) | 1 line svnmerge didn't work for me in this case. Remove svn merge info. ................ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@647787 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 +- .../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 | 24 +- .../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 +- .../org/apache/fop/render/afp/AFPSVGHandler.java | 3 +- .../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 | 3 + .../ps/extensions/PSCommentBeforeElement.java | 3 + .../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, 9158 insertions(+), 1624 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/java') 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 495983750..502fb07b8 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.Map; 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/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 c0c9ce88c..185aed817 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -30,12 +30,16 @@ 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; /** @@ -73,7 +77,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 +87,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 +120,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 e50e77830..629a7b62f 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -69,6 +69,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; @@ -295,7 +296,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 ", @@ -908,7 +911,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)); context.setProperty(AFPRendererContextConstants.AFP_FONT_INFO, this.fontInfo); context.setProperty(AFPRendererContextConstants.AFP_RESOLUTION, @@ -1045,13 +1048,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); } finally { if (in != null) { IOUtils.closeQuietly(in); @@ -1217,7 +1224,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { //memory consumption (see PostScript output) ImageEncodingHelper.encodeRenderedImageAsRGB(image, baout); } catch (IOException ioe) { - log.error("Error while serializing bitmap: " + ioe.getMessage(), ioe); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageWritingError(this, ioe); return; } //int res = getResolution(); @@ -1363,8 +1372,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/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 0d3b864b0..939892648 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -113,8 +113,7 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { if (cfg != null) { strokeText = cfg.getChild("stroke-text", true).getValueAsBoolean(strokeText); } - final float uaResolution = context.getUserAgent().getSourceResolution(); - SVGUserAgent svgUserAgent = new SVGUserAgent(25.4f / uaResolution, new AffineTransform()); + SVGUserAgent svgUserAgent = new SVGUserAgent(context.getUserAgent(), new AffineTransform()); BridgeContext ctx = new BridgeContext(svgUserAgent); AFPTextHandler afpTextHandler = null; 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 55524534e..d2c8446eb 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 @@ -1811,18 +1809,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 4bbfa0c73..d03a0220c 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,9 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; */ public class PSCommentAfterElement extends AbstractPSCommentElement { + /** the element name */ + protected static final String ELEMENT = "ps-comment-after"; + /** * Main constructor * @param parent node 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 f05e7c7fe..d74d3a194 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,9 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; */ public class PSCommentBeforeElement extends AbstractPSCommentElement { + /** the element name */ + protected static final String ELEMENT = "ps-comment-before"; + /** * Main constructor * @param parent parent node 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 bf8220d231490280738f0fb7629f329bf332b2f0 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 15 Apr 2008 08:53:51 +0000 Subject: Merged revisions 647770,648122 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r647770 | jeremias | 2008-04-14 13:41:00 +0100 (Mon, 14 Apr 2008) | 1 line Fixed a possible follow-up NPE when the TTC cannot be loaded. ........ r648122 | jeremias | 2008-04-15 07:07:00 +0100 (Tue, 15 Apr 2008) | 1 line A note about the generation of event-model.xml. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@648187 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/events.xml | 6 ++++++ src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src/java') 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 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 592835167ab8951f61d1590197f646984588d070 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 16 Apr 2008 08:21:34 +0000 Subject: Merged revisions 648381 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r648381 | jeremias | 2008-04-15 20:18:46 +0100 (Tue, 15 Apr 2008) | 1 line 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/branches/Temp_AFPGOCAResources@648611 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/java') 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 18e3a8208cc7e574e8fd4183efd99d4107ba19d0 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 16 Apr 2008 12:03:15 +0000 Subject: Further reworking and refinements. Not a working model yet. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@648675 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/afp/AFPGraphics2D.java | 14 +- .../fop/render/afp/AFPGraphics2DAdapter.java | 24 ++- .../org/apache/fop/render/afp/AFPRenderer.java | 43 +++-- .../org/apache/fop/render/afp/AFPSVGHandler.java | 26 +-- .../org/apache/fop/render/afp/DataObjectInfo.java | 68 ++++--- .../org/apache/fop/render/afp/ResourceInfo.java | 2 +- .../render/afp/goca/AbstractGraphicsContainer.java | 95 ---------- .../apache/fop/render/afp/goca/GraphicsArea.java | 4 +- .../render/afp/goca/GraphicsChainedSegment.java | 17 +- .../apache/fop/render/afp/goca/GraphicsData.java | 9 +- .../fop/render/afp/goca/GraphicsImageData.java | 5 +- .../apache/fop/render/afp/modca/AFPDataStream.java | 57 ++++-- .../fop/render/afp/modca/AFPDataStreamWriter.java | 36 ++++ .../fop/render/afp/modca/AbstractAFPObject.java | 10 +- .../fop/render/afp/modca/AbstractDataObject.java | 3 +- .../fop/render/afp/modca/AbstractPageObject.java | 24 --- .../afp/modca/AbstractPreparedAFPObject.java | 8 + .../afp/modca/AbstractPreparedObjectContainer.java | 96 ++++++++++ .../AbstractResourceEnvironmentGroupContainer.java | 3 + .../afp/modca/AbstractResourceGroupContainer.java | 13 +- .../afp/modca/AbstractStructuredAFPObject.java | 3 +- .../fop/render/afp/modca/DataObjectAccessor.java | 31 ++++ .../fop/render/afp/modca/GraphicsObject.java | 42 ++--- .../apache/fop/render/afp/modca/IncludeObject.java | 87 +++++---- .../fop/render/afp/modca/MapDataResource.java | 8 +- .../fop/render/afp/modca/ObjectContainer.java | 133 +++++++++----- .../fop/render/afp/modca/ObjectTypeRegistry.java | 204 --------------------- .../org/apache/fop/render/afp/modca/Registry.java | 200 ++++++++++++++++++++ .../apache/fop/render/afp/modca/ResourceGroup.java | 98 ++++------ .../fop/render/afp/modca/ResourceObject.java | 83 +++++---- .../modca/triplets/FullyQualifiedNameTriplet.java | 5 +- .../modca/triplets/MeasurementUnitsTriplet.java | 3 +- .../afp/modca/triplets/ObjectAreaSizeTriplet.java | 3 +- .../triplets/ObjectClassificationTriplet.java | 84 +++++++-- .../fop/render/afp/modca/triplets/Triplet.java | 19 +- 35 files changed, 875 insertions(+), 685 deletions(-) delete mode 100644 src/java/org/apache/fop/render/afp/goca/AbstractGraphicsContainer.java create mode 100644 src/java/org/apache/fop/render/afp/modca/AFPDataStreamWriter.java create mode 100644 src/java/org/apache/fop/render/afp/modca/AbstractPreparedObjectContainer.java create mode 100644 src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java delete mode 100644 src/java/org/apache/fop/render/afp/modca/ObjectTypeRegistry.java create mode 100644 src/java/org/apache/fop/render/afp/modca/Registry.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java index 974155630..f8737d91a 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java @@ -486,13 +486,13 @@ public class AFPGraphics2D extends AbstractGraphics2D { this.customTextHandler = handler; } - /** - * Sets the SVG document URI - * @param documentURI the SVG document URI - */ - public void setDocumentURI(String documentURI) { - this.documentURI = documentURI; - } +// /** +// * Sets the SVG document URI +// * @param documentURI the SVG document URI +// */ +// public void setDocumentURI(String documentURI) { +// this.documentURI = documentURI; +// } /** * @return the GOCA graphics object diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index af8c7fedf..1531e6d86 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -22,8 +22,13 @@ package org.apache.fop.render.afp; import java.awt.image.BufferedImage; import java.io.IOException; +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.java2d.Graphics2DImagePainter; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.RendererContext; @@ -48,16 +53,23 @@ public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter { Boolean grayObj = (Boolean)context.getProperty(AFPRendererContextConstants.AFP_GRAYSCALE); boolean gray = (grayObj != null ? grayObj.booleanValue() : false); + FOUserAgent userAgent = context.getUserAgent(); + //Paint to a BufferedImage - int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); + int resolution = (int)Math.round(userAgent.getTargetResolution()); BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, gray, false); + ImageManager manager = userAgent.getFactory().getImageManager(); + ImageSessionContext sessionContext = userAgent.getImageSessionContext(); //TODO: AC - fix -// String uri = null; -// java.util.Map foreignAttributes = null; -// ImageInfo imageInfo = new ImageInfo(); -// afp.drawBufferedImage(uri, bi, resolution, x, y, width, height, foreignAttributes); + String uri = null; + + try { + ImageInfo info = manager.getImageInfo(uri, sessionContext); + java.util.Map foreignAttributes = null; + afp.drawBufferedImage(info, bi, resolution, x, y, width, height, foreignAttributes); + } catch (ImageException e) { + } } - } diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 629a7b62f..526fc43f3 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -344,7 +344,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { public void startRenderer(OutputStream outputStream) throws IOException { currentPageFonts = new java.util.HashMap(); currentColor = new Color(255, 255, 255); - afpDataStream = new AFPDataStream(); + this.afpDataStream = new AFPDataStream(); afpDataStream.setPortraitRotation(portraitRotation); afpDataStream.setLandscapeRotation(landscapeRotation); afpDataStream.setOutputStream(outputStream); @@ -354,7 +354,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ public void stopRenderer() throws IOException { - afpDataStream.write(); + getAFPDataStream().write(); + afpDataStream = null; } /** @@ -391,7 +392,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // renderPageGroupExtensions(page); final int pageRotation = 0; - this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation, + getAFPDataStream().startPage(pageWidth, pageHeight, pageRotation, getResolution(), getResolution()); renderPageObjectExtensions(page); @@ -399,7 +400,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (this.pages == null) { this.pages = new java.util.HashMap(); } - this.pages.put(page, afpDataStream.savePage()); + this.pages.put(page, getAFPDataStream().savePage()); } @@ -620,13 +621,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (pages != null && pages.containsKey(pageViewport)) { - this.afpDataStream.restorePage((PageObject) pages.remove(pageViewport)); + getAFPDataStream().restorePage((PageObject) pages.remove(pageViewport)); } else { // renderPageGroupExtensions(page); final int pageRotation = 0; - this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation, + getAFPDataStream().startPage(pageWidth, pageHeight, pageRotation, getResolution(), getResolution()); renderPageObjectExtensions(pageViewport); @@ -641,14 +642,14 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { while (i.hasNext()) { AFPFontAttributes afpFontAttributes = (AFPFontAttributes) i.next(); - afpDataStream.createFont( + getAFPDataStream().createFont( (byte)afpFontAttributes.getFontReference(), afpFontAttributes.getFont(), afpFontAttributes.getPointSize()); } - afpDataStream.endPage(); + getAFPDataStream().endPage(); popViewPortPos(); } @@ -702,7 +703,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { currentColor.getGreen(), currentColor.getBlue()); */ - afpDataStream.createLine( + getAFPDataStream().createLine( pts2units(x), pts2units(y), pts2units(x + width), @@ -722,6 +723,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { log.error("Negative extent received. Border won't be painted."); return; } + switch (style) { case Constants.EN_DOUBLE: if (horz) { @@ -947,7 +949,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { String name = (String)getPageSegments().get(uri); if (name != null) { - afpDataStream.createIncludePageSegment(name, mpts2units(x), mpts2units(y)); + getAFPDataStream().createIncludePageSegment(name, mpts2units(x), mpts2units(y)); } else { ImageManager manager = getUserAgent().getFactory().getImageManager(); ImageInfo info = null; @@ -1007,7 +1009,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { imageObjectInfo.setCompression(ccitt.getCompression()); imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); - afpDataStream.createObject(imageObjectInfo); + getAFPDataStream().createObject(imageObjectInfo); // ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph, @@ -1251,7 +1253,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { imageObjectInfo.setBitsPerPixel(bitsPerPixel); imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); - AbstractNamedAFPObject obj = afpDataStream.createObject(imageObjectInfo); + //AbstractNamedAFPObject obj = + getAFPDataStream().createObject(imageObjectInfo); // ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, // afph, afpres, afpres); // io.setImageParameters(imageResolution, imageResolution, @@ -1379,7 +1382,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } try { - afpDataStream.createText( + getAFPDataStream().createText( afpFontAttributes.getFontReference(), mpts2units(rx), mpts2units(bl), @@ -1596,7 +1599,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) { String overlay = aps.getName(); if (overlay != null) { - afpDataStream.createIncludePageOverlay(overlay); + getAFPDataStream().createIncludePageOverlay(overlay); } } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT .equals(element)) { @@ -1607,11 +1610,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { .equals(element)) { String name = aps.getName(); String value = aps.getValue(); - afpDataStream.createTagLogicalElement(name, value); + getAFPDataStream().createTagLogicalElement(name, value); } else if (AFPElementMapping.NO_OPERATION.equals(element)) { String content = aps.getContent(); if (content != null) { - afpDataStream.createNoOperation(content); + getAFPDataStream().createNoOperation(content); } } // else if (AFPElementMapping.RESOURCE.equals(element)) { @@ -1814,14 +1817,14 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private void pushViewPortPos(ViewPortPos vpp) { viewPortPositions.add(vpp); - afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); + getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot); } private void popViewPortPos() { 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); + getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot); } } @@ -1913,7 +1916,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** {@inheritDoc} */ public void startPageSequence(LineArea seqTitle) { - afpDataStream.endPageGroup(); - afpDataStream.startPageGroup(); + getAFPDataStream().endPageGroup(); + getAFPDataStream().startPageGroup(); } } diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 939892648..86c26d74f 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -30,15 +30,12 @@ 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.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.render.afp.modca.AFPDataStream; import org.apache.fop.render.afp.modca.GraphicsObject; -import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.fop.svg.SVGUserAgent; import org.w3c.dom.Document; @@ -60,10 +57,10 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { } /** - * Get the afp information from the render context. + * Get the AFP information from the render context. * * @param context the renderer context - * @return the afp information retrieved from the context + * @return the AFP information retrieved from the context */ public static AFPInfo getAFPInfo(RendererContext context) { AFPInfo afpi = new AFPInfo(); @@ -103,9 +100,6 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); graphics.setAFPInfo(afpInfo); - String uri = ((AbstractDocument)doc).getDocumentURI(); - graphics.setDocumentURI(uri); - GVTBuilder builder = new GVTBuilder(); boolean strokeText = false; @@ -160,7 +154,9 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { // set the data object parameters DataObjectInfo info = new DataObjectInfo(); - info.setUri(uri); + + String docUri = ((AbstractDocument)doc).getDocumentURI(); + info.setUri(docUri); info.setX(x); info.setY(y); info.setWidth(width); @@ -170,14 +166,11 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { Map/**/ foreignAttributes = (Map/**/)context.getProperty( RendererContextConstants.FOREIGN_ATTRIBUTES); - if (foreignAttributes != null) { - info.setResourceInfoFromForeignAttributes(foreignAttributes); - } + info.setResourceInfoFromForeignAttributes(foreignAttributes); - //TODO: AC - fix -// IncludeObject includeObj = afpInfo.getAFPDataStream().createObject(info); -// GraphicsObject graphicsObj = (GraphicsObject)includeObj.getReferencedObject(); -// graphics.setGraphicsObject(graphicsObj); + AFPDataStream afpDataStream = afpInfo.getAFPDataStream(); + GraphicsObject graphicsObj = (GraphicsObject)afpDataStream.createObject(info); + graphics.setGraphicsObject(graphicsObj); try { root.paint(graphics); @@ -203,5 +196,4 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, Boolean.FALSE); } - } diff --git a/src/java/org/apache/fop/render/afp/DataObjectInfo.java b/src/java/org/apache/fop/render/afp/DataObjectInfo.java index d363dd5ea..58fbd11b1 100644 --- a/src/java/org/apache/fop/render/afp/DataObjectInfo.java +++ b/src/java/org/apache/fop/render/afp/DataObjectInfo.java @@ -25,14 +25,20 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.render.afp.extensions.AFPElementMapping; -import org.apache.fop.render.afp.modca.ObjectTypeRegistry; -import org.apache.fop.render.afp.modca.ObjectTypeRegistry.ObjectType; -import org.apache.fop.util.QName; +import org.apache.fop.render.afp.modca.Registry; +import org.apache.fop.render.afp.modca.Registry.ObjectType; +import org.apache.xmlgraphics.util.QName; /** * A list of parameters associated with an AFP data objects */ public class DataObjectInfo { + private static final Log log = LogFactory.getLog("org.apache.fop.afp"); + + private static final String RESOURCE_NAME = "afp:resource-name"; + private static final String RESOURCE_LEVEL = "afp:resource-level"; + private static final String RESOURCE_GROUP_FILE = "afp:resource-group-file"; + private static final ResourceInfo DEFAULT_RESOURCE_INFO = new ResourceInfo(); private String uri; @@ -42,16 +48,19 @@ public class DataObjectInfo { private int height; private int widthRes; private int heightRes; + private int rotation = 0; - // object type entry - private ObjectType objectTypeEntry; + /** object type entry */ + private ObjectType objectType; + + /** resource info */ private ResourceInfo resourceInfo = DEFAULT_RESOURCE_INFO; /** * Sets the data object uri * @param uri the data object uri */ - protected void setUri(String uri) { + public void setUri(String uri) { this.uri = uri; } @@ -159,18 +168,33 @@ public class DataObjectInfo { } /** - * Sets the object type entry - * @param entry the object type entry + * @return the rotation of this data object + */ + public int getRotation() { + return rotation; + } + + /** + * Sets the data object rotation + * @param rotation the data object rotation + */ + protected void setRotation(int rotation) { + this.rotation = rotation; + } + + /** + * Sets the object type + * @param objectType the object type */ - public void setObjectType(ObjectTypeRegistry.ObjectType entry) { - this.objectTypeEntry = entry; + public void setObjectType(Registry.ObjectType objectType) { + this.objectType = objectType; } /** * @return the object type entry */ - protected ObjectType getObjectTypeEntry() { - return objectTypeEntry; + protected ObjectType getObjectType() { + return objectType; } /** @@ -188,17 +212,12 @@ public class DataObjectInfo { this.resourceInfo = resourceInfo; } - - private static final String RESOURCE_NAME = "afp:resource-name"; - private static final String RESOURCE_LEVEL = "afp:resource-level"; - private static final String RESOURCE_GROUP_FILE = "afp:resource-group-file"; - /** * Sets the resource group settings using the given foreign attributes * @param foreignAttributes a mapping of element attributes names to values */ public void setResourceInfoFromForeignAttributes(Map/**/ foreignAttributes) { - if (foreignAttributes != null) { + if (foreignAttributes != null && !foreignAttributes.isEmpty()) { this.resourceInfo = new ResourceInfo(); QName resourceNameKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_NAME); String resourceName = (String)foreignAttributes.get(resourceNameKey); @@ -214,15 +233,19 @@ public class DataObjectInfo { RESOURCE_GROUP_FILE); String resourceExternalDest = (String)foreignAttributes.get(resourceGroupFileKey); + if (resourceExternalDest == null) { + String msg = RESOURCE_GROUP_FILE + " not specified"; + log.warn(msg); + throw new UnsupportedOperationException(msg); + } File resourceExternalGroupFile = new File(resourceExternalDest); if (resourceExternalGroupFile.canWrite()) { resourceInfo.setExternalResourceGroupFile(resourceExternalGroupFile); } } } else { - Log log = LogFactory.getLog("org.apache.fop.afp"); - log.warn("invalid resource level '" + level - + "', using default document level"); + String msg = RESOURCE_LEVEL + " is null or not valid"; + log.warn(msg); } } } @@ -239,7 +262,8 @@ public class DataObjectInfo { + ", height=" + height + ", widthRes=" + widthRes + ", heightRes=" + heightRes + + ", rotation=" + rotation + (resourceInfo != null ? ", resourceInfo=" + resourceInfo : "") - + (objectTypeEntry != null ? ", objectTypeEntry=" + objectTypeEntry : ""); + + (objectType != null ? ", objectTypeEntry=" + objectType : ""); } } diff --git a/src/java/org/apache/fop/render/afp/ResourceInfo.java b/src/java/org/apache/fop/render/afp/ResourceInfo.java index 5c39d48b0..86add31d2 100644 --- a/src/java/org/apache/fop/render/afp/ResourceInfo.java +++ b/src/java/org/apache/fop/render/afp/ResourceInfo.java @@ -99,7 +99,7 @@ public class ResourceInfo { * @return true if the resource level was successfully set */ public boolean setLevel(String lvl) { - if (isValid(lvl)) { + if (lvl != null && isValid(lvl)) { this.level = lvl; return true; } diff --git a/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsContainer.java b/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsContainer.java deleted file mode 100644 index e6966d5d3..000000000 --- a/src/java/org/apache/fop/render/afp/goca/AbstractGraphicsContainer.java +++ /dev/null @@ -1,95 +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.goca; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.Iterator; -import java.util.List; - -import org.apache.fop.render.afp.modca.AbstractNamedAFPObject; -import org.apache.fop.render.afp.modca.PreparedAFPObject; - -/** - * A base class container of GOCA structured objects - */ -public abstract class AbstractGraphicsContainer extends AbstractNamedAFPObject -implements PreparedAFPObject { - - /** - * list of objects contained within this container - */ - protected List objects = null; - - /** - * Default constructor - */ - protected AbstractGraphicsContainer() { - } - - /** - * Named constructor - * @param name the name of the container - */ - protected AbstractGraphicsContainer(String name) { - super(name); - } - - /** - * {@inheritDoc} - */ - protected void writeContent(OutputStream os) throws IOException { - if (objects != null) { - super.writeObjects(objects, os); - } - } - - /** - * Adds a given graphics drawing order to this container - * @param drawingOrder the graphics drawing order - * @return the drawingOrder if it was added, null otherwise - */ - protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { - log.debug(this + " adding " + drawingOrder); - if (objects == null) { - this.objects = new java.util.ArrayList(); - } - objects.add(drawingOrder); - return drawingOrder; - } - - /** - * @return the current data length of this container including - * all enclosed GOCA drawing objects (and their containers) - */ - public int getDataLength() { - int dataLen = 0; - if (objects != null) { - Iterator it = objects.iterator(); - while (it.hasNext()) { - Object obj = it.next(); - if (obj instanceof PreparedAFPObject) { - dataLen += ((PreparedAFPObject)obj).getDataLength(); - } - } - } - return dataLen; - } -} diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsArea.java b/src/java/org/apache/fop/render/afp/goca/GraphicsArea.java index c0d1040c8..46b343eb1 100644 --- a/src/java/org/apache/fop/render/afp/goca/GraphicsArea.java +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsArea.java @@ -22,10 +22,12 @@ package org.apache.fop.render.afp.goca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.modca.AbstractPreparedObjectContainer; + /** * A GOCA graphics area (container for filled shapes/objects) */ -public final class GraphicsArea extends AbstractGraphicsContainer { +public final class GraphicsArea extends AbstractPreparedObjectContainer { /** draw boundary lines around this area */ private boolean drawBoundary = false; diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java b/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java index f63aff1ea..ad8410b82 100644 --- a/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java @@ -22,13 +22,14 @@ package org.apache.fop.render.afp.goca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.modca.AbstractPreparedObjectContainer; import org.apache.fop.render.afp.modca.PreparedAFPObject; import org.apache.fop.render.afp.tools.BinaryUtils; /** * A GOCA graphics segment */ -public final class GraphicsChainedSegment extends AbstractGraphicsContainer { +public final class GraphicsChainedSegment extends AbstractPreparedObjectContainer { /** * The maximum segment data length @@ -91,10 +92,8 @@ public final class GraphicsChainedSegment extends AbstractGraphicsContainer { } private static final byte APPEND_NEW_SEGMENT = 0; - - private static final byte PROLOG = 4; - - private static final byte APPEND_TO_EXISING = 48; +// private static final byte PROLOG = 4; +// private static final byte APPEND_TO_EXISING = 48; /** * {@inheritDoc} @@ -148,7 +147,7 @@ public final class GraphicsChainedSegment extends AbstractGraphicsContainer { */ protected void beginArea() { this.currentArea = new GraphicsArea(); - super.addDrawingOrder(currentArea); + super.addObject(currentArea); } /** @@ -161,11 +160,11 @@ public final class GraphicsChainedSegment extends AbstractGraphicsContainer { /** * {@inheritDoc} */ - protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { + public PreparedAFPObject addObject(PreparedAFPObject drawingOrder) { if (currentArea != null) { - currentArea.addDrawingOrder(drawingOrder); + currentArea.addObject(drawingOrder); } else { - super.addDrawingOrder(drawingOrder); + super.addObject(drawingOrder); } return drawingOrder; } diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsData.java b/src/java/org/apache/fop/render/afp/goca/GraphicsData.java index 3c95bb245..d2626ccaf 100644 --- a/src/java/org/apache/fop/render/afp/goca/GraphicsData.java +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsData.java @@ -22,6 +22,7 @@ package org.apache.fop.render.afp.goca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.modca.AbstractPreparedObjectContainer; import org.apache.fop.render.afp.modca.PreparedAFPObject; import org.apache.fop.render.afp.tools.BinaryUtils; import org.apache.fop.render.afp.tools.StringUtils; @@ -29,7 +30,7 @@ import org.apache.fop.render.afp.tools.StringUtils; /** * A GOCA graphics data */ -public final class GraphicsData extends AbstractGraphicsContainer { +public final class GraphicsData extends AbstractPreparedObjectContainer { /** * The maximum graphics data length @@ -115,20 +116,20 @@ public final class GraphicsData extends AbstractGraphicsContainer { } else { this.currentSegment = new GraphicsChainedSegment(name, currentSegment); } - super.addDrawingOrder(currentSegment); + super.addObject(currentSegment); return currentSegment; } /** * {@inheritDoc} */ - public PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { + public PreparedAFPObject addObject(PreparedAFPObject drawingOrder) { if (currentSegment == null || (currentSegment.getDataLength() + drawingOrder.getDataLength()) >= GraphicsChainedSegment.MAX_DATA_LEN) { newSegment(); } - currentSegment.addDrawingOrder(drawingOrder); + currentSegment.addObject(drawingOrder); return drawingOrder; } diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsImageData.java b/src/java/org/apache/fop/render/afp/goca/GraphicsImageData.java index b17c3d7d4..1fc7e2332 100644 --- a/src/java/org/apache/fop/render/afp/goca/GraphicsImageData.java +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsImageData.java @@ -41,10 +41,13 @@ public final class GraphicsImageData extends AbstractPreparedAFPObject { if (startIndex + MAX_DATA_LEN >= imageData.length) { dataLen = imageData.length - startIndex - 1; } - super.data = new byte[dataLen + 2]; + + byte[] data = new byte[dataLen + 2]; data[0] = (byte) 0x92; // GIMD data[1] = BinaryUtils.convert(dataLen, 1)[0]; // LENGTH System.arraycopy(imageData, startIndex, data, 2, dataLen); + + super.setData(data); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java index e6790e91c..c556fa82d 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java @@ -431,6 +431,9 @@ public class AFPDataStream extends AbstractResourceGroupContainer { col, vsci, ica, data); } + /** Maintain a reference count of instream objects */ + private int instreamObjectCount = 0; + /** * Creates a data object in the datastream. The data object resides according * to its type, info and MO:DCA-L (resource) support. @@ -441,20 +444,35 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * a data object */ public AbstractNamedAFPObject createObject(DataObjectInfo dataObjectInfo) { - ObjectTypeRegistry registry = ObjectTypeRegistry.getInstance(); - ObjectTypeRegistry.ObjectType objectType = registry.getObjectType(dataObjectInfo); + String uri = dataObjectInfo.getUri(); + + // if this is an instream data object adjust uri to ensure that it is unique + if (uri.endsWith("/")) { + uri += "#" + (++instreamObjectCount); + dataObjectInfo.setUri(uri); + } + + Registry.ObjectType objectType = Registry.getInstance().getObjectType(dataObjectInfo); + // recognised object type if (objectType != null) { dataObjectInfo.setObjectType(objectType); - } - AbstractNamedAFPObject dataObj; - // can this data object use the include object (IOB) mechanism? - if (objectType.canBeIncluded()) { - ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); - ResourceGroup resourceGroup = getResourceGroup(resourceInfo); - dataObj = resourceGroup.createObject(dataObjectInfo); - } else { - dataObj = getCurrentPage().createObject(dataObjectInfo); + + // can this data object use the include object (IOB) referencing mechanism? + if (objectType.canBeIncluded()) { + ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + ResourceGroup resourceGroup = getResourceGroup(resourceInfo); + IncludeObject includeObject = resourceGroup.createObject(dataObjectInfo); + + // add include to current page + getCurrentPage().addObject(includeObject); + return includeObject.getDataObject(); + } else { + log.warn(uri + "cannot be included so will embed directly"); + } } + // unrecognised/unsupported object type so create/embed data object directly in current page + AbstractNamedAFPObject dataObj = getCurrentPage().createObject(dataObjectInfo); + getCurrentPage().addObject(dataObj); return dataObj; } @@ -822,28 +840,27 @@ public class AFPDataStream extends AbstractResourceGroupContainer { // write any external resources Iterator it = getExternalResourceGroups().keySet().iterator(); while (it.hasNext()) { - String externalDest = (String)it.next(); + File resourceGroupFile = (File)it.next(); ResourceGroup resourceGroup - = (ResourceGroup)getExternalResourceGroups().get(externalDest); + = (ResourceGroup)getExternalResourceGroups().get(resourceGroupFile); OutputStream os = null; try { - log.debug("Writing external AFP resource file " + externalDest); - os = new java.io.FileOutputStream(externalDest); + log.debug("Writing external AFP resource file " + + resourceGroupFile.getAbsolutePath()); + + os = new java.io.FileOutputStream(resourceGroupFile); resourceGroup.writeDataStream(os); - } catch (FileNotFoundException e) { - log.error("Failed to open external AFP resource file " - + externalDest); } catch (IOException e) { log.error( "An error occurred when attempting to write external AFP resource file " - + externalDest); + + resourceGroupFile.getAbsolutePath()); } finally { if (os != null) { try { os.close(); } catch (IOException e) { log.error("Failed to close outputstream for external AFP resource file " - + externalDest); + + resourceGroupFile.getAbsolutePath()); } } } diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStreamWriter.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStreamWriter.java new file mode 100644 index 000000000..35b651fa2 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStreamWriter.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; + +/** + * Implementing object is able to write to an AFPDataStream + */ +public interface AFPDataStreamWriter { + /** + * DataStream objects must implement the writeDataStream() + * method to write its data to the given OutputStream + * @param os The outputsteam stream + * @throws java.io.IOException an I/O exception of some sort has occurred. + */ + void writeDataStream(OutputStream os) throws IOException; +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java index 60cfeb623..27fe3121e 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java @@ -33,21 +33,13 @@ import org.apache.commons.logging.LogFactory; * AFP format. * */ -public abstract class AbstractAFPObject { +public abstract class AbstractAFPObject implements AFPDataStreamWriter { /** * Static logging instance */ protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.modca"); - /** - * DataStream objects must implement the writeDataStream() - * method to write its data to the given OutputStream - * @param os The outputsteam stream - * @throws java.io.IOException an I/O exception of some sort has occurred. - */ - public abstract void writeDataStream(OutputStream os) throws IOException; - /** * Help method to write a set of AFPObjects to the AFP datastream. * @param objects a list of AFPObjects 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 aa97065d1..f6473cfdc 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java @@ -22,13 +22,12 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.goca.AbstractGraphicsContainer; /** * Abstract base class used by the ImageObject and GraphicsObject which both * have define an ObjectEnvironmentGroup */ -public abstract class AbstractDataObject extends AbstractGraphicsContainer { +public abstract class AbstractDataObject extends AbstractPreparedObjectContainer { /** * The object environment group diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java index 95dd303b2..41cf78162 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java @@ -410,22 +410,6 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer writeObjects(objects, os); } -// /** -// * {@inheritDoc} -// */ -// public IncludeObject createImageObject(ImageObjectParameters params) { -// endPresentationObject(); -// return super.createImageObject(params); -// } -// -// /** -// * {@inheritDoc} -// */ -// public IncludeObject createGraphicsObject(DataObjectParameters params) { -// endPresentationObject(); -// return super.createGraphicsObject(params); -// } - /** * {@inheritDoc} */ @@ -437,12 +421,4 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer endPresentationObject(); super.addObject(obj); } - -// /** -// * {@inheritDoc} -// */ -// protected void addObject(AbstractStructuredAFPObject obj) { -// endPresentationObject(); -// super.addObject(obj); -// } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java index e40aa1b4f..d707384ed 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java @@ -80,4 +80,12 @@ implements PreparedAFPObject { protected int getLength() { return getStartDataLength() + getTripletDataLength() + getDataLength(); } + + /** + * Sets the data + * @param data the data + */ + protected void setData(byte[] data) { + this.data = data; + } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPreparedObjectContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractPreparedObjectContainer.java new file mode 100644 index 000000000..3c2b3981d --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPreparedObjectContainer.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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.List; + +/** + * A base container of prepared structured AFP objects + */ +public abstract class AbstractPreparedObjectContainer extends AbstractNamedAFPObject +implements PreparedAFPObject { + + /** + * list of objects contained within this container + */ + protected List/**/ objects = null; + + /** + * Default constructor + */ + protected AbstractPreparedObjectContainer() { + } + + /** + * Named constructor + * @param name the name of the container + */ + protected AbstractPreparedObjectContainer(String name) { + super(name); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + if (objects != null) { + super.writeObjects(objects, os); + } + } + + private List/**/ getObjects() { + if (objects == null) { + this.objects = new java.util.ArrayList/**/(); + } + return this.objects; + } + + /** + * Adds a given prepared object to this container + * @param preparedObject the prepared object + * @return the drawingOrder if it was added, null otherwise + */ + public PreparedAFPObject addObject(PreparedAFPObject preparedObject) { + log.debug(this + " adding " + preparedObject); + getObjects().add(preparedObject); + return preparedObject; + } + + /** + * @return the current data length of this container including + * all enclosed objects (and their containers) + */ + public int getDataLength() { + int dataLen = 0; + if (objects != null) { + Iterator it = objects.iterator(); + while (it.hasNext()) { + Object obj = it.next(); + if (obj instanceof PreparedAFPObject) { + dataLen += ((PreparedAFPObject)obj).getDataLength(); + } + } + } + return dataLen; + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java index eac4b778f..ea6ca4b2e 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java @@ -91,6 +91,9 @@ public abstract class AbstractResourceEnvironmentGroupContainer } } + /** + * @return the resource environment group + */ private ResourceEnvironmentGroup getResourceEnvironmentGroup() { if (resourceEnvironmentGroup == null) { this.resourceEnvironmentGroup = new ResourceEnvironmentGroup(); diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java index 896771cd7..25dc547fb 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java @@ -194,9 +194,6 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj "Invalid compression scheme: " + compression); } } - imageObj.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, - FullyQualifiedNameTriplet.FORMAT_URL, info.getUri()); imageObj.setImageParameters(info.getWidthRes(), info.getHeightRes(), info.getDataWidth(), info.getDataHeight()); if (info.isColor()) { @@ -213,9 +210,10 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj /** * Helper method to create a graphic in the current container and to return * the object. + * @param info the data object info * @return a newly created graphics object */ - protected GraphicsObject createGraphic() { + protected GraphicsObject createGraphic(DataObjectInfo info) { String name = GRAPHIC_NAME_PREFIX + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); GraphicsObject graphicsObj = new GraphicsObject(name); @@ -244,8 +242,13 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj if (info instanceof ImageObjectInfo) { dataObject = createImage((ImageObjectInfo)info); } else { - dataObject = createGraphic(); + dataObject = createGraphic(info); } + + dataObject.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_URL, info.getUri()); + return dataObject; } 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 6ec3a6d63..e82371a81 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java @@ -63,6 +63,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { try { getTripletData(); } catch (IOException e) { + log.error("failed to get triplet data"); } } if (tripletData != null) { @@ -228,7 +229,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { * object/component type of the object * @param strucFlgs information on the structure of the object and its container */ - public void setObjectClassification(byte objectClass, ObjectTypeRegistry.ObjectType objectType, + public void setObjectClassification(byte objectClass, Registry.ObjectType objectType, StrucFlgs strucFlgs) { addTriplet(new ObjectClassificationTriplet(objectClass, objectType, strucFlgs)); } diff --git a/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java b/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java new file mode 100644 index 000000000..c8c55bebc --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.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.render.afp.modca; + +/** + * A common interface of ResourceObject and ContainerObject + */ +public interface DataObjectAccessor extends AFPDataStreamWriter { + + /** + * @return the actual data object referenced in this envelope + */ + AbstractNamedAFPObject getDataObject(); +} 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 7e5f12877..823353375 100644 --- a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java @@ -127,13 +127,13 @@ public class GraphicsObject extends AbstractDataObject { /** * {@inheritDoc} */ - protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) { + public PreparedAFPObject addObject(PreparedAFPObject drawingOrder) { if (graphicsData == null || (graphicsData.getDataLength() + drawingOrder.getDataLength()) >= GraphicsData.MAX_DATA_LEN) { newData(); } - graphicsData.addDrawingOrder(drawingOrder); + graphicsData.addObject(drawingOrder); return drawingOrder; } @@ -154,7 +154,7 @@ public class GraphicsObject extends AbstractDataObject { */ private GraphicsData newData() { this.graphicsData = new GraphicsData(); - super.addDrawingOrder(graphicsData); + super.addObject(graphicsData); return graphicsData; } @@ -163,7 +163,7 @@ public class GraphicsObject extends AbstractDataObject { * @param col the active color to use */ public void setColor(Color col) { - addDrawingOrder(new GraphicsSetProcessColor(col)); + addObject(new GraphicsSetProcessColor(col)); } /** @@ -171,7 +171,7 @@ public class GraphicsObject extends AbstractDataObject { * @param coords the x and y coordinates of the current position */ public void setCurrentPosition(int[] coords) { - addDrawingOrder(new GraphicsSetCurrentPosition(coords)); + addObject(new GraphicsSetCurrentPosition(coords)); } /** @@ -180,7 +180,7 @@ public class GraphicsObject extends AbstractDataObject { */ public void setLineWidth(int multiplier) { GraphicsSetLineWidth lw = new GraphicsSetLineWidth(multiplier); - addDrawingOrder(lw); + addObject(lw); } /** @@ -189,7 +189,7 @@ public class GraphicsObject extends AbstractDataObject { */ public void setLineType(byte type) { GraphicsSetLineType lt = new GraphicsSetLineType(type); - addDrawingOrder(lt); + addObject(lt); } /** @@ -201,7 +201,7 @@ public class GraphicsObject extends AbstractDataObject { fill ? GraphicsSetPatternSymbol.SOLID_FILL : GraphicsSetPatternSymbol.NO_FILL ); - addDrawingOrder(pat); + addObject(pat); } /** @@ -209,7 +209,7 @@ public class GraphicsObject extends AbstractDataObject { * @param fontReference the character set (font) reference */ public void setCharacterSet(int fontReference) { - addDrawingOrder(new GraphicsSetCharacterSet(fontReference)); + addObject(new GraphicsSetCharacterSet(fontReference)); } /** @@ -217,7 +217,7 @@ public class GraphicsObject extends AbstractDataObject { * @param coords the x/y coordinates (can be a series) */ public void addLine(int[] coords) { - addDrawingOrder(new GraphicsLine(coords)); + addObject(new GraphicsLine(coords)); } /** @@ -225,7 +225,7 @@ public class GraphicsObject extends AbstractDataObject { * @param coords the x/y coordinates */ public void addBox(int[] coords) { - addDrawingOrder(new GraphicsBox(coords)); + addObject(new GraphicsBox(coords)); } /** @@ -233,7 +233,7 @@ public class GraphicsObject extends AbstractDataObject { * @param coords the x/y coordinates */ public void addFillet(int[] coords) { - addDrawingOrder(new GraphicsFillet(coords)); + addObject(new GraphicsFillet(coords)); } /** @@ -244,7 +244,7 @@ public class GraphicsObject extends AbstractDataObject { * @param ymaj the maximum value of the y coordinate */ public void setArcParams(int xmaj, int ymin, int xmin, int ymaj) { - addDrawingOrder(new GraphicsSetArcParameters(xmaj, ymin, xmin, ymaj)); + addObject(new GraphicsSetArcParameters(xmaj, ymin, xmin, ymaj)); } /** @@ -255,7 +255,7 @@ public class GraphicsObject extends AbstractDataObject { * @param mhr the fractional portion of the multiplier */ public void addFullArc(int x, int y, int mh, int mhr) { - addDrawingOrder(new GraphicsFullArc(x, y, mh, mhr)); + addObject(new GraphicsFullArc(x, y, mh, mhr)); } /** @@ -264,16 +264,16 @@ public class GraphicsObject extends AbstractDataObject { * @param y the y coordinate * @param width the image width * @param height the image height - * @param rawData the image data + * @param imgData the image data */ - public void addImage(int x, int y, int width, int height, byte[] rawData) { - addDrawingOrder(new GraphicsImageBegin(x, y, width, height)); + public void addImage(int x, int y, int width, int height, byte[] imgData) { + addObject(new GraphicsImageBegin(x, y, width, height)); for (int startIndex = 0; - startIndex <= rawData.length; + startIndex <= imgData.length; startIndex += GraphicsImageData.MAX_DATA_LEN) { - addDrawingOrder(new GraphicsImageData(rawData, startIndex)); + addObject(new GraphicsImageData(imgData, startIndex)); } - addDrawingOrder(new GraphicsImageEnd()); + addObject(new GraphicsImageEnd()); } /** @@ -283,7 +283,7 @@ public class GraphicsObject extends AbstractDataObject { * @param y the y coordinate */ public void addString(String str, int x, int y) { - addDrawingOrder(new GraphicsString(str, x, y)); + addObject(new GraphicsString(str, x, y)); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java index 799578966..92244d66a 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java @@ -19,7 +19,6 @@ package org.apache.fop.render.afp.modca; -import java.io.File; import java.io.IOException; import java.io.OutputStream; @@ -40,7 +39,7 @@ import org.apache.fop.render.afp.tools.BinaryUtils; * data objects in the page segment. *

      */ -public class IncludeObject extends AbstractNamedAFPObject { +public class IncludeObject extends AbstractNamedAFPObject implements DataObjectAccessor { /** * the include object is of type page segment @@ -96,45 +95,69 @@ public class IncludeObject extends AbstractNamedAFPObject { * The Y-axis origin defined in the object */ private int yContentOffset = -1; - -// /** -// * The object referenced by this include object -// */ -// private Resource resourceObj = null; - + /** - * the level at which this resource object resides + * the resource info */ - private ResourceInfo level = null; + private ResourceInfo resourceInfo = null; /** * the referenced data object */ - private AbstractNamedAFPObject dataObj = null; + private DataObjectAccessor dataObjectAccessor = null; /** * Constructor for the include object with the specified name, the name must * be a fixed length of eight characters and is the name of the referenced * object. * - * @param resourceObj the resource object wrapper + * @param name the name of this include object + * @param dataObjectAccessor the data object accessor + * @param resourceInfo the resource information */ - public IncludeObject(AbstractNamedAFPObject dataObj) { - super(dataObj.getName()); - this.dataObj = dataObj; -// AbstractStructuredAFPObject referencedObject = resourceObj.getReferencedObject(); - if (dataObj instanceof ImageObject) { + public IncludeObject(String name, DataObjectAccessor dataObjectAccessor, + ResourceInfo resourceInfo) { + super(name); + + setDataObjectAccessor(dataObjectAccessor); + setResourceInfo(resourceInfo); + } + + /** + * Sets the data object accessor and the object type + * @param dataObjectAccessor the data object accessor + */ + private void setDataObjectAccessor(DataObjectAccessor dataObjectAccessor) { + this.dataObjectAccessor = dataObjectAccessor; + + AbstractNamedAFPObject dataObject = dataObjectAccessor.getDataObject(); + + if (dataObject instanceof ImageObject) { this.objectType = TYPE_IMAGE; - } else if (dataObj instanceof GraphicsObject) { + } else if (dataObject instanceof GraphicsObject) { this.objectType = TYPE_GRAPHIC; - } else if (dataObj instanceof PageSegment) { + } else if (dataObject instanceof PageSegment) { this.objectType = TYPE_PAGE_SEGMENT; } else { this.objectType = TYPE_OTHER; } + } + /** + * @return the data object accessor + */ + private DataObjectAccessor getDataObjectAccessor() { + return this.dataObjectAccessor; + } + + /** + * Sets the resource level for this resource object + * @param resourceInfo the resource information + */ + private void setResourceInfo(ResourceInfo resourceInfo) { + this.resourceInfo = resourceInfo; + // set data object reference triplet - ResourceInfo resourceInfo = getResourceInfo(); if (resourceInfo != null && resourceInfo.isExternal()) { String dest = resourceInfo.getExternalResourceGroupDest(); super.setFullyQualifiedName( @@ -143,38 +166,22 @@ public class IncludeObject extends AbstractNamedAFPObject { } else { super.setFullyQualifiedName( FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, - FullyQualifiedNameTriplet.FORMAT_CHARSTR, dataObj.getName()); + FullyQualifiedNameTriplet.FORMAT_CHARSTR, getDataObject().getName()); } } - - /** - * Sets the resource level for this resource object - * @param level the resource level - */ - public void setResourceInfo(ResourceInfo level) { - this.level = level; - } /** * @return the resource info of this resource object */ public ResourceInfo getResourceInfo() { - return this.level; + return this.resourceInfo; } -// /** -// * @return the resource container object referenced by this include object -// */ -// public Resource getResource() { -// return this.resourceObj; -// } - /** * @return the actual resource data object referenced by this include object */ - public AbstractStructuredAFPObject getReferencedObject() { - return this.dataObj; - //getResource().getReferencedObject(); + public AbstractNamedAFPObject getDataObject() { + return getDataObjectAccessor().getDataObject(); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java index 3ccfd450a..01db7b9d8 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java +++ b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java @@ -41,12 +41,12 @@ public class MapDataResource extends AbstractStructuredAFPObject { /** * Main constructor - * @param obj a map data resource for a given structured AFP object + * @param includeObj a map data resource for a given structured AFP object */ public MapDataResource(IncludeObject includeObj) { - AbstractStructuredAFPObject refObj = includeObj.getReferencedObject(); + AbstractStructuredAFPObject dataObject = includeObj.getDataObject(); // ResourceObject resObj = includeObj.getResource(); - String fqName = refObj.getFullyQualifiedName(); + String fqName = dataObject.getFullyQualifiedName(); ResourceInfo resourceInfo = includeObj.getResourceInfo(); if (fqName != null) { if (resourceInfo.isExternal()) { @@ -75,7 +75,7 @@ public class MapDataResource extends AbstractStructuredAFPObject { dataInContainer, containerHasOEG, dataInOCD ); - //TODO: AC - fix + // // super.setObjectClassification( // ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, // objectType, strucFlgs); diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java index 59e770d6d..909476772 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java @@ -31,40 +31,56 @@ import org.apache.fop.render.afp.tools.BinaryUtils; /** * Object containers are MO:DCA objects that envelop and carry object data. */ -public class ObjectContainer extends AbstractNamedAFPObject { +public class ObjectContainer extends AbstractPreparedAFPObject implements DataObjectAccessor { + + /** + * the data object + */ + private AbstractDataObject dataObj = null; /** - * the object container data + * the object data */ - private ObjectContainerData objectContainerData; - + private byte[] objectData = null; + /** * Main constructor * @param name the name of this object container - * @param dataObj the data object to reside within this object container - * @param info the data object info about the data object + * @param dataObjectInfo the data object info */ - public ObjectContainer(String name, AbstractDataObject dataObj, DataObjectInfo info) { + public ObjectContainer(String name, DataObjectInfo dataObjectInfo) { super(name); - final boolean dataInContainer = true; final boolean containerHasOEG = false; final boolean dataInOCD = true; StrucFlgs strucFlgs = new StrucFlgs( dataInContainer, containerHasOEG, dataInOCD ); - ObjectTypeRegistry registry = ObjectTypeRegistry.getInstance(); - ObjectTypeRegistry.ObjectType entry = registry.getObjectType(info); - super.setObjectClassification( - ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, - entry, strucFlgs - ); - - // write data object to object container data - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - // TODO: AC - fix -// dataObj.writeDataStream(bos); - this.objectContainerData = new ObjectContainerData(bos.toByteArray()); + Registry registry = Registry.getInstance(); + Registry.ObjectType objectType = registry.getObjectType(dataObjectInfo); + if (objectType != null) { + super.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, + objectType, strucFlgs + ); + } else { + log.warn("no object type for " + dataObjectInfo.getUri()); + } + } + + /** + * Sets the data object for this object container + * @param dataObj the data object to reside within this object container + */ + public void setDataObject(AbstractDataObject dataObj) { + this.dataObj = dataObj; + } + + /** + * {@inheritDoc} + */ + public AbstractNamedAFPObject getDataObject() { + return this.dataObj; } /** @@ -73,8 +89,13 @@ public class ObjectContainer extends AbstractNamedAFPObject { protected void writeStart(OutputStream os) throws IOException { super.writeStart(os); + // create object data from data object + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + dataObj.writeDataStream(bos); + this.objectData = bos.toByteArray(); + // Set the total record length - byte[] len = BinaryUtils.convert(18 + getTripletDataLength(), 2); + byte[] len = BinaryUtils.convert(18 + getTripletDataLength() + objectData.length, 2); byte[] data = new byte[] { 0x5A, // Structured field identifier len[0], // Length byte 1 @@ -92,23 +113,24 @@ public class ObjectContainer extends AbstractNamedAFPObject { nameBytes[4], nameBytes[5], nameBytes[6], - nameBytes[7], - 0x00, // Reserved - 0x00, // Reserved + nameBytes[7] }; os.write(data); } - + /** * {@inheritDoc} */ protected void writeContent(OutputStream os) throws IOException { - super.writeContent(os); // write triplets - if (objectContainerData != null) { + super.writeContent(os); + + // write out object data in chunks of object container data + for (int i = 0; i <= objectData.length; i += ObjectContainerData.MAX_DATA_LEN) { + ObjectContainerData objectContainerData = new ObjectContainerData(objectData, i); objectContainerData.writeDataStream(os); } } - + /** * {@inheritDoc} */ @@ -135,37 +157,50 @@ public class ObjectContainer extends AbstractNamedAFPObject { os.write(data); } - private class ObjectContainerData extends AbstractStructuredAFPObject { - /** the object data */ - private byte[] objData = null; + /** + * An Object Container Data holds a chunk of the data object + */ + private class ObjectContainerData extends AbstractPreparedAFPObject { + + /** + * The maximum object container data length + */ + private static final int MAX_DATA_LEN = 32759; /** * Main constructor * @param objData the object data */ - public ObjectContainerData(byte[] objData) { - this.objData = objData; + public ObjectContainerData(byte[] objData, int startIndex) { + int dataLen = MAX_DATA_LEN; + if (startIndex + MAX_DATA_LEN >= objData.length) { + dataLen = objData.length - startIndex - 1; + } + byte[] len = BinaryUtils.convert(8 + dataLen, 2); + byte[] data = new byte[9 + dataLen]; + data[0] = 0x5A; // Structured field identifier + data[1] = len[0]; // Length byte 1 + data[2] = len[1]; // Length byte 2 + data[3] = (byte)0xD3; // Structured field id byte 1 + data[4] = (byte)0xEE; // Structured field id byte 2 + data[5] = (byte)0x92; // Structured field id byte 3 + data[6] = 0x00; // Flags + data[7] = 0x00; // Reserved + data[8] = 0x00; // Reserved + + // copy object data chunk + System.arraycopy(data, startIndex, data, 9, dataLen); + + super.setData(data); } /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { - // Set the total record length - byte[] len = BinaryUtils.convert(8 + objData.length, 2); - byte[] data = new byte[] { - 0x5A, // Structured field identifier - len[0], // Length byte 1 - len[1], // Length byte 2 - (byte)0xD3, // Structured field id byte 1 - (byte)0xEE, // Structured field id byte 2 - (byte)0x92, // Structured field id byte 3 - 0x00, // Flags - 0x00, // Reserved - 0x00, // Reserved - }; - - os.write(data); + public String toString() { + return "ObjectContainerData(" + + (data != null ? "" + (data.length - 2) : "null") + + ")"; } } } diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectTypeRegistry.java b/src/java/org/apache/fop/render/afp/modca/ObjectTypeRegistry.java deleted file mode 100644 index 278a56732..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ObjectTypeRegistry.java +++ /dev/null @@ -1,204 +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.UnsupportedEncodingException; -import java.util.Collections; - -import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.DataObjectInfo; -import org.apache.fop.render.afp.ImageObjectInfo; -import org.apache.xmlgraphics.util.MimeConstants; - -/** - * MOD:CA object type registry - */ -public final class ObjectTypeRegistry { - /** IOB supported object types */ - private static final byte COMPID_GIF = 22; - private static final byte COMPID_JFIF = 23; // jpeg file interchange format - private static final byte COMPID_PDF_SINGLE_PAGE = 25; - private static final byte COMPID_PCL_PAGE_OBJECT = 34; - - /** IOB unsupported object types */ - private static final byte COMPID_EPS = 13; - private static final byte COMPID_TIFF = 14; - - /** mime type entry mapping */ - private java.util.Map/**/ mimeEntryMap - = Collections.synchronizedMap( - Collections.unmodifiableMap( - new java.util.HashMap/**/())); - - private static ObjectTypeRegistry instance = null; - - /** - * @return a single instance of Registry - */ - public static ObjectTypeRegistry getInstance() { - synchronized (instance) { - if (instance == null) { - instance = new ObjectTypeRegistry(); - } - } - return instance; - } - - private ObjectTypeRegistry() { - init(); - } - - private void init() { - mimeEntryMap.put( - MimeConstants.MIME_EPS, - new ObjectType( - COMPID_EPS, - new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D}, - "Encapsulated Postscript", - false - ) - ); - mimeEntryMap.put( - MimeConstants.MIME_TIFF, - new ObjectType( - COMPID_TIFF, - new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E}, - "TIFF", - false - ) - ); - mimeEntryMap.put( - MimeConstants.MIME_GIF, - new ObjectType( - COMPID_GIF, - new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16}, - "GIF", - true - ) - ); - mimeEntryMap.put( - MimeConstants.MIME_JPEG, - new ObjectType( - COMPID_JFIF, - new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17}, - "JFIF", - true - ) - ); - mimeEntryMap.put(MimeConstants.MIME_PDF, - new ObjectType( - COMPID_PDF_SINGLE_PAGE, - new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19}, - "PDF Single-page Object", - true - ) - ); - mimeEntryMap.put( - MimeConstants.MIME_PCL, - new ObjectType( - COMPID_PCL_PAGE_OBJECT, - new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22}, - "PCL Page Object", - true - ) - ); - } - - /** - * Returns the registry Entry for a given data object info - * - * @param info - * the data object info - * @return the registry Entry for a given data object info - */ - public ObjectType getObjectType(DataObjectInfo info) { - ObjectType entry = null; - if (info instanceof ImageObjectInfo) { - ImageObjectInfo imageInfo = (ImageObjectInfo)info; - String mimeType = imageInfo.getMimeType(); - entry = (ObjectType)mimeEntryMap.get(mimeType); - } - return entry; - } - - /** - * Encapsulates a MOD:CA Registry Object Type entry - */ - public class ObjectType { - private byte componentId; - private byte[] oid; - private byte[] name; - private boolean canBeIncluded; - - /** - * Main constructor - * @param componentId the component id of this object type - * @param oid the object id of this object type - * @param objectTypeName the object type name - * @param canBeIncluded true if this object can be included with an IOB structured field - */ - public ObjectType(byte componentId, byte[] oid, String objectTypeName, - boolean canBeIncluded) { - this.componentId = componentId; - this.oid = oid; - try { - this.name = objectTypeName.getBytes(AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException e) { - // should never happen! - LogFactory.getLog("org.apache.fop.render.afp.modca.Registry.Entry").error( - "character encoding error occurred on componentId " - + componentId - + " : " - + e.getMessage()); - } - this.canBeIncluded = canBeIncluded; - } - - /** - * Returns a MOD:CA object type OID from a given a componentId - * @return the corresponding object type id for a given component id - * or null if the component id is unknown and the object type OID was not found. - */ - public byte[] getOID() { - return this.oid; - } - - /** - * @return the object type name for the given componentId - */ - public byte[] getName() { - return this.name; - } - - /** - * @return the compontentId for this entry - */ - public byte getComponentId() { - return this.componentId; - } - - /** - * @return true if this component can be included with an IOB structured field - */ - public boolean canBeIncluded() { - return this.canBeIncluded; - } - } -} diff --git a/src/java/org/apache/fop/render/afp/modca/Registry.java b/src/java/org/apache/fop/render/afp/modca/Registry.java new file mode 100644 index 000000000..c81b4a289 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/Registry.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.afp.modca; + +import java.util.Collections; + +import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.ImageObjectInfo; +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * MOD:CA Registry of object types + */ +public final class Registry { + + /** IOB supported object types */ + private static final byte COMPID_GIF = 22; + private static final byte COMPID_JFIF = 23; // jpeg file interchange format + private static final byte COMPID_PDF_SINGLE_PAGE = 25; + private static final byte COMPID_PCL_PAGE_OBJECT = 34; + + /** IOB unsupported object types */ + private static final byte COMPID_EPS = 13; + private static final byte COMPID_TIFF = 14; + + /** mime type entry mapping */ + private java.util.Map/**/ mimeEntryMap + = Collections.synchronizedMap( + new java.util.HashMap/**/()); + + /** singleton instance */ + private static Registry instance = null; + + /** + * @return a single instance of an ObjectTypeRegistry + */ + public static Registry getInstance() { + synchronized (Registry.class) { + if (instance == null) { + instance = new Registry(); + } + } + return instance; + } + + private Registry() { + init(); + } + + private void init() { + mimeEntryMap.put( + MimeConstants.MIME_EPS, + new ObjectType( + COMPID_EPS, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D}, + "Encapsulated Postscript", + false + ) + ); + mimeEntryMap.put( + MimeConstants.MIME_TIFF, + new ObjectType( + COMPID_TIFF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E}, + "TIFF", + false + ) + ); + mimeEntryMap.put( + MimeConstants.MIME_GIF, + new ObjectType( + COMPID_GIF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16}, + "GIF", + true + ) + ); + mimeEntryMap.put( + MimeConstants.MIME_JPEG, + new ObjectType( + COMPID_JFIF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17}, + "JFIF", + true + ) + ); + mimeEntryMap.put(MimeConstants.MIME_PDF, + new ObjectType( + COMPID_PDF_SINGLE_PAGE, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19}, + "PDF Single-page Object", + true + ) + ); + mimeEntryMap.put( + MimeConstants.MIME_PCL, + new ObjectType( + COMPID_PCL_PAGE_OBJECT, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22}, + "PCL Page Object", + true + ) + ); + } + + /** + * Returns the Registry ObjectType for a given data object info + * + * @param dataObjectInfo the data object info + * @return the Registry ObjectType for a given data object info + */ + public Registry.ObjectType getObjectType(DataObjectInfo dataObjectInfo) { + ObjectType entry = null; + if (dataObjectInfo instanceof ImageObjectInfo) { + ImageObjectInfo imageInfo = (ImageObjectInfo)dataObjectInfo; + String mimeType = imageInfo.getMimeType(); + entry = (Registry.ObjectType)mimeEntryMap.get(mimeType); + } + return entry; + } + + /** + * Encapsulates a MOD:CA Registry Object Type entry + */ + public class ObjectType { + private byte componentId; + private byte[] oid; + private String name; + private boolean canBeIncluded; + + /** + * Main constructor + * @param componentId the component id of this object type + * @param oid the object id of this object type + * @param name the object type name + * @param canBeIncluded true if this object can be included with an IOB structured field + */ + public ObjectType(byte componentId, byte[] oid, String name, + boolean canBeIncluded) { + this.componentId = componentId; + this.oid = oid; + this.name = name; + this.canBeIncluded = canBeIncluded; + } + + /** + * Returns a MOD:CA object type OID from a given a componentId + * @return the corresponding object type id for a given component id + * or null if the component id is unknown and the object type OID was not found. + */ + public byte[] getOID() { + return this.oid; + } + + /** + * @return the object type name for the given componentId + */ + public String getName() { + return this.name; + } + + /** + * @return the compontentId for this entry + */ + public byte getComponentId() { + return this.componentId; + } + + /** + * @return true if this component can be included with an IOB structured field + */ + public boolean canBeIncluded() { + return this.canBeIncluded; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return this.getName(); + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java index 38b9524e6..18026a6b3 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java @@ -30,7 +30,6 @@ import org.apache.fop.render.afp.ImageObjectInfo; import org.apache.fop.render.afp.ResourceInfo; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.tools.StringUtils; -import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; /** * A Resource Group contains a set of overlays. @@ -45,7 +44,7 @@ public final class ResourceGroup extends AbstractNamedAFPObject { /** * Mapping of resource uri to data resource object (image/graphic) */ - private Map/**/ resourceMap = null; + private Map/**/ resourceMap = null; /** * This resource groups container @@ -64,6 +63,7 @@ public final class ResourceGroup extends AbstractNamedAFPObject { * Constructor for the ResourceGroup, this takes a * name parameter which must be 8 characters long. * @param name the resource group name + * @param container the parent resource group container */ public ResourceGroup(String name, AbstractResourceGroupContainer container) { super(name); @@ -71,8 +71,7 @@ public final class ResourceGroup extends AbstractNamedAFPObject { } private static final String RESOURCE_NAME_PREFIX = "RES"; - private static final String INCLUDE_NAME_PREFIX = "INC"; - + /** * Helper method to create a new resource object in the current container and to return * the object. @@ -84,68 +83,50 @@ public final class ResourceGroup extends AbstractNamedAFPObject { ResourceObject resource = new ResourceObject(name); return resource; } - -// /** -// * Helper method to create a new resource object in the current container and to return -// * the object. -// * @return a newly created resource object -// */ -// private IncludeObject createIncludeObject() { -// String name = INCLUDE_NAME_PREFIX -// + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); -// IncludeObject includeObj = new IncludeObject(name); -// return includeObj; -// } + + private AbstractResourceGroupContainer getContainer() { + return this.container; + } /** * Creates a data object in this resource group - * @param info the data object info + * @param dataObjectInfo the data object info * @return an include object reference */ - public IncludeObject createObject(DataObjectInfo info) { - IncludeObject includeObj = (IncludeObject)getResourceMap().get(info.getUri()); - if (includeObj == null) { - AbstractDataObject dataObj; - if (info instanceof ImageObjectInfo) { - dataObj = container.createImage((ImageObjectInfo)info); + public IncludeObject createObject(DataObjectInfo dataObjectInfo) { + DataObjectAccessor dataObjectAccessor + = (DataObjectAccessor)getResourceMap().get(dataObjectInfo.getUri()); + ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + AbstractDataObject dataObj; + if (dataObjectAccessor == null) { + if (dataObjectInfo instanceof ImageObjectInfo) { + dataObj = getContainer().createImage((ImageObjectInfo)dataObjectInfo); } else { - dataObj = container.createGraphic(); + dataObj = getContainer().createGraphic(dataObjectInfo); } - ResourceInfo resourceInfo = info.getResourceInfo(); - String resourceName = resourceInfo.getName(); - if (resourceInfo.isExternal()) { - ObjectContainer objectContainer = new ObjectContainer(resourceName, dataObj, info); - } else { - - } - - // Wrap the data object in a page segment - PageSegment pageSegment = container.createPageSegment(); - pageSegment.addObject(dataObj); + dataObj.setViewport(dataObjectInfo.getX(), dataObjectInfo.getY(), + dataObjectInfo.getWidth(), dataObjectInfo.getHeight(), + dataObjectInfo.getWidthRes(), dataObjectInfo.getHeightRes(), + dataObjectInfo.getRotation()); + String resourceName = resourceInfo.getName(); + ObjectContainer objectContainer = new ObjectContainer(resourceName, dataObjectInfo); + objectContainer.setDataObject(dataObj); - // TODO: AC - rotation? - int rotation = 0; - dataObj.setViewport(info.getX(), info.getY(), - info.getWidth(), info.getHeight(), - info.getWidthRes(), info.getHeightRes(), rotation); - - includeObj.setResourceInfo(resourceInfo); - - // If resource is to be stored externally, - // wrap the page segment in a resource object + // When externally located, Wrap data object in a resource object if (resourceInfo.isExternal()) { - ResourceObject resource = createResourceObject(); - resource.setReferencedObject(pageSegment); - includeObj = new IncludeObject(resource); - } else { - includeObj = new IncludeObject(pageSegment); + ResourceObject resourceObj = createResourceObject(); + resourceObj.setObjectContainer(objectContainer); + dataObjectAccessor = resourceObj; + } else { // no wrappers just container + dataObjectAccessor = objectContainer; } - // Add include object to resource map - getResourceMap().put(info.getUri(), includeObj); + getResourceMap().put(dataObjectInfo.getUri(), dataObjectAccessor); } - //includeObj.setObjectAreaSize(params.getX(), params.getY()); + AbstractNamedAFPObject dataObject = dataObjectAccessor.getDataObject(); + String name = dataObject.getName(); + IncludeObject includeObj = new IncludeObject(name, dataObjectAccessor, resourceInfo); return includeObj; } @@ -174,9 +155,9 @@ public final class ResourceGroup extends AbstractNamedAFPObject { * Returns the list of resources * @return the list of resources */ - public Map/**/ getResourceMap() { + public Map/**/ getResourceMap() { if (resourceMap == null) { - resourceMap = new java.util.HashMap/**/(); + resourceMap = new java.util.HashMap/**/(); } return resourceMap; } @@ -189,9 +170,8 @@ public final class ResourceGroup extends AbstractNamedAFPObject { Collection includes = resourceMap.values(); Iterator it = includes.iterator(); while (it.hasNext()) { - IncludeObject includeObj = (IncludeObject)it.next(); - AbstractStructuredAFPObject obj = includeObj.getReferencedObject(); - obj.writeDataStream(os); + DataObjectAccessor dataObjectAccessor = (DataObjectAccessor)it.next(); + dataObjectAccessor.writeDataStream(os); } } } @@ -240,6 +220,6 @@ public final class ResourceGroup extends AbstractNamedAFPObject { * {@inheritDoc} */ public String toString() { - return this.name + " " + this.resourceMap; + return this.name + " " + getResourceMap(); } } diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java index c0d4d88df..57d7f0105 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java @@ -22,7 +22,6 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.ResourceInfo; import org.apache.fop.render.afp.modca.triplets.Triplet; import org.apache.fop.render.afp.tools.BinaryUtils; @@ -30,34 +29,17 @@ import org.apache.fop.render.afp.tools.BinaryUtils; * This resource structured field begins an envelope that is used to carry * resource objects in print-file-level (external) resource groups. */ -public class ResourceObject extends AbstractPreparedAFPObject { +public class ResourceObject extends AbstractPreparedAFPObject implements DataObjectAccessor { /** - * Resource object types + * the object container of this resource object */ - private static final byte GRAPHICS_OBJECT = 0x03; - private static final byte BARCODE_OBJECT = 0x05; - private static final byte IMAGE_OBJECT = 0x06; - private static final byte FONT_CHARACTER_SET_OBJECT = 0x40; - private static final byte CODE_PAGE_OBJECT = 0x41; - private static final byte CODED_FONT_OBJECT = 0x42; - private static final byte OBJECT_CONTAINER = (byte) 0x92; - private static final byte DOCUMENT_OBJECT = (byte) 0xA8; - private static final byte PAGE_SEGMENT_OBJECT = (byte) 0xFB; - private static final byte OVERLAY_OBJECT = (byte) 0xFC; - private static final byte PAGEDEF_OBJECT = (byte) 0xFD; - private static final byte FORMDEF_OBJECT = (byte) 0xFE; - - /** - * the referenced data object - */ - private AbstractNamedAFPObject dataObj = null; + private ObjectContainer objectContainer; /** * Default constructor * * @param name the name of this resource (reference id) - * @param dataObj the resource object to be added */ public ResourceObject(String name) { super(name); @@ -65,32 +47,41 @@ public class ResourceObject extends AbstractPreparedAFPObject { /** * Sets the data object referenced by this resource object - * @param dataObj the data object + * @param objectContainer the object container */ - public void setReferencedObject(AbstractNamedAFPObject dataObj) { - this.dataObj = dataObj; - setResourceObjectType(dataObj); + public void setObjectContainer(ObjectContainer objectContainer) { + this.objectContainer = objectContainer; + setResourceObjectType(objectContainer); } - + /** - * @return the resource object contained in this envelope + * {@inheritDoc} */ - public AbstractNamedAFPObject getReferencedObject() { - return this.dataObj; + public AbstractNamedAFPObject getDataObject() { + if (objectContainer != null) { + return objectContainer.getDataObject(); + } + return null; } - private void setResourceObjectType(AbstractNamedAFPObject resourceObj) { + /** + * Sets the resource object type + * @param resourceObj the resource object + */ + public void setResourceObjectType(AbstractNamedAFPObject resourceObj) { byte type; - if (resourceObj instanceof ImageObject) { - type = IMAGE_OBJECT; + if (resourceObj instanceof ObjectContainer) { + type = ResourceObjectTypeTriplet.OBJECT_CONTAINER; + } else if (resourceObj instanceof ImageObject) { + type = ResourceObjectTypeTriplet.IMAGE_OBJECT; } else if (resourceObj instanceof GraphicsObject) { - type = GRAPHICS_OBJECT; + type = ResourceObjectTypeTriplet.GRAPHICS_OBJECT; } else if (resourceObj instanceof Document) { - type = DOCUMENT_OBJECT; + type = ResourceObjectTypeTriplet.DOCUMENT_OBJECT; } else if (resourceObj instanceof PageSegment) { - type = PAGE_SEGMENT_OBJECT; + type = ResourceObjectTypeTriplet.PAGE_SEGMENT_OBJECT; } else if (resourceObj instanceof Overlay) { - type = OVERLAY_OBJECT; + type = ResourceObjectTypeTriplet.OVERLAY_OBJECT; } else { throw new UnsupportedOperationException( "Unsupported resource object type " + resourceObj); @@ -135,8 +126,8 @@ public class ResourceObject extends AbstractPreparedAFPObject { */ protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); // write triplets - if (dataObj != null) { - dataObj.writeDataStream(os); + if (objectContainer != null) { + objectContainer.writeDataStream(os); } } @@ -177,6 +168,22 @@ public class ResourceObject extends AbstractPreparedAFPObject { private static final byte RESOURCE_OBJECT = 0x21; + /** + * Resource object types + */ + private static final byte GRAPHICS_OBJECT = 0x03; +// private static final byte BARCODE_OBJECT = 0x05; + private static final byte IMAGE_OBJECT = 0x06; +// private static final byte FONT_CHARACTER_SET_OBJECT = 0x40; +// private static final byte CODE_PAGE_OBJECT = 0x41; +// private static final byte CODED_FONT_OBJECT = 0x42; + private static final byte OBJECT_CONTAINER = (byte) 0x92; + private static final byte DOCUMENT_OBJECT = (byte) 0xA8; + private static final byte PAGE_SEGMENT_OBJECT = (byte) 0xFB; + private static final byte OVERLAY_OBJECT = (byte) 0xFC; +// private static final byte PAGEDEF_OBJECT = (byte) 0xFD; +// private static final byte FORMDEF_OBJECT = (byte) 0xFE; + /** * Main constructor * diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java index e1a36b4da..21dbaa99f 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java @@ -96,12 +96,15 @@ public class FullyQualifiedNameTriplet extends Triplet { */ public FullyQualifiedNameTriplet(byte type, byte format, byte[] name) { super(FULLY_QUALIFIED_NAME); + this.nameBytes = name; - super.data = new byte[2 + name.length]; + byte[] data = new byte[2 + name.length]; data[0] = type; data[1] = format; // FQName System.arraycopy(name, 0, data, 2, name.length); + + super.setData(data); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java index e99045292..7350db27f 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java @@ -38,7 +38,7 @@ public class MeasurementUnitsTriplet extends Triplet { //TODO: units correct? byte[] xUnits = BinaryUtils.convert(1, 2); byte[] yUnits = BinaryUtils.convert(1, 2); - super.data = new byte[] { + byte[] data = new byte[] { TEN_INCHES, // XoaBase TEN_INCHES, // YoaBase xUnits[0], // XoaUnits (x units per unit base) @@ -46,5 +46,6 @@ public class MeasurementUnitsTriplet extends Triplet { yUnits[0], // YoaUnits (y units per unit base) yUnits[1] }; + super.setData(data); } } diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java index bd026763d..caf6e86fa 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java @@ -36,7 +36,7 @@ public class ObjectAreaSizeTriplet extends Triplet { super(Triplet.OBJECT_AREA_SIZE); byte[] xOASize = BinaryUtils.convert(x, 3); byte[] yOASize = BinaryUtils.convert(y, 3); - super.data = new byte[] { + byte[] data = new byte[] { 0x02, // SizeType xOASize[0], // XoaSize - Object area extent for X axis xOASize[1], @@ -45,5 +45,6 @@ public class ObjectAreaSizeTriplet extends Triplet { yOASize[1], yOASize[2] }; + super.setData(data); } } diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java index 28c3dca4e..45e08eaab 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java @@ -19,7 +19,11 @@ package org.apache.fop.render.afp.modca.triplets; -import org.apache.fop.render.afp.modca.ObjectTypeRegistry; +import java.io.UnsupportedEncodingException; + +import org.apache.fop.render.afp.modca.AFPConstants; +import org.apache.fop.render.afp.modca.Registry; +import org.apache.fop.render.afp.tools.StringUtils; /** * The Object Classification is used to classify and identify object data. @@ -65,15 +69,45 @@ public class ObjectClassificationTriplet extends Triplet { * * @param objectClass * the object class type - * @param entry + * @param objectType * the object type registry entry * @param strucFlgs * the structured flags pertaining to this object classification triplet */ - public ObjectClassificationTriplet(byte objectClass, ObjectTypeRegistry.ObjectType entry, + public ObjectClassificationTriplet(byte objectClass, Registry.ObjectType objectType, StrucFlgs strucFlgs) { + // no object level or company name specified + this(objectClass, objectType, strucFlgs, null, null); + } + + + private static final int OBJECT_LEVEL_LEN = 8; + private static final int OBJECT_TYPE_NAME_LEN = 32; + private static final int COMPANY_NAME_LEN = 32; + + /** + * Fully parameterized constructor + * + * @param objectClass + * the object class type + * @param objectType + * the object type registry entry + * @param strucFlgs + * the structured flags pertaining to this object classification triplet + * @param objLev + * the release level or version number of the object type + * @param compName + * the name of the company or organization that owns the object definition + */ + public ObjectClassificationTriplet(byte objectClass, Registry.ObjectType objectType, + StrucFlgs strucFlgs, String objLev, String compName) { super(OBJECT_CLASSIFICATION); - byte[] data = new byte[93]; + + if (objectType == null) { + throw new UnsupportedOperationException("MO:DCA Registry object type is null"); + } + + byte[] data = new byte[94]; data[0] = 0x00; // reserved (must be zero) data[1] = objectClass; // ObjClass data[2] = 0x00; // reserved (must be zero) @@ -81,21 +115,41 @@ public class ObjectClassificationTriplet extends Triplet { // StrucFlgs - Information on the structure of the object container data[4] = strucFlgs.getValue(); data[5] = 0x00; // StrucFlgs - - if (entry == null) { - throw new UnsupportedOperationException("Unknown registry entry"); - } - - byte[] oid = entry.getOID(); + + byte[] oid = objectType.getOID(); // RegObjId - MOD:CA-registered ASN.1 OID for object type (8-23) System.arraycopy(oid, 0, data, 6, oid.length); - byte[] objectTypeName = entry.getName(); // ObjTpName - name of object type (24-55) - System.arraycopy(objectTypeName, 0, data, 22, objectTypeName.length); + byte[] objTpName; + try { + objTpName = StringUtils.rpad(objectType.getName(), ' ', OBJECT_TYPE_NAME_LEN).getBytes( + AFPConstants.EBCIDIC_ENCODING); + System.arraycopy(objTpName, 0, data, 22, objTpName.length); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException("an encoding exception occurred"); + } - // ObjLev (not specified) - Release level or version number of object type (56-63) - - // CompName (not specified) - Name of company or org that owns object definition (64-95) + // ObjLev - release level or version number of object type (56-63) + byte[] objectLevel; + try { + objectLevel = StringUtils.rpad(objLev, ' ', OBJECT_LEVEL_LEN).getBytes( + AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException("an encoding exception occurred"); + } + System.arraycopy(objectLevel, 0, data, 54, objectLevel.length); + + // CompName - name of company or org that owns object definition (64-95) + byte[] companyName; + try { + companyName = StringUtils.rpad(compName, ' ', COMPANY_NAME_LEN).getBytes( + AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException("an encoding exception occurred"); + } + System.arraycopy(companyName, 0, data, 62, companyName.length); + + super.setData(data); } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java index bcf6f22c3..9467c522a 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java @@ -31,6 +31,8 @@ import org.apache.fop.render.afp.modca.AbstractAFPObject; */ public class Triplet extends AbstractAFPObject { public static final byte CODED_GRAPHIC_CHARACTER_SET_GLOBAL_IDENTIFIER = 0x01; + + /** Triplet identifiers */ public static final byte FULLY_QUALIFIED_NAME = 0x02; public static final byte MAPPING_OPTION = 0x04; public static final byte OBJECT_CLASSIFICATION = 0x10; @@ -89,21 +91,21 @@ public class Triplet extends AbstractAFPObject { /** * the triplet identifier */ - protected byte id; + private byte id; /** * the triplet's data contents */ - protected byte[] data; + private byte[] data; /** * Main constructor * @param id the triplet identifier (see static definitions above) - * @param contents the data item contained in this triplet + * @param data the data item contained in this triplet */ - public Triplet(byte id, byte[] contents) { + public Triplet(byte id, byte[] data) { this(id); - this.data = contents; + setData(data); } /** @@ -150,9 +152,10 @@ public class Triplet extends AbstractAFPObject { } /** - * @return the contents of the triplet + * Sets the data contents of this triplet + * @param data the data contents */ - public byte[] getData() { - return this.data; + protected void setData(byte[] data) { + this.data = data; } } -- cgit v1.2.3 From 72e6f108465cc95fc96d82e9f519bc8b9c7709c3 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 16 Apr 2008 12:44:07 +0000 Subject: Structured field length fix for ObjectContainer. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@648684 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/modca/ObjectContainer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java index 909476772..b29a14719 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java @@ -31,7 +31,7 @@ import org.apache.fop.render.afp.tools.BinaryUtils; /** * Object containers are MO:DCA objects that envelop and carry object data. */ -public class ObjectContainer extends AbstractPreparedAFPObject implements DataObjectAccessor { +public class ObjectContainer extends AbstractNamedAFPObject implements DataObjectAccessor { /** * the data object @@ -95,7 +95,7 @@ public class ObjectContainer extends AbstractPreparedAFPObject implements DataOb this.objectData = bos.toByteArray(); // Set the total record length - byte[] len = BinaryUtils.convert(18 + getTripletDataLength() + objectData.length, 2); + byte[] len = BinaryUtils.convert(16 + getTripletDataLength(), 2); byte[] data = new byte[] { 0x5A, // Structured field identifier len[0], // Length byte 1 @@ -106,7 +106,7 @@ public class ObjectContainer extends AbstractPreparedAFPObject implements DataOb 0x00, // Flags 0x00, // Reserved 0x00, // Reserved - nameBytes[0], + nameBytes[0], nameBytes[1], nameBytes[2], nameBytes[3], -- cgit v1.2.3 From c1293d0e53b566b1c7fc0cddef997785aabb73bd Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 17 Apr 2008 16:30:02 +0000 Subject: Merged revisions 648985,649012,649091,649119,649146,649149,649160 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r648985 | jeremias | 2008-04-17 08:01:19 +0100 (Thu, 17 Apr 2008) | 1 line HeadURL was missing in the properties. ........ r649012 | jeremias | 2008-04-17 09:59:48 +0100 (Thu, 17 Apr 2008) | 2 lines Bugfix: Avoid stopping early when no EmbedFontInfos are found during font detection. Submitted by: Raphael Parree ........ r649091 | jeremias | 2008-04-17 14:33:07 +0100 (Thu, 17 Apr 2008) | 7 lines 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 ........ r649119 | vhennebert | 2008-04-17 15:10:04 +0100 (Thu, 17 Apr 2008) | 2 lines Fixed minor typo ........ r649146 | jeremias | 2008-04-17 16:12:23 +0100 (Thu, 17 Apr 2008) | 2 lines 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". ........ r649149 | jeremias | 2008-04-17 16:14:26 +0100 (Thu, 17 Apr 2008) | 2 lines Bugzilla #43383: Made sure the pages don't appear out of order in AWT preview. ........ r649160 | jeremias | 2008-04-17 17:01:41 +0100 (Thu, 17 Apr 2008) | 3 lines Now tunneling all events through a special event listener in tests. This serves two purposes: - Better readability of the test output. - Identification of messages that are not sent through the event subsystem, yet. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@649175 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/embedding/ExampleFO2OldStylePrint.java | 24 ++-- .../content/xdocs/trunk/embedding.xml | 2 +- src/java/org/apache/fop/Version.java | 2 +- .../org/apache/fop/cli/CommandLineOptions.java | 61 ++++++-- src/java/org/apache/fop/cli/Main.java | 5 +- .../fop/render/PrintRendererConfigurator.java | 2 +- .../org/apache/fop/render/awt/AWTRenderer.java | 4 +- .../apache/fop/render/java2d/Java2DRenderer.java | 7 +- .../org/apache/fop/render/print/PagesMode.java | 69 ++++++++++ .../org/apache/fop/render/print/PrintRenderer.java | 153 +++++++++++++++++---- status.xml | 8 ++ .../org/apache/fop/fotreetest/FOTreeTestSuite.java | 12 +- .../org/apache/fop/fotreetest/FOTreeTester.java | 11 +- .../apache/fop/fotreetest/FOTreeUnitTester.java | 6 +- .../fop/intermediate/AreaTreeParserTestCase.java | 3 + .../intermediate/IntermediateFormatTestSuite.java | 12 +- .../fop/layoutengine/LayoutEngineTestSuite.java | 29 ++-- .../fop/layoutengine/LayoutEngineTester.java | 21 ++- .../fop/util/ConsoleEventListenerForTests.java | 56 ++++++++ 19 files changed, 393 insertions(+), 94 deletions(-) create mode 100644 src/java/org/apache/fop/render/print/PagesMode.java create mode 100644 test/java/org/apache/fop/util/ConsoleEventListenerForTests.java (limited to 'src/java') 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/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
      • 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); 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/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++) { 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} */ 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 e4c159815..2774b5373 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,59 +42,155 @@ import org.apache.fop.render.java2d.Java2DRenderer; */ public class PrintRenderer extends Java2DRenderer implements Pageable { - private static final int EVEN_AND_ALL = 0; - - private static final int EVEN = 1; + /** + * Printing parameter: the preconfigured PrinterJob to use, + * datatype: java.awt.print.PrinterJob + */ + 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"; - 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; 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; + 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; + } + } + + /** {@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( + "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); + } + 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(); + } - printerJob = PrinterJob.getPrinterJob(); - printerJob.setJobName("FOP Document"); - printerJob.setCopies(copies); - if (System.getProperty("dialog") != null) { - if (!printerJob.printDialog()) { + private int getPositiveInteger(Object o) { + if (o instanceof Integer) { + Integer i = (Integer)o; + if (i.intValue() < 1) { throw new IllegalArgumentException( - "Printing cancelled by operator"); + "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"); } - printerJob.setPageable(this); } /** @return the PrinterJob instance that this renderer prints to */ @@ -126,6 +224,7 @@ public class PrintRenderer extends Java2DRenderer implements Pageable { this.startNumber = start; } + /** {@inheritDoc} */ public void stopRenderer() throws IOException { super.stopRenderer(); @@ -136,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 { @@ -149,7 +249,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 { @@ -166,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; @@ -219,6 +319,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 1d2f91e60..c2bb24a52 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,14 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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. + Added a public accessor for reference to the current page to PDFGraphics2D. diff --git a/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java b/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java index 04752064f..aa9af4226 100644 --- a/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java +++ b/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java @@ -35,6 +35,7 @@ import org.apache.commons.io.filefilter.NameFileFilter; 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; @@ -104,9 +105,14 @@ public final class FOTreeTestSuite { final FOTreeTester tester, final File f) { suite.addTest(new FOTreeTestCase(f.getName()) { public void runTest() throws Exception { - org.apache.commons.logging.LogFactory.getLog(this.getClass()).info("Starting " + f.getName()); - prepare(tester, f); - testMain(); + try { + prepare(tester, f); + testMain(); + } catch (Exception e) { + org.apache.commons.logging.LogFactory.getLog(this.getClass()).info( + "Error on " + f.getName()); + throw e; + } } }); } diff --git a/test/java/org/apache/fop/fotreetest/FOTreeTester.java b/test/java/org/apache/fop/fotreetest/FOTreeTester.java index 9c2a260bc..6ffad6989 100644 --- a/test/java/org/apache/fop/fotreetest/FOTreeTester.java +++ b/test/java/org/apache/fop/fotreetest/FOTreeTester.java @@ -25,14 +25,15 @@ import java.util.List; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLFilterImpl; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; - import org.apache.fop.fotreetest.ext.TestElementMapping; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.XMLFilterImpl; +import org.apache.fop.util.ConsoleEventListenerForTests; /** * Test driver class for FO tree tests. @@ -66,6 +67,8 @@ public class FOTreeTester { FOUserAgent ua = fopFactory.newFOUserAgent(); ua.setBaseURL(testFile.getParentFile().toURL().toString()); ua.setFOEventHandlerOverride(new DummyFOEventHandler(ua)); + ua.getEventBroadcaster().addEventListener( + new ConsoleEventListenerForTests(testFile.getName())); //Used to set values in the user agent through processing instructions reader = new PIListener(reader, ua); diff --git a/test/java/org/apache/fop/fotreetest/FOTreeUnitTester.java b/test/java/org/apache/fop/fotreetest/FOTreeUnitTester.java index e19547345..a7fa11950 100644 --- a/test/java/org/apache/fop/fotreetest/FOTreeUnitTester.java +++ b/test/java/org/apache/fop/fotreetest/FOTreeUnitTester.java @@ -26,11 +26,13 @@ import javax.xml.parsers.SAXParserFactory; import junit.framework.TestCase; +import org.xml.sax.XMLReader; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.fo.FOEventHandler; -import org.xml.sax.XMLReader; +import org.apache.fop.util.ConsoleEventListenerForTests; /** @@ -82,6 +84,8 @@ public abstract class FOTreeUnitTester extends TestCase { public void setUp(String filename, FOEventHandlerFactory factory) throws Exception { FOUserAgent ua = fopFactory.newFOUserAgent(); ua.setFOEventHandlerOverride(factory.createFOEventHandler(ua)); + ua.getEventBroadcaster().addEventListener( + new ConsoleEventListenerForTests(filename)); Fop fop = fopFactory.newFop(ua); diff --git a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java index ced81932b..96aa89bc3 100644 --- a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java +++ b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java @@ -50,6 +50,7 @@ import org.apache.fop.area.RenderPagesModel; import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.Renderer; import org.apache.fop.render.xml.XMLRenderer; +import org.apache.fop.util.ConsoleEventListenerForTests; //XML Unit 1.0: See http://xmlunit.sourceforge.net (BSD-style License) import org.custommonkey.xmlunit.XMLTestCase; @@ -170,6 +171,8 @@ public class AreaTreeParserTestCase extends XMLTestCase { FOUserAgent userAgent = fopFactory.newFOUserAgent(); try { userAgent.setBaseURL(testDir.toURL().toExternalForm()); + userAgent.getEventBroadcaster().addEventListener( + new ConsoleEventListenerForTests(testFile.getName())); } catch (MalformedURLException e) { //ignore, won't happen } diff --git a/test/java/org/apache/fop/intermediate/IntermediateFormatTestSuite.java b/test/java/org/apache/fop/intermediate/IntermediateFormatTestSuite.java index f72b2da87..68c81da81 100644 --- a/test/java/org/apache/fop/intermediate/IntermediateFormatTestSuite.java +++ b/test/java/org/apache/fop/intermediate/IntermediateFormatTestSuite.java @@ -56,10 +56,14 @@ public class IntermediateFormatTestSuite { final File f) { suite.addTest(new AreaTreeParserTestCase(f) { public void runTest() throws Exception { - org.apache.commons.logging.LogFactory.getLog( - this.getClass()).info("Starting " + f.getName()); - testParserToAT(); - testParserToPDF(); + try { + testParserToAT(); + testParserToPDF(); + } catch (Exception e) { + org.apache.commons.logging.LogFactory.getLog( + this.getClass()).error("Error on " + f.getName()); + throw e; + } } }); } diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java index 99a63f2b7..0597e0e91 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTestSuite.java @@ -34,6 +34,14 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamSource; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.AndFileFilter; import org.apache.commons.io.filefilter.IOFileFilter; @@ -42,15 +50,8 @@ import org.apache.commons.io.filefilter.NotFileFilter; 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.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; +import org.apache.fop.DebugHelper; /** * JUnit test suit for running layout engine test under JUnit control. @@ -187,10 +188,14 @@ public class LayoutEngineTestSuite { final LayoutEngineTester tester, final File f) { suite.addTest(new LayoutEngineTestCase(f.getName()) { public void runTest() throws Exception { - org.apache.commons.logging.LogFactory.getLog( - this.getClass()).info("Starting " + f.getName()); - prepare(tester, f); - testMain(); + try { + prepare(tester, f); + testMain(); + } catch (Exception e) { + org.apache.commons.logging.LogFactory.getLog( + this.getClass()).error("Error on " + f.getName()); + throw e; + } } }); } diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java index a10bfa0e3..bcd5f1db4 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTester.java @@ -43,19 +43,23 @@ 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.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.xml.sax.SAXException; + +import org.apache.xpath.XPathAPI; +import org.apache.xpath.objects.XObject; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.FormattingResults; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.render.xml.XMLRenderer; -import org.apache.xpath.XPathAPI; -import org.apache.xpath.objects.XObject; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; +import org.apache.fop.util.ConsoleEventListenerForTests; /** * Class for testing the FOP's layout engine using testcases specified in XML @@ -154,6 +158,9 @@ public class LayoutEngineTester { //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); diff --git a/test/java/org/apache/fop/util/ConsoleEventListenerForTests.java b/test/java/org/apache/fop/util/ConsoleEventListenerForTests.java new file mode 100644 index 000000000..9e8a57285 --- /dev/null +++ b/test/java/org/apache/fop/util/ConsoleEventListenerForTests.java @@ -0,0 +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.util; + +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; + +/** A simple event listener that writes the events to stdout and sterr. */ +public class ConsoleEventListenerForTests implements EventListener { + + private String name; + + public ConsoleEventListenerForTests(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + public void processEvent(Event event) { + if (this.name != null) { + System.out.println("Test: " + this.name); + this.name = null; + } + 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.out.println(" [ERROR] " + msg); + } else if (severity == EventSeverity.FATAL) { + System.out.println(" [FATAL] " + msg); + } else { + assert false; + } + } +} \ No newline at end of file -- cgit v1.2.3 From 6ef7ba4acbc6813dc15670630a47b9e5ad9d87ce Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 18 Apr 2008 10:06:07 +0000 Subject: Merged revisions 649279,649283,649285,649393,649396,649420 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r649279 | jeremias | 2008-04-17 22:23:15 +0100 (Thu, 17 Apr 2008) | 1 line clone() did not propagate the page's page index. ........ r649283 | jeremias | 2008-04-17 22:25:02 +0100 (Thu, 17 Apr 2008) | 1 line 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(). ........ r649285 | jeremias | 2008-04-17 22:27:46 +0100 (Thu, 17 Apr 2008) | 2 lines 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). ........ r649393 | jeremias | 2008-04-18 08:40:27 +0100 (Fri, 18 Apr 2008) | 1 line Forgot to include in commit for revision 649285. ........ r649396 | jeremias | 2008-04-18 08:44:32 +0100 (Fri, 18 Apr 2008) | 1 line 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. ........ r649420 | jeremias | 2008-04-18 10:16:28 +0100 (Fri, 18 Apr 2008) | 1 line Fixed build problem. FOPException is no longer thrown there. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@649444 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/embedding/ExampleFO2JPSPrint.java | 143 ++++++++++++++ ...p.events.EventExceptionManager$ExceptionFactory | 1 + src/java/org/apache/fop/apps/FOPException.java | 2 +- src/java/org/apache/fop/area/PageViewport.java | 1 + 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 +++-- .../org/apache/fop/render/AbstractRenderer.java | 9 +- .../apache/fop/render/java2d/Java2DRenderer.java | 30 ++- .../apache/fop/render/print/PageableRenderer.java | 214 +++++++++++++++++++++ .../org/apache/fop/render/print/PrintRenderer.java | 176 +---------------- src/java/org/apache/fop/render/rtf/RTFHandler.java | 3 - status.xml | 4 + 17 files changed, 545 insertions(+), 231 deletions(-) create mode 100644 examples/embedding/java/embedding/ExampleFO2JPSPrint.java create mode 100644 src/java/org/apache/fop/fo/pagination/PageProductionException.java create mode 100644 src/java/org/apache/fop/render/print/PageableRenderer.java (limited to 'src/java') 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/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/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(); 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 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() 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; - } } 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); } } diff --git a/status.xml b/status.xml index c2bb24a52..009c827c9 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,10 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + Added support for rendering pages using JPS (Java Printing System). See new example: + examples/embedding/java/ExamplesFO2JPSPrint.java + Restored ability to specify from/to and odd/even pages as well as the number of copies for printing from the command-line. -- cgit v1.2.3 From 61fe816e71ee48e847a7a2555ff1c0d973877def Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 18 Apr 2008 16:37:33 +0000 Subject: Merged revisions 649477,649552 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r649477 | jeremias | 2008-04-18 13:03:24 +0100 (Fri, 18 Apr 2008) | 1 line Bugfix: If the first event is not issued over an event producer, the fallback logging event listener was not installed. ........ r649552 | jeremias | 2008-04-18 15:40:56 +0100 (Fri, 18 Apr 2008) | 1 line 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/branches/Temp_AFPGOCAResources@649600 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/apps/FOUserAgent.java | 34 ++++++++++++----------- src/java/org/apache/fop/fonts/SingleByteFont.java | 18 ++++++------ 2 files changed, 27 insertions(+), 25 deletions(-) (limited to 'src/java') 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); - } - } } 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 7c637cc8f0a1f0ff305f6a2fa68018d50ee52170 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 21 Apr 2008 09:51:21 +0000 Subject: Merged revisions 649657,650050 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r649657 | spepping | 2008-04-18 20:07:57 +0100 (Fri, 18 Apr 2008) | 4 lines 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. ........ r650050 | jeremias | 2008-04-21 09:32:02 +0100 (Mon, 21 Apr 2008) | 1 line 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/branches/Temp_AFPGOCAResources@650069 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 ++++++++++++++++++++++ .../apache/fop/render/pdf/ImageRawJPEGAdapter.java | 17 ----------- status.xml | 5 ---- 5 files changed, 42 insertions(+), 48 deletions(-) (limited to 'src/java') 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(); 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 009c827c9..df47e25da 100644 --- a/status.xml +++ b/status.xml @@ -82,11 +82,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 25a8131ea662070fddd811a77c9de352dea3b050 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 25 Apr 2008 10:56:53 +0000 Subject: Merged revisions 651323,651333,651538,651540,651543-651544,651551,651558 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r651323 | spepping | 2008-04-24 18:46:31 +0100 (Thu, 24 Apr 2008) | 3 lines Improve table-unit computation if proportional-column-width() is used as a subexpression. Fixes bug 44658. ........ r651333 | spepping | 2008-04-24 19:19:06 +0100 (Thu, 24 Apr 2008) | 4 lines Make the eventResourceGenerator task for the test files a separate task. Now one can do: ant codegen, compile outside of ant, ant compile-copy-resources, ant junit-compile-copy-resources. ........ r651538 | jeremias | 2008-04-25 09:42:02 +0100 (Fri, 25 Apr 2008) | 1 line Javadocs ........ r651540 | jeremias | 2008-04-25 09:44:39 +0100 (Fri, 25 Apr 2008) | 1 line Cleanup ........ r651543 | adelmelle | 2008-04-25 09:59:56 +0100 (Fri, 25 Apr 2008) | 3 lines 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 ........ r651544 | acumiskey | 2008-04-25 10:04:06 +0100 (Fri, 25 Apr 2008) | 1 line Removed the tab characters that were causing a big moan from eclipse ........ r651551 | adelmelle | 2008-04-25 10:30:09 +0100 (Fri, 25 Apr 2008) | 3 lines Cleanup: removal of commented block/methods + some javadoc updates ........ r651558 | jeremias | 2008-04-25 11:07:58 +0100 (Fri, 25 Apr 2008) | 1 line 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/branches/Temp_AFPGOCAResources@651570 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 8 +- .../apache/fop/tools/EventConventionException.java | 9 + .../apache/fop/tools/EventProducerCollector.java | 30 +++- .../fop/tools/EventProducerCollectorTask.java | 43 ++++- src/java/org/apache/fop/events/EventFormatter.xml | 1 + .../apache/fop/fo/FOValidationEventProducer.java | 9 + .../fop/fo/expr/RelativeNumericProperty.java | 64 ++++++- .../org/apache/fop/fo/flow/BlockContainer.java | 87 ++++------ src/java/org/apache/fop/fo/flow/table/EffRow.java | 44 ++--- .../apache/fop/fo/flow/table/PrimaryGridUnit.java | 31 ++-- .../org/apache/fop/fo/pagination/PageSequence.java | 160 +++--------------- .../apache/fop/fo/properties/LengthProperty.java | 16 -- .../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 +- .../apache/fop/layoutmgr/table/ColumnSetup.java | 5 +- .../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-cell_table-units_mixed.xml | 61 +++++++ .../table_keep-with-next_integers_1.xml | 184 +++++++++++++++++++++ .../table_keep-with-previous_integers_1.xml | 146 ++++++++++++++++ 48 files changed, 1746 insertions(+), 527 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-cell_table-units_mixed.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/java') diff --git a/build.xml b/build.xml index f946872ef..c4eb1e94d 100644 --- a/build.xml +++ b/build.xml @@ -790,7 +790,8 @@ list of possible build targets. - + + @@ -807,6 +808,9 @@ list of possible build targets. + + + @@ -823,6 +827,8 @@ list of possible build targets. + + 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..ebb960a8e 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); } } } @@ -98,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); @@ -172,10 +185,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(); 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/expr/RelativeNumericProperty.java b/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java index ae140b6b7..647528692 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,64 @@ 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/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; 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/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; } 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/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 61d0f8e6f..1e5120700 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/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/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 df47e25da..0b2b2ac38 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,11 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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-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 + + + + + + + + + + + + +
          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 7a70e99012aece4d8c53121d11b454b43e432994 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 25 Apr 2008 13:12:30 +0000 Subject: Merged revisions 651575 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r651575 | adelmelle | 2008-04-25 12:27:19 +0100 (Fri, 25 Apr 2008) | 3 lines 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/branches/Temp_AFPGOCAResources@651599 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 | 5 + .../basic-link_external-destination.xml | 4 +- 13 files changed, 221 insertions(+), 194 deletions(-) (limited to 'src/java') 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 @@
      - + - + 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 d2c8446eb..eae961e9b 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 0b2b2ac38..7d813f6f8 100644 --- a/status.xml +++ b/status.xml @@ -53,11 +53,16 @@ + + + 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 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 637c844c8a6130f1c804afa7f3e2b3bd884e1bee Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 25 Apr 2008 15:13:28 +0000 Subject: Merged revisions 651577,651591,651613,651622-651623 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r651577 | adelmelle | 2008-04-25 12:37:11 +0100 (Fri, 25 Apr 2008) | 1 line Correction: remove unfinished sentence... ........ r651591 | jeremias | 2008-04-25 13:31:44 +0100 (Fri, 25 Apr 2008) | 1 line Update for advanced keeps. ........ r651613 | adelmelle | 2008-04-25 15:13:08 +0100 (Fri, 25 Apr 2008) | 1 line Added missing file from r651575 ........ r651622 | acumiskey | 2008-04-25 15:59:49 +0100 (Fri, 25 Apr 2008) | 1 line Renamed method. ........ r651623 | jeremias | 2008-04-25 16:03:17 +0100 (Fri, 25 Apr 2008) | 3 lines 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/branches/Temp_AFPGOCAResources@651625 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/compliance.ihtml | 14 ++++++---- src/java/org/apache/fop/area/Area.java | 12 -------- src/java/org/apache/fop/area/Trait.java | 32 ++++++++++------------ .../fop/fonts/autodetect/FontInfoFinder.java | 6 ++-- .../basic-link_external-destination.xml | 8 ++++-- 5 files changed, 33 insertions(+), 39 deletions(-) (limited to 'src/java') diff --git a/src/documentation/content/xdocs/compliance.ihtml b/src/documentation/content/xdocs/compliance.ihtml index 2c1af46c3..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.
    • @@ -5283,7 +5287,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.

    • + 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. * 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/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 { 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 1ad900d08ad58f356f1789813c18a0096c889d5b Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 30 Apr 2008 11:02:03 +0000 Subject: Merged revisions 651853,651855-651856,651866-651867,651880,651898 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r651853 | adelmelle | 2008-04-26 21:06:04 +0100 (Sat, 26 Apr 2008) | 3 lines Bugzilla 44203: Fixed a logic error in Hyphenator.java where an UnsupportedOperationException was erroneously thrown if the supplied source had an associated InputStream. ........ r651855 | adelmelle | 2008-04-26 21:19:59 +0100 (Sat, 26 Apr 2008) | 3 lines Basic activation of keep-* properties on Character and AbstractGraphics + javadoc updates ........ r651856 | adelmelle | 2008-04-26 21:21:44 +0100 (Sat, 26 Apr 2008) | 3 lines Basic activation on some widely used properties (prepare for implementation) + javadoc updates ........ r651866 | adelmelle | 2008-04-26 23:08:10 +0100 (Sat, 26 Apr 2008) | 2 lines Javadoc updates: attempt at improving interactivity and consistency ........ r651867 | adelmelle | 2008-04-27 00:07:51 +0100 (Sun, 27 Apr 2008) | 2 lines Minor refactoring: consolidate getPSLM().notifyEndOfLayout(fobj.getId()) in AbstractLayoutManager.notifyEndOfLayout() ........ r651880 | clay | 2008-04-27 04:27:39 +0100 (Sun, 27 Apr 2008) | 1 line Updated to include dev (0.95beta) release. ........ r651898 | adelmelle | 2008-04-27 09:18:31 +0100 (Sun, 27 Apr 2008) | 1 line Correction of r651866 ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@652318 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/doap.rdf | 9 +- 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 - .../org/apache/fop/fo/flow/AbstractGraphics.java | 93 +++---- .../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 +++------ src/java/org/apache/fop/fo/flow/Character.java | 103 +++----- .../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 ++-- .../org/apache/fop/fo/flow/InlineContainer.java | 116 ++++++--- 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 | 25 +- .../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 +-- .../org/apache/fop/hyphenation/Hyphenator.java | 10 +- .../fop/layoutmgr/AbstractLayoutManager.java | 16 +- .../fop/layoutmgr/BlockContainerLayoutManager.java | 18 +- .../apache/fop/layoutmgr/BlockLayoutManager.java | 5 +- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 2 +- .../list/ListItemContentLayoutManager.java | 4 +- .../fop/layoutmgr/list/ListItemLayoutManager.java | 4 +- .../layoutmgr/table/TableCellLayoutManager.java | 4 +- .../fop/layoutmgr/table/TableLayoutManager.java | 2 +- status.xml | 5 + 84 files changed, 1327 insertions(+), 1223 deletions(-) (limited to 'src/java') 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 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/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/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/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; 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/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; 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..c9dd792db 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,7 +59,7 @@ 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 @@ -70,15 +71,16 @@ public class RegionBody extends Region { } /** - * 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; } 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/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(); } /** diff --git a/status.xml b/status.xml index 7d813f6f8..0c5edf1fc 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,11 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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 57f554c453e44d309ddba9ac748772c13b24cf38 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 2 May 2008 16:48:57 +0000 Subject: Merged revisions 652456,652465,652467,652520,652525,652565,652581-652582,652673-652674 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r652456 | adelmelle | 2008-05-01 10:16:05 +0100 (Thu, 01 May 2008) | 3 lines Tweak: activate max-height/min-height and max-width/min-width ........ r652465 | adelmelle | 2008-05-01 10:52:24 +0100 (Thu, 01 May 2008) | 3 lines Added enum "none" as a legitimate value for max-height/min-height (behavior to be checked) Added small testcase to check the correspondence mapping. ........ r652467 | adelmelle | 2008-05-01 11:01:51 +0100 (Thu, 01 May 2008) | 3 lines Minor cleanup: remove height/width members and unused getHeight()/getWidth() accessors ........ r652520 | acumiskey | 2008-05-01 14:46:21 +0100 (Thu, 01 May 2008) | 2 lines Renamed variable ........ r652525 | acumiskey | 2008-05-01 15:01:54 +0100 (Thu, 01 May 2008) | 2 lines Forgot about dependency on PrintRenderer, last commit broke the build - will commit this rename later. ........ r652565 | adelmelle | 2008-05-01 17:15:44 +0100 (Thu, 01 May 2008) | 2 lines Javadoc corrections ........ r652581 | jeremias | 2008-05-01 18:15:49 +0100 (Thu, 01 May 2008) | 1 line Website fixes. ........ r652582 | jeremias | 2008-05-01 18:16:57 +0100 (Thu, 01 May 2008) | 1 line DSC = Document Structuring Conventions! ........ r652673 | adelmelle | 2008-05-01 22:34:19 +0100 (Thu, 01 May 2008) | 2 lines First steps towards fo:retrieve-table-marker ........ r652674 | adelmelle | 2008-05-01 22:39:17 +0100 (Thu, 01 May 2008) | 1 line Code style: single class imports only... ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@652813 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/0.95/graphics.xml | 12 ++ src/documentation/content/xdocs/compliance.ihtml | 8 +- src/documentation/content/xdocs/news.xml | 30 ++-- src/documentation/content/xdocs/trunk/graphics.xml | 12 ++ 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 | 35 ++++- .../apache/fop/fo/flow/AbstractRetrieveMarker.java | 172 +++++++++++++++++++++ .../org/apache/fop/fo/flow/BlockContainer.java | 14 -- src/java/org/apache/fop/fo/flow/Footnote.java | 5 +- src/java/org/apache/fop/fo/flow/FootnoteBody.java | 2 +- .../org/apache/fop/fo/flow/InitialPropertySet.java | 2 +- .../org/apache/fop/fo/flow/RetrieveMarker.java | 145 +++-------------- .../apache/fop/fo/flow/RetrieveTableMarker.java | 111 +++++++++++++ .../apache/fop/layoutmgr/LayoutManagerMapping.java | 19 +-- src/java/org/apache/fop/render/ps/PSRenderer.java | 19 ++- test/fotree/testcases/ipd_bpd_corresponding.fo | 57 +++++++ .../testcases/table_retrieve-table-marker.fo | 68 ++++++++ 19 files changed, 548 insertions(+), 194 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/ipd_bpd_corresponding.fo create mode 100644 test/fotree/testcases/table_retrieve-table-marker.fo (limited to 'src/java') 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/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 @@
      - + @@ -4014,7 +4014,7 @@ - + @@ -4033,7 +4033,7 @@ - + @@ -4052,7 +4052,7 @@ - + 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 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 5d4185d68..643fc7b73 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1423,27 +1423,33 @@ 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.addEnum("NONE", getEnumProperty(EN_NONE, "NONE")); 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.addEnum("NONE", getEnumProperty(EN_NONE, "NONE")); 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 @@ -2091,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..334f98e2f --- /dev/null +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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; + +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/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"; 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 { 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/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) 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! + + + + + 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 e413e9c8a102146703e2f47291f5894476edc48b Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 6 May 2008 09:14:47 +0000 Subject: Merged revisions 652821-652822,652835,653036,653045,653048,653106,653144,653202,653204,653311,653564 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r652821 | adelmelle | 2008-05-02 17:58:26 +0100 (Fri, 02 May 2008) | 6 lines 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 ........ r652822 | adelmelle | 2008-05-02 18:00:33 +0100 (Fri, 02 May 2008) | 1 line Expand imports... ........ r652835 | adelmelle | 2008-05-02 18:28:25 +0100 (Fri, 02 May 2008) | 3 lines Bugzilla 42703: Fixed a regression introduced by the fix for Bugzilla 44286 ........ r653036 | adelmelle | 2008-05-03 11:21:45 +0100 (Sat, 03 May 2008) | 2 lines Cleanup: improve code-readibility ........ r653045 | adelmelle | 2008-05-03 11:51:16 +0100 (Sat, 03 May 2008) | 2 lines Tweak/correction: save local hash-code (as originally intended...) ........ r653048 | adelmelle | 2008-05-03 11:55:07 +0100 (Sat, 03 May 2008) | 2 lines Tweaks: make fobj member final; have default implementations for some methods throw an UnsupportedOperationException instead of merely logging an error ........ r653106 | acumiskey | 2008-05-03 20:07:18 +0100 (Sat, 03 May 2008) | 1 line Fixed the build. Assignment on final variable fobj. ........ r653144 | acumiskey | 2008-05-03 22:29:09 +0100 (Sat, 03 May 2008) | 1 line Fix that preserves the final status of the fobj member variable. ........ r653202 | adelmelle | 2008-05-04 12:37:31 +0100 (Sun, 04 May 2008) | 2 lines Change private element-generating methods to add the elements to a passed List (improves code-readability and reduces the amount of temporary LinkedList instances) ........ r653204 | adelmelle | 2008-05-04 14:04:28 +0100 (Sun, 04 May 2008) | 4 lines Further refinements: -> use cached auxiliary position where possible (analogous to BlockStackingLM) -> consolidate makeXXXPenalty() helpers ........ r653311 | jeremias | 2008-05-05 07:50:54 +0100 (Mon, 05 May 2008) | 6 lines 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. ........ r653564 | adelmelle | 2008-05-05 20:27:10 +0100 (Mon, 05 May 2008) | 2 lines Correction of indentation ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@653718 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FObj.java | 49 +- .../org/apache/fop/fo/XMLWhiteSpaceHandler.java | 5 +- .../apache/fop/fo/flow/AbstractRetrieveMarker.java | 29 + .../org/apache/fop/fo/flow/RetrieveMarker.java | 53 +- .../apache/fop/fo/flow/RetrieveTableMarker.java | 18 +- .../fop/fo/properties/CommonHyphenation.java | 5 +- .../fop/layoutmgr/AbstractBaseLayoutManager.java | 53 +- .../fop/layoutmgr/inline/TextLayoutManager.java | 1015 +++++++++----------- .../layoutmgr/table/TableCellLayoutManager.java | 1 - .../org/apache/fop/render/pcl/PCLRenderer.java | 54 +- status.xml | 15 +- .../testcases/table_retrieve-table-marker.fo | 4 +- .../marker_white-space-treatment_bug42703.xml | 29 + 13 files changed, 616 insertions(+), 714 deletions(-) (limited to 'src/java') 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/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/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java index 334f98e2f..83a0ddbdc 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java @@ -23,9 +23,11 @@ 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; @@ -40,6 +42,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 +54,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 +72,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 +188,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/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; } } diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java index c5e0ddfc9..7fd289c05 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; } /** @@ -58,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); @@ -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; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 40e1c087a..be8a13d50 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 + "]"; } @@ -120,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; /** @@ -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; @@ -152,23 +153,23 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** 1/2 of word-spacing value */ 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 SpaceVal halfLS; + + private boolean hasChanged = false; + private int returnedIndex = 0; + private short thisStart = 0; + private short tempStart = 0; private LinkedList changeList = null; private AlignmentContext alignmentContext = null; private int lineStartBAP = 0; private int lineEndBAP = 0; - + private boolean keepTogether; + private final Position auxiliaryPosition = new LeafPosition(this, -1); + /** * Create a Text layout manager. * @@ -177,7 +178,7 @@ 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); @@ -185,22 +186,39 @@ public class TextLayoutManager extends LeafNodeLayoutManager { vecAreaInfo = new java.util.ArrayList(); } - + + private KnuthPenalty makeZeroWidthPenalty(int penaltyValue) { + return new KnuthPenalty( + 0, + penaltyValue, + false, + auxiliaryPosition, + true); + } + + private KnuthBox makeAuxiliaryZeroWidthBox() { + return new KnuthInlineBox( + 0, + null, + notifyPos(new LeafPosition(this, -1)), + true); + } + /** {@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)); - + // 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), @@ -219,33 +237,9 @@ 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; - - } - - // 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); + keepTogether = foText.getKeepTogether().getWithinLine().getEnum() == Constants.EN_ALWAYS; - 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; } /** @@ -262,8 +256,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,102 +275,102 @@ 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++) { - MinOptMax ladj = letterAdjustArray[i + 1]; + + 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 // 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 + - // + (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 @@ -395,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 */ @@ -431,7 +425,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 +439,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) { + && i == lastIndex + && areaInfo.isHyphenated) { len++; } StringBuffer wordChars = new StringBuffer(len); @@ -459,10 +453,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); } @@ -475,8 +469,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } // String wordChars = new String(textArray, wordStartIndex, len); if (isLastArea - && i == lastIndex - && areaInfo.bHyphenated) { + && i == lastIndex + && areaInfo.isHyphenated) { // add the hyphenation character wordChars.append(foText.getCommonHyphenation().getHyphChar(font)); } @@ -487,21 +481,13 @@ 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); - } else { - letterAdjustArray[index].add(width); - } - } - private void addToLetterAdjust(int index, MinOptMax width) { + private void addToLetterAdjust(int index, int width) { if (letterAdjustArray[index] == null) { letterAdjustArray[index] = new MinOptMax(width); } else { @@ -519,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(); @@ -533,14 +519,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]; + char ch = 0; + 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 +544,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 +561,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,94 +591,91 @@ 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 - sequence.addAll(createElementsForAWordFragment(alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD)); + //add the elements + addElementsForAWordFragment(sequence, 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), - false, true, breakOpportunity); + ai = new AreaInfo(thisStart, nextStart, + (short) (nextStart - thisStart), (short) 0, + MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), + false, true, breakOpportunity); vecAreaInfo.add(ai); prevAi = ai; // create the elements - sequence.addAll - (createElementsForASpace(alignment, ai, vecAreaInfo.size() - 1)); + addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); ai = null; - iThisStart = iNextStart; + thisStart = nextStart; } } else { 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, - new LeafPosition(this, -1), true)); + sequence.add( + new KnuthGlue(lineEndBAP, 0, 0, + auxiliaryPosition, true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); 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 - 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); + ipd, false, true, breakOpportunity); + 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 +685,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,38 +703,36 @@ 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)); + addElementsForAWordFragment(sequence, 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), - false, true, true); + ai = new AreaInfo(thisStart, (short) (nextStart), + (short) (nextStart - thisStart), (short) 0, + MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), + false, true, true); 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) { sequence.add (new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), true)); + auxiliaryPosition, true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -782,29 +763,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)); + auxiliaryPosition, false)); oldListIterator.add(new KnuthGlue(letterSpaceIPD.opt, letterSpaceIPD.max - letterSpaceIPD.opt, letterSpaceIPD.opt - letterSpaceIPD.min, - new LeafPosition(this, -1), false)); + auxiliaryPosition, 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), + auxiliaryPosition, true)); } } return oldList; @@ -844,37 +825,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,69 +866,66 @@ 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; - } - if (!bChanged && !bNothingChanged) { - bChanged = true; + startIndex = stopIndex; } + hasChanged = !nothingChanged; } /** {@inheritDoc} */ public boolean applyChanges(List oldList) { setFinished(false); - if (changeList != null) { - int iAddedAI = 0; - int iRemovedAI = 0; - int iOldIndex = -1; - PendingChange currChange = null; + if (changeList != null && !changeList.isEmpty()) { + int areaInfosAdded = 0; + int areaInfosRemoved = 0; + int oldIndex = -1, changeIndex; + PendingChange currChange; 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, - currChange.ai); + if (currChange.index != oldIndex) { + areaInfosRemoved++; + areaInfosAdded++; + oldIndex = currChange.index; + changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; + vecAreaInfo.remove(changeIndex); } else { - iAddedAI++; - vecAreaInfo.add(currChange.index + iAddedAI - iRemovedAI, - currChange.ai); + areaInfosAdded++; + changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; } + vecAreaInfo.add(changeIndex, currChange.ai); } changeList.clear(); } - iReturnedIndex = 0; - return bChanged; + returnedIndex = 0; + return hasChanged; } /** {@inheritDoc} */ @@ -959,18 +937,16 @@ 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)); + addElementsForAWordFragment(returnList, alignment, ai, returnedIndex, letterSpaceIPD); } else { // ai refers to a space - returnList.addAll - (createElementsForASpace(alignment, ai, iReturnedIndex)); + addElementsForASpace(returnList, alignment, ai, returnedIndex); } - iReturnedIndex++; + returnedIndex++; } // end of while setFinished(true); //ElementListObserver.observe(returnList, "text-changed", null); @@ -979,63 +955,55 @@ 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(textArray, ai.startIndex, ai.breakIndex - ai.startIndex); } } - 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) { // 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)); + 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 { // 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, + baseList.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) { 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 - spaceElements.add(new KnuthGlue(lineEndBAP, + baseList.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( + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); + baseList.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, + 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)); break; @@ -1043,124 +1011,102 @@ 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 - spaceElements.add(new KnuthGlue(lineEndBAP, + baseList.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( + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); + baseList.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, + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + 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, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - 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, + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue( + - (lineStartBAP + 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, mainPosition, false)); break; default: // 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)); - 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, + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue( + - (lineStartBAP + 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, 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 - spaceElements.add(new KnuthGlue(lineEndBAP, + baseList.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 + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); + baseList.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(new KnuthGlue(lineStartBAP, + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); + auxiliaryPosition, 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 + // 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) { - spaceElements.add(new KnuthGlue(lineEndBAP, + baseList.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 + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); + baseList.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(new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, + auxiliaryPosition, false)); } else { - spaceElements.add(new KnuthGlue(0, + baseList.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 + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, mainPosition, false)); } @@ -1170,26 +1116,22 @@ 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, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue( - ai.ipdArea.opt - (lineStartBAP + lineEndBAP), - ai.ipdArea.max - ai.ipdArea.opt, - ai.ipdArea.opt - ai.ipdArea.min, + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, + 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)); - 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, 0, 0, - new LeafPosition(this, -1), false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, + auxiliaryPosition, false)); } else { - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, - ai.ipdArea.max - ai.ipdArea.opt, - ai.ipdArea.opt - ai.ipdArea.min, + baseList.add(new KnuthGlue(ai.areaIPD.opt, + ai.areaIPD.max - ai.areaIPD.opt, + ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); } break; @@ -1198,279 +1140,190 @@ 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, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthPenalty(0, 0, false, - new LeafPosition(this, -1), false)); - spaceElements.add(new KnuthGlue( - ai.ipdArea.opt - (lineStartBAP + lineEndBAP), - ai.ipdArea.max - ai.ipdArea.opt, + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, + auxiliaryPosition, false)); + baseList.add(makeZeroWidthPenalty(0)); + baseList.add(new KnuthGlue( + 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(new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, + auxiliaryPosition, false)); } else { - spaceElements.add(new KnuthGlue(ai.ipdArea.opt, - ai.ipdArea.max - ai.ipdArea.opt, 0, + 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 '/', // 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, + baseList.add(new KnuthInlineBox( + 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; - wordElements.add - (new KnuthInlineBox(ai.ipdArea.opt - - ai.iLScount * letterSpaceWidth.opt, + int unsuppressibleLetterSpaces + = suppressibleLetterSpace ? ai.letterSpaceCount - 1 : ai.letterSpaceCount; + baseList.add + (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 + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.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)); + 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.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) { + 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 - (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 - (new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), true)); - hyphenElements.add - (new KnuthPenalty(hyphIPD, + 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, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthGlue(-(lineEndBAP + lineStartBAP), + auxiliaryPosition, false)); + baseList.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)); - hyphenElements.add - (new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), true)); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + 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: - /* - 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 - (new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + auxiliaryPosition, false)); + baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthGlue(widthIfNoBreakOccurs.opt - (lineStartBAP + lineEndBAP), + auxiliaryPosition, false)); + baseList.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)); - hyphenElements.add - (new KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, + auxiliaryPosition, false)); } else { - hyphenElements.add - (new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); - hyphenElements.add - (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + auxiliaryPosition, false)); + baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthGlue(widthIfNoBreakOccurs.opt, + auxiliaryPosition, false)); + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - new LeafPosition(this, -1), false)); + auxiliaryPosition, 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 - (new KnuthGlue(lineEndBAP, 0, 0, - new LeafPosition(this, -1), false)); - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, + auxiliaryPosition, false)); + baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); + auxiliaryPosition, 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, - new LeafPosition(this, -1), false)); + auxiliaryPosition, false)); } else { - hyphenElements.add - (new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, - new LeafPosition(this, -1), false)); + baseList.add(new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, + auxiliaryPosition, 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 KnuthGlue(lineStartBAP, 0, 0, - new LeafPosition(this, -1), false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, + auxiliaryPosition, false)); } else { - hyphenElements.add - (new KnuthPenalty(widthIfBreakOccurs, + baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - new LeafPosition(this, -1), false)); + auxiliaryPosition, 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, - new LeafPosition(this, -1), false)); + auxiliaryPosition, false)); } } } - - return hyphenElements; - } -} - + } +} 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; } 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 0c5edf1fc..222d41b80 100644 --- a/status.xml +++ b/status.xml @@ -60,12 +60,23 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. - + + PCL Renderer: Improved page format selection so it doesn't interfere with + duplex printing. + + + 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. - + Add partial support for the "show-destination" property on fo:basic-link (PDF output only; see limitations on the compliance page) 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 @@ - - + + 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 175c6a8d234fc44e8b41bad5816645c2a9184a87 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 6 May 2008 16:18:51 +0000 Subject: Merged revisions 653826 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r653826 | acumiskey | 2008-05-06 17:14:09 +0100 (Tue, 06 May 2008) | 6 lines * 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/branches/Temp_AFPGOCAResources@653827 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/java') 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 222d41b80..63a060896 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,10 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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 f9f85a1e74881074d432f426249b2f62a9b3712f Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 8 May 2008 15:45:26 +0000 Subject: Merged revisions 654111,654121,654190,654314,654322-654323,654338,654347,654437,654461,654528,654557 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r654111 | adelmelle | 2008-05-07 15:04:17 +0100 (Wed, 07 May 2008) | 6 lines 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. ........ r654121 | adelmelle | 2008-05-07 15:19:13 +0100 (Wed, 07 May 2008) | 1 line Small correction: use appropriate value for 'context' ........ r654190 | adelmelle | 2008-05-07 18:41:07 +0100 (Wed, 07 May 2008) | 1 line Added comment ........ r654314 | adelmelle | 2008-05-07 23:45:46 +0100 (Wed, 07 May 2008) | 1 line Corrected errors in ColumnNumberPropertyMaker.java; temporarily disabled two testcases for a non-standard feature ........ r654322 | acumiskey | 2008-05-08 00:27:45 +0100 (Thu, 08 May 2008) | 1 line 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. ........ r654323 | acumiskey | 2008-05-08 00:29:04 +0100 (Thu, 08 May 2008) | 1 line Whoops.. small checkstyle nit :) ........ r654338 | adelmelle | 2008-05-08 01:18:14 +0100 (Thu, 08 May 2008) | 1 line Removed inadvertently added override [Avoid late night commits...] ........ r654347 | acumiskey | 2008-05-08 01:33:21 +0100 (Thu, 08 May 2008) | 1 line Removed tabs. Checkstyle now configured. Late nights.. and a new machine build.. :S ........ r654437 | jeremias | 2008-05-08 08:32:02 +0100 (Thu, 08 May 2008) | 1 line Checkstyle fix. ........ r654461 | jeremias | 2008-05-08 10:55:55 +0100 (Thu, 08 May 2008) | 5 lines 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. ........ r654528 | adelmelle | 2008-05-08 14:56:14 +0100 (Thu, 08 May 2008) | 5 lines Tweak: -> add 'runtimeType' member and toString() to PropertyCache to facilitate debugging -> modify the initial assignment in the related Property types accordingly ........ r654557 | pietsch | 2008-05-08 16:36:02 +0100 (Thu, 08 May 2008) | 1 line Quick fix for XML validation error ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@654562 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/events/EventFormatter.xml | 3 +- src/java/org/apache/fop/fo/flow/Wrapper.java | 61 +++++++++------ .../org/apache/fop/fo/flow/table/TableFObj.java | 21 ++--- .../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 +++++----- src/java/org/apache/fop/fonts/EmbedFontInfo.java | 33 +++++++- src/java/org/apache/fop/fonts/FontCache.java | 5 ++ 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/layoutmgr/BlockStackingLayoutManager.java | 16 +++- .../apache/fop/layoutmgr/FlowLayoutManager.java | 4 +- .../fop/layoutmgr/inline/WrapperLayoutManager.java | 19 ++++- .../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 | 13 +++- test/basictests.xml | 4 +- test/fotree/disabled-testcases.xml | 10 +++ test/layoutengine/disabled-testcases.xml | 6 -- 41 files changed, 552 insertions(+), 239 deletions(-) (limited to 'src/java') 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/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..5ed594ecc 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,17 @@ public class Wrapper extends FObjMixed { "(#PCDATA|%inline;|%block;)"); } } else if (isBlockOrInlineItem(nsURI, localName)) { - //delegate validation to parent - FONode.validateChildNode(this.parent, loc, 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 { + 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 +86,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/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 9b60de740..ca1afa622 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -51,7 +51,7 @@ public abstract class TableFObj extends FObj { /** * Main constructor - * + * * @param parent the parent node */ public TableFObj(FONode parent) { @@ -76,7 +76,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 +98,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 +142,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,15 +155,18 @@ 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()); } } 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(); } 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/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index c5b6ab9c7..ba9529c02 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; 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/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/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 63a060896..1bb818326 100644 --- a/status.xml +++ b/status.xml @@ -60,10 +60,21 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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. + + + 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/basictests.xml b/test/basictests.xml index 7b01d3f41..8f5dfc719 100644 --- a/test/basictests.xml +++ b/test/basictests.xml @@ -1,9 +1,9 @@ - + - + simple test 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 + + 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 d972250786d5575d56a55aede884e9df46450c60 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 9 May 2008 11:00:03 +0000 Subject: Merged revisions 654563,654600,654654 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r654563 | pietsch | 2008-05-08 16:53:23 +0100 (Thu, 08 May 2008) | 1 line Fix validation errors ........ r654600 | vhennebert | 2008-05-08 20:29:55 +0100 (Thu, 08 May 2008) | 2 lines 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 ........ r654654 | adelmelle | 2008-05-09 00:46:45 +0100 (Fri, 09 May 2008) | 1 line 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/branches/Temp_AFPGOCAResources@654753 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/IDTracker.java | 8 +- .../fo/flow/table/CollapsingBorderResolver.java | 69 ++++++----- .../fop/fo/flow/table/ConditionalBorder.java | 79 ++++++------- .../org/apache/fop/fo/flow/table/GridUnit.java | 34 +++--- test/bugtests.xml | 128 ++++++++++----------- .../table/CollapsedConditionalBorderTestCase.java | 16 +-- 6 files changed, 167 insertions(+), 167 deletions(-) (limited to 'src/java') 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); 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/bugtests.xml b/test/bugtests.xml index cb45879e2..b458bf59e 100644 --- a/test/bugtests.xml +++ b/test/bugtests.xml @@ -3,7 +3,7 @@ - + Checks the width of all the defined characters @@ -12,18 +12,18 @@ Checks the width of all the defined characters - + Some lists with nested list and large list item bodies. - + Nested lists with page breaks inside list items. Used to show that it correctly places the list items and labels. The break before does not put the list item label on the correct page. - + Nested lists used to show that the indentation is correct for lists inside lists. @@ -33,155 +33,155 @@ Nested lists used to show that the indentation is correct for lists inside lists - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + 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 df8430fb6c4d776b404455baeb5c56617b54f0db Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 12 May 2008 08:58:21 +0000 Subject: Merged revisions 654783,654849,654869,654946,654982,655085,655093,655275,655281,655285,655309,655349,655370 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r654783 | vhennebert | 2008-05-09 13:30:40 +0100 (Fri, 09 May 2008) | 3 lines Checkstyle and minor typo fixes Set svn:keywords and svn:eol-style properties on new files ........ r654849 | acumiskey | 2008-05-09 16:14:37 +0100 (Fri, 09 May 2008) | 1 line Unwanted list self concatenation :). ........ r654869 | acumiskey | 2008-05-09 17:13:47 +0100 (Fri, 09 May 2008) | 1 line Moved the instantiation of the FontManager to the constructor along with all the other aggregated objects. ........ r654946 | adelmelle | 2008-05-09 22:40:14 +0100 (Fri, 09 May 2008) | 6 lines 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) ........ r654982 | acumiskey | 2008-05-10 00:47:28 +0100 (Sat, 10 May 2008) | 1 line Checkstyle cleanup and javadoc ........ r655085 | adelmelle | 2008-05-10 14:44:09 +0100 (Sat, 10 May 2008) | 5 lines 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...) ........ r655093 | adelmelle | 2008-05-10 15:23:56 +0100 (Sat, 10 May 2008) | 1 line Correction: set default to true... ........ r655275 | maxberger | 2008-05-11 08:30:55 +0100 (Sun, 11 May 2008) | 1 line made sure warning for missing glyphs is emitted in all cases ........ r655281 | maxberger | 2008-05-11 10:01:31 +0100 (Sun, 11 May 2008) | 1 line Support character-by-character font-selection strategy on fo:character element ........ r655285 | maxberger | 2008-05-11 10:17:07 +0100 (Sun, 11 May 2008) | 1 line Forgot to update testcases ........ r655309 | adelmelle | 2008-05-11 13:22:22 +0100 (Sun, 11 May 2008) | 3 lines 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. ........ r655349 | spepping | 2008-05-11 19:05:51 +0100 (Sun, 11 May 2008) | 2 lines The spec requires rounding, not truncating ........ r655370 | adelmelle | 2008-05-11 22:03:41 +0100 (Sun, 11 May 2008) | 1 line Avoid creation of unnecessary dummy areas. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@655445 13f79535-47bb-0310-9956-ffa450edef68 --- src/codegen/fonts/font-file.xsl | 4 +- 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 | 148 ++++++----- .../apache/fop/apps/FopFactoryConfigurator.java | 46 ++-- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- src/java/org/apache/fop/fo/FObj.java | 9 +- .../org/apache/fop/fo/properties/CommonFont.java | 276 +++++++-------------- .../apache/fop/fo/properties/NumberProperty.java | 2 +- .../apache/fop/fo/properties/PropertyCache.java | 38 +-- .../org/apache/fop/fonts/CustomFontCollection.java | 13 +- src/java/org/apache/fop/fonts/EmbedFontInfo.java | 34 +-- src/java/org/apache/fop/fonts/Font.java | 18 +- 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 +- 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 +++- .../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 | 91 ++++--- .../apache/fop/layoutmgr/BlockLayoutManager.java | 4 +- .../layoutmgr/inline/CharacterLayoutManager.java | 34 ++- .../fop/layoutmgr/inline/InlineLayoutManager.java | 1 + .../fop/layoutmgr/inline/WrapperLayoutManager.java | 7 +- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 2 +- .../list/ListItemContentLayoutManager.java | 2 +- .../fop/layoutmgr/list/ListItemLayoutManager.java | 2 +- .../fop/render/AbstractRendererConfigurator.java | 12 +- src/java/org/apache/fop/render/PrintRenderer.java | 20 +- .../fop/render/PrintRendererConfigurator.java | 54 ++-- .../org/apache/fop/render/afp/AFPRenderer.java | 28 +-- .../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 ++-- status.xml | 8 + test/fotree/testcases/demo-test-success.fo | 2 +- test/fotree/testcases/no_namespace_prefix.fo | 2 +- .../apache/fop/config/BaseUserConfigTestCase.java | 20 +- .../fop/config/FontsSubstitutionTestCase.java | 21 +- .../fop/layoutengine/LayoutEngineTester.java | 52 ++-- .../org/apache/fop/render/pdf/BasePDFTestCase.java | 6 +- .../fop/render/pdf/PDFAConformanceTestCase.java | 12 +- test/layoutengine/disabled-testcases.xml | 5 - .../page-number-citation_bugzilla44794.xml | 70 ++++++ .../page-number-citation_list.xml | 126 ++++++++++ 67 files changed, 1265 insertions(+), 1060 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/java') 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/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..2d4029da8 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. */ @@ -144,13 +144,21 @@ 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(); this.xmlHandlers = new XMLHandlerRegistry(); this.ignoredNamespaces = new java.util.HashSet(); } - + /** * Returns a new FopFactory instance. * @return the requested FopFactory instance. @@ -158,13 +166,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 +180,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 +194,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 +235,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 +275,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 +318,7 @@ public class FopFactory implements ImageContext { public LayoutManagerMaker getLayoutManagerMakerOverride() { return this.lmMakerOverride; } - + /** * Sets the base URL. * @param base the base URL @@ -327,7 +335,7 @@ public class FopFactory implements ImageContext { public String getBaseURL() { return this.base; } - + /** * Sets the font base URL. * @param fontBase font base URL @@ -367,10 +375,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 +405,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 +432,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 +455,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 +463,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 +472,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 +485,7 @@ public class FopFactory implements ImageContext { * @see #getSourceResolution() */ public float getSourcePixelUnitToMillimeter() { - return 25.4f / getSourceResolution(); + return 25.4f / getSourceResolution(); } /** @@ -488,7 +496,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 +513,7 @@ public class FopFactory implements ImageContext { * @see #getTargetResolution() */ public float getTargetPixelUnitToMillimeter() { - return 25.4f / this.targetResolution; + return 25.4f / this.targetResolution; } /** @@ -525,7 +533,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 +543,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 +556,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 +566,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 +579,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 +608,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 +635,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,25 +698,15 @@ public class FopFactory implements ImageContext { public FontCache getFontCache() { return getFontManager().getFontCache(); } - + /** * Returns the font manager. * @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; } - + /** * Attempts to resolve the given URI. * Will use the configured resolver and if not successful fall back @@ -716,7 +714,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 +726,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/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/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/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/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; } diff --git a/src/java/org/apache/fop/fo/properties/PropertyCache.java b/src/java/org/apache/fop/fo/properties/PropertyCache.java index 2c51bc081..b5f4f90ba 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,8 +268,13 @@ public final class PropertyCache { * @param c Runtime type of the objects that will be stored in the cache */ public PropertyCache(Class c) { - 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; } @@ -278,6 +289,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 +306,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 +319,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 +332,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. * 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..3a0d82046 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 @@ -212,12 +212,12 @@ public class Font { c = d; } else { log.warn("Glyph " + (int) c + " not available in font " + fontName); - c = '#'; + c = Typeface.NOT_FOUND; } 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/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()); + } + } + } + } } - 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..3f2143bae 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 { /** @@ -56,14 +56,14 @@ 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; - + /** child LM iterator during getNextKnuthElement phase */ protected ListIterator childLMiter = null; - + private int lastGeneratedPosition = -1; private int smallestPosNumberChecked = Integer.MAX_VALUE; @@ -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,18 +144,14 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager * @param fin the flag value to be set */ public void setFinished(boolean fin) { - bFinished = fin; + 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!"); @@ -229,20 +223,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} */ @@ -302,11 +296,12 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager if (pos.getIndex() >= 0) { throw new IllegalStateException("Position already got its index"); } + lastGeneratedPosition++; 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 +321,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 +344,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 +355,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); } } @@ -386,9 +381,49 @@ 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()} and cleans up. + * + * @param pos the {@link Position} to check + */ + protected void checkEndOfLayout(Position pos) { + 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; + } + } + } + /** {@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/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/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/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); 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/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..35630d628 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 @@ -54,10 +54,10 @@ public abstract class PrintRenderer extends AbstractRenderer { if (embedFontInfoList == null) { setFontList(fontList); } else { - fontList.addAll(fontList); + embedFontInfoList.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 14eb33510..626ca47da 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -502,7 +502,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); @@ -511,7 +511,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; @@ -542,7 +542,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); @@ -600,7 +600,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { //Not used here since AFPRenderer defines its own renderBlockViewport() method. throw new UnsupportedOperationException("NYI"); } - + /** * {@inheritDoc} */ @@ -930,7 +930,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}; @@ -957,12 +957,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; @@ -1066,7 +1066,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { IOUtils.closeQuietly(in); } } - + /* ImageFactory fact = userAgent.getFactory().getImageFactory(); FopImage fopimage = fact.getImage(url, userAgent); @@ -1139,7 +1139,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 { @@ -1474,9 +1474,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ // UNUSED // public void setOptions(Map options) { -// +// // this.afpOptions = options; -// +// // } /** * Determines the orientation from the string representation, this method @@ -1543,7 +1543,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. */ @@ -1714,7 +1714,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { io.setImageIDESize((byte) bitsPerPixel); io.setImageData(bw); } - + private final class ViewPortPos { private int x = 0; @@ -1882,7 +1882,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/status.xml b/status.xml index 1bb818326..593d1c567 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,14 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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 + 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/fotree/testcases/demo-test-success.fo b/test/fotree/testcases/demo-test-success.fo index 6d4696ebc..7af8a73c7 100644 --- a/test/fotree/testcases/demo-test-success.fo +++ b/test/fotree/testcases/demo-test-success.fo @@ -8,7 +8,7 @@ Hello World! - + diff --git a/test/fotree/testcases/no_namespace_prefix.fo b/test/fotree/testcases/no_namespace_prefix.fo index 6cae6e9c9..f9719a22d 100644 --- a/test/fotree/testcases/no_namespace_prefix.fo +++ b/test/fotree/testcases/no_namespace_prefix.fo @@ -26,7 +26,7 @@ Hello World! - + 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..6f286a3fb 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; @@ -29,8 +29,16 @@ import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.render.PrintRenderer; -public class FontsSubstitutionTestCase extends BaseConstructiveUserConfigTestCase { +/** + * Tests the font substitution mechanism + */ +public class FontsSubstitutionTestCase extends + BaseConstructiveUserConfigTestCase { + /** + * Main constructor + * @param name test case name + */ public FontsSubstitutionTestCase(String name) { super(name); } @@ -38,13 +46,16 @@ public class FontsSubstitutionTestCase extends BaseConstructiveUserConfigTestCas /** * {@inheritDoc} */ - protected byte[] convertFO(File foFile, FOUserAgent ua, boolean dumpPdfFile) throws Exception { - PrintRenderer renderer = (PrintRenderer)ua.getRendererFactory().createRenderer(ua, MimeConstants.MIME_PDF); + 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); + 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) 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 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 ae943c148037cc35741b38b9857e8594de44d058 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 13 May 2008 08:49:16 +0000 Subject: Merged revisions 655489,655500,655522,655531,655578,655601,655603,655614,655766,655771,655775 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r655489 | vhennebert | 2008-05-12 13:30:42 +0100 (Mon, 12 May 2008) | 2 lines 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 ........ r655500 | adelmelle | 2008-05-12 14:42:49 +0100 (Mon, 12 May 2008) | 2 lines Extended caching to CondLengthProperty CommonBorderPaddingBackground.BorderInfo and CommonBorderPaddingBackground. ........ r655522 | adelmelle | 2008-05-12 16:24:06 +0100 (Mon, 12 May 2008) | 2 lines Tweak: avoid preloading the background-image with each pass through the constructor; only do so for non-cached instances ........ r655531 | adelmelle | 2008-05-12 16:34:49 +0100 (Mon, 12 May 2008) | 2 lines Avoid an error if unspecified... ........ r655578 | spepping | 2008-05-12 18:53:21 +0100 (Mon, 12 May 2008) | 3 lines Restore the previous behaviour of the column-number property, viz. if it is negative, it is set the next free column ........ r655601 | adelmelle | 2008-05-12 20:06:04 +0100 (Mon, 12 May 2008) | 1 line Added missing file from r655500 ........ r655603 | adelmelle | 2008-05-12 20:11:00 +0100 (Mon, 12 May 2008) | 1 line Re-enabled testcases that pass again after r655578 ........ r655614 | vhennebert | 2008-05-12 20:37:39 +0100 (Mon, 12 May 2008) | 3 lines 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 ........ r655766 | adelmelle | 2008-05-13 08:58:31 +0100 (Tue, 13 May 2008) | 2 lines Added support for auto-generated initial value for the "id" property. ........ r655771 | adelmelle | 2008-05-13 09:11:12 +0100 (Tue, 13 May 2008) | 1 line Alter auto-id naming to avoid confusion with URI fragment identifiers ........ r655775 | adelmelle | 2008-05-13 09:20:57 +0100 (Tue, 13 May 2008) | 1 line Javadoc fixups ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@655782 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOEventHandler.java | 26 +- src/java/org/apache/fop/fo/FOPropertyMapping.java | 2 +- src/java/org/apache/fop/fo/PropertyList.java | 13 +- .../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 | 69 ++-- .../org/apache/fop/fo/flow/table/TableRow.java | 9 - .../properties/CommonBorderPaddingBackground.java | 377 ++++++++++++++++----- .../fop/fo/properties/CondLengthProperty.java | 47 ++- .../apache/fop/fo/properties/PropertyCache.java | 26 ++ .../apache/fop/fo/properties/StringProperty.java | 47 +++ .../org/apache/fop/layoutmgr/table/ActiveCell.java | 14 +- .../apache/fop/layoutmgr/table/TableStepper.java | 11 +- test/fotree/disabled-testcases.xml | 10 - test/fotree/testcases/id_auto.fo | 28 ++ 19 files changed, 576 insertions(+), 200 deletions(-) create mode 100644 test/fotree/testcases/id_auto.fo (limited to 'src/java') diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 5a9a5bb9d..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. */ @@ -131,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; @@ -155,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) { @@ -163,11 +174,22 @@ public abstract class FOEventHandler { /** * Check whether in marker context + * + * @return true if a marker is being processed */ protected boolean inMarker() { 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 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/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); } /** 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 ca1afa622..6bc113fd0 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} */ @@ -197,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 @@ -205,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) { @@ -224,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; diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java index 96c1e80e2..35913ce3a 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,62 +268,44 @@ 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(); 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, @@ -272,18 +331,67 @@ 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); + 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()) + && (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())) { + cachedInstance = cache.fetch(newInstance); + } + + /* for non-cached, or not-yet-cached instances, preload the image */ + if ((cachedInstance == null + || cachedInstance == newInstance) + && !("".equals(newInstance.backgroundImage))) { + //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 (cachedInstance != null ? cachedInstance : 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 +399,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 +415,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 +424,103 @@ 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(); } } + /** + * The border-color for the given side + * + * @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) { return borderInfo[side].getColor(); @@ -390,6 +529,12 @@ public class CommonBorderPaddingBackground { } } + /** + * The border-style for the given side + * + * @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) { return borderInfo[side].mStyle; @@ -398,8 +543,18 @@ public class CommonBorderPaddingBackground { } } - public int getPadding(int side, boolean bDiscard, PercentBaseContext context) { - if ((padding[side] == null) || (bDiscard && padding[side].isDiscard())) { + /** + * Return the padding for the given side, taking into account + * the conditionality and evaluating any percentages in the given + * context. + * + * @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())) { return 0; } else { return padding[side].getLengthValue(context); @@ -418,27 +573,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 +634,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 + "]"; diff --git a/src/java/org/apache/fop/fo/properties/StringProperty.java b/src/java/org/apache/fop/fo/properties/StringProperty.java index 194170fec..8880921de 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/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 1e5120700..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,6 +547,13 @@ class ActiveCell { return keepWithNextStrength; } + int getPenaltyValue() { + if (includedInLastStep()) { + return nextStep.penaltyValue; + } else { + return previousStep.penaltyValue; + } + } /** {@inheritDoc} */ public String toString() { 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()); diff --git a/test/fotree/disabled-testcases.xml b/test/fotree/disabled-testcases.xml index 0d0a76f6b..196eafcc4 100644 --- a/test/fotree/disabled-testcases.xml +++ b/test/fotree/disabled-testcases.xml @@ -28,14 +28,4 @@ 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 - - diff --git a/test/fotree/testcases/id_auto.fo b/test/fotree/testcases/id_auto.fo new file mode 100644 index 000000000..8e8d03b7e --- /dev/null +++ b/test/fotree/testcases/id_auto.fo @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + Hello + + World! + + + + ઎ + + + + + -- cgit v1.2.3 From a3a8de868227ec7db6daae8e3018cfe750f527f7 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 14 May 2008 10:54:08 +0000 Subject: Merged revisions 655791,655801 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r655791 | adelmelle | 2008-05-13 10:58:01 +0100 (Tue, 13 May 2008) | 3 lines Undo r655765, which was causing NPEs in the layout-tests ........ r655801 | adelmelle | 2008-05-13 11:37:59 +0100 (Tue, 13 May 2008) | 1 line Use absolute initial value instead of percentage (better for memory consumption) ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@656234 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FOEventHandler.java | 13 ------- src/java/org/apache/fop/fo/FOPropertyMapping.java | 36 +++++++++--------- .../apache/fop/fo/properties/StringProperty.java | 44 +--------------------- test/fotree/testcases/id_auto.fo | 28 -------------- 4 files changed, 19 insertions(+), 102 deletions(-) delete mode 100644 test/fotree/testcases/id_auto.fo (limited to 'src/java') 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..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); @@ -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); @@ -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); 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 2baad1404411d87dbf30c9f3debe56188787834a Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 14 May 2008 10:55:24 +0000 Subject: Merged revisions 655829,656104 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r655829 | adelmelle | 2008-05-13 13:19:03 +0100 (Tue, 13 May 2008) | 1 line Check updated: wrapper now generates a Block, if descendant of an fo:block-container ........ r656104 | adelmelle | 2008-05-14 06:11:15 +0100 (Wed, 14 May 2008) | 1 line Avoid error-message if the text-node is white-space only. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@656235 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FObjMixed.java | 3 ++- test/layoutengine/standard-testcases/wrapper_block.xml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/java') 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."); } diff --git a/test/layoutengine/standard-testcases/wrapper_block.xml b/test/layoutengine/standard-testcases/wrapper_block.xml index 295b7b968..490bab995 100644 --- a/test/layoutengine/standard-testcases/wrapper_block.xml +++ b/test/layoutengine/standard-testcases/wrapper_block.xml @@ -41,6 +41,7 @@ + 2 3 -- cgit v1.2.3 From 616fb91de653cc2a144095e65cf9ccf87b9fd941 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 14 May 2008 12:26:18 +0000 Subject: Further progress. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@656249 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/render/AbstractPathOrientedRenderer.java | 3 +- .../org/apache/fop/render/afp/AFPRenderer.java | 1203 ++++++++------------ .../fop/render/afp/AFPRendererConfigurator.java | 58 +- .../org/apache/fop/render/afp/DataObjectInfo.java | 26 +- .../render/afp/goca/GraphicsChainedSegment.java | 2 +- .../apache/fop/render/afp/modca/AFPDataStream.java | 332 +++--- .../fop/render/afp/modca/AFPDataStreamWriter.java | 36 - .../fop/render/afp/modca/AbstractAFPObject.java | 4 +- .../fop/render/afp/modca/AbstractDataObject.java | 2 +- .../fop/render/afp/modca/AbstractPageObject.java | 233 ++-- .../AbstractResourceEnvironmentGroupContainer.java | 15 +- .../afp/modca/AbstractResourceGroupContainer.java | 66 +- .../afp/modca/AbstractStructuredAFPObject.java | 31 +- .../render/afp/modca/ActiveEnvironmentGroup.java | 16 +- .../fop/render/afp/modca/DataObjectAccessor.java | 15 +- .../org/apache/fop/render/afp/modca/Document.java | 4 +- .../render/afp/modca/GraphicsDataDescriptor.java | 2 +- .../apache/fop/render/afp/modca/IMImageObject.java | 8 +- .../fop/render/afp/modca/ImageCellPosition.java | 2 +- .../apache/fop/render/afp/modca/ImageContent.java | 2 +- .../fop/render/afp/modca/ImageDataDescriptor.java | 2 +- .../fop/render/afp/modca/ImageInputDescriptor.java | 2 +- .../apache/fop/render/afp/modca/ImageObject.java | 2 +- .../fop/render/afp/modca/ImageOutputControl.java | 2 +- .../fop/render/afp/modca/ImageRasterData.java | 2 +- .../apache/fop/render/afp/modca/ImageSegment.java | 2 +- .../fop/render/afp/modca/ImageSizeParameter.java | 2 +- .../apache/fop/render/afp/modca/IncludeObject.java | 111 +- .../fop/render/afp/modca/IncludePageOverlay.java | 2 +- .../fop/render/afp/modca/IncludePageSegment.java | 2 +- .../fop/render/afp/modca/InterchangeSet.java | 106 ++ .../fop/render/afp/modca/InvokeMediumMap.java | 2 +- .../apache/fop/render/afp/modca/MapCodedFont.java | 2 +- .../fop/render/afp/modca/MapDataResource.java | 54 +- .../fop/render/afp/modca/MapPageOverlay.java | 2 +- .../apache/fop/render/afp/modca/NoOperation.java | 2 +- .../fop/render/afp/modca/ObjectAreaDescriptor.java | 2 +- .../fop/render/afp/modca/ObjectAreaPosition.java | 2 +- .../fop/render/afp/modca/ObjectContainer.java | 55 +- .../render/afp/modca/ObjectEnvironmentGroup.java | 8 +- .../fop/render/afp/modca/PageDescriptor.java | 2 +- .../org/apache/fop/render/afp/modca/PageGroup.java | 9 +- .../apache/fop/render/afp/modca/PageObject.java | 150 ++- .../apache/fop/render/afp/modca/PageSegment.java | 9 +- .../afp/modca/PreprocessPresentationObject.java | 4 - .../fop/render/afp/modca/PresentationTextData.java | 12 +- .../afp/modca/PresentationTextDescriptor.java | 2 +- .../render/afp/modca/PresentationTextObject.java | 34 +- .../render/afp/modca/ResourceEnvironmentGroup.java | 13 +- .../apache/fop/render/afp/modca/ResourceGroup.java | 70 +- .../fop/render/afp/modca/ResourceObject.java | 69 +- .../fop/render/afp/modca/TagLogicalElement.java | 2 +- .../org/apache/fop/render/afp/modca/Writable.java | 36 + .../modca/triplets/FullyQualifiedNameTriplet.java | 137 ++- .../fop/render/afp/modca/triplets/StrucFlgs.java | 20 + .../fop/render/afp/modca/triplets/Triplet.java | 2 +- 56 files changed, 1612 insertions(+), 1383 deletions(-) delete mode 100644 src/java/org/apache/fop/render/afp/modca/AFPDataStreamWriter.java create mode 100644 src/java/org/apache/fop/render/afp/modca/InterchangeSet.java create mode 100644 src/java/org/apache/fop/render/afp/modca/Writable.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index b38d973c5..0c5732ac7 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -129,8 +129,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { BorderProps bpsStart = (BorderProps)area.getTrait(Trait.BORDER_START); BorderProps bpsEnd = (BorderProps)area.getTrait(Trait.BORDER_END); - Trait.Background back; - back = (Trait.Background)area.getTrait(Trait.BACKGROUND); + Trait.Background back = (Trait.Background)area.getTrait(Trait.BACKGROUND); if (back != null) { endTextObject(); diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 626ca47da..90f07cb8b 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -26,7 +26,6 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; 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; @@ -53,6 +52,7 @@ import org.apache.xmlgraphics.ps.ImageEncodingHelper; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; +import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; @@ -65,9 +65,7 @@ import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.Image; 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.events.ResourceEventProducer; import org.apache.fop.fo.Constants; @@ -89,9 +87,7 @@ import org.apache.fop.render.afp.fonts.FopCharacterSet; import org.apache.fop.render.afp.fonts.OutlineFont; import org.apache.fop.render.afp.modca.AFPConstants; import org.apache.fop.render.afp.modca.AFPDataStream; -import org.apache.fop.render.afp.modca.AbstractNamedAFPObject; import org.apache.fop.render.afp.modca.ImageObject; -import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.fop.render.afp.modca.PageObject; /** @@ -142,11 +138,11 @@ import org.apache.fop.render.afp.modca.PageObject; * handle all types of inline area, text, image etc and draws various lines and * rectangles. *

        - * - * Note: There are specific extensions that have been added to the - * FO. They are specific to their location within the FO and have to be - * processed accordingly (ie. at the start or end of the page). - * + * + * Note: There are specific extensions that have been added to the FO. They are + * specific to their location within the FO and have to be processed accordingly + * (ie. at the start or end of the page). + * */ public class AFPRenderer extends AbstractPathOrientedRenderer { @@ -173,12 +169,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * The map of page segments */ - private Map pageSegmentsMap = null; + private Map/**/pageSegmentsMap = null; /** * The fonts on the current page */ - private Map currentPageFonts = null; + private Map/* 0) { + if (super.embedFontInfoList != null + && super.embedFontInfoList.size() > 0) { for (Iterator it = super.embedFontInfoList.iterator(); it.hasNext();) { - AFPFontInfo afi = (AFPFontInfo)it.next(); - AFPFont bf = (AFPFont)afi.getAFPFont(); - for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) { - FontTriplet ft = (FontTriplet)it2.next(); - this.fontInfo.addFontProperties("F" + num, ft.getName() - , ft.getStyle(), ft.getWeight()); + AFPFontInfo afi = (AFPFontInfo) it.next(); + AFPFont bf = (AFPFont) afi.getAFPFont(); + for (Iterator it2 = afi.getFontTriplets().iterator(); it2 + .hasNext();) { + FontTriplet ft = (FontTriplet) it2.next(); + this.fontInfo.addFontProperties("F" + num, ft.getName(), ft + .getStyle(), ft.getWeight()); this.fontInfo.addMetrics("F" + num, bf); num++; } } } else { - AFPEventProducer eventProducer = AFPEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); + 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 ", - 1, new Helvetica()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", + "CZH200 ", 1, new Helvetica()); AFPFont bf = new OutlineFont("Helvetica", cs); - this.fontInfo.addFontProperties("F" + num, "sans-serif", "normal", 400); + this.fontInfo.addFontProperties("F" + num, "sans-serif", "normal", + 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("serif", "normal", 400) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZN200 ", - 1, new TimesRoman()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", + "CZN200 ", 1, new TimesRoman()); AFPFont bf = new OutlineFont("Helvetica", cs); this.fontInfo.addFontProperties("F" + num, "serif", "normal", 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("monospace", "normal", 400) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZ4200 ", - 1, new Courier()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", + "CZ4200 ", 1, new Courier()); AFPFont bf = new OutlineFont("Helvetica", cs); - this.fontInfo.addFontProperties("F" + num, "monospace", "normal", 400); + this.fontInfo.addFontProperties("F" + num, "monospace", "normal", + 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("any", "normal", 400) == null) { - FontTriplet ft = this.fontInfo.fontLookup("sans-serif", "normal", 400); - this.fontInfo.addFontProperties( - this.fontInfo.getInternalFontKey(ft), "any", "normal", 400); + FontTriplet ft = this.fontInfo.fontLookup("sans-serif", "normal", + 400); + this.fontInfo.addFontProperties(this.fontInfo + .getInternalFontKey(ft), "any", "normal", 400); } } @@ -338,16 +340,24 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { super.setUserAgent(agent); } + private Map/* - * - * The region may clip the area and it establishes a position from where - * the region is placed.

        - * - * @param port The region viewport to be rendered + * Renders a region viewport. + *

        + * + * The region may clip the area and it establishes a position from where the + * region is placed. + *

        + * + * @param port + * The region viewport to be rendered */ public void renderRegionViewport(RegionViewport port) { if (port != null) { @@ -451,11 +472,10 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { handleRegionTraits(port); /* - _afpDataStream.startOverlay(mpts2units(view.getX()) - , mpts2units(view.getY()) - , mpts2units(view.getWidth()) - , mpts2units(view.getHeight()) - , rotation); + * _afpDataStream.startOverlay(mpts2units(view.getX()) , + * mpts2units(view.getY()) , mpts2units(view.getWidth()) , + * mpts2units(view.getHeight()) + * , rotation); */ pushViewPortPos(new ViewPortPos(view, regionReference.getCTM())); @@ -466,12 +486,47 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { renderRegion(regionReference); } /* - _afpDataStream.endOverlay(); + * _afpDataStream.endOverlay(); */ popViewPortPos(); } } + /** + * {@inheritDoc} + */ + // TODO - AC fix + protected void drawBackAndBorders(Area area, float startx, float starty, + float width, float height) { + super.drawBackAndBorders(area, startx, starty, width, height); + Trait.Background back = (Trait.Background) area + .getTrait(Trait.BACKGROUND); + + // the current block has a background so its contents are placed inside + // an overlay + // after drawing the background and borders + if (back != null) { + int x = pts2units(startx); + int y = pts2units(starty); + int w = mpts2units(width); + int h = mpts2units(height); + int res = getResolution(); + final int rotation = 0; + getAFPDataStream().startOverlay(x, y, w, h, res, res, rotation); + } + } + + /** + * {@inheritDoc} + */ + protected void renderBlock(Block block) { + // new block so start page segment + getAFPDataStream().startPageSegment(); + super.renderBlock(block); + getAFPDataStream().endOverlay(); + getAFPDataStream().endPageSegment(); + } + /** * {@inheritDoc} */ @@ -485,16 +540,17 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { CTM ctm = bv.getCTM(); int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore(); - //This is the content-rect - float width = (float)bv.getIPD() / 1000f; - float height = (float)bv.getBPD() / 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) { - //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. + // 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. List breakOutList = null; if (bv.getPositioning() == Block.FIXED) { breakOutList = breakOutOfStateStack(); @@ -503,45 +559,55 @@ 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); + // "left/"top" (bv.getX/YOffset()) specify the position of the + // content rectangle + positionTransform.translate(-borderPaddingStart, + -borderPaddingBefore); - //skipping fox:transform here + // skipping fox:transform here - //saveGraphicsState(); - //Viewport position - //concatenateTransformationMatrix(mptToPt(positionTransform)); + // saveGraphicsState(); + // Viewport position + // concatenateTransformationMatrix(mptToPt(positionTransform)); - //Background and borders - float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; - float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; + // Background and borders + float bpwidth = (borderPaddingStart + bv + .getBorderAndPaddingWidthEnd()) / 1000f; + float bpheight = (borderPaddingBefore + bv + .getBorderAndPaddingWidthAfter()) / 1000f; Point2D ptSrc = new Point(0, 0); Point2D ptDst = positionTransform.transform(ptSrc, null); - Rectangle2D borderRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(), - 1000 * (width + bpwidth), 1000 * (height + bpheight)); - pushViewPortPos(new ViewPortPos(borderRect, new CTM(positionTransform))); + Rectangle2D borderRect = new Rectangle2D.Double(ptDst.getX(), ptDst + .getY(), 1000 * (width + bpwidth), + 1000 * (height + bpheight)); + pushViewPortPos(new ViewPortPos(borderRect, new CTM( + positionTransform))); drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight); - //Shift to content rectangle after border painting + // Shift to content rectangle after border painting AffineTransform contentRectTransform = new AffineTransform(); - contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); - //concatenateTransformationMatrix(mptToPt(contentRectTransform)); + contentRectTransform.translate(borderPaddingStart, + borderPaddingBefore); + // concatenateTransformationMatrix(mptToPt(contentRectTransform)); ptSrc = new Point(0, 0); ptDst = contentRectTransform.transform(ptSrc, null); - Rectangle2D contentRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(), - 1000 * width, 1000 * height); - pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentRectTransform))); + Rectangle2D contentRect = new Rectangle2D.Double(ptDst.getX(), + ptDst.getY(), 1000 * width, 1000 * height); + pushViewPortPos(new ViewPortPos(contentRect, new CTM( + contentRectTransform))); - //Clipping is not supported, yet - //Rectangle2D clippingRect = null; - //clippingRect = new Rectangle(0, 0, bv.getIPD(), bv.getBPD()); + // Clipping is not supported, yet + // Rectangle2D clippingRect = null; + // clippingRect = new Rectangle(0, 0, bv.getIPD(), bv.getBPD()); - //saveGraphicsState(); - //Set up coordinate system for content rectangle + // saveGraphicsState(); + // Set up coordinate system for content rectangle AffineTransform contentTransform = ctm.toAffineTransform(); - //concatenateTransformationMatrix(mptToPt(contentTransform)); - contentRect = new Rectangle2D.Double(0, 0, 1000 * width, 1000 * height); - pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentTransform))); + // concatenateTransformationMatrix(mptToPt(contentTransform)); + contentRect = new Rectangle2D.Double(0, 0, 1000 * width, + 1000 * height); + pushViewPortPos(new ViewPortPos(contentRect, new CTM( + contentTransform))); currentIPPosition = 0; currentBPPosition = 0; @@ -549,9 +615,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { popViewPortPos(); popViewPortPos(); - //restoreGraphicsState(); + // restoreGraphicsState(); popViewPortPos(); - //restoreGraphicsState(); + // restoreGraphicsState(); if (breakOutList != null) { restoreStateStackAfterBreakOut(breakOutList); @@ -563,41 +629,42 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { currentBPPosition += bv.getSpaceBefore(); - //borders and background in the old coordinate system + // borders and background in the old coordinate system handleBlockTraits(bv); - //Advance to start of content area + // Advance to start of content area currentIPPosition += bv.getStartIndent(); CTM tempctm = new CTM(containingIPPosition, currentBPPosition); ctm = tempctm.multiply(ctm); - //Now adjust for border/padding + // Now adjust for border/padding currentBPPosition += borderPaddingBefore; Rectangle2D clippingRect = null; clippingRect = new Rectangle(currentIPPosition, currentBPPosition, bv.getIPD(), bv.getBPD()); - //startVParea(ctm, clippingRect); + // startVParea(ctm, clippingRect); pushViewPortPos(new ViewPortPos(clippingRect, ctm)); currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); - //endVParea(); + // endVParea(); popViewPortPos(); currentIPPosition = saveIP; currentBPPosition = saveBP; - currentBPPosition += (int)(bv.getAllocBPD()); + currentBPPosition += (int) (bv.getAllocBPD()); } } /** {@inheritDoc} */ protected void concatenateTransformationMatrix(AffineTransform at) { - //Not used here since AFPRenderer defines its own renderBlockViewport() method. + // Not used here since AFPRenderer defines its own renderBlockViewport() + // method. throw new UnsupportedOperationException("NYI"); } @@ -611,7 +678,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // this.currentFontFamily = ""; this.currentFontSize = 0; this.pageFontCounter = 0; - this.currentPageFonts.clear(); + this.currentPageFontMap = null; // this.lineCache = new HashSet(); Rectangle2D bounds = pageViewport.getViewArea(); @@ -621,7 +688,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (pages != null && pages.containsKey(pageViewport)) { - getAFPDataStream().restorePage((PageObject) pages.remove(pageViewport)); + getAFPDataStream().restorePage( + (PageObject) pages.remove(pageViewport)); } else { // renderPageGroupExtensions(page); @@ -638,19 +706,21 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { renderPageAreas(pageViewport.getPage()); - Iterator i = currentPageFonts.values().iterator(); - while (i.hasNext()) { - AFPFontAttributes afpFontAttributes = (AFPFontAttributes) i.next(); - - getAFPDataStream().createFont( - (byte)afpFontAttributes.getFontReference(), - afpFontAttributes.getFont(), - afpFontAttributes.getPointSize()); + if (currentPageFontMap != null) { + Iterator iter = currentPageFontMap.values().iterator(); + while (iter.hasNext()) { + AFPFontAttributes afpFontAttributes = (AFPFontAttributes) iter + .next(); + getAFPDataStream().createFont( + (byte) afpFontAttributes.getFontReference(), + afpFontAttributes.getFont(), + afpFontAttributes.getPointSize()); + } } getAFPDataStream().endPage(); - + popViewPortPos(); } @@ -694,22 +764,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ public void fillRect(float x, float y, float width, float height) { /* - afpDataStream.createShading( - pts2units(x), - pts2units(y), - pts2units(width), - pts2units(height), - currentColor.getRed(), - currentColor.getGreen(), - currentColor.getBlue()); + * getAFPDataStream().createShading( pts2units(x), pts2units(y), + * pts2units(width), pts2units(height), currentColor); */ - getAFPDataStream().createLine( - pts2units(x), - pts2units(y), - pts2units(x + width), - pts2units(y), - pts2units(height), - currentColor); + getAFPDataStream().createLine(pts2units(x), pts2units(y), + pts2units(x + width), pts2units(y), pts2units(height), + currentColor); } /** @@ -723,197 +783,118 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { log.error("Negative extent received. Border won't be painted."); return; } - + switch (style) { - case Constants.EN_DOUBLE: - if (horz) { - float h3 = h / 3; - float ym1 = y1; - float ym2 = ym1 + h3 + h3; - afpDataStream.createLine( - pts2units(x1), - pts2units(ym1), - pts2units(x2), - pts2units(ym1), - pts2units(h3), - col - ); - afpDataStream.createLine( - pts2units(x1), - pts2units(ym2), - pts2units(x2), - pts2units(ym2), - pts2units(h3), - col - ); - } else { - float w3 = w / 3; - float xm1 = x1; - float xm2 = xm1 + w3 + w3; - afpDataStream.createLine( - pts2units(xm1), - pts2units(y1), - pts2units(xm1), - pts2units(y2), - pts2units(w3), - col - ); - afpDataStream.createLine( - pts2units(xm2), - pts2units(y1), - pts2units(xm2), - pts2units(y2), - pts2units(w3), - col - ); + case Constants.EN_DOUBLE: + if (horz) { + float h3 = h / 3; + float ym1 = y1; + float ym2 = ym1 + h3 + h3; + getAFPDataStream().createLine(pts2units(x1), pts2units(ym1), + pts2units(x2), pts2units(ym1), pts2units(h3), col); + getAFPDataStream().createLine(pts2units(x1), pts2units(ym2), + pts2units(x2), pts2units(ym2), pts2units(h3), col); + } else { + float w3 = w / 3; + float xm1 = x1; + float xm2 = xm1 + w3 + w3; + getAFPDataStream().createLine(pts2units(xm1), pts2units(y1), + pts2units(xm1), pts2units(y2), pts2units(w3), col); + getAFPDataStream().createLine(pts2units(xm2), pts2units(y1), + pts2units(xm2), pts2units(y2), pts2units(w3), col); + } + break; + case Constants.EN_DASHED: + if (horz) { + float w2 = 2 * h; + while (x1 + w2 < x2) { + getAFPDataStream().createLine(pts2units(x1), pts2units(y1), + pts2units(x1 + w2), pts2units(y1), pts2units(h), + col); + x1 += 2 * w2; } - break; - case Constants.EN_DASHED: - if (horz) { - float w2 = 2 * h; - while (x1 + w2 < x2) { - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(x1 + w2), - pts2units(y1), - pts2units(h), - col - ); - x1 += 2 * w2; - } - } else { - float h2 = 2 * w; - while (y1 + h2 < y2) { - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(x1), - pts2units(y1 + h2), - pts2units(w), - col - ); - y1 += 2 * h2; - } + } else { + float h2 = 2 * w; + while (y1 + h2 < y2) { + getAFPDataStream().createLine(pts2units(x1), pts2units(y1), + pts2units(x1), pts2units(y1 + h2), pts2units(w), + col); + y1 += 2 * h2; } - break; - case Constants.EN_DOTTED: - if (horz) { - while (x1 + h < x2) { - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(x1 + h), - pts2units(y1), - pts2units(h), - col - ); - x1 += 2 * h; - } - } else { - while (y1 + w < y2) { - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(x1), - pts2units(y1 + w), - pts2units(w), - col - ); - y1 += 2 * w; - } + } + break; + case Constants.EN_DOTTED: + if (horz) { + while (x1 + h < x2) { + getAFPDataStream() + .createLine(pts2units(x1), pts2units(y1), + pts2units(x1 + h), pts2units(y1), + pts2units(h), col); + x1 += 2 * h; } - break; - case Constants.EN_GROOVE: - case Constants.EN_RIDGE: - { - float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f); - if (horz) { - Color uppercol = lightenColor(col, -colFactor); - Color lowercol = lightenColor(col, colFactor); - float h3 = h / 3; - float ym1 = y1; - afpDataStream.createLine( - pts2units(x1), - pts2units(ym1), - pts2units(x2), - pts2units(ym1), - pts2units(h3), - uppercol - ); - afpDataStream.createLine( - pts2units(x1), - pts2units(ym1 + h3), - pts2units(x2), - pts2units(ym1 + h3), - pts2units(h3), - col - ); - afpDataStream.createLine( - pts2units(x1), - pts2units(ym1 + h3 + h3), - pts2units(x2), - pts2units(ym1 + h3 + h3), - pts2units(h3), - lowercol - ); - } else { - Color leftcol = lightenColor(col, -colFactor); - Color rightcol = lightenColor(col, colFactor); - float w3 = w / 3; - float xm1 = x1 + (w3 / 2); - afpDataStream.createLine( - pts2units(xm1), - pts2units(y1), - pts2units(xm1), - pts2units(y2), - pts2units(w3), - leftcol - ); - afpDataStream.createLine( - pts2units(xm1 + w3), - pts2units(y1), - pts2units(xm1 + w3), - pts2units(y2), - pts2units(w3), - col - ); - afpDataStream.createLine( - pts2units(xm1 + w3 + w3), - pts2units(y1), - pts2units(xm1 + w3 + w3), - pts2units(y2), - pts2units(w3), - rightcol - ); + } else { + while (y1 + w < y2) { + getAFPDataStream() + .createLine(pts2units(x1), pts2units(y1), + pts2units(x1), pts2units(y1 + w), + pts2units(w), col); + y1 += 2 * w; } - break; } - case Constants.EN_HIDDEN: - break; - case Constants.EN_INSET: - case Constants.EN_OUTSET: - default: - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(horz ? x2 : x1), - pts2units(horz ? y1 : y2), - pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), - col - ); + break; + case Constants.EN_GROOVE: + case Constants.EN_RIDGE: { + float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f); + if (horz) { + Color uppercol = lightenColor(col, -colFactor); + Color lowercol = lightenColor(col, colFactor); + float h3 = h / 3; + float ym1 = y1; + getAFPDataStream().createLine(pts2units(x1), pts2units(ym1), + pts2units(x2), pts2units(ym1), pts2units(h3), uppercol); + getAFPDataStream().createLine(pts2units(x1), + pts2units(ym1 + h3), pts2units(x2), + pts2units(ym1 + h3), pts2units(h3), col); + getAFPDataStream().createLine(pts2units(x1), + pts2units(ym1 + h3 + h3), pts2units(x2), + pts2units(ym1 + h3 + h3), pts2units(h3), lowercol); + } else { + Color leftcol = lightenColor(col, -colFactor); + Color rightcol = lightenColor(col, colFactor); + float w3 = w / 3; + float xm1 = x1 + (w3 / 2); + getAFPDataStream().createLine(pts2units(xm1), pts2units(y1), + pts2units(xm1), pts2units(y2), pts2units(w3), leftcol); + getAFPDataStream().createLine(pts2units(xm1 + w3), + pts2units(y1), pts2units(xm1 + w3), pts2units(y2), + pts2units(w3), col); + getAFPDataStream().createLine(pts2units(xm1 + w3 + w3), + pts2units(y1), pts2units(xm1 + w3 + w3), pts2units(y2), + pts2units(w3), rightcol); + } + break; + } + case Constants.EN_HIDDEN: + break; + case Constants.EN_INSET: + case Constants.EN_OUTSET: + default: + getAFPDataStream().createLine(pts2units(x1), pts2units(y1), + pts2units(horz ? x2 : x1), pts2units(horz ? y1 : y2), + pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), col); } } /** * {@inheritDoc} */ - protected RendererContext createRendererContext(int x, int y, int width, int height, - Map foreignAttributes) { + protected RendererContext createRendererContext(int x, int y, int width, + int height, Map foreignAttributes) { RendererContext context; - context = super.createRendererContext(x, y, width, height, foreignAttributes); - context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, - Boolean.valueOf(!this.colorImages)); + context = super.createRendererContext(x, y, width, height, + foreignAttributes); + context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, Boolean + .valueOf(!this.colorImages)); context.setProperty(AFPRendererContextConstants.AFP_FONT_INFO, this.fontInfo); context.setProperty(AFPRendererContextConstants.AFP_RESOLUTION, @@ -922,67 +903,61 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { new Integer(this.bitsPerPixel)); context.setProperty(AFPRendererContextConstants.AFP_DATASTREAM, getAFPDataStream()); - context.setProperty(AFPRendererContextConstants.AFP_STATE, - getState()); + context.setProperty(AFPRendererContextConstants.AFP_STATE, getState()); return context; } - private static final ImageFlavor[] FLAVORS = new ImageFlavor[] - {ImageFlavor.RAW_CCITTFAX, - ImageFlavor.GRAPHICS2D, - ImageFlavor.BUFFERED_IMAGE, - ImageFlavor.RENDERED_IMAGE, - ImageFlavor.XML_DOM}; + 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()); + 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 = (String)getPageSegments().get(uri); + String name = (String) getPageSegments().get(uri); if (name != null) { - getAFPDataStream().createIncludePageSegment(name, mpts2units(x), mpts2units(y)); + getAFPDataStream().createIncludePageSegment(name, mpts2units(x), + mpts2units(y)); } else { - ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageManager manager = getUserAgent().getFactory() + .getImageManager(); ImageInfo info = null; InputStream in = null; try { - ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + ImageSessionContext sessionContext = getUserAgent() + .getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); - //Only now fully load/prepare the image + // 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); + org.apache.xmlgraphics.image.loader.Image img = manager + .getImage(info, FLAVORS, hints, sessionContext); - //...and process the image + // ...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, + 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; + ImageRendered imgRend = (ImageRendered) img; RenderedImage ri = imgRend.getRenderedImage(); - drawBufferedImage(info, ri, getResolution(), - posInt.x + currentIPPosition, - posInt.y + currentBPPosition, - posInt.width, - posInt.height, foreignAttributes); + drawBufferedImage(info, ri, getResolution(), posInt.x + + currentIPPosition, posInt.y + currentBPPosition, + posInt.width, posInt.height, foreignAttributes); } else if (img instanceof ImageRawCCITTFax) { - ImageRawCCITTFax ccitt = (ImageRawCCITTFax)img; + ImageRawCCITTFax ccitt = (ImageRawCCITTFax) img; in = ccitt.createInputStream(); byte[] buf = IOUtils.toByteArray(in); int afpx = mpts2units(posInt.x + currentIPPosition); @@ -990,7 +965,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int afpw = mpts2units(posInt.getWidth()); int afph = mpts2units(posInt.getHeight()); int afpres = getResolution(); - + // create image object parameters ImageObjectInfo imageObjectInfo = new ImageObjectInfo(); imageObjectInfo.setUri(uri); @@ -1002,179 +977,44 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { imageObjectInfo.setWidthRes(afpres); imageObjectInfo.setHeightRes(afpres); imageObjectInfo.setData(buf); - imageObjectInfo.setDataHeight(ccitt.getSize().getHeightPx()); + imageObjectInfo + .setDataHeight(ccitt.getSize().getHeightPx()); imageObjectInfo.setDataWidth(ccitt.getSize().getWidthPx()); imageObjectInfo.setColor(colorImages); imageObjectInfo.setBitsPerPixel(bitsPerPixel); imageObjectInfo.setCompression(ccitt.getCompression()); - imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); - + imageObjectInfo + .setResourceInfoFromForeignAttributes(foreignAttributes); getAFPDataStream().createObject(imageObjectInfo); - - -// 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); + ImageXMLDOM imgXML = (ImageXMLDOM) img; + renderDocument(imgXML.getDocument(), imgXML + .getRootNamespace(), pos, foreignAttributes); } else { - throw new UnsupportedOperationException("Unsupported image type: " + img); + throw new UnsupportedOperationException( + "Unsupported image type: " + img); } } catch (ImageException ie) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); + 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); + 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); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider + .get(getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info + .toString() : uri), ioe, null); } finally { if (in != null) { IOUtils.closeQuietly(in); } } - - /* - 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) || MimeConstants.MIME_SVG.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 (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; } - * fact.releaseImage(url, userAgent); - * - * int x = mpts2units(pos.getX() + currentIPPosition); int y = - * mpts2units(pos.getY() + currentBPPosition); int w = - * mpts2units(pos.getWidth()); int h = - * mpts2units(pos.getHeight()); ImageObject io = - * _afpDataStream.getImageObject(); io.setImageViewport(x, y, w, - * h); io.setImageParameters( - * (int)(fopimage.getHorizontalResolution() * 10), - * (int)(fopimage.getVerticalResolution() * 10), - * fopimage.getWidth(), fopimage.getHeight() ); - * 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; - int x = mpts2units(pos.getX() + currentIPPosition); - int y = mpts2units(pos.getY() + currentBPPosition); - int w = mpts2units(pos.getWidth()); - int h = mpts2units(pos.getHeight()); - ImageObject io = afpDataStream.getImageObject(x, y, w, h, - getResolution(), getResolution()); - io.setImageParameters( - (int)(fopimage.getHorizontalResolution() * 10), - (int)(fopimage.getVerticalResolution() * 10), - fopimage.getWidth(), - fopimage.getHeight() - ); - if (tiffImage.getStripCount() == 1) { - int comp = tiffImage.getCompression(); - if (comp == 3) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - io.setImageEncoding((byte)0x81); - io.setImageData(fopimage.getRessourceBytes()); - } else if (comp == 4) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - io.setImageEncoding((byte)0x82); - io.setImageData(fopimage.getRessourceBytes()); - } else { - if (!fopimage.load(FopImage.BITMAP)) { - return; - } - convertToGrayScaleImage(io, fopimage.getBitmaps(), - fopimage.getWidth(), fopimage.getHeight()); - } - } else { - if (!fopimage.load(FopImage.BITMAP)) { - return; - } - convertToGrayScaleImage(io, fopimage.getBitmaps(), - fopimage.getWidth(), fopimage.getHeight()); - } - } else { - if (!fopimage.load(FopImage.BITMAP)) { - return; - } - fact.releaseImage(url, userAgent); - - int x = mpts2units(pos.getX() + currentIPPosition); - int y = mpts2units(pos.getY() + currentBPPosition); - int w = mpts2units(pos.getWidth()); - int h = mpts2units(pos.getHeight()); - ImageObject io = afpDataStream.getImageObject(x, y, w, h, - getResolution(), getResolution()); - io.setImageParameters( - (int)(fopimage.getHorizontalResolution() * 10), - (int)(fopimage.getVerticalResolution() * 10), - fopimage.getWidth(), - fopimage.getHeight() - ); - if (colorImages) { - io.setImageIDESize((byte)24); - io.setImageData(fopimage.getBitmaps()); - } else { - convertToGrayScaleImage(io, fopimage.getBitmaps(), - fopimage.getWidth(), fopimage.getHeight()); - } - }*/ } } @@ -1186,9 +1026,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @param out * the OutputStream * @throws IOException - * In case of an I/O error. - * @deprecated - * use ImageEncodingHelper.encodeRenderedImageAsRGB(image, out) directly instead + * In case of an I/O error. + * @deprecated use ImageEncodingHelper.encodeRenderedImageAsRGB(image, out) + * directly instead */ public static void writeImage(RenderedImage image, OutputStream out) throws IOException { @@ -1198,8 +1038,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Draws a BufferedImage to AFP. * - * @param uri - * the uri of the image + * @param imageInfo + * the image info * @param image * the RenderedImage * @param imageRes @@ -1212,34 +1052,29 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * the width of the viewport (in mpt) * @param h * the height of the viewport (in mpt) + * @param foreignAttributes + * a mapping of foreign attributes */ - public void drawBufferedImage(ImageInfo info, RenderedImage image, int imageRes, int x, - int y, int w, int h, Map foreignAttributes) { -// int afpx = mpts2units(x); -// int afpy = mpts2units(y); -// int afpw = mpts2units(w); -// int afph = mpts2units(h); + public void drawBufferedImage(ImageInfo imageInfo, RenderedImage image, + int imageRes, int x, int y, int w, int h, Map foreignAttributes) { ByteArrayOutputStream baout = new ByteArrayOutputStream(); try { // Serialize image - //TODO Eventually, this should be changed not to buffer as this increases the - //memory consumption (see PostScript output) + // TODO Eventually, this should be changed not to buffer as this + // increases the + // memory consumption (see PostScript output) ImageEncodingHelper.encodeRenderedImageAsRGB(image, baout); } catch (IOException ioe) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider + .get(getUserAgent().getEventBroadcaster()); eventProducer.imageWritingError(this, ioe); return; } - //int res = getResolution(); -// String uri = null;// = image.getProperty(name); -// String uri = image.getProperty(name); - // Generate image - + // create image object parameters ImageObjectInfo imageObjectInfo = new ImageObjectInfo(); - imageObjectInfo.setUri(info.getOriginalURI()); - imageObjectInfo.setMimeType(info.getMimeType()); + imageObjectInfo.setUri(imageInfo.getOriginalURI()); + imageObjectInfo.setMimeType(imageInfo.getMimeType()); imageObjectInfo.setX(mpts2units(x)); imageObjectInfo.setY(mpts2units(y)); imageObjectInfo.setWidth(mpts2units(w)); @@ -1253,26 +1088,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { imageObjectInfo.setBitsPerPixel(bitsPerPixel); imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); - //AbstractNamedAFPObject obj = getAFPDataStream().createObject(imageObjectInfo); -// ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, -// afph, afpres, afpres); -// io.setImageParameters(imageResolution, imageResolution, -// 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, -// image.getWidth(), image.getHeight(), this.bitsPerPixel); -// } } /** - * Establishes a new foreground or fill color. - * {@inheritDoc} + * Establishes a new foreground or fill color. {@inheritDoc} */ public void updateColor(Color col, boolean fill) { if (fill) { @@ -1282,7 +1102,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Restores the state stack after a break out. - * @param breakOutList the state stack to restore. + * + * @param breakOutList + * the state stack to restore. */ public void restoreStateStackAfterBreakOut(List breakOutList) { @@ -1290,6 +1112,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Breaks out of the state stack to handle fixed block-containers. + * * @return the saved state stack to recreate later */ public List breakOutOfStateStack() { @@ -1330,194 +1153,158 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { renderInlineAreaBackAndBorders(text); String name = getInternalFontNameForArea(text); - currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); - AFPFont tf = (AFPFont) fontInfo.getFonts().get(name); + this.currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)) + .intValue(); + AFPFont font = (AFPFont) fontInfo.getFonts().get(name); Color col = (Color) text.getTrait(Trait.COLOR); - int vsci = mpts2units(tf.getWidth(' ', currentFontSize) / 1000 - + text.getTextWordSpaceAdjust() - + text.getTextLetterSpaceAdjust()); + int vsci = mpts2units(font.getWidth(' ', currentFontSize) / 1000 + + text.getTextWordSpaceAdjust() + + text.getTextLetterSpaceAdjust()); // word.getOffset() = only height of text itself // currentBlockIPPosition: 0 for beginning of line; nonzero - // where previous line area failed to take up entire allocated space + // where previous line area failed to take up entire allocated space int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); - int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); + int bl = currentBPPosition + text.getOffset() + + text.getBaselineOffset(); // Set letterSpacing - //float ls = fs.getLetterSpacing() / this.currentFontSize; + // float ls = fs.getLetterSpacing() / this.currentFontSize; String worddata = text.getText(); // Create an AFPFontAttributes object from the current font details - AFPFontAttributes afpFontAttributes = new AFPFontAttributes(name, tf, currentFontSize); + AFPFontAttributes afpFontAttributes = new AFPFontAttributes(name, font, + currentFontSize); - if (!currentPageFonts.containsKey(afpFontAttributes.getFontKey())) { + if (!getCurrentPageFonts().containsKey(afpFontAttributes.getFontKey())) { // Font not found on current page, so add the new one - pageFontCounter++; + this.pageFontCounter++; afpFontAttributes.setFontReference(pageFontCounter); - currentPageFonts.put( - afpFontAttributes.getFontKey(), - afpFontAttributes); - + getCurrentPageFonts().put(afpFontAttributes.getFontKey(), + afpFontAttributes); } else { // Use the previously stored font attributes - afpFontAttributes = (AFPFontAttributes) currentPageFonts.get( - afpFontAttributes.getFontKey()); + afpFontAttributes = (AFPFontAttributes) currentPageFontMap + .get(afpFontAttributes.getFontKey()); } // Try and get the encoding to use for the font String encoding = null; try { - encoding = tf.getCharacterSet(currentFontSize).getEncoding(); + encoding = font.getCharacterSet(currentFontSize).getEncoding(); } catch (Throwable ex) { encoding = AFPConstants.EBCIDIC_ENCODING; - log.warn( - "renderText():: Error getting encoding for font '" - + tf.getFullName() - + "' - using default encoding " - + encoding); + log.warn("renderText():: Error getting encoding for font '" + + font.getFullName() + "' - using default encoding " + + encoding); } try { - getAFPDataStream().createText( - afpFontAttributes.getFontReference(), - mpts2units(rx), - mpts2units(bl), - col, - vsci, - mpts2units(text.getTextLetterSpaceAdjust()), - worddata.getBytes(encoding)); + getAFPDataStream().createText(afpFontAttributes.getFontReference(), + mpts2units(rx), mpts2units(bl), col, vsci, + mpts2units(text.getTextLetterSpaceAdjust()), + worddata.getBytes(encoding)); } catch (UnsupportedEncodingException usee) { - log.error( - "renderText:: Font " - + afpFontAttributes.getFontKey() - + " caused UnsupportedEncodingException"); + log.error("renderText:: Font " + afpFontAttributes.getFontKey() + + " caused UnsupportedEncodingException"); } super.renderText(text); - renderTextDecoration(tf, currentFontSize, text, bl, rx); + renderTextDecoration(font, currentFontSize, text, bl, rx); } /** - * {@inheritDoc} - */ - public void renderWord(WordArea word) { - // UNUSED - // String name = getInternalFontNameForArea(word.getParentArea()); - // int size = ((Integer) - // word.getParentArea().getTrait(Trait.FONT_SIZE)).intValue(); - // AFPFont tf = (AFPFont) fontInfo.getFonts().get(name); - // - // String s = word.getWord(); - // - // FontMetrics metrics = fontInfo.getMetricsFor(name); - - super.renderWord(word); - } - - /** - * {@inheritDoc} - */ - public void renderSpace(SpaceArea space) { - // UNUSED - // String name = getInternalFontNameForArea(space.getParentArea()); - // int size = ((Integer) - // space.getParentArea().getTrait(Trait.FONT_SIZE)).intValue(); - // AFPFont tf = (AFPFont) fontInfo.getFonts().get(name); - // - // String s = space.getSpace(); - // - // FontMetrics metrics = fontInfo.getMetricsFor(name); - - super.renderSpace(space); - } - - /** - * Render leader area. - * This renders a leader area which is an area with a rule. - * @param area the leader area to render + * Render leader area. This renders a leader area which is an area with a + * rule. + * + * @param area + * the leader area to render */ public void renderLeader(Leader area) { renderInlineAreaBackAndBorders(area); int style = area.getRuleStyle(); - float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; + float startx = (currentIPPosition + area + .getBorderAndPaddingWidthStart()) / 1000f; float starty = (currentBPPosition + area.getOffset()) / 1000f; - float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() - + area.getIPD()) / 1000f; + float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + area + .getIPD()) / 1000f; float ruleThickness = area.getRuleThickness() / 1000f; - Color col = (Color)area.getTrait(Trait.COLOR); + Color col = (Color) area.getTrait(Trait.COLOR); switch (style) { - case EN_SOLID: - case EN_DASHED: - case EN_DOUBLE: - case EN_DOTTED: - case EN_GROOVE: - case EN_RIDGE: - drawBorderLine(startx, starty, endx, starty + ruleThickness, - true, true, style, col); - break; - default: - throw new UnsupportedOperationException("rule style not supported"); + case EN_SOLID: + case EN_DASHED: + case EN_DOUBLE: + case EN_DOTTED: + case EN_GROOVE: + case EN_RIDGE: + drawBorderLine(startx, starty, endx, starty + ruleThickness, true, + true, style, col); + break; + default: + throw new UnsupportedOperationException("rule style not supported"); } super.renderLeader(area); } /** * Sets the AFPRenderer options - * @param options the Map containing the options + * + * @param options + * the Map containing the options */ -// UNUSED -// public void setOptions(Map options) { -// -// this.afpOptions = options; -// -// } + // UNUSED + // public void setOptions(Map options) { + // + // this.afpOptions = options; + // + // } /** * Determines the orientation from the string representation, this method * guarantees to return a value of either 0, 90, 180 or 270. - * + * * @return the orientation */ -// UNUSED -// private int getOrientation(String orientationString) { -// -// int orientation = 0; -// if (orientationString != null && orientationString.length() > 0) { -// try { -// orientation = Integer.parseInt(orientationString); -// } catch (NumberFormatException nfe) { -// log.error("Cannot use orientation of " + orientation -// + " defaulting to zero."); -// orientation = 0; -// } -// } else { -// orientation = 0; -// } -// switch (orientation) { -// case 0: -// break; -// case 90: -// break; -// case 180: -// break; -// case 270: -// break; -// default: -// log.error("Cannot use orientation of " + orientation -// + " defaulting to zero."); -// orientation = 0; -// break; -// } -// -// return orientation; -// -// } + // UNUSED + // private int getOrientation(String orientationString) { + // + // int orientation = 0; + // if (orientationString != null && orientationString.length() > 0) { + // try { + // orientation = Integer.parseInt(orientationString); + // } catch (NumberFormatException nfe) { + // log.error("Cannot use orientation of " + orientation + // + " defaulting to zero."); + // orientation = 0; + // } + // } else { + // orientation = 0; + // } + // switch (orientation) { + // case 0: + // break; + // case 90: + // break; + // case 180: + // break; + // case 270: + // break; + // default: + // log.error("Cannot use orientation of " + orientation + // + " defaulting to zero."); + // orientation = 0; + // break; + // } + // + // return orientation; + // + // } /** * Sets the rotation to be used for portrait pages, valid values are 0 * (default), 90, 180, 270. @@ -1526,18 +1313,15 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * The rotation in degrees. */ public void setPortraitRotation(int rotation) { - - if (rotation == 0 - || rotation == 90 - || rotation == 180 - || rotation == 270) { + if (rotation == 0 || rotation == 90 || rotation == 180 + || rotation == 270) { portraitRotation = rotation; } else { - throw new IllegalArgumentException("The portrait rotation must be one" - + " of the values 0, 90, 180, 270"); + throw new IllegalArgumentException( + "The portrait rotation must be one" + + " of the values 0, 90, 180, 270"); } - } /** @@ -1548,58 +1332,57 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * The rotation in degrees. */ public void setLandscapeRotation(int rotation) { - - if (rotation == 0 - || rotation == 90 - || rotation == 180 - || rotation == 270) { + if (rotation == 0 || rotation == 90 || rotation == 180 + || rotation == 270) { landscapeRotation = rotation; } else { - throw new IllegalArgumentException("The landscape rotation must be one" - + " of the values 0, 90, 180, 270"); + throw new IllegalArgumentException( + "The landscape rotation must be one" + + " of the values 0, 90, 180, 270"); } - } /** * Get the MIME type of the renderer. * - * @return The MIME type of the renderer + * @return The MIME type of the renderer */ public String getMimeType() { return MimeConstants.MIME_AFP; } - private Map getPageSegments() { + private Map/**/getPageSegments() { if (pageSegmentsMap == null) { - pageSegmentsMap = new java.util.HashMap(); + pageSegmentsMap = new java.util.HashMap/**/(); } return pageSegmentsMap; } - + /** * Method to render the page extension. *

        * - * @param pageViewport the page object + * @param pageViewport + * the page object */ private void renderPageObjectExtensions(PageViewport pageViewport) { - pageSegmentsMap = null; + this.pageSegmentsMap = null; if (pageViewport.getExtensionAttachments() != null && pageViewport.getExtensionAttachments().size() > 0) { // Extract all AFPPageSetup instances from the attachment list on // the s-p-m Iterator i = pageViewport.getExtensionAttachments().iterator(); while (i.hasNext()) { - ExtensionAttachment attachment = (ExtensionAttachment)i.next(); + ExtensionAttachment attachment = (ExtensionAttachment) i.next(); if (AFPPageSetup.CATEGORY.equals(attachment.getCategory())) { AFPPageSetup aps = (AFPPageSetup) attachment; String element = aps.getElementName(); if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) { String overlay = aps.getName(); if (overlay != null) { - getAFPDataStream().createIncludePageOverlay(overlay); + getAFPDataStream() + .createIncludePageOverlay(overlay); } } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT .equals(element)) { @@ -1617,9 +1400,6 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { getAFPDataStream().createNoOperation(content); } } -// else if (AFPElementMapping.RESOURCE.equals(element)) { -// log.info("resource: " + attachment); -// } } } } @@ -1628,7 +1408,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Converts FOP mpt measurement to afp measurement units - * @param mpt the millipoints value + * + * @param mpt + * the millipoints value */ private int mpts2units(int mpt) { return mpts2units((double) mpt); @@ -1636,7 +1418,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Converts FOP pt measurement to afp measurement units - * @param mpt the millipoints value + * + * @param mpt + * the millipoints value */ private int pts2units(float mpt) { return mpts2units(mpt * 1000d); @@ -1650,7 +1434,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @return afp measurement unit value */ private int mpts2units(double mpt) { - return (int)Math.round(mpt / (DPI_CONVERSION_FACTOR / getResolution())); + return (int) Math + .round(mpt / (DPI_CONVERSION_FACTOR / getResolution())); } /** @@ -1668,8 +1453,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @param bitsPerPixel * the number of bits to use per pixel */ - protected static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, - int height, int bitsPerPixel) { + protected static void convertToGrayScaleImage(ImageObject io, byte[] raw, + int width, int height, int bitsPerPixel) { int pixelsPerByte = 8 / bitsPerPixel; int bytewidth = (width / pixelsPerByte); if ((width % pixelsPerByte) != 0) { @@ -1823,7 +1608,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private void popViewPortPos() { viewPortPositions.remove(viewPortPositions.size() - 1); if (viewPortPositions.size() > 0) { - ViewPortPos vpp = (ViewPortPos)viewPortPositions.get(viewPortPositions.size() - 1); + ViewPortPos vpp = (ViewPortPos) viewPortPositions + .get(viewPortPositions.size() - 1); getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot); } } @@ -1837,9 +1623,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { public void setBitsPerPixel(int bitsPerPixel) { this.bitsPerPixel = bitsPerPixel; switch (bitsPerPixel) { - case 1: - case 4: - case 8: + case 1: + case 4: + case 8: break; default: log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8."); @@ -1885,12 +1671,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Returns the output/device resolution. + * * @return the resolution in dpi */ public int getResolution() { return this.resolution; } - + private AFPState getState() { if (currentState == null) { currentState = new AFPState(); @@ -1901,7 +1688,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private boolean gocaEnabled = false; /** - * @param enabled true if AFP GOCA is enabled for SVG support + * @param enabled + * true if AFP GOCA is enabled for SVG support */ protected void setGOCAEnabled(boolean enabled) { this.gocaEnabled = enabled; @@ -1913,10 +1701,5 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { protected boolean isGOCAEnabled() { return this.gocaEnabled; } - - /** {@inheritDoc} */ - public void startPageSequence(LineArea seqTitle) { - getAFPDataStream().endPageGroup(); - getAFPDataStream().startPageGroup(); - } + } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index f83aaf9f6..c75205c12 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -36,6 +36,8 @@ import org.apache.fop.render.afp.fonts.CharacterSet; import org.apache.fop.render.afp.fonts.FopCharacterSet; import org.apache.fop.render.afp.fonts.OutlineFont; import org.apache.fop.render.afp.fonts.RasterFont; +import org.apache.fop.render.afp.modca.AFPDataStream; +import org.apache.fop.render.afp.modca.InterchangeSet; import org.apache.fop.util.LogUtil; /** @@ -240,30 +242,44 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240)); } - // a default external resource group file setting - Configuration resourceGroupFileCfg = cfg.getChild("resource-group-file", false); - if (resourceGroupFileCfg != null) { - String resourceGroupDest = null; - try { - resourceGroupDest = resourceGroupFileCfg.getValue(); - } catch (ConfigurationException e) { - LogUtil.handleException(log, e, - userAgent.getFactory().validateUserConfigStrictly()); + // the MO:DCA interchange set in use (defaults to MO:DCA-L) + Configuration interchangeSetCfg = cfg.getChild("interchange-set", false); + if (interchangeSetCfg != null) { + String interchangeSetString = interchangeSetCfg.getAttribute( + "name", InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2); + AFPDataStream afpDatastream = afpRenderer.getAFPDataStream(); + InterchangeSet interchangeSet = InterchangeSet.valueOf(interchangeSetString); + afpDatastream.setInterchangeSet(interchangeSet); + + if (interchangeSet.supportsLevel2()) { + + // a default external resource group file setting + Configuration resourceGroupFileCfg + = interchangeSetCfg.getChild("resource-group-file", false); + if (resourceGroupFileCfg != null) { + String resourceGroupDest = null; + try { + resourceGroupDest = resourceGroupFileCfg.getValue(); + } catch (ConfigurationException e) { + LogUtil.handleException(log, e, + userAgent.getFactory().validateUserConfigStrictly()); + } + File resourceGroupFile = new File(resourceGroupDest); + if (resourceGroupFile.canWrite()) { + afpDatastream.setDefaultResourceGroupFile(resourceGroupFile); + } else { + log.warn("Unable to write to default external resource group file '" + + resourceGroupDest); + } + } } - File resourceGroupFile = new File(resourceGroupDest); - if (resourceGroupFile.canWrite()) { - afpRenderer.getAFPDataStream().setDefaultResourceGroupFile(resourceGroupFile); - } else { - log.warn("Unable to write to default external resource group file '" - + resourceGroupDest); + + // goca enabled + Configuration gocaSupportCfg = interchangeSetCfg.getChild("goca-enabled", false); + if (gocaSupportCfg != null) { + afpRenderer.setGOCAEnabled(true); } } - - // goca enabled - Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false); - if (gocaSupportCfg != null) { - afpRenderer.setGOCAEnabled(true); - } } } } diff --git a/src/java/org/apache/fop/render/afp/DataObjectInfo.java b/src/java/org/apache/fop/render/afp/DataObjectInfo.java index 58fbd11b1..e56e6338c 100644 --- a/src/java/org/apache/fop/render/afp/DataObjectInfo.java +++ b/src/java/org/apache/fop/render/afp/DataObjectInfo.java @@ -191,14 +191,14 @@ public class DataObjectInfo { } /** - * @return the object type entry + * @return the object type MOD:CA Registry entry */ - protected ObjectType getObjectType() { + public ObjectType getObjectType() { return objectType; } /** - * @return returns the resource level at which this data object should reside + * @return the resource level at which this data object should reside */ public ResourceInfo getResourceInfo() { return resourceInfo; @@ -239,8 +239,26 @@ public class DataObjectInfo { throw new UnsupportedOperationException(msg); } File resourceExternalGroupFile = new File(resourceExternalDest); - if (resourceExternalGroupFile.canWrite()) { + SecurityManager security = System.getSecurityManager(); + try { + if (security != null) { + security.checkWrite(resourceExternalGroupFile.getPath()); + } + } catch (SecurityException ex) { + log.warn("unable to gain write access to external resource file: " + + resourceExternalDest); + } + + try { + boolean exists = resourceExternalGroupFile.exists(); + if (exists) { + log.warn("overwritting external resource file: " + + resourceExternalDest); + } resourceInfo.setExternalResourceGroupFile(resourceExternalGroupFile); + } catch (SecurityException ex) { + log.warn("unable to gain read access to external resource file: " + + resourceExternalDest); } } } else { diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java b/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java index ad8410b82..613a24a3d 100644 --- a/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsChainedSegment.java @@ -136,7 +136,7 @@ public final class GraphicsChainedSegment extends AbstractPreparedObjectContaine if (previous == null) { GraphicsChainedSegment current = this.next; while (current != null) { - current.writeDataStream(os); + current.write(os); current = current.next; } } diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java index c556fa82d..ace60e331 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java @@ -21,7 +21,6 @@ package org.apache.fop.render.afp.modca; import java.awt.Color; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; @@ -57,7 +56,8 @@ public class AFPDataStream extends AbstractResourceGroupContainer { /** * Static logging instance */ - protected static Log log = LogFactory.getLog("org.apache.fop.render.afp.modca"); + protected static Log log = LogFactory + .getLog("org.apache.fop.render.afp.modca"); /** * Boolean completion indicator @@ -67,9 +67,8 @@ public class AFPDataStream extends AbstractResourceGroupContainer { /** * The application producing the AFP document */ -// not used -// private String producer = null; - + // not used + // private String producer = null; /** * The AFP document object */ @@ -85,11 +84,6 @@ public class AFPDataStream extends AbstractResourceGroupContainer { */ private PageObject currentPageObject = null; - /** - * The current resource group - */ -// private ResourceGroup currentResourceGroup = null; - /** * The current overlay object */ @@ -113,7 +107,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { /** * The overlay count */ - private int ovlCount = 0; + private int overlayCount = 0; /** * The portrait rotation @@ -145,11 +139,20 @@ public class AFPDataStream extends AbstractResourceGroupContainer { */ private OutputStream outputStream = null; + /** Maintain a reference count of instream objects for referencing purposes */ + private int instreamObjectCount = 0; + + /** + * The MO:DCA interchange set in use (default to MO:DCA-L resource set) + */ + private InterchangeSet interchangeSet + = InterchangeSet.valueOf(InterchangeSet.MODCA_RESOURCE_INTERCHANGE_SET); + /** * The external resource group manager */ private ExternalResourceGroupManager externalResourceGroupManager = null; - + /** * Default constructor for the AFPDataStream. */ @@ -157,10 +160,16 @@ public class AFPDataStream extends AbstractResourceGroupContainer { this.document = new Document(); } + /** + * @return the document object + */ private Document getDocument() { return this.document; } - + + /** + * @return the current page + */ private AbstractPageObject getCurrentPage() { return this.currentPage; } @@ -173,37 +182,28 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * the name of this document. */ public void setDocumentName(String name) { -// if (document != null) { -// String msg = "Invalid state - document already started."; -// log.warn("startDocument():: " + msg); -// throw new IllegalStateException(msg); -// } -// if (document != null) { -// String msg = "Invalid state - print file level document already started"; -// log.warn(msg); -// throw new IllegalStateException(msg); -// } - if (name != null) { - document.setFullyQualifiedName( + getDocument().setFullyQualifiedName( FullyQualifiedNameTriplet.TYPE_BEGIN_DOCUMENT_REF, - FullyQualifiedNameTriplet.FORMAT_CHARSTR, - name); + FullyQualifiedNameTriplet.FORMAT_CHARSTR, name); } } /** * Sets the OutputStream - * @param outputStream the AFP OutputStream + * + * @param outputStream + * the AFP OutputStream */ public void setOutputStream(OutputStream outputStream) { this.outputStream = outputStream; } - + /** - * The document is written/ended by invoking this method which creates an instance - * of the AFP Document object and registers the start with a validation map - * which ensures that methods are not invoked out of the correct sequence. + * The document is written/ended by invoking this method which creates an + * instance of the AFP Document object and registers the start with a + * validation map which ensures that methods are not invoked out of the + * correct sequence. * * @throws java.io.IOException * throws an I/O exception of some sort has occurred @@ -230,24 +230,24 @@ public class AFPDataStream extends AbstractResourceGroupContainer { // Write out any print-file level resources if (hasResources()) { - getResourceGroup().writeDataStream(this.outputStream); + getResourceGroup().write(this.outputStream); } // Write out document if (document != null) { document.endDocument(); - document.writeDataStream(this.outputStream); + document.write(this.outputStream); } this.outputStream.flush(); - complete = true; + this.complete = true; - document = null; + this.document = null; this.outputStream = null; } - + /** * Start a new page. When processing has finished on the current page, the * {@link #endPage()}method must be invoked to mark the page ending. @@ -266,7 +266,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { public void startPage(int pageWidth, int pageHeight, int pageRotation, int pageWidthRes, int pageHeightRes) { String pageName = "PGN" - + StringUtils.lpad(String.valueOf(pageCount++), '0', 5); + + StringUtils.lpad(String.valueOf(++pageCount), '0', 5); currentPageObject = new PageObject(pageName, pageWidth, pageHeight, pageRotation, pageWidthRes, pageHeightRes); @@ -292,17 +292,18 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * the width resolution of the overlay * @param heightRes * the height resolution of the overlay - * @param rotation + * @param overlayRotation * the rotation of the overlay */ public void startOverlay(int x, int y, int width, int height, int widthRes, - int heightRes, int rotation) { + int heightRes, int overlayRotation) { String overlayName = "OVL" - + StringUtils.lpad(String.valueOf(ovlCount++), '0', 5); + + StringUtils.lpad(String.valueOf(++overlayCount), '0', 5); - currentOverlay = new Overlay(overlayName, width, height, - widthRes, heightRes, rotation); - + this.currentOverlay = new Overlay(overlayName, width, height, widthRes, + heightRes, overlayRotation); + + getResourceGroup().addObject(currentOverlay); currentPageObject.createIncludePageOverlay(overlayName, x, y, 0); currentPage = currentOverlay; setOffsets(0, 0, 0); @@ -312,9 +313,11 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * Helper method to mark the end of the current overlay. */ public void endOverlay() { - currentOverlay.endPage(); - currentOverlay = null; - currentPage = currentPageObject; + if (currentOverlay != null) { + currentOverlay.endPage(); + currentOverlay = null; + currentPage = currentPageObject; + } } /** @@ -349,11 +352,13 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * Helper method to mark the end of the current page. */ public void endPage() { - currentPageObject.endPage(); - if (currentPageGroup != null) { - currentPageGroup.addPage(currentPageObject); - } else { - document.addPage(currentPageObject); + if (currentPageObject != null) { + currentPageObject.endPage(); + if (currentPageGroup != null) { + currentPageGroup.addPage(currentPageObject); + } else { + document.addPage(currentPageObject); + } } currentPageObject = null; currentPage = null; @@ -377,16 +382,17 @@ public class AFPDataStream extends AbstractResourceGroupContainer { /** * Creates the given page fonts in the current page - * @param pageFonts a collection of AFP font attributes + * + * @param pageFonts + * a collection of AFP font attributes */ public void addFontsToCurrentPage(Map pageFonts) { Iterator iter = pageFonts.values().iterator(); while (iter.hasNext()) { - AFPFontAttributes afpFontAttributes = (AFPFontAttributes)iter.next(); - createFont( - afpFontAttributes.getFontReference(), - afpFontAttributes.getFont(), - afpFontAttributes.getPointSize()); + AFPFontAttributes afpFontAttributes = (AFPFontAttributes) iter + .next(); + createFont(afpFontAttributes.getFontReference(), afpFontAttributes + .getFont(), afpFontAttributes.getPointSize()); } } @@ -425,60 +431,71 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * @param data * the text data to create */ - public void createText(int fontReference, int x, int y, Color col, int vsci, - int ica, byte[] data) { - getCurrentPage().createText(fontReference, x + xOffset, y + yOffset, rotation, - col, vsci, ica, data); + public void createText(int fontReference, int x, int y, Color col, + int vsci, int ica, byte[] data) { + getCurrentPage().createText(fontReference, x + xOffset, y + yOffset, + rotation, col, vsci, ica, data); } - /** Maintain a reference count of instream objects */ - private int instreamObjectCount = 0; - /** - * Creates a data object in the datastream. The data object resides according - * to its type, info and MO:DCA-L (resource) support. + * Creates a data object in the datastream. The data object resides + * according to its type, info and MO:DCA-L (resource) support. * * @param dataObjectInfo * the data object info - * @return - * a data object + * @return a data object */ public AbstractNamedAFPObject createObject(DataObjectInfo dataObjectInfo) { String uri = dataObjectInfo.getUri(); - - // if this is an instream data object adjust uri to ensure that it is unique + + // if this is an instream data object adjust uri to ensure that it is + // unique if (uri.endsWith("/")) { uri += "#" + (++instreamObjectCount); dataObjectInfo.setUri(uri); } - - Registry.ObjectType objectType = Registry.getInstance().getObjectType(dataObjectInfo); + + Registry registry = Registry.getInstance(); + Registry.ObjectType objectType = registry.getObjectType(dataObjectInfo); // recognised object type if (objectType != null) { dataObjectInfo.setObjectType(objectType); - // can this data object use the include object (IOB) referencing mechanism? - if (objectType.canBeIncluded()) { - ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); - ResourceGroup resourceGroup = getResourceGroup(resourceInfo); - IncludeObject includeObject = resourceGroup.createObject(dataObjectInfo); - - // add include to current page - getCurrentPage().addObject(includeObject); - return includeObject.getDataObject(); + ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + + // is MO:DCA-L available? + if (interchangeSet.supportsLevel2()) { + // can this data object use the include object (IOB) referencing + // mechanism? + if (objectType.canBeIncluded()) { + ResourceGroup resourceGroup = getResourceGroup(resourceInfo); + IncludeObject includeObject = resourceGroup.createObject(dataObjectInfo); + + // add include to current page + getCurrentPage().addObject(includeObject); + return includeObject.getDataObject(); + } else { + log.warn("data object located at '" + uri + + "' cannot be referenced with an include so it will be embedded directly"); + } } else { - log.warn(uri + "cannot be included so will embed directly"); + if (resourceInfo.isExternal()) { + log.warn( interchangeSet + + ": not available, object " + getName() + " will reside inline"); + } } + } - // unrecognised/unsupported object type so create/embed data object directly in current page - AbstractNamedAFPObject dataObj = getCurrentPage().createObject(dataObjectInfo); + // unrecognised/unsupported object type so create/embed data object + // directly in current page + AbstractNamedAFPObject dataObj = currentPageObject.createObject(dataObjectInfo); getCurrentPage().addObject(dataObj); return dataObj; } - + /** * Sets the object view port taking into account rotation. - * + * * @param x * the x position of the object * @param y @@ -491,11 +508,10 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * the resolution width of the object * @param hr * the resolution height of the object - * @return - * a new graphics object + * @return a new graphics object */ - private void setObjectViewPort(AbstractDataObject dataObj, - int x, int y, int w, int h, int wr, int hr) { + private void setObjectViewPort(AbstractDataObject dataObj, int x, int y, + int w, int h, int wr, int hr) { int xOrigin; int yOrigin; int width; @@ -536,9 +552,10 @@ public class AFPDataStream extends AbstractResourceGroupContainer { heightRes = hr; break; } - dataObj.setViewport(xOrigin, yOrigin, width, height, widthRes, heightRes, rotation); + dataObj.setViewport(xOrigin, yOrigin, width, height, widthRes, + heightRes, rotation); } - + /** * Method to create a line on the current page. * @@ -557,8 +574,8 @@ public class AFPDataStream extends AbstractResourceGroupContainer { */ public void createLine(int x1, int y1, int x2, int y2, int thickness, Color col) { - getCurrentPage().createLine(x1 + xOffset, y1 + yOffset, x2 + xOffset, y2 - + yOffset, thickness, rotation, col); + getCurrentPage().createLine(x1 + xOffset, y1 + yOffset, x2 + xOffset, + y2 + yOffset, thickness, rotation, col); } /** @@ -574,17 +591,12 @@ public class AFPDataStream extends AbstractResourceGroupContainer { * the width of the shaded area * @param h * the height of the shaded area - * @param red - * the red value - * @param green - * the green value - * @param blue - * the blue value + * @param col + * the shading color */ - public void createShading(int x, int y, int w, int h, int red, int green, - int blue) { - getCurrentPage().createShading(x + xOffset, y + xOffset, w, h, red, green, - blue); + public void createShading(int x, int y, int w, int h, Color col) { + currentPageObject.createShading(x + xOffset, y + xOffset, w, h, + col.getRed(), col.getGreen(), col.getBlue()); } /** @@ -700,12 +712,13 @@ public class AFPDataStream extends AbstractResourceGroupContainer { private PageGroup getCurrentPageGroup() { if (currentPageGroup == null) { String pageGroupName = "PGP" - + StringUtils.lpad(String.valueOf(pageGroupCount++), '0', 5); + + StringUtils + .lpad(String.valueOf(++pageGroupCount), '0', 5); this.currentPageGroup = new PageGroup(pageGroupName); } return currentPageGroup; } - + /** * Start a new page group. When processing has finished on the current page * group the {@link #endPageGroup()}method must be invoked to mark the page @@ -760,10 +773,11 @@ public class AFPDataStream extends AbstractResourceGroupContainer { } } - /** * Returns the resource group for a given resource into - * @param resourceInfo resource info + * + * @param resourceInfo + * resource info * @return a resource group container for the given resource info */ private ResourceGroup getResourceGroup(ResourceInfo resourceInfo) { @@ -775,20 +789,23 @@ public class AFPDataStream extends AbstractResourceGroupContainer { } else if (resourceInfo.isPageGroup()) { resourceGroup = getCurrentPageGroup().getResourceGroup(); } else if (resourceInfo.isPage()) { - resourceGroup = getCurrentPage().getResourceGroup(); + resourceGroup = currentPageObject.getResourceGroup(); } else if (resourceInfo.isExternal()) { - resourceGroup = getExternalResourceGroupManager().getExternalResourceGroup( - resourceInfo); + resourceGroup = getExternalResourceGroupManager() + .getExternalResourceGroup(resourceInfo); } return resourceGroup; } /** * Sets the default resource group file - * @param resourceGroupFile the default resource group file + * + * @param resourceGroupFile + * the default resource group file */ public void setDefaultResourceGroupFile(File resourceGroupFile) { - getExternalResourceGroupManager().setDefaultResourceGroupFile(resourceGroupFile); + getExternalResourceGroupManager().setDefaultResourceGroupFile( + resourceGroupFile); } /** @@ -801,7 +818,6 @@ public class AFPDataStream extends AbstractResourceGroupContainer { return this.externalResourceGroupManager; } - /** * Manages the use of resource groups (external and internal) */ @@ -809,7 +825,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { /** * A mapping of external resource destinations to resource groups */ - private Map/**/ externalResourceGroups = null; + private Map/**/externalResourceGroups = null; /** sets the default resource group file */ private File defaultResourceGroupFile; @@ -819,15 +835,20 @@ public class AFPDataStream extends AbstractResourceGroupContainer { /** * Main constructor - * @param container the container of this manager + * + * @param container + * the container of this manager */ - private ExternalResourceGroupManager(AbstractResourceGroupContainer container) { + private ExternalResourceGroupManager( + AbstractResourceGroupContainer container) { this.container = container; } - + /** * Sets the default resource group file - * @param resourceGroupFile the default resource group file + * + * @param resourceGroupFile + * the default resource group file */ private void setDefaultResourceGroupFile(File resourceGroupFile) { this.defaultResourceGroupFile = resourceGroupFile; @@ -840,36 +861,44 @@ public class AFPDataStream extends AbstractResourceGroupContainer { // write any external resources Iterator it = getExternalResourceGroups().keySet().iterator(); while (it.hasNext()) { - File resourceGroupFile = (File)it.next(); - ResourceGroup resourceGroup - = (ResourceGroup)getExternalResourceGroups().get(resourceGroupFile); + File resourceGroupFile = (File) it.next(); + ResourceGroup resourceGroup = (ResourceGroup) getExternalResourceGroups() + .get(resourceGroupFile); OutputStream os = null; try { log.debug("Writing external AFP resource file " + resourceGroupFile.getAbsolutePath()); - + os = new java.io.FileOutputStream(resourceGroupFile); - resourceGroup.writeDataStream(os); + resourceGroup.write(os); } catch (IOException e) { log.error( "An error occurred when attempting to write external AFP resource file " - + resourceGroupFile.getAbsolutePath()); + + resourceGroupFile.getAbsolutePath()); } finally { if (os != null) { try { os.close(); } catch (IOException e) { log.error("Failed to close outputstream for external AFP resource file " - + resourceGroupFile.getAbsolutePath()); + + resourceGroupFile.getAbsolutePath()); } } } } } - + + /** + * Returns the corresponding resource group for the given resource info + * + * @param resourceInfo + * resource info + * @return the corresponding resource group for the given resource info + */ private ResourceGroup getExternalResourceGroup(ResourceInfo resourceInfo) { ResourceGroup resourceGroup; - // this resource info does not have a an external resource group file definition + // this resource info does not have a an external resource group + // file definition if (!resourceInfo.hasExternalResourceGroupFile()) { if (defaultResourceGroupFile != null) { // fallback to default resource group file @@ -881,21 +910,52 @@ public class AFPDataStream extends AbstractResourceGroupContainer { resourceGroup = container.getResourceGroup(); } } else { - File resourceGroupFile = resourceInfo.getExternalResourceGroupFile(); + File resourceGroupFile = resourceInfo + .getExternalResourceGroupFile(); resourceGroup = (ResourceGroup)getExternalResourceGroups().get(resourceGroupFile); - if (resourceGroup == null) { + if (resourceGroup == null) { resourceGroup = new ResourceGroup(container); - externalResourceGroups.put(resourceGroupFile, resourceGroup); + externalResourceGroups + .put(resourceGroupFile, resourceGroup); } } return resourceGroup; } - - private Map/**/ getExternalResourceGroups() { + + private Map/**/getExternalResourceGroups() { if (externalResourceGroups == null) { - externalResourceGroups = new java.util.HashMap/**/(); + externalResourceGroups = new java.util.HashMap/**/(); } return externalResourceGroups; - } + } + } + + /** + * Starts a new page segment. + */ + public void startPageSegment() { + currentPageObject.startPageSegment(); + } + + /** + * Ends the current page segment. + */ + public void endPageSegment() { + currentPageObject.endPageSegment(); + } + + /** + * Sets the MO:DCA interchange set to use + * @param interchangeSet the MO:DCA interchange set + */ + public void setInterchangeSet(InterchangeSet interchangeSet) { + this.interchangeSet = interchangeSet; + } + + /** + * @return the MO:DCA interchange set in use + */ + public InterchangeSet getInterchangeSet() { + return this.interchangeSet; } } diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStreamWriter.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStreamWriter.java deleted file mode 100644 index 35b651fa2..000000000 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStreamWriter.java +++ /dev/null @@ -1,36 +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; - -/** - * Implementing object is able to write to an AFPDataStream - */ -public interface AFPDataStreamWriter { - /** - * DataStream objects must implement the writeDataStream() - * method to write its data to the given OutputStream - * @param os The outputsteam stream - * @throws java.io.IOException an I/O exception of some sort has occurred. - */ - void writeDataStream(OutputStream os) throws IOException; -} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java index 27fe3121e..9cad38ef5 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java @@ -33,7 +33,7 @@ import org.apache.commons.logging.LogFactory; * AFP format. * */ -public abstract class AbstractAFPObject implements AFPDataStreamWriter { +public abstract class AbstractAFPObject implements Writable { /** * Static logging instance @@ -51,7 +51,7 @@ public abstract class AbstractAFPObject implements AFPDataStreamWriter { if (objects != null) { for (Iterator it = objects.iterator(); it.hasNext();) { AbstractAFPObject obj = (AbstractAFPObject)it.next(); - obj.writeDataStream(os); + obj.write(os); } } } 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 f6473cfdc..a57526a04 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java @@ -82,7 +82,7 @@ public abstract class AbstractDataObject extends AbstractPreparedObjectContainer */ protected void writeContent(OutputStream os) throws IOException { if (objectEnvironmentGroup != null) { - objectEnvironmentGroup.writeDataStream(os); + objectEnvironmentGroup.write(os); } super.writeContent(os); } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java index 41cf78162..e1035a6c6 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java @@ -25,7 +25,6 @@ import java.io.OutputStream; import java.util.List; import org.apache.fop.render.afp.fonts.AFPFont; -import org.apache.fop.render.afp.tools.StringUtils; /** * Pages contain the data objects that comprise a presentation document. Each @@ -47,27 +46,32 @@ import org.apache.fop.render.afp.tools.StringUtils; * in page state. * */ -public abstract class AbstractPageObject extends AbstractResourceGroupContainer { +public abstract class AbstractPageObject extends AbstractNamedAFPObject { /** * The active environment group for the page */ - protected ActiveEnvironmentGroup activeEnvironmentGroup; + protected ActiveEnvironmentGroup activeEnvironmentGroup = null; /** - * The presentation text object, we only have one per page + * The current presentation text object */ - private PresentationTextObject presentationTextObject; + private PresentationTextObject currentPresentationTextObject = null; /** * The list of tag logical elements */ - protected List tagLogicalElements; + protected List/**/ tagLogicalElements = null; /** * The list of the include page segments */ - protected List segments; + protected List/**/ includePageSegments = null; + + /** + * The list of objects within this resource container + */ + protected List/**/ objects = null; /** * The page width @@ -82,13 +86,37 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer /** * The page rotation */ - private int rotation = 0; + protected int rotation = 0; /** * The page state */ private boolean complete = false; + /** + * The width resolution + */ + private int widthRes; + + /** + * The height resolution + */ + private int heightRes; + + /** + * Default constructor + */ + public AbstractPageObject() { + } + + /** + * Named constructor + * @param name the name of this page object + */ + public AbstractPageObject(String name) { + super(name); + } + /** * Construct a new page object for the specified name argument, the page * name should be an 8 character identifier. @@ -113,27 +141,8 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer this.width = width; this.height = height; this.rotation = rotation; - - /** - * Every page object must have an ActiveEnvironmentGroup - */ - this.activeEnvironmentGroup = new ActiveEnvironmentGroup( - width, height, widthRes, heightRes); - - if (rotation != 0) { - switch (rotation) { - case 90: - activeEnvironmentGroup.setPosition(width, 0, rotation); - break; - case 180: - activeEnvironmentGroup.setPosition(width, height, rotation); - break; - case 270: - activeEnvironmentGroup.setPosition(0, height, rotation); - break; - default: - } - } + this.widthRes = widthRes; + this.heightRes = heightRes; } /** @@ -208,111 +217,31 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer * sequence on the current presentation text object. */ public void endPage() { - if (presentationTextObject != null) { - presentationTextObject.endControlSequence(); + if (currentPresentationTextObject != null) { + currentPresentationTextObject.endControlSequence(); } complete = true; } - /** - * This method will create shading on the page using the specified - * coordinates (the shading contrast is controlled via the red, green blue - * parameters, by converting this to grey scale). - * - * @param x - * the x coordinate of the shading - * @param y - * the y coordinate of the shading - * @param w - * the width of the shaded area - * @param h - * the height of the shaded area - * @param red - * the red value - * @param green - * the green value - * @param blue - * the blue value - */ - public void createShading(int x, int y, int w, int h, int red, int green, int blue) { - int xCoord = 0; - int yCoord = 0; - int areaWidth = 0; - int areaHeight = 0; - switch (rotation) { - case 90: - xCoord = areaWidth - y - h; - yCoord = x; - areaWidth = h; - areaHeight = w; - break; - case 180: - xCoord = areaWidth - x - w; - yCoord = areaHeight - y - h; - areaWidth = w; - areaHeight = h; - break; - case 270: - xCoord = y; - yCoord = areaHeight - x - w; - areaWidth = h; - areaHeight = w; - break; - default: - xCoord = x; - yCoord = y; - areaWidth = w; - areaHeight = h; - break; - } - - // Convert the color to grey scale - float shade = (float) ((red * 0.3) + (green * 0.59) + (blue * 0.11)); - - int greyscale = Math.round((shade / 255) * 16); - - String imageName = "IMG" - + StringUtils.lpad(String.valueOf(getResourceCount() + 1), - '0', 5); - - IMImageObject io = new IMImageObject(imageName); - ImageOutputControl ioc = new ImageOutputControl(0, 0); - ImageInputDescriptor iid = new ImageInputDescriptor(); - ImageCellPosition icp = new ImageCellPosition(xCoord, yCoord); - icp.setXFillSize(areaWidth); - icp.setYFillSize(areaHeight); - icp.setXSize(64); - icp.setYSize(8); - - //defining this as a resource - ImageRasterData ird = new ImageRasterData( - ImageRasterPattern.getRasterData(greyscale)); - - io.setImageOutputControl(ioc); - io.setImageInputDescriptor(iid); - io.setImageCellPosition(icp); - io.setImageRasterData(ird); - addObject(io); - } - private void endPresentationObject() { - if (presentationTextObject != null) { - presentationTextObject.endControlSequence(); - presentationTextObject = null; + if (currentPresentationTextObject != null) { + currentPresentationTextObject.endControlSequence(); + currentPresentationTextObject = null; } } - + /** * Helper method to create a presentation text object * on the current page and to return the object. * @return the presentation text object */ private PresentationTextObject getPresentationTextObject() { - if (presentationTextObject == null) { - this.presentationTextObject = new PresentationTextObject(); - super.addObject(this.presentationTextObject); + if (currentPresentationTextObject == null) { + PresentationTextObject presentationTextObject = new PresentationTextObject(); + addObject(presentationTextObject); + this.currentPresentationTextObject = presentationTextObject; } - return presentationTextObject; + return currentPresentationTextObject; } /** @@ -326,7 +255,7 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer public void createTagLogicalElement(String name, String value) { TagLogicalElement tle = new TagLogicalElement(name, value); if (tagLogicalElements == null) { - tagLogicalElements = new java.util.ArrayList(); + tagLogicalElements = new java.util.ArrayList/**/(); } tagLogicalElements.add(tle); } @@ -352,10 +281,10 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer */ public void createIncludePageSegment(String name, int xCoor, int yCoor) { IncludePageSegment ips = new IncludePageSegment(name, xCoor, yCoor); - if (segments == null) { - segments = new java.util.ArrayList(); + if (includePageSegments == null) { + includePageSegments = new java.util.ArrayList/**/(); } - segments.add(ips); + includePageSegments.add(ips); } /** @@ -364,6 +293,28 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer * @return the ActiveEnvironmentGroup object */ public ActiveEnvironmentGroup getActiveEnvironmentGroup() { + if (activeEnvironmentGroup == null) { + /** + * Every page object must have an ActiveEnvironmentGroup + */ + this.activeEnvironmentGroup = new ActiveEnvironmentGroup( + width, height, widthRes, heightRes); + + if (rotation != 0) { + switch (rotation) { + case 90: + activeEnvironmentGroup.setPosition(width, 0, rotation); + break; + case 180: + activeEnvironmentGroup.setPosition(width, height, rotation); + break; + case 270: + activeEnvironmentGroup.setPosition(0, height, rotation); + break; + default: + } + } + } return activeEnvironmentGroup; } @@ -404,21 +355,33 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer */ protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); - getActiveEnvironmentGroup().writeDataStream(os); - writeObjects(segments, os); - writeObjects(tagLogicalElements, os); - writeObjects(objects, os); + if (this instanceof PageObject) { + getActiveEnvironmentGroup().write(os); + } + writeObjects(this.includePageSegments, os); + writeObjects(this.tagLogicalElements, os); + writeObjects(this.objects, os); } /** - * {@inheritDoc} + * Adds an AFP object to the resource group in this container + * @param obj an AFP object */ - protected void addObject(AbstractStructuredAFPObject obj) { - if (obj instanceof IncludeObject) { - IncludeObject includeObj = (IncludeObject)obj; - getActiveEnvironmentGroup().createResource(includeObj); + protected void addObject(AbstractAFPObject obj) { + if (objects == null) { + this.objects = new java.util.ArrayList/**/(); } - endPresentationObject(); - super.addObject(obj); + objects.add(obj); } + +// /** +// * {@inheritDoc} +// */ +// protected void addObject(AbstractAFPObject obj) { +// if (obj instanceof DataObjectAccessor) { +// DataObjectAccessor dataObjectAccessor = (DataObjectAccessor)obj; +// getActiveEnvironmentGroup().createMapDataResource(dataObjectAccessor); +// } +// endPresentationObject(); +// } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java index ea6ca4b2e..9449108eb 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java @@ -21,7 +21,6 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import java.util.Iterator; /** * An abstract class which encapsulates the common features of @@ -75,19 +74,7 @@ public abstract class AbstractResourceEnvironmentGroupContainer protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); if (resourceEnvironmentGroup != null) { - resourceEnvironmentGroup.writeDataStream(os); - } - if (objects != null) { - for (Iterator it = objects.iterator(); it.hasNext();) { - AbstractAFPObject ao = (AbstractAFPObject)it.next(); - if (ao instanceof PageObject && ((PageObject)ao).isComplete() - || ao instanceof PageGroup && ((PageGroup)ao).isComplete()) { - ao.writeDataStream(os); - it.remove(); - } else { - break; - } - } + resourceEnvironmentGroup.write(os); } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java index 25dc547fb..1bdf7d8bd 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java @@ -21,7 +21,6 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import java.util.Set; import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.ImageObjectInfo; @@ -32,21 +31,17 @@ import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; /** * An abstract container of resource objects */ -public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObject { +public abstract class AbstractResourceGroupContainer extends AbstractPageObject { /** * The resource group object */ private ResourceGroup resourceGroup = null; - - /** - * The list of objects within this resource container - */ - protected Set/**/ objects = null; /** - * Unnamed constructor + * Default constructor */ public AbstractResourceGroupContainer() { + super(); } /** @@ -57,6 +52,28 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj super(name); } + /** + * Construct a new page object for the specified name argument, the page + * name should be an 8 character identifier. + * + * @param name + * the name of the page. + * @param width + * the width of the page. + * @param height + * the height of the page. + * @param rotation + * the rotation of the page. + * @param widthRes + * the width resolution of the page. + * @param heightRes + * the height resolution of the page. + */ + public AbstractResourceGroupContainer(String name, int width, int height, + int rotation, int widthRes, int heightRes) { + super(name, width, height, rotation, widthRes, heightRes); + } + /** * @return the number of resources in this container */ @@ -67,17 +84,6 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj return 0; } - /** - * Adds an AFP object to the resource group in this container - * @param obj an AFP object - */ - protected void addObject(AbstractAFPObject obj) { - if (objects == null) { - this.objects = new java.util.LinkedHashSet/**/(); - } - objects.add(obj); - } - /** * @return true if this resource group container contains resources */ @@ -161,7 +167,6 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj private static final String IMAGE_NAME_PREFIX = "IMG"; private static final String GRAPHIC_NAME_PREFIX = "GRA"; - private static final String PAGE_SEGMENT_NAME_PREFIX = "PSG"; // not currently used/implemented private static final String BARCODE_NAME_PREFIX = "BAR"; @@ -220,18 +225,6 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj return graphicsObj; } - /** - * Helper method to create a page segment in the current container and to return - * the object. - * @return a newly created page segment - */ - protected PageSegment createPageSegment() { - String name = PAGE_SEGMENT_NAME_PREFIX - + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); - PageSegment pageSegment = new PageSegment(name); - return pageSegment; - } - /** * Creates and returns a new data object * @param info the data object parameters @@ -244,10 +237,9 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj } else { dataObject = createGraphic(info); } - - dataObject.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, - FullyQualifiedNameTriplet.FORMAT_URL, info.getUri()); + dataObject.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, dataObject.getName()); return dataObject; } @@ -258,7 +250,7 @@ public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObj protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); if (resourceGroup != null) { - resourceGroup.writeDataStream(os); + resourceGroup.write(os); } } } 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 e82371a81..1573ea1a4 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java @@ -129,7 +129,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { * @param os The stream to write to * @throws IOException in the event that an I/O exception occurred */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { writeStart(os); writeContent(os); writeEnd(os); @@ -193,12 +193,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { * @param fqName the fully qualified name of this resource */ public void setFullyQualifiedName(byte fqnType, byte fqnFormat, String fqName) { - try { - byte[] fqNameBytes = fqName.getBytes(AFPConstants.EBCIDIC_ENCODING); - addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqNameBytes)); - } catch (UnsupportedEncodingException e) { - log.error(e.getMessage()); - } + addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqName)); } /** @@ -208,17 +203,9 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { FullyQualifiedNameTriplet fqNameTriplet = (FullyQualifiedNameTriplet)getTriplet(Triplet.FULLY_QUALIFIED_NAME); if (fqNameTriplet != null) { - byte[] nameBytes = fqNameTriplet.getFullyQualifiedName(); - if (nameBytes != null) { - try { - return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException e) { - log.error(e.getMessage()); - } - } else { - log.warn(this + " has no fully qualified name"); - } + return fqNameTriplet.getFullyQualifiedName(); } + log.warn(this + " has no fully qualified name"); return null; } @@ -233,6 +220,16 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { StrucFlgs strucFlgs) { addTriplet(new ObjectClassificationTriplet(objectClass, objectType, strucFlgs)); } + + /** + * Sets the objects classification with the default structure flags + * @param objectClass the classification of the object + * @param objectType the MOD:CA registry object type entry for the given + * object/component type of the object + */ + public void setObjectClassification(byte objectClass, Registry.ObjectType objectType) { + setObjectClassification(objectClass, objectType, StrucFlgs.getDefault()); + } /** * Specifies the extent of an object area in the X and Y directions diff --git a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java index df4975e59..4dd735ccc 100644 --- a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java @@ -150,14 +150,14 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { writeObjects(mapPageOverlays, os); if (pageDescriptor != null) { - pageDescriptor.writeDataStream(os); + pageDescriptor.write(os); } if (objectAreaDescriptor != null && objectAreaPosition != null) { - objectAreaDescriptor.writeDataStream(os); - objectAreaPosition.writeDataStream(os); + objectAreaDescriptor.write(os); + objectAreaPosition.write(os); } if (presentationTextDataDescriptor != null) { - presentationTextDataDescriptor.writeDataStream(os); + presentationTextDataDescriptor.write(os); } } @@ -243,7 +243,7 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { } } } - + /** * Getter method for the most recent MapCodedFont added to the * Active Environment Group (returns null if no MapCodedFonts exist) @@ -260,9 +260,9 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { /** * Method to create a map data resource object - * @param obj creates a map data resource entry for a given AFP data resource object + * @param dataObjectAccessor a data object accessor */ - public void createResource(IncludeObject obj) { - getMapDataResources().add(new MapDataResource(obj)); + protected void createMapDataResource(DataObjectAccessor dataObjectAccessor) { + getMapDataResources().add(new MapDataResource(dataObjectAccessor)); } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java b/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java index c8c55bebc..f8a779707 100644 --- a/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java +++ b/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java @@ -19,13 +19,26 @@ package org.apache.fop.render.afp.modca; +import org.apache.fop.render.afp.DataObjectInfo; + /** * A common interface of ResourceObject and ContainerObject */ -public interface DataObjectAccessor extends AFPDataStreamWriter { +public interface DataObjectAccessor extends Writable { /** * @return the actual data object referenced in this envelope */ AbstractNamedAFPObject getDataObject(); + + /** + * @return the data object info relating to the data object + */ + DataObjectInfo getDataObjectInfo(); + + /** + * Sets the data object info + * @param dataObjectInfo the data object info + */ + void setDataObjectInfo(DataObjectInfo dataObjectInfo); } diff --git a/src/java/org/apache/fop/render/afp/modca/Document.java b/src/java/org/apache/fop/render/afp/modca/Document.java index 72c65e8a7..efa022952 100644 --- a/src/java/org/apache/fop/render/afp/modca/Document.java +++ b/src/java/org/apache/fop/render/afp/modca/Document.java @@ -94,9 +94,9 @@ public final class Document extends AbstractResourceEnvironmentGroupContainer { * @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 { + public void write(OutputStream os) throws IOException { if (isComplete()) { - super.writeDataStream(os); + super.write(os); } } 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 8fecc0e5b..53ebe233f 100644 --- a/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java @@ -61,7 +61,7 @@ public class GraphicsDataDescriptor extends AbstractAFPObject { /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] xreswind = BinaryUtils.convert(xresol * 10, 2); byte[] yreswind = BinaryUtils.convert(yresol * 10, 2); byte[] xlcoord = BinaryUtils.convert(xlwind, 2); diff --git a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java b/src/java/org/apache/fop/render/afp/modca/IMImageObject.java index 2afd3fa49..73abb2843 100644 --- a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IMImageObject.java @@ -104,16 +104,16 @@ public class IMImageObject extends AbstractNamedAFPObject { protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); if (imageOutputControl != null) { - imageOutputControl.writeDataStream(os); + imageOutputControl.write(os); } if (imageInputDescriptor != null) { - imageInputDescriptor.writeDataStream(os); + imageInputDescriptor.write(os); } if (imageCellPosition != null) { - imageCellPosition.writeDataStream(os); + imageCellPosition.write(os); } if (imageRasterData != null) { - imageRasterData.writeDataStream(os); + imageRasterData.write(os); } } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java b/src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java index c0b28904d..c0eb77953 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java @@ -74,7 +74,7 @@ public class ImageCellPosition extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException if an I/O exception occurred */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[21]; data[0] = 0x5A; diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java index 726c58762..7a86fdddb 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageContent.java @@ -143,7 +143,7 @@ public class ImageContent extends AbstractStructuredAFPObject { */ protected void writeContent(OutputStream os) throws IOException { if (_imageSizeParameter != null) { - _imageSizeParameter.writeDataStream(os); + _imageSizeParameter.write(os); } os.write(getImageEncodingParameter()); os.write(getImageIDESizeParameter()); diff --git a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java index 9250f0c7f..45c029f71 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java @@ -54,7 +54,7 @@ public class ImageDataDescriptor extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException */ - public void writeDataStream(OutputStream os) + public void write(OutputStream os) throws IOException { byte[] data = new byte[] { diff --git a/src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java index bba416c88..a9aef38b9 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java @@ -41,7 +41,7 @@ public class ImageInputDescriptor extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException if an I/O exception occurred */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[45]; diff --git a/src/java/org/apache/fop/render/afp/modca/ImageObject.java b/src/java/org/apache/fop/render/afp/modca/ImageObject.java index c13fcbb59..67c0a0858 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageObject.java @@ -144,7 +144,7 @@ public class ImageObject extends AbstractDataObject { super.writeContent(os); if (imageSegment != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - imageSegment.writeDataStream(baos); + imageSegment.write(baos); byte[] b = baos.toByteArray(); int off = 0; while (off < b.length) { diff --git a/src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java b/src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java index 558a600a5..0c38273de 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java @@ -78,7 +78,7 @@ public class ImageOutputControl extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException if an I/O exception occured */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[33]; diff --git a/src/java/org/apache/fop/render/afp/modca/ImageRasterData.java b/src/java/org/apache/fop/render/afp/modca/ImageRasterData.java index ca440a859..dd9c5f699 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageRasterData.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageRasterData.java @@ -63,7 +63,7 @@ public class ImageRasterData extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException if an I/O exception occurred */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[9]; diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java index ea8eb334b..e579052b0 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java @@ -141,7 +141,7 @@ public class ImageSegment extends AbstractNamedAFPObject { */ public void writeContent(OutputStream os) throws IOException { if (imageContent != null) { - imageContent.writeDataStream(os); + imageContent.write(os); } } 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 7dd210a1e..f66b76853 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java @@ -53,7 +53,7 @@ public class ImageSizeParameter extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException if an I/O exception occured */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[] { (byte)0x94, // ID = Image Size Parameter 0x09, // Length diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java index 92244d66a..1817bc8cc 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java @@ -22,8 +22,8 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.ResourceInfo; -import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; import org.apache.fop.render.afp.tools.BinaryUtils; /** @@ -69,7 +69,7 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA /** * The object type (default is other) */ - private byte objectType = TYPE_OTHER; + private byte dataObjectType = TYPE_OTHER; /** * The orientation on the include object @@ -95,11 +95,6 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA * The Y-axis origin defined in the object */ private int yContentOffset = -1; - - /** - * the resource info - */ - private ResourceInfo resourceInfo = null; /** * the referenced data object @@ -113,75 +108,72 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA * * @param name the name of this include object * @param dataObjectAccessor the data object accessor - * @param resourceInfo the resource information */ - public IncludeObject(String name, DataObjectAccessor dataObjectAccessor, - ResourceInfo resourceInfo) { + public IncludeObject(String name, DataObjectAccessor dataObjectAccessor) { super(name); - - setDataObjectAccessor(dataObjectAccessor); - setResourceInfo(resourceInfo); - } - /** - * Sets the data object accessor and the object type - * @param dataObjectAccessor the data object accessor - */ - private void setDataObjectAccessor(DataObjectAccessor dataObjectAccessor) { this.dataObjectAccessor = dataObjectAccessor; AbstractNamedAFPObject dataObject = dataObjectAccessor.getDataObject(); - + + // Strip any object container + if (dataObject instanceof ObjectContainer) { + ObjectContainer objectContainer = (ObjectContainer)dataObject; + dataObject = objectContainer.getDataObject(); + } if (dataObject instanceof ImageObject) { - this.objectType = TYPE_IMAGE; + this.dataObjectType = TYPE_IMAGE; } else if (dataObject instanceof GraphicsObject) { - this.objectType = TYPE_GRAPHIC; + this.dataObjectType = TYPE_GRAPHIC; } else if (dataObject instanceof PageSegment) { - this.objectType = TYPE_PAGE_SEGMENT; + this.dataObjectType = TYPE_PAGE_SEGMENT; } else { - this.objectType = TYPE_OTHER; + this.dataObjectType = TYPE_OTHER; + DataObjectInfo dataObjectInfo = dataObjectAccessor.getDataObjectInfo(); + Registry registry = Registry.getInstance(); + Registry.ObjectType objectType = registry.getObjectType(dataObjectInfo); + // When other type must set object classification + super.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT, + objectType); } + +// ResourceInfo resourceInfo = dataObjectAccessor.getDataObjectInfo().getResourceInfo(); +// // Set data object reference triplet +// if (resourceInfo != null && resourceInfo.isExternal()) { +// String dest = resourceInfo.getExternalResourceGroupDest(); +// super.setFullyQualifiedName( +// FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, +// FullyQualifiedNameTriplet.FORMAT_URL, dest); +// } else { +// super.setFullyQualifiedName( +// FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, +// FullyQualifiedNameTriplet.FORMAT_CHARSTR, dataObject.getName()); +// } + + // Set measurement units triplet + setMeasurementUnits(); } /** - * @return the data object accessor - */ - private DataObjectAccessor getDataObjectAccessor() { - return this.dataObjectAccessor; - } - - /** - * Sets the resource level for this resource object - * @param resourceInfo the resource information + * {@inheritDoc} */ - private void setResourceInfo(ResourceInfo resourceInfo) { - this.resourceInfo = resourceInfo; - - // set data object reference triplet - if (resourceInfo != null && resourceInfo.isExternal()) { - String dest = resourceInfo.getExternalResourceGroupDest(); - super.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, - FullyQualifiedNameTriplet.FORMAT_URL, dest); - } else { - super.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, - FullyQualifiedNameTriplet.FORMAT_CHARSTR, getDataObject().getName()); - } + public AbstractNamedAFPObject getDataObject() { + return dataObjectAccessor.getDataObject(); } /** - * @return the resource info of this resource object + * {@inheritDoc} */ - public ResourceInfo getResourceInfo() { - return this.resourceInfo; + public DataObjectInfo getDataObjectInfo() { + return dataObjectAccessor.getDataObjectInfo(); } /** - * @return the actual resource data object referenced by this include object + * {@inheritDoc} */ - public AbstractNamedAFPObject getDataObject() { - return getDataObjectAccessor().getDataObject(); + public void setDataObjectInfo(DataObjectInfo dataObjectInfo) { + dataObjectAccessor.setDataObjectInfo(dataObjectInfo); } /** @@ -223,7 +215,7 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[36]; data[0] = 0x5A; @@ -246,7 +238,7 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA } data[17] = 0x00; // reserved - data[18] = objectType; + data[18] = dataObjectType; //XoaOset (object area) if (xOffset > 0) { @@ -337,4 +329,11 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA byte[] tripletData = super.getTripletData(); os.write(tripletData); } + + /** + * {@inheritDoc} + */ + public String toString() { + return "IOB: " + this.getName(); + } } \ No newline at end of file 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 8a7d4720a..31021392e 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java @@ -87,7 +87,7 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[25]; //(9 +16) data[0] = 0x5A; 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 b87222c00..4183b6717 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java @@ -67,7 +67,7 @@ public class IncludePageSegment extends AbstractNamedAFPObject { /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[23]; //(9 +14) diff --git a/src/java/org/apache/fop/render/afp/modca/InterchangeSet.java b/src/java/org/apache/fop/render/afp/modca/InterchangeSet.java new file mode 100644 index 000000000..1ef72b3cf --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/InterchangeSet.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.render.afp.modca; + +/** + * MO:DCA Interchange Set + */ +public class InterchangeSet { + /** interchange set 1 string value */ + public static final String MODCA_PRESENTATION_INTERCHANGE_SET_1 = "MO:DCA-P IS/1"; + + /** interchange set 2 string value */ + public static final String MODCA_PRESENTATION_INTERCHANGE_SET_2 = "MO:DCA-P IS/2"; + + /** resource interchange set string value */ + public static final String MODCA_RESOURCE_INTERCHANGE_SET = "MO:DCA-L"; + + private static final String[] NAMES = { + MODCA_PRESENTATION_INTERCHANGE_SET_1, + MODCA_PRESENTATION_INTERCHANGE_SET_2, + MODCA_RESOURCE_INTERCHANGE_SET + }; + + private static final int SET_1 = 0; + private static final int SET_2 = 1; + private static final int RESOURCE_SET = 2; + + /** the actual interchange set in use */ + private int value; + + /** + * @param str an interchange set value + * @return an interchange set + */ + public static InterchangeSet valueOf(String str) { + if (MODCA_PRESENTATION_INTERCHANGE_SET_1.equals(str)) { + return new InterchangeSet(SET_1); + } else if (MODCA_PRESENTATION_INTERCHANGE_SET_2.equals(str)) { + return new InterchangeSet(SET_2); + } else if (MODCA_RESOURCE_INTERCHANGE_SET.equals(str)) { + return new InterchangeSet(RESOURCE_SET); + } else { + throw new IllegalArgumentException("Invalid MO:DCA interchange set :" + str); + } + } + /** + * Main constructor + * + * @param value the interchange set value + */ + public InterchangeSet(int value) { + this.value = value; + } + + /** + * @return true if complies with MOD:CA interchange set 1 + */ + protected boolean is1() { + return value == SET_1; + } + + /** + * @return true if complies with MOD:CA interchange set 2 + */ + public boolean is2() { + return value == SET_2; + } + + /** + * @return true if complies with MOD:CA resource set + */ + public boolean isResource() { + return value == RESOURCE_SET; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return NAMES[value]; + } + + /** + * @return true if MOD:CA interchange set 2 (resource groups) is supported + */ + public boolean supportsLevel2() { + return is2() || isResource(); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java b/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java index f67ee8268..f72ee4e23 100644 --- a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java +++ b/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java @@ -43,7 +43,7 @@ public class InvokeMediumMap extends AbstractNamedAFPObject { /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[17]; diff --git a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java b/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java index e83f04b78..d4b868bcb 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java +++ b/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java @@ -63,7 +63,7 @@ public class MapCodedFont extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException an I/O exception of some sort has occurred */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write(0x5A); diff --git a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java index 01db7b9d8..3c9794e7d 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java +++ b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.OutputStream; //import org.apache.fop.render.afp.ResourceLevel; +import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.ResourceInfo; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; @@ -41,44 +42,31 @@ public class MapDataResource extends AbstractStructuredAFPObject { /** * Main constructor - * @param includeObj a map data resource for a given structured AFP object + * @param dataObjectAccessor a data object accessor */ - public MapDataResource(IncludeObject includeObj) { - AbstractStructuredAFPObject dataObject = includeObj.getDataObject(); -// ResourceObject resObj = includeObj.getResource(); - String fqName = dataObject.getFullyQualifiedName(); - ResourceInfo resourceInfo = includeObj.getResourceInfo(); - if (fqName != null) { - if (resourceInfo.isExternal()) { - String dest = resourceInfo.getExternalResourceGroupDest(); + public MapDataResource(DataObjectAccessor dataObjectAccessor) { + AbstractNamedAFPObject namedDataObject = dataObjectAccessor.getDataObject(); + DataObjectInfo dataObjectInfo = dataObjectAccessor.getDataObjectInfo(); + ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + if (resourceInfo.isExternal()) { + String dest = resourceInfo.getExternalResourceGroupDest(); + if (dest != null) { super.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, - FullyQualifiedNameTriplet.FORMAT_CHARSTR, dest); - } else { -// super.setFullyQualifiedName( -// FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, -// FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); - super.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, - FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); + FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, + FullyQualifiedNameTriplet.FORMAT_URL, dest); } + } else { + String fqName = namedDataObject.getFullyQualifiedName(); + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); } -// if (fqName != null) { -// super.setFullyQualifiedName( -// FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, -// FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); -// } - final boolean dataInContainer = true; - final boolean containerHasOEG = false; - final boolean dataInOCD = true; - StrucFlgs strucFlgs = new StrucFlgs( - dataInContainer, containerHasOEG, dataInOCD - ); - // -// super.setObjectClassification( -// ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, -// objectType, strucFlgs); + // Set object classification + Registry.ObjectType objectType = dataObjectInfo.getObjectType(); + super.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, + objectType); } /** 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 65f90aa2b..02237ca90 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java @@ -83,7 +83,7 @@ public class MapPageOverlay extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException if an I/O exception occurred */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { int oLayCount = getOverlays().size(); int recordlength = oLayCount * 18; diff --git a/src/java/org/apache/fop/render/afp/modca/NoOperation.java b/src/java/org/apache/fop/render/afp/modca/NoOperation.java index 0ba354195..2c6e7abcc 100644 --- a/src/java/org/apache/fop/render/afp/modca/NoOperation.java +++ b/src/java/org/apache/fop/render/afp/modca/NoOperation.java @@ -60,7 +60,7 @@ public class NoOperation extends AbstractAFPObject { * @param os The outputsteam stream * @throws java.io.IOException if an I/O exception occurs during processing */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] contentData = content.getBytes(AFPConstants.EBCIDIC_ENCODING); int contentLen = contentData.length; diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java index 7c940148b..95f7b0c45 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java @@ -47,7 +47,7 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { * @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) + public void write(OutputStream os) throws IOException { byte[] data = new byte[29]; diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java index 6ff3f03f8..7ef00dede 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java @@ -51,7 +51,7 @@ public class ObjectAreaPosition extends AbstractAFPObject { * @param os The stream to write to * @throws java.io.IOException in the event that an I/O exception of some sort has occurred. */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] len = BinaryUtils.convert(32, 2); byte[] xcoord = BinaryUtils.convert(x, 3); byte[] ycoord = BinaryUtils.convert(y, 3); diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java index b29a14719..ebc402954 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java @@ -25,7 +25,6 @@ import java.io.OutputStream; import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; -import org.apache.fop.render.afp.modca.triplets.StrucFlgs; import org.apache.fop.render.afp.tools.BinaryUtils; /** @@ -42,30 +41,18 @@ public class ObjectContainer extends AbstractNamedAFPObject implements DataObjec * the object data */ private byte[] objectData = null; + + /** + * the data object info + */ + private DataObjectInfo dataObjectInfo; /** * Main constructor * @param name the name of this object container - * @param dataObjectInfo the data object info */ - public ObjectContainer(String name, DataObjectInfo dataObjectInfo) { - super(name); - final boolean dataInContainer = true; - final boolean containerHasOEG = false; - final boolean dataInOCD = true; - StrucFlgs strucFlgs = new StrucFlgs( - dataInContainer, containerHasOEG, dataInOCD - ); - Registry registry = Registry.getInstance(); - Registry.ObjectType objectType = registry.getObjectType(dataObjectInfo); - if (objectType != null) { - super.setObjectClassification( - ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, - objectType, strucFlgs - ); - } else { - log.warn("no object type for " + dataObjectInfo.getUri()); - } + public ObjectContainer(String name) { + super(name); } /** @@ -83,6 +70,30 @@ public class ObjectContainer extends AbstractNamedAFPObject implements DataObjec return this.dataObj; } + /** + * {@inheritDoc} + */ + public DataObjectInfo getDataObjectInfo() { + return this.dataObjectInfo; + } + + /** + * {@inheritDoc} + */ + public void setDataObjectInfo(DataObjectInfo dataObjectInfo) { + this.dataObjectInfo = dataObjectInfo; + + Registry registry = Registry.getInstance(); + Registry.ObjectType objectType = registry.getObjectType(dataObjectInfo); + if (objectType != null) { + super.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, + objectType); + } else { + log.warn("no object type for " + dataObjectInfo.getUri()); + } + } + /** * {@inheritDoc} */ @@ -91,7 +102,7 @@ public class ObjectContainer extends AbstractNamedAFPObject implements DataObjec // create object data from data object ByteArrayOutputStream bos = new ByteArrayOutputStream(); - dataObj.writeDataStream(bos); + dataObj.write(bos); this.objectData = bos.toByteArray(); // Set the total record length @@ -127,7 +138,7 @@ public class ObjectContainer extends AbstractNamedAFPObject implements DataObjec // write out object data in chunks of object container data for (int i = 0; i <= objectData.length; i += ObjectContainerData.MAX_DATA_LEN) { ObjectContainerData objectContainerData = new ObjectContainerData(objectData, i); - objectContainerData.writeDataStream(os); + objectContainerData.write(os); } } diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java index b2108d0d7..b673dec46 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java @@ -153,15 +153,15 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject { protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); - objectAreaDescriptor.writeDataStream(os); - objectAreaPosition.writeDataStream(os); + objectAreaDescriptor.write(os); + objectAreaPosition.write(os); if (imageDataDescriptor != null) { - imageDataDescriptor.writeDataStream(os); + imageDataDescriptor.write(os); } if (graphicsDataDescriptor != null) { - graphicsDataDescriptor.writeDataStream(os); + graphicsDataDescriptor.write(os); } } diff --git a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java index 1cdec7616..e38c576d4 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java @@ -47,7 +47,7 @@ public class PageDescriptor extends AbstractDescriptor { * @param os The stream to write to * @throws java.io.IOException in the event that an I/O Exception occurred */ - public void writeDataStream(OutputStream os) + public void write(OutputStream os) throws IOException { log.debug("width=" + width); diff --git a/src/java/org/apache/fop/render/afp/modca/PageGroup.java b/src/java/org/apache/fop/render/afp/modca/PageGroup.java index 39d7920e6..8131eb7b0 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/PageGroup.java @@ -31,8 +31,6 @@ import java.util.List; * entity. Page groups are often processed in stand-alone fashion; that is, they * are indexed, retrieved, and presented outside the context of the containing * document. - * - * @author Pete Townsend */ public class PageGroup extends AbstractResourceEnvironmentGroupContainer { @@ -140,4 +138,11 @@ public class PageGroup extends AbstractResourceEnvironmentGroupContainer { } os.write(data); } + + /** + * {@inheritDoc} + */ + public String toString() { + return this.getName(); + } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java index 9a8646ba0..1d9dc6985 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PageObject.java @@ -22,6 +22,8 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.tools.StringUtils; + /** * Pages contain the data objects that comprise a presentation document. Each * page has a set of data objects associated with it. Each page within a @@ -42,7 +44,17 @@ import java.io.OutputStream; * in page state. * */ -public class PageObject extends AbstractPageObject { +public class PageObject extends AbstractResourceGroupContainer { + + /** + * The page segment count + */ + private int pageSegmentCount = 0; + + /** + * The current page segment + */ + private PageSegment currentPageSegment = null; /** * Construct a new page object for the specified name argument, the page @@ -82,6 +94,135 @@ public class PageObject extends AbstractPageObject { addObject(new IncludePageOverlay(name, x, y, orientation)); } + /** + * @return a new page segment object + */ + private PageSegment createPageSegment() { + String name = PAGE_SEGMENT_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++pageSegmentCount), '0', 5); + PageSegment pageSegment = new PageSegment(name); + return pageSegment; + } + + /** + * @return the current page segment + */ + private PageSegment getCurrentPageSegment() { + if (currentPageSegment == null) { + this.currentPageSegment = createPageSegment(); + super.addObject(currentPageSegment); + } + return this.currentPageSegment; + } + + private static final String PAGE_SEGMENT_NAME_PREFIX = "PSG"; + + /** + * Starts a new page segment and makes it current. + */ + public void startPageSegment() { + getCurrentPageSegment(); + } + + /** + * Ends the current page segment. + */ + public void endPageSegment() { + this.currentPageSegment = null; + } + + /** + * {@inheritDoc} + */ + protected void addObject(AbstractAFPObject obj) { + if (currentPageSegment != null) { + getCurrentPageSegment().addObject(obj); + } else { + super.addObject(obj); + } + } + + /** + * This method will create shading on the page using the specified + * coordinates (the shading contrast is controlled via the red, green blue + * parameters, by converting this to grayscale). + * + * @param x + * the x coordinate of the shading + * @param y + * the y coordinate of the shading + * @param w + * the width of the shaded area + * @param h + * the height of the shaded area + * @param red + * the red value + * @param green + * the green value + * @param blue + * the blue value + */ + public void createShading(int x, int y, int w, int h, int red, int green, int blue) { + int xCoord = 0; + int yCoord = 0; + int areaWidth = 0; + int areaHeight = 0; + switch (rotation) { + case 90: + xCoord = areaWidth - y - h; + yCoord = x; + areaWidth = h; + areaHeight = w; + break; + case 180: + xCoord = areaWidth - x - w; + yCoord = areaHeight - y - h; + areaWidth = w; + areaHeight = h; + break; + case 270: + xCoord = y; + yCoord = areaHeight - x - w; + areaWidth = h; + areaHeight = w; + break; + default: + xCoord = x; + yCoord = y; + areaWidth = w; + areaHeight = h; + break; + } + + // Convert the color to grey scale + float shade = (float) ((red * 0.3) + (green * 0.59) + (blue * 0.11)); + + int grayscale = Math.round((shade / 255) * 16); + + String imageName = "IMG" + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), + '0', 5); + + IMImageObject imImageObject = new IMImageObject(imageName); + ImageOutputControl imageOutputControl = new ImageOutputControl(0, 0); + ImageInputDescriptor imageInputDescriptor = new ImageInputDescriptor(); + ImageCellPosition imageCellPosition = new ImageCellPosition(xCoord, yCoord); + imageCellPosition.setXFillSize(areaWidth); + imageCellPosition.setYFillSize(areaHeight); + imageCellPosition.setXSize(64); + imageCellPosition.setYSize(8); + + //defining this as a resource + ImageRasterData imageRasterData = new ImageRasterData( + ImageRasterPattern.getRasterData(grayscale)); + + imImageObject.setImageOutputControl(imageOutputControl); + imImageObject.setImageInputDescriptor(imageInputDescriptor); + imImageObject.setImageCellPosition(imageCellPosition); + imImageObject.setImageRasterData(imageRasterData); + addObject(imImageObject); + } + /** * {@inheritDoc} */ @@ -121,4 +262,11 @@ public class PageObject extends AbstractPageObject { } os.write(data); } + + /** + * {@inheritDoc} + */ + public String toString() { + return this.getName(); + } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageSegment.java b/src/java/org/apache/fop/render/afp/modca/PageSegment.java index 1ff4b8e5f..92d3c4470 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/PageSegment.java @@ -105,5 +105,12 @@ public class PageSegment extends AbstractNamedAFPObject { data[9 + i] = nameBytes[i]; } os.write(data); - } + } + + /** + * {@inheritDoc} + */ + public String toString() { + return this.name; + } } diff --git a/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java b/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java index 33e6407ee..688b9a28f 100644 --- a/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java @@ -56,10 +56,6 @@ public class PreprocessPresentationObject extends AbstractStructuredAFPObject { prePresObj.getFullyQualifiedName()); } else { this.objType = TYPE_OTHER; -// Registry registry = Registry.getInstance(); -// Registry.Entry entry = registry.getEntry(compontentId); -// entry. -// setObjectClassification(objectClass, componentId) } } diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java index ec93ebebd..b6b367ab5 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java @@ -109,7 +109,8 @@ public class PresentationTextData extends AbstractAFPObject { * The control sequence indicator. */ public PresentationTextData(boolean controlInd) { - baos.write(new byte[] { 0x5A, // Structured field identifier + final byte[] data = { + 0x5A, // Structured field identifier 0x00, // Record length byte 1 0x00, // Record length byte 2 (byte) 0xD3, // PresentationTextData identifier byte 1 @@ -118,7 +119,8 @@ public class PresentationTextData extends AbstractAFPObject { 0x00, // Flag 0x00, // Reserved 0x00, // Reserved - }, 0, 9); + }; + baos.write(data, 0, 9); if (controlInd) { baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2); @@ -481,9 +483,7 @@ public class PresentationTextData extends AbstractAFPObject { * @param afpdata * The output stream to which data should be written. */ - private void setVariableSpaceCharacterIncrement(int incr, - ByteArrayOutputStream afpdata) { - + private void setVariableSpaceCharacterIncrement(int incr, ByteArrayOutputStream afpdata) { byte[] b = BinaryUtils.convert(incr, 2); afpdata.write(new byte[] { @@ -517,7 +517,7 @@ public class PresentationTextData extends AbstractAFPObject { /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = baos.toByteArray(); byte[] size = BinaryUtils.convert(data.length - 1, 2); data[1] = size[0]; diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java index 3858f4169..10af1536e 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java @@ -65,7 +65,7 @@ public class PresentationTextDescriptor extends AbstractDescriptor { * @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) + public void write(OutputStream os) throws IOException { byte[] data = new byte[23]; diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java index 5df9fdb4c..3dda2006a 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java @@ -47,9 +47,15 @@ public class PresentationTextObject extends AbstractNamedAFPObject { */ private static final String DEFAULT_NAME = "PTO00001"; - private PresentationTextData currentPresentationTextData; + /** + * The current presentation text data + */ + private PresentationTextData currentPresentationTextData = null; - private List presentationTextData; + /** + * The presentation text data list + */ + private List/**/ presentationTextDataList = null; /** * Default constructor for the PresentationTextObject @@ -183,22 +189,22 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * Helper method to mark the start of the presentation text data */ private void startPresentationTextData() { - if (presentationTextData == null) { - presentationTextData = new java.util.ArrayList(); + if (presentationTextDataList == null) { + presentationTextDataList = new java.util.ArrayList/**/(); } - if (presentationTextData.size() == 0) { + if (presentationTextDataList.size() == 0) { currentPresentationTextData = new PresentationTextData(true); } else { currentPresentationTextData = new PresentationTextData(); } - presentationTextData.add(currentPresentationTextData); + presentationTextDataList.add(currentPresentationTextData); } /** * Helper method to mark the end of the presentation text data */ private void endPresentationTextData() { - currentPresentationTextData = null; + this.currentPresentationTextData = null; } /** @@ -206,9 +212,9 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @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 { + public void write(OutputStream os) throws IOException { writeStart(os); - writeObjects(presentationTextData, os); + writeObjects(this.presentationTextDataList, os); writeEnd(os); } @@ -278,4 +284,14 @@ public class PresentationTextObject extends AbstractNamedAFPObject { endControlSequence(); } } + + /** + * {@inheritDoc} + */ + public String toString() { + if (presentationTextDataList != null) { + return presentationTextDataList.toString(); + } + return null; + } } diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java index 09d4fabb6..aff5cc6eb 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java @@ -36,7 +36,7 @@ public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup { /** * The maps data resources contained in this resource environment group */ - private List mapDataResources = null; + private List/**/ mapDataResources = null; /** * The maps page overlays contained in this resource environment group @@ -46,7 +46,7 @@ public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup { /** * The pre-process presentation objects contained in this resource environment group */ - private List preProcessPresentationObjects = null; + private List/**/ preProcessPresentationObjects = null; /** * The resource environment group state @@ -60,9 +60,9 @@ public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup { this(DEFAULT_NAME); } - private List getMapDataResources() { + private List/**/ getMapDataResources() { if (mapDataResources == null) { - this.mapDataResources = new java.util.ArrayList(); + this.mapDataResources = new java.util.ArrayList/**/(); } return this.mapDataResources; } @@ -74,9 +74,10 @@ public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup { return this.mapPageOverlays; } - private List getPreprocessPresentationObjects() { + private List/**/ getPreprocessPresentationObjects() { if (preProcessPresentationObjects == null) { - this.preProcessPresentationObjects = new java.util.ArrayList(); + this.preProcessPresentationObjects + = new java.util.ArrayList/**/(); } return this.preProcessPresentationObjects; } diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java index 18026a6b3..f8c9d5fc0 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java @@ -28,8 +28,6 @@ import java.util.Map; import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.ImageObjectInfo; import org.apache.fop.render.afp.ResourceInfo; -import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; -import org.apache.fop.render.afp.tools.StringUtils; /** * A Resource Group contains a set of overlays. @@ -44,7 +42,7 @@ public final class ResourceGroup extends AbstractNamedAFPObject { /** * Mapping of resource uri to data resource object (image/graphic) */ - private Map/**/ resourceMap = null; + private Map/**/ resourceMap = null; /** * This resource groups container @@ -70,20 +68,6 @@ public final class ResourceGroup extends AbstractNamedAFPObject { this.container = container; } - private static final String RESOURCE_NAME_PREFIX = "RES"; - - /** - * Helper method to create a new resource object in the current container and to return - * the object. - * @return a newly created resource object - */ - private ResourceObject createResourceObject() { - String name = RESOURCE_NAME_PREFIX - + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); - ResourceObject resource = new ResourceObject(name); - return resource; - } - private AbstractResourceGroupContainer getContainer() { return this.container; } @@ -111,25 +95,57 @@ public final class ResourceGroup extends AbstractNamedAFPObject { dataObjectInfo.getRotation()); String resourceName = resourceInfo.getName(); - ObjectContainer objectContainer = new ObjectContainer(resourceName, dataObjectInfo); + ObjectContainer objectContainer = new ObjectContainer(resourceName); objectContainer.setDataObject(dataObj); + objectContainer.setDataObjectInfo(dataObjectInfo); - // When externally located, Wrap data object in a resource object + // When externally located, wrap the object container in a resource object if (resourceInfo.isExternal()) { - ResourceObject resourceObj = createResourceObject(); - resourceObj.setObjectContainer(objectContainer); - dataObjectAccessor = resourceObj; - } else { // no wrappers just container + ResourceObject resourceObject = new ResourceObject(resourceName); + resourceObject.setDataObject(objectContainer); + dataObjectAccessor = resourceObject; + } else { // Access data object through container dataObjectAccessor = objectContainer; } + dataObjectAccessor.setDataObjectInfo(dataObjectInfo); + + // Add to resource map getResourceMap().put(dataObjectInfo.getUri(), dataObjectAccessor); } + // Return include object AbstractNamedAFPObject dataObject = dataObjectAccessor.getDataObject(); String name = dataObject.getName(); - IncludeObject includeObj = new IncludeObject(name, dataObjectAccessor, resourceInfo); + IncludeObject includeObj = new IncludeObject(name, dataObjectAccessor); return includeObj; } + /** + * Checks if a named object is of a valid type to be added to a resource group + * @param namedObj a named object + * @return true if the named object is of a valid type to be added to a resource group + */ + private boolean isValidObjectType(AbstractNamedAFPObject namedObj) { + return (namedObj instanceof Overlay + || namedObj instanceof PageSegment + // || namedObj instanceof FormMap + // || namedObj instanceof BarcodeObject + || namedObj instanceof GraphicsObject + || namedObj instanceof ImageObject + || namedObj instanceof ObjectContainer + || namedObj instanceof Document); + } + /** + * Adds a named object to this resource group + * @param namedObj a named AFP object + */ + protected void addObject(AbstractNamedAFPObject namedObj) { + if (isValidObjectType(namedObj)) { + getResourceMap().put(namedObj.getName(), namedObj); + } else { + throw new IllegalArgumentException("invalid object type " + namedObj); + } + } + /** * @return the number of resources contained in this resource group */ @@ -157,7 +173,7 @@ public final class ResourceGroup extends AbstractNamedAFPObject { */ public Map/**/ getResourceMap() { if (resourceMap == null) { - resourceMap = new java.util.HashMap/**/(); + resourceMap = new java.util.HashMap/**/(); } return resourceMap; } @@ -170,8 +186,8 @@ public final class ResourceGroup extends AbstractNamedAFPObject { Collection includes = resourceMap.values(); Iterator it = includes.iterator(); while (it.hasNext()) { - DataObjectAccessor dataObjectAccessor = (DataObjectAccessor)it.next(); - dataObjectAccessor.writeDataStream(os); + Writable dataObject = (Writable)it.next(); + dataObject.write(os); } } } diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java index 57d7f0105..58c61fc58 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java @@ -22,6 +22,8 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; import org.apache.fop.render.afp.modca.triplets.Triplet; import org.apache.fop.render.afp.tools.BinaryUtils; @@ -34,8 +36,13 @@ public class ResourceObject extends AbstractPreparedAFPObject implements DataObj /** * the object container of this resource object */ - private ObjectContainer objectContainer; + private AbstractNamedAFPObject namedObject; + /** + * the data object info + */ + private DataObjectInfo dataObjectInfo; + /** * Default constructor * @@ -44,49 +51,63 @@ public class ResourceObject extends AbstractPreparedAFPObject implements DataObj public ResourceObject(String name) { super(name); } - + /** * Sets the data object referenced by this resource object - * @param objectContainer the object container + * @param namedObject the named data object */ - public void setObjectContainer(ObjectContainer objectContainer) { - this.objectContainer = objectContainer; - setResourceObjectType(objectContainer); + public void setDataObject(AbstractNamedAFPObject namedObject) { + this.namedObject = namedObject; } - + /** * {@inheritDoc} */ public AbstractNamedAFPObject getDataObject() { - if (objectContainer != null) { - return objectContainer.getDataObject(); - } - return null; + return namedObject; + } + + /** + * {@inheritDoc} + */ + public DataObjectInfo getDataObjectInfo() { + return this.dataObjectInfo; } /** - * Sets the resource object type - * @param resourceObj the resource object + * {@inheritDoc} */ - public void setResourceObjectType(AbstractNamedAFPObject resourceObj) { + public void setDataObjectInfo(DataObjectInfo dataObjectInfo) { + this.dataObjectInfo = dataObjectInfo; + byte type; - if (resourceObj instanceof ObjectContainer) { + if (namedObject instanceof ObjectContainer) { type = ResourceObjectTypeTriplet.OBJECT_CONTAINER; - } else if (resourceObj instanceof ImageObject) { + +// ObjectContainer objectContainer = (ObjectContainer)namedObject; +// DataObjectInfo dataObjectInfo = objectContainer.getDataObjectInfo(); + Registry.ObjectType objectType = dataObjectInfo.getObjectType(); + super.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT, + objectType); + + } else if (namedObject instanceof ImageObject) { type = ResourceObjectTypeTriplet.IMAGE_OBJECT; - } else if (resourceObj instanceof GraphicsObject) { + } else if (namedObject instanceof GraphicsObject) { type = ResourceObjectTypeTriplet.GRAPHICS_OBJECT; - } else if (resourceObj instanceof Document) { + } else if (namedObject instanceof Document) { type = ResourceObjectTypeTriplet.DOCUMENT_OBJECT; - } else if (resourceObj instanceof PageSegment) { + } else if (namedObject instanceof PageSegment) { type = ResourceObjectTypeTriplet.PAGE_SEGMENT_OBJECT; - } else if (resourceObj instanceof Overlay) { + } else if (namedObject instanceof Overlay) { type = ResourceObjectTypeTriplet.OVERLAY_OBJECT; } else { throw new UnsupportedOperationException( - "Unsupported resource object type " + resourceObj); + "Unsupported resource object type " + namedObject); } + getTriplets().add(new ResourceObjectTypeTriplet(type)); + } /** @@ -126,8 +147,8 @@ public class ResourceObject extends AbstractPreparedAFPObject implements DataObj */ protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); // write triplets - if (objectContainer != null) { - objectContainer.writeDataStream(os); + if (namedObject != null) { + namedObject.write(os); } } @@ -194,7 +215,7 @@ public class ResourceObject extends AbstractPreparedAFPObject implements DataObj super(RESOURCE_OBJECT, new byte[] { type, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Constant Data } ); } diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java b/src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java index 937f2019a..844434aff 100644 --- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java +++ b/src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java @@ -99,7 +99,7 @@ public class TagLogicalElement extends AbstractAFPObject { * @param os The outputsteam stream * @throws java.io.IOException if an I/O exception occurred */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { byte[] data = new byte[17 + tleName.length() + tleValue.length()]; diff --git a/src/java/org/apache/fop/render/afp/modca/Writable.java b/src/java/org/apache/fop/render/afp/modca/Writable.java new file mode 100644 index 000000000..beaa6e21c --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/Writable.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; + +/** + * Implementing object is able to write to an AFPDataStream + */ +public interface Writable { + /** + * DataStream objects must implement the write() + * method to write its data to the given OutputStream + * @param outputStream The outputsteam stream + * @throws java.io.IOException an I/O exception of some sort has occurred. + */ + void write(OutputStream outputStream) throws IOException; +} diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java index 21dbaa99f..2be37b818 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java @@ -17,92 +17,163 @@ /* $Id: $ */ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.triplets; import java.io.UnsupportedEncodingException; import org.apache.fop.render.afp.modca.AFPConstants; - /** * A Fully Qualified Name triplet enable the identification and referencing of * objects using Gloabl Identifiers (GIDs). */ public class FullyQualifiedNameTriplet extends Triplet { + // Specifies how the GID will be used + + /** This GID replaces the first parameter in the structured field that contains a GID name. */ public static final byte TYPE_REPLACE_FIRST_GID_NAME = 0x01; + + /** This triplet contains the name of a font family. */ public static final byte TYPE_FONT_FAMILY_NAME = 0x07; + + /** This triplet contains the name of a font typeface. */ public static final byte TYPE_FONT_TYPEFACE_NAME = 0x08; + + /** This triplet specifies a reference to the MO:DCA resource hierarchy. */ public static final byte TYPE_MODCA_RESOURCE_HIERARCHY_REF = 0x09; + + /** The triplet contains a GID reference to a begin resource group structured field. */ public static final byte TYPE_BEGIN_RESOURCE_GROUP_REF = 0x0A; + + /** The triplet contains a GID reference to a document attribute. */ public static final byte TYPE_ATTRIBUTE_GID = 0x0B; + + /** The triplet contains the GID of a process element. */ public static final byte TYPE_PROCESS_ELEMENT_GID = 0x0C; + + /** The triplet contains a reference to a begin page group structured field. */ public static final byte TYPE_BEGIN_PAGE_GROUP_REF = 0x0D; + + /** The triplet contains a reference to a media type. */ public static final byte TYPE_MEDIA_TYPE_REF = 0x11; + + /** The triplet contains a reference to a color management resource. */ public static final byte TYPE_COLOR_MANAGEMENT_RESOURCE_REF = 0x41; + + /** The triplet contains a reference to a data-object font file that defines a base font. */ public static final byte TYPE_DATA_OBJECT_FONT_BASE_FONT_ID = 0x6E; + + /** The triplet contains a reference to a data-object font file that defines a linked font. */ public static final byte TYPE_DATA_OBJECT_FONT_LINKED_FONT_ID = 0x7E; + + /** The triplet contains a reference to a begin document structured field. */ public static final byte TYPE_BEGIN_DOCUMENT_REF = (byte)0x83; + + /** + * The triplet contains a reference to a begin structured field associated with a resource; + * or contains a GID reference to a coded font. + */ public static final byte TYPE_BEGIN_RESOURCE_OBJECT_REF = (byte)0x84; - public static final byte TYPE_CODE_PAGE_NAME_REF = (byte)0x85; + + /** + * The triplet contains a GID reference to a code page that specifies the code points and + * graphic character names for a coded font. + */ + public static final byte TYPE_CODE_PAGE_NAME_REF = (byte)0x85; + + /** + * The triplet contains a GID name reference to a font character set that specifies + * a set of graphics characters. + */ public static final byte TYPE_FONT_CHARSET_NAME_REF = (byte)0x86; + + /** The triplet contains a GID reference to a begin page structured field. */ public static final byte TYPE_BEGIN_PAGE_REF = (byte)0x87; + + /** The triplet contains a GID reference to a begin medium map structured field. */ public static final byte TYPE_BEGIN_MEDIUM_MAP_REF = (byte)0x8D; - public static final byte TYPE_CODED_FONT_NAME_REF = (byte)0x8E; - public static final byte TYPE_BEGIN_DOCUMENT_INDEX_REF = (byte)0x98; + + /** + * The triplet contains a GID reference to a coded font, which identifies a specific + * code page and a specific font character set. + */ + public static final byte TYPE_CODED_FONT_NAME_REF = (byte)0x8E; + + /** The triplet contains a GID reference to a begin document index structured field. */ + public static final byte TYPE_BEGIN_DOCUMENT_INDEX_REF = (byte)0x98; + + /** The triplet contains a GID reference to a begin overlay structured field. */ public static final byte TYPE_BEGIN_OVERLAY_REF = (byte)0xB0; + + /** The triplet contains a GID reference to a resource used by a data object. */ public static final byte TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF = (byte)0xBE; + + /** The triplet contains a GID reference to an index element structured field. */ public static final byte TYPE_INDEX_ELEMENT_GID = (byte)0xCA; + + /** + * The triplet contains a reference to other object data which may or may + * not be defined by an IBM presentation architecture. + */ public static final byte TYPE_OTHER_OBJECT_DATA_REF = (byte)0xCE; + + /** + * The triplet contains a reference to a resource used by a data object. + * The GID may be a filename or any other identifier associated with the + * resource and is used to located the resource object in the resource hierarchy. + * The data object that uses the resource may or may not be defined by an + * IBM presentation architecture. + */ public static final byte TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF = (byte)0xDE; + // GID Format + + /** The GID is a character encoded name. */ public static final byte FORMAT_CHARSTR = (byte)0x00; + + /** the GID is a ASN.1 object identifier (OID). */ public static final byte FORMAT_OID = (byte)0x10; + + /** the GID is a uniform resource locator (URL). */ public static final byte FORMAT_URL = (byte)0x20; + - private byte[] nameBytes; + private String fqName; /** * @return the actual fully qualified name of this triplet */ - public byte[] getFullyQualifiedName() { - return nameBytes; + public String getFullyQualifiedName() { + return fqName; } /** * Main constructor + * * @param type the fully qualified name type * @param format the fully qualified name format - * @param name the fully qualified name + * @param fqName the fully qualified name */ - public FullyQualifiedNameTriplet(byte type, byte format, byte[] name) { + public FullyQualifiedNameTriplet(byte type, byte format, String fqName) { super(FULLY_QUALIFIED_NAME); - this.nameBytes = name; - byte[] data = new byte[2 + name.length]; + this.fqName = fqName; + + byte[] fqNameBytes; + try { + fqNameBytes = fqName.getBytes(AFPConstants.ASCII_ENCODING); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException( + AFPConstants.ASCII_ENCODING + " encoding failed"); + } + + byte[] data = new byte[2 + fqNameBytes.length]; data[0] = type; data[1] = format; // FQName - System.arraycopy(name, 0, data, 2, name.length); + System.arraycopy(fqNameBytes, 0, data, 2, fqNameBytes.length); super.setData(data); } @@ -111,10 +182,6 @@ public class FullyQualifiedNameTriplet extends Triplet { * {@inheritDoc} */ public String toString() { - try { - return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException e) { - } - return null; + return this.fqName; } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/StrucFlgs.java b/src/java/org/apache/fop/render/afp/modca/triplets/StrucFlgs.java index 87601c435..1478500a8 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/StrucFlgs.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/StrucFlgs.java @@ -35,6 +35,8 @@ public class StrucFlgs { private static final int OBJECT_CONTAINER_DATA_NOT_CARRIED_IN_OBJECT_DATA = 16; private static final int OBJECT_CONTAINER_DATA_OBJECT_DATA_CONTAINMENT_UNKNOWN = 32; private static final int OBJECT_CONTAINER_DATA_CARRIES_OBJECT_DATA = 48; + + private static StrucFlgs DEFAULT_STRUC_FLGS = null; private byte value = 0; @@ -77,4 +79,22 @@ public class StrucFlgs { public byte getValue() { return this.value; } + + /** + * Returns the default strucflg setting + * (data in container, container without OEG, data in OCD) + * + * @return the default strucflg settings + */ + public static StrucFlgs getDefault() { + synchronized (StrucFlgs.class) { + if (DEFAULT_STRUC_FLGS == null) { + final boolean dataInContainer = true; + final boolean containerHasOEG = false; + final boolean dataInOCD = true; + DEFAULT_STRUC_FLGS = new StrucFlgs(dataInContainer, containerHasOEG, dataInOCD); + } + } + return DEFAULT_STRUC_FLGS; + } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java index 9467c522a..550066af1 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java @@ -138,7 +138,7 @@ public class Triplet extends AbstractAFPObject { /** * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { + public void write(OutputStream os) throws IOException { os.write((byte)data.length + 2); os.write(id); os.write(data); -- cgit v1.2.3 From e217d5d5a7a7719ec9e5866911c65b54d3cbf7b2 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 15 May 2008 09:18:34 +0000 Subject: Merged revisions 656546 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r656546 | adelmelle | 2008-05-15 09:33:19 +0100 (Thu, 15 May 2008) | 1 line Tweak: make sure the fo:flow's id is bound to the FObj ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@656564 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/pagination/Flow.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src/java') 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 d3fedf5ec86b2e16de41a9c2dd7420287f3e8911 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 20 May 2008 15:46:22 +0000 Subject: Merged revisions 657465,657521,657921 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r657465 | adelmelle | 2008-05-17 22:18:19 +0100 (Sat, 17 May 2008) | 1 line Corrected testcase: since the fo:flow's ID is correctly processed... ........ r657521 | maxberger | 2008-05-18 10:39:03 +0100 (Sun, 18 May 2008) | 1 line Updated as per suggestions in bug 45019 ........ r657921 | spepping | 2008-05-19 20:02:18 +0100 (Mon, 19 May 2008) | 6 lines 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/branches/Temp_AFPGOCAResources@658286 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/events/EventFormatter.xml | 1 + .../fop/fo/flow/table/TableEventProducer.java | 11 +++++ .../org/apache/fop/fo/flow/table/TableFObj.java | 9 ++-- .../page-number-citation_background-color.xml | 2 +- xmlgraphics-fop-pom-template.pom | 51 +++++++++++----------- 5 files changed, 45 insertions(+), 29 deletions(-) (limited to 'src/java') 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); } 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 c3f845b79..6db100dd5 100644 --- a/test/layoutengine/standard-testcases/page-number-citation_background-color.xml +++ b/test/layoutengine/standard-testcases/page-number-citation_background-color.xml @@ -30,7 +30,7 @@ - + To emphasize a page number citation highlight it. diff --git a/xmlgraphics-fop-pom-template.pom b/xmlgraphics-fop-pom-template.pom index abebcc8fc..1898c4e9d 100644 --- a/xmlgraphics-fop-pom-template.pom +++ b/xmlgraphics-fop-pom-template.pom @@ -70,48 +70,48 @@ http://maven.apache.org/maven-v4_0_0.xsd"> org.apache.xmlgraphics xmlgraphics-commons - 1.2 + 1.3 - batik + org.apache.xmlgraphics batik-svg-dom - 1.6-1 + 1.7 - batik + org.apache.xmlgraphics batik-bridge - 1.6-1 + 1.7 - batik + org.apache.xmlgraphics batik-awt-util - 1.6-1 + 1.7 - batik + org.apache.xmlgraphics batik-gvt - 1.6-1 + 1.7 - batik + org.apache.xmlgraphics batik-transcoder - 1.6-1 + 1.7 - fop + org.apache.xmlgraphics fop - batik + org.apache.xmlgraphics batik-extension - 1.6-1 + 1.7 - batik + org.apache.xmlgraphics batik-ext - 1.6-1 + 1.7 @@ -122,23 +122,24 @@ http://maven.apache.org/maven-v4_0_0.xsd"> commons-io commons-io - 1.1 + 1.3.1 org.apache.avalon.framework avalon-framework-api 4.3.1 - - org.apache.avalon.framework - avalon-framework-impl - 4.3.1 - - + javax.servlet servlet-api - 2.3 + 2.2 + provided + + + xalan + xalan + 2.7.0 provided - + -- cgit v1.2.3 From df1aab82cfb90510c5108cb87e03623aa1c77be2 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 20 May 2008 16:02:09 +0000 Subject: Broke out data members from ResourceInfo and created ResourceLevel class Added MappingOptionTriplet and corresponding setMappingOption() triplet setter Correctly furnished (AFAICT) IncludeObject with ObjectClassificationTriplet MappingOptionTriplet MeasurementUnits and ObjectAreaSize FullyQualifiedNameTriplet now correctly encodes its name dependant upon its format Added resolution settings to MeasurementUnitsTriplet Added Overlay enclosure when fo:block has background color git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@658303 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/afp/AFPRenderer.java | 27 ++-- .../org/apache/fop/render/afp/DataObjectInfo.java | 38 ++--- .../org/apache/fop/render/afp/ImageObjectInfo.java | 1 + .../org/apache/fop/render/afp/ResourceInfo.java | 130 +++-------------- .../org/apache/fop/render/afp/ResourceLevel.java | 160 +++++++++++++++++++++ .../apache/fop/render/afp/modca/AFPConstants.java | 5 + .../apache/fop/render/afp/modca/AFPDataStream.java | 97 +++++++------ .../fop/render/afp/modca/AbstractPageObject.java | 2 +- .../AbstractResourceEnvironmentGroupContainer.java | 12 +- .../afp/modca/AbstractResourceGroupContainer.java | 6 +- .../afp/modca/AbstractStructuredAFPObject.java | 17 ++- .../fop/render/afp/modca/DataObjectAccessor.java | 5 + .../apache/fop/render/afp/modca/ImageSegment.java | 2 +- .../apache/fop/render/afp/modca/IncludeObject.java | 61 ++++---- .../fop/render/afp/modca/MapDataResource.java | 12 +- .../fop/render/afp/modca/MapPageOverlay.java | 4 +- .../fop/render/afp/modca/ObjectContainer.java | 14 ++ .../apache/fop/render/afp/modca/PageObject.java | 110 +++++++------- .../render/afp/modca/ResourceEnvironmentGroup.java | 16 +-- .../apache/fop/render/afp/modca/ResourceGroup.java | 35 +++-- .../fop/render/afp/modca/ResourceObject.java | 56 ++++---- .../modca/triplets/FullyQualifiedNameTriplet.java | 10 +- .../afp/modca/triplets/MappingOptionTriplet.java | 68 +++++++++ .../modca/triplets/MeasurementUnitsTriplet.java | 9 +- 24 files changed, 556 insertions(+), 341 deletions(-) create mode 100644 src/java/org/apache/fop/render/afp/ResourceLevel.java create mode 100644 src/java/org/apache/fop/render/afp/modca/triplets/MappingOptionTriplet.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 90f07cb8b..fbcd368fd 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -513,18 +513,20 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int res = getResolution(); final int rotation = 0; getAFPDataStream().startOverlay(x, y, w, h, res, res, rotation); +// Color col = back.getColor(); +// getAFPDataStream().createShading(x, y, w, h, col); } } - /** - * {@inheritDoc} - */ +// /** +// * {@inheritDoc} +// */ protected void renderBlock(Block block) { - // new block so start page segment - getAFPDataStream().startPageSegment(); +// // new block so start page segment +//// getAFPDataStream().startPageSegment(); super.renderBlock(block); getAFPDataStream().endOverlay(); - getAFPDataStream().endPageSegment(); +//// getAFPDataStream().endPageSegment(); } /** @@ -763,13 +765,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ public void fillRect(float x, float y, float width, float height) { - /* - * getAFPDataStream().createShading( pts2units(x), pts2units(y), - * pts2units(width), pts2units(height), currentColor); - */ - getAFPDataStream().createLine(pts2units(x), pts2units(y), - pts2units(x + width), pts2units(y), pts2units(height), + getAFPDataStream().createShading( + pts2units(x), pts2units(y), pts2units(width), pts2units(height), currentColor); +// getAFPDataStream().createLine(pts2units(x), pts2units(y), +// pts2units(x + width), pts2units(y), pts2units(height), +// currentColor); } /** @@ -921,7 +922,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int x = origin.x + posInt.x; int y = origin.y + posInt.y; - String name = (String) getPageSegments().get(uri); + String name = (String)getPageSegments().get(uri); if (name != null) { getAFPDataStream().createIncludePageSegment(name, mpts2units(x), mpts2units(y)); diff --git a/src/java/org/apache/fop/render/afp/DataObjectInfo.java b/src/java/org/apache/fop/render/afp/DataObjectInfo.java index e56e6338c..00044da96 100644 --- a/src/java/org/apache/fop/render/afp/DataObjectInfo.java +++ b/src/java/org/apache/fop/render/afp/DataObjectInfo.java @@ -56,6 +56,12 @@ public class DataObjectInfo { /** resource info */ private ResourceInfo resourceInfo = DEFAULT_RESOURCE_INFO; + /** + * Default constructor + */ + public DataObjectInfo() { + } + /** * Sets the data object uri * @param uri the data object uri @@ -111,12 +117,6 @@ public class DataObjectInfo { protected void setHeightRes(int heightRes) { this.heightRes = heightRes; } - - /** - * Default constructor - */ - public DataObjectInfo() { - } /** * @return the uri of this data object @@ -226,16 +226,19 @@ public class DataObjectInfo { } QName resourceLevelKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_LEVEL); if (foreignAttributes.containsKey(resourceLevelKey)) { - String level = (String)foreignAttributes.get(resourceLevelKey); - if (resourceInfo.setLevel(level)) { - if (resourceInfo.isExternal()) { + String level = (String)foreignAttributes.get(resourceLevelKey); + ResourceLevel resourceLevel = null; + try { + resourceLevel = ResourceLevel.valueOf(level); + resourceInfo.setLevel(resourceLevel); + if (resourceLevel.isExternal()) { QName resourceGroupFileKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_GROUP_FILE); String resourceExternalDest = (String)foreignAttributes.get(resourceGroupFileKey); if (resourceExternalDest == null) { String msg = RESOURCE_GROUP_FILE + " not specified"; - log.warn(msg); + log.error(msg); throw new UnsupportedOperationException(msg); } File resourceExternalGroupFile = new File(resourceExternalDest); @@ -245,25 +248,26 @@ public class DataObjectInfo { security.checkWrite(resourceExternalGroupFile.getPath()); } } catch (SecurityException ex) { - log.warn("unable to gain write access to external resource file: " + log.error("unable to gain write access to external resource file: " + resourceExternalDest); } - + try { boolean exists = resourceExternalGroupFile.exists(); if (exists) { log.warn("overwritting external resource file: " + resourceExternalDest); } - resourceInfo.setExternalResourceGroupFile(resourceExternalGroupFile); + resourceLevel.setExternalResourceGroupFile(resourceExternalGroupFile); } catch (SecurityException ex) { - log.warn("unable to gain read access to external resource file: " + log.error("unable to gain read access to external resource file: " + resourceExternalDest); } } - } else { - String msg = RESOURCE_LEVEL + " is null or not valid"; - log.warn(msg); + } catch (IllegalArgumentException e) { + // default to print-file resource level if invalid resource level provided + resourceLevel = new ResourceLevel(ResourceLevel.PRINT_FILE); + log.error(e.getMessage() + ", defaulting to '" + resourceLevel + "' level"); } } } diff --git a/src/java/org/apache/fop/render/afp/ImageObjectInfo.java b/src/java/org/apache/fop/render/afp/ImageObjectInfo.java index 16f9d1103..cf5e7f951 100644 --- a/src/java/org/apache/fop/render/afp/ImageObjectInfo.java +++ b/src/java/org/apache/fop/render/afp/ImageObjectInfo.java @@ -35,6 +35,7 @@ public class ImageObjectInfo extends DataObjectInfo { * Default constructor */ public ImageObjectInfo() { + super(); } /** diff --git a/src/java/org/apache/fop/render/afp/ResourceInfo.java b/src/java/org/apache/fop/render/afp/ResourceInfo.java index 86add31d2..3c95b2f65 100644 --- a/src/java/org/apache/fop/render/afp/ResourceInfo.java +++ b/src/java/org/apache/fop/render/afp/ResourceInfo.java @@ -19,124 +19,21 @@ package org.apache.fop.render.afp; -import java.io.File; - /** * The level at which a resource is to reside in the AFP output */ public class ResourceInfo { - private static final String LEVEL_EXTERNAL = "external"; - - private static final String LEVEL_PRINT_FILE = "print-file"; - - private static final String LEVEL_DOCUMENT = "document"; - - private static final String LEVEL_PAGE_GROUP = "page-group"; - - private static final String LEVEL_PAGE = "page"; - + /** * the reference name of this resource */ private String name = null; - + /** - * where the resource will reside in the AFP output + * the resource level (default to print-file) */ - private String level = LEVEL_PAGE; // default is page level + private ResourceLevel level = new ResourceLevel(ResourceLevel.PRINT_FILE); - /** - * the external resource group file - */ - private File externalResourceGroupFile = null; - - /** - * @return true if this is a page level resource group - */ - public boolean isPage() { - return level.equals(LEVEL_PAGE); - } - - /** - * @return true if this is a page group level resource group - */ - public boolean isPageGroup() { - return level.equals(LEVEL_PAGE_GROUP); - } - - /** - * @return true if this is a document level resource group - */ - public boolean isDocument() { - return level.equals(LEVEL_DOCUMENT); - } - - /** - * @return true if this is an external level resource group - */ - public boolean isExternal() { - return level.equals(LEVEL_EXTERNAL); - } - - /** - * @return true if this is a print-file level resource group - */ - public boolean isPrintFile() { - return level.equals(LEVEL_PRINT_FILE); - } - - private boolean isValid(String lvl) { - return lvl.equals(LEVEL_EXTERNAL) - || lvl.equals(LEVEL_PRINT_FILE) - || lvl.equals(LEVEL_DOCUMENT) - || lvl.equals(LEVEL_PAGE_GROUP) - || lvl.equals(LEVEL_PAGE); - } - - /** - * Sets the resource placement level within the AFP output - * @param lvl the resource level (page, page-group, document, print-file or external) - * @return true if the resource level was successfully set - */ - public boolean setLevel(String lvl) { - if (lvl != null && isValid(lvl)) { - this.level = lvl; - return true; - } - return false; - } - - /** - * @return the external resource group file of this resource - */ - public File getExternalResourceGroupFile() { - return this.externalResourceGroupFile; - } - - /** - * @return the destination file path of the external resource group file - */ - public String getExternalResourceGroupDest() { - if (externalResourceGroupFile != null) { - return externalResourceGroupFile.getAbsolutePath(); - } - return null; - } - - /** - * @return true if this resource has a defined external resource group file destination - */ - public boolean hasExternalResourceGroupFile() { - return getExternalResourceGroupFile() != null; - } - - /** - * Sets the external destination of the resource - * @param file the external resource group file - */ - public void setExternalResourceGroupFile(File file) { - this.externalResourceGroupFile = file; - } /** * Sets the resource reference name @@ -157,8 +54,21 @@ public class ResourceInfo { * {@inheritDoc} */ public String toString() { - return "ResourceInfo(name=" + name + ", level=" + level - + (isExternal() ? ", externalResourceGroupFile=" + externalResourceGroupFile : "") - + ")"; + return "ResourceInfo(" + (name != null ? "name=" + name : "" ) + ", level=" + level + ")"; + } + + /** + * @return the resource level + */ + public ResourceLevel getLevel() { + return this.level; + } + + /** + * Sets the resource level + * @param resourceLevel the resource level + */ + public void setLevel(ResourceLevel resourceLevel) { + this.level = resourceLevel; } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/ResourceLevel.java b/src/java/org/apache/fop/render/afp/ResourceLevel.java new file mode 100644 index 000000000..37a8e6dce --- /dev/null +++ b/src/java/org/apache/fop/render/afp/ResourceLevel.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.render.afp; + +import java.io.File; + +/** + * A resource level + */ +public class ResourceLevel { + /** page level **/ + public static final int PAGE = 0; + + /** page group level **/ + public static final int PAGE_GROUP = 1; + + /** document level **/ + public static final int DOCUMENT = 2; + + /** print file level **/ + public static final int PRINT_FILE = 3; + + /** external level **/ + public static final int EXTERNAL = 4; + + private static final String NAME_PAGE = "page"; + private static final String NAME_PAGE_GROUP = "page-group"; + private static final String NAME_DOCUMENT = "document"; + private static final String NAME_PRINT_FILE = "print-file"; + private static final String NAME_EXTERNAL = "external"; + + private static final String[] NAMES + = new String[] {NAME_PAGE, NAME_PAGE_GROUP, NAME_DOCUMENT, NAME_PRINT_FILE, NAME_EXTERNAL}; + + /** + * where the resource will reside in the AFP output + */ + private int level = PRINT_FILE; // default is print-file level + + /** + * the external resource group file + */ + private File externalResourceGroupFile = null; + + /** + * Sets the resource placement level within the AFP output + * @param lvl the resource level (page, page-group, document, print-file or external) + * @return true if the resource level was successfully set + */ + public static ResourceLevel valueOf(String lvl) { + ResourceLevel level = null; + for (int i = 0; i < NAMES.length; i++) { + if (NAMES[i].equals(lvl)) { + level = new ResourceLevel(i); + break; + } + } + if (lvl == null) { + throw new IllegalArgumentException("Unknown resource level '" + lvl + "'"); + } + return level; + } + + /** + * Main constructor + * @param level the resource level + */ + public ResourceLevel(int level) { + this.level = level; + } + + /** + * @return true if this is a page level resource group + */ + public boolean isPage() { + return level == PAGE; + } + + /** + * @return true if this is a page group level resource group + */ + public boolean isPageGroup() { + return level == PAGE_GROUP; + } + + /** + * @return true if this is a document level resource group + */ + public boolean isDocument() { + return level == DOCUMENT; + } + + /** + * @return true if this is an external level resource group + */ + public boolean isExternal() { + return level == EXTERNAL; + } + + /** + * @return true if this is a print-file level resource group + */ + public boolean isPrintFile() { + return level == PRINT_FILE; + } + + /** + * @return the external resource group file of this resource + */ + public File getExternalResourceGroupFile() { + return this.externalResourceGroupFile; + } + + /** + * @return the destination file path of the external resource group file + */ + public String getExternalResourceGroupFilePath() { + if (externalResourceGroupFile != null) { + return externalResourceGroupFile.getAbsolutePath(); + } + return null; + } + + /** + * Sets the external destination of the resource + * @param file the external resource group file + */ + public void setExternalResourceGroupFile(File file) { + this.externalResourceGroupFile = file; + } + + /** + * @return true if this resource has a defined external resource group file destination + */ + public boolean hasExternalResourceGroupFile() { + return getExternalResourceGroupFile() != null; + } + + /** {@inheritDoc} */ + public String toString() { + return NAMES[level] + (isExternal() ? ", file=" + externalResourceGroupFile : ""); + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/AFPConstants.java b/src/java/org/apache/fop/render/afp/modca/AFPConstants.java index 73c39f2f0..e2e2a8bbe 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPConstants.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPConstants.java @@ -34,4 +34,9 @@ public interface AFPConstants { * The encoding to use to convert to ASCII */ String ASCII_ENCODING = "Cp1252"; + + /** + * The encoding to use to convert to US ASCII (7 bit) + */ + String US_ASCII_ENCODING = "US-ASCII"; } diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java index ace60e331..fdb0e5cc3 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java @@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.render.afp.AFPFontAttributes; import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.ResourceInfo; +import org.apache.fop.render.afp.ResourceLevel; import org.apache.fop.render.afp.fonts.AFPFont; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.tools.StringUtils; @@ -170,7 +171,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { /** * @return the current page */ - private AbstractPageObject getCurrentPage() { + protected AbstractPageObject getCurrentPage() { return this.currentPage; } @@ -225,14 +226,16 @@ public class AFPDataStream extends AbstractResourceGroupContainer { endPageGroup(); } - // Write out any external resource groups - getExternalResourceGroupManager().writeExternalResources(); - - // Write out any print-file level resources - if (hasResources()) { - getResourceGroup().write(this.outputStream); + if (interchangeSet.supportsLevel2()) { + // Write out any external resource groups + getExternalResourceGroupManager().writeExternalResources(); + + // Write out any print-file level resources + if (hasResources()) { + getResourceGroup().write(this.outputStream); + } } - + // Write out document if (document != null) { document.endDocument(); @@ -303,7 +306,14 @@ public class AFPDataStream extends AbstractResourceGroupContainer { this.currentOverlay = new Overlay(overlayName, width, height, widthRes, heightRes, overlayRotation); - getResourceGroup().addObject(currentOverlay); + if (interchangeSet.supportsLevel2()) { + ResourceObject resourceObject = new ResourceObject(overlayName); + resourceObject.setDataObject(currentOverlay); + getResourceGroup().addObject(resourceObject); + } +// currentPageGroup.getResourceEnvironmentGroup().addObject(currentOverlay); +// currentPageObject.getActiveEnvironmentGroup().createOverlay(overlayName); + currentPageObject.createIncludePageOverlay(overlayName, x, y, 0); currentPage = currentOverlay; setOffsets(0, 0, 0); @@ -462,13 +472,14 @@ public class AFPDataStream extends AbstractResourceGroupContainer { dataObjectInfo.setObjectType(objectType); ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); - + ResourceLevel resourceLevel = resourceInfo.getLevel(); + // is MO:DCA-L available? if (interchangeSet.supportsLevel2()) { // can this data object use the include object (IOB) referencing // mechanism? if (objectType.canBeIncluded()) { - ResourceGroup resourceGroup = getResourceGroup(resourceInfo); + ResourceGroup resourceGroup = getResourceGroup(resourceLevel); IncludeObject includeObject = resourceGroup.createObject(dataObjectInfo); // add include to current page @@ -479,7 +490,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { + "' cannot be referenced with an include so it will be embedded directly"); } } else { - if (resourceInfo.isExternal()) { + if (resourceLevel.isExternal()) { log.warn( interchangeSet + ": not available, object " + getName() + " will reside inline"); } @@ -776,23 +787,23 @@ public class AFPDataStream extends AbstractResourceGroupContainer { /** * Returns the resource group for a given resource into * - * @param resourceInfo + * @param level * resource info * @return a resource group container for the given resource info */ - private ResourceGroup getResourceGroup(ResourceInfo resourceInfo) { + private ResourceGroup getResourceGroup(ResourceLevel level) { ResourceGroup resourceGroup = null; - if (resourceInfo.isPrintFile()) { + if (level.isPrintFile()) { resourceGroup = getResourceGroup(); - } else if (resourceInfo.isDocument()) { + } else if (level.isDocument()) { resourceGroup = getDocument().getResourceGroup(); - } else if (resourceInfo.isPageGroup()) { + } else if (level.isPageGroup()) { resourceGroup = getCurrentPageGroup().getResourceGroup(); - } else if (resourceInfo.isPage()) { + } else if (level.isPage()) { resourceGroup = currentPageObject.getResourceGroup(); - } else if (resourceInfo.isExternal()) { + } else if (level.isExternal()) { resourceGroup = getExternalResourceGroupManager() - .getExternalResourceGroup(resourceInfo); + .getExternalResourceGroup(level); } return resourceGroup; } @@ -889,28 +900,28 @@ public class AFPDataStream extends AbstractResourceGroupContainer { } /** - * Returns the corresponding resource group for the given resource info + * Returns the corresponding resource group for the given resource level * - * @param resourceInfo - * resource info - * @return the corresponding resource group for the given resource info + * @param level + * the resource level + * @return the corresponding resource group for the given resource level */ - private ResourceGroup getExternalResourceGroup(ResourceInfo resourceInfo) { + private ResourceGroup getExternalResourceGroup(ResourceLevel level) { ResourceGroup resourceGroup; - // this resource info does not have a an external resource group + // this resource info does not have an external resource group // file definition - if (!resourceInfo.hasExternalResourceGroupFile()) { + if (!level.hasExternalResourceGroupFile()) { if (defaultResourceGroupFile != null) { // fallback to default resource group file - resourceInfo.setExternalResourceGroupFile(defaultResourceGroupFile); - resourceGroup = getExternalResourceGroup(resourceInfo); + level.setExternalResourceGroupFile(defaultResourceGroupFile); + resourceGroup = getExternalResourceGroup(level); } else { // use print-file level resource group in the absence // of an external resource group file definition resourceGroup = container.getResourceGroup(); } } else { - File resourceGroupFile = resourceInfo + File resourceGroupFile = level .getExternalResourceGroupFile(); resourceGroup = (ResourceGroup)getExternalResourceGroups().get(resourceGroupFile); if (resourceGroup == null) { @@ -930,19 +941,19 @@ public class AFPDataStream extends AbstractResourceGroupContainer { } } - /** - * Starts a new page segment. - */ - public void startPageSegment() { - currentPageObject.startPageSegment(); - } - - /** - * Ends the current page segment. - */ - public void endPageSegment() { - currentPageObject.endPageSegment(); - } +// /** +// * Starts a new page segment. +// */ +// public void startPageSegment() { +// currentPageObject.startPageSegment(); +// } +// +// /** +// * Ends the current page segment. +// */ +// public void endPageSegment() { +// currentPageObject.endPageSegment(); +// } /** * Sets the MO:DCA interchange set to use diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java index e1035a6c6..065886a49 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java @@ -355,7 +355,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { */ protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); - if (this instanceof PageObject) { + if (this instanceof PageObject || this instanceof Overlay) { getActiveEnvironmentGroup().write(os); } writeObjects(this.includePageSegments, os); diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java index 9449108eb..4a5785981 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java @@ -81,18 +81,10 @@ public abstract class AbstractResourceEnvironmentGroupContainer /** * @return the resource environment group */ - private ResourceEnvironmentGroup getResourceEnvironmentGroup() { + protected ResourceEnvironmentGroup getResourceEnvironmentGroup() { if (resourceEnvironmentGroup == null) { this.resourceEnvironmentGroup = new ResourceEnvironmentGroup(); } return this.resourceEnvironmentGroup; - } - - /** - * Adds a resource mapping to this resource environment group - * @param obj a resource to be referenced in this resource environment group - */ - protected void addResource(AbstractStructuredAFPObject obj) { - getResourceEnvironmentGroup().addObject(obj); - } + } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java index 1bdf7d8bd..5df2ed3e8 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java @@ -169,8 +169,8 @@ public abstract class AbstractResourceGroupContainer extends AbstractPageObject private static final String GRAPHIC_NAME_PREFIX = "GRA"; // not currently used/implemented - private static final String BARCODE_NAME_PREFIX = "BAR"; - private static final String OTHER_NAME_PREFIX = "OTH"; +// private static final String BARCODE_NAME_PREFIX = "BAR"; +// private static final String OTHER_NAME_PREFIX = "OTH"; /** * Helper method to create an image on the current container and to return @@ -248,9 +248,9 @@ public abstract class AbstractResourceGroupContainer extends AbstractPageObject * {@inheritDoc} */ protected void writeContent(OutputStream os) throws IOException { - super.writeContent(os); if (resourceGroup != null) { resourceGroup.write(os); } + super.writeContent(os); } } 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 1573ea1a4..1a23511f5 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.List; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.modca.triplets.MappingOptionTriplet; import org.apache.fop.render.afp.modca.triplets.MeasurementUnitsTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectAreaSizeTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; @@ -232,7 +233,7 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { } /** - * Specifies the extent of an object area in the X and Y directions + * Sets the extent of an object area in the X and Y directions * @param x the x direction extent * @param y the y direction extent */ @@ -242,11 +243,21 @@ public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { /** * Sets the measurement units used to specify the units of measure + * @param xRes units per base on the x-axis + * @param yRes units per base on the y-axis */ - public void setMeasurementUnits() { - addTriplet(new MeasurementUnitsTriplet()); + public void setMeasurementUnits(int xRes, int yRes) { + addTriplet(new MeasurementUnitsTriplet(xRes, xRes)); } + /** + * Sets the mapping option + * @param optionValue the mapping option value + */ + public void setMappingOption(byte optionValue) { + addTriplet(new MappingOptionTriplet(optionValue)); + } + /** * Sets a comment on this resource * @param comment a comment string diff --git a/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java b/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java index f8a779707..b1d8aeb2a 100644 --- a/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java +++ b/src/java/org/apache/fop/render/afp/modca/DataObjectAccessor.java @@ -41,4 +41,9 @@ public interface DataObjectAccessor extends Writable { * @param dataObjectInfo the data object info */ void setDataObjectInfo(DataObjectInfo dataObjectInfo); + + /** + * @return the data object accessor name + */ + String getName(); } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java index e579052b0..813dffed2 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java @@ -36,7 +36,7 @@ public class ImageSegment extends AbstractNamedAFPObject { /** * Default name for the object environment group */ - private static final String DEFAULT_NAME = "IS01"; + private static final String DEFAULT_NAME = "IS000001"; /** * The ImageContent for the image segment diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java index 1817bc8cc..1b1b6c1ed 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java @@ -23,6 +23,8 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.modca.triplets.MappingOptionTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; import org.apache.fop.render.afp.tools.BinaryUtils; @@ -74,27 +76,27 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA /** * The orientation on the include object */ - private int orientation = -1; + private int orientation = 0; /** * The X-axis origin of the object area */ - private int xOffset = -1; + private int xOffset = 0; /** * The Y-axis origin of the object area */ - private int yOffset = -1; + private int yOffset = 0; /** * The X-axis origin defined in the object */ - private int xContentOffset = -1; + private int xContentOffset = 0; /** * The Y-axis origin defined in the object */ - private int yContentOffset = -1; + private int yContentOffset = 0; /** * the referenced data object @@ -115,7 +117,6 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA this.dataObjectAccessor = dataObjectAccessor; AbstractNamedAFPObject dataObject = dataObjectAccessor.getDataObject(); - // Strip any object container if (dataObject instanceof ObjectContainer) { ObjectContainer objectContainer = (ObjectContainer)dataObject; @@ -129,30 +130,28 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA this.dataObjectType = TYPE_PAGE_SEGMENT; } else { this.dataObjectType = TYPE_OTHER; - DataObjectInfo dataObjectInfo = dataObjectAccessor.getDataObjectInfo(); - Registry registry = Registry.getInstance(); - Registry.ObjectType objectType = registry.getObjectType(dataObjectInfo); - // When other type must set object classification - super.setObjectClassification( - ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT, - objectType); } + + DataObjectInfo dataObjectInfo = dataObjectAccessor.getDataObjectInfo(); + + setObjectArea(dataObjectInfo.getX(), dataObjectInfo.getY()); + + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_REPLACE_FIRST_GID_NAME, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, + dataObjectInfo.getUri()); + + Registry registry = Registry.getInstance(); + Registry.ObjectType objectType = registry.getObjectType(dataObjectInfo); + super.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT, + objectType); + + super.setMeasurementUnits(dataObjectInfo.getWidthRes(), dataObjectInfo.getHeightRes()); -// ResourceInfo resourceInfo = dataObjectAccessor.getDataObjectInfo().getResourceInfo(); -// // Set data object reference triplet -// if (resourceInfo != null && resourceInfo.isExternal()) { -// String dest = resourceInfo.getExternalResourceGroupDest(); -// super.setFullyQualifiedName( -// FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, -// FullyQualifiedNameTriplet.FORMAT_URL, dest); -// } else { -// super.setFullyQualifiedName( -// FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, -// FullyQualifiedNameTriplet.FORMAT_CHARSTR, dataObject.getName()); -// } + super.setMappingOption(MappingOptionTriplet.SCALE_TO_FIT); - // Set measurement units triplet - setMeasurementUnits(); + super.setObjectAreaSize(dataObjectInfo.getWidth(), dataObjectInfo.getHeight()); } /** @@ -241,7 +240,7 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA data[18] = dataObjectType; //XoaOset (object area) - if (xOffset > 0) { + if (xOffset >= -1) { byte[] x = BinaryUtils.convert(xOffset, 3); data[19] = x[0]; data[20] = x[1]; @@ -253,7 +252,7 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA } // YoaOset (object area) - if (yOffset > 0) { + if (yOffset > -1) { byte[] y = BinaryUtils.convert(yOffset, 3); data[22] = y[0]; data[23] = y[1]; @@ -298,7 +297,7 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA } // XocaOset (object content) - if (xContentOffset > 0) { + if (xContentOffset > -1) { byte[] y = BinaryUtils.convert(xContentOffset, 3); data[29] = y[0]; data[30] = y[1]; @@ -310,7 +309,7 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA } // YocaOset (object content) - if (yContentOffset > 0) { + if (yContentOffset > -1) { byte[] y = BinaryUtils.convert(yContentOffset, 3); data[32] = y[0]; data[33] = y[1]; diff --git a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java index 3c9794e7d..9b1abe06c 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java +++ b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java @@ -22,12 +22,11 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -//import org.apache.fop.render.afp.ResourceLevel; import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.ResourceInfo; +import org.apache.fop.render.afp.ResourceLevel; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; -import org.apache.fop.render.afp.modca.triplets.StrucFlgs; import org.apache.fop.render.afp.tools.BinaryUtils; /** @@ -48,12 +47,13 @@ public class MapDataResource extends AbstractStructuredAFPObject { AbstractNamedAFPObject namedDataObject = dataObjectAccessor.getDataObject(); DataObjectInfo dataObjectInfo = dataObjectAccessor.getDataObjectInfo(); ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); - if (resourceInfo.isExternal()) { - String dest = resourceInfo.getExternalResourceGroupDest(); - if (dest != null) { + ResourceLevel resourceLevel = resourceInfo.getLevel(); + if (resourceLevel.isExternal()) { + String url = resourceLevel.getExternalResourceGroupFilePath(); + if (url != null) { super.setFullyQualifiedName( FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, - FullyQualifiedNameTriplet.FORMAT_URL, dest); + FullyQualifiedNameTriplet.FORMAT_CHARSTR, url); } } else { String fqName = namedDataObject.getFullyQualifiedName(); 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 02237ca90..67dcaa74f 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java @@ -33,6 +33,8 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class MapPageOverlay extends AbstractAFPObject { + private static final int MAX_SIZE = 253; + /** * The collection of overlays (maximum of 254 stored as byte[]) */ @@ -59,7 +61,7 @@ public class MapPageOverlay extends AbstractAFPObject { * @throws MaximumSizeExceededException if the maximum size is reached */ public void addOverlay(String name) throws MaximumSizeExceededException { - if (getOverlays().size() > 253) { + if (getOverlays().size() > MAX_SIZE) { throw new MaximumSizeExceededException(); } if (name.length() != 8) { diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java index ebc402954..2e06c1b2c 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; import org.apache.fop.render.afp.tools.BinaryUtils; @@ -32,6 +33,8 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class ObjectContainer extends AbstractNamedAFPObject implements DataObjectAccessor { + private static final String DEFAULT_NAME = "OC000001"; + /** * the data object */ @@ -47,6 +50,13 @@ public class ObjectContainer extends AbstractNamedAFPObject implements DataObjec */ private DataObjectInfo dataObjectInfo; + /** + * Default constructor + */ + public ObjectContainer() { + super(DEFAULT_NAME); + } + /** * Main constructor * @param name the name of this object container @@ -92,6 +102,10 @@ public class ObjectContainer extends AbstractNamedAFPObject implements DataObjec } else { log.warn("no object type for " + dataObjectInfo.getUri()); } + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_REPLACE_FIRST_GID_NAME, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, + dataObjectInfo.getUri()); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java index 1d9dc6985..1db9c4c41 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PageObject.java @@ -46,15 +46,15 @@ import org.apache.fop.render.afp.tools.StringUtils; */ public class PageObject extends AbstractResourceGroupContainer { - /** - * The page segment count - */ - private int pageSegmentCount = 0; - - /** - * The current page segment - */ - private PageSegment currentPageSegment = null; +// /** +// * The page segment count +// */ +// private int pageSegmentCount = 0; +// +// /** +// * The current page segment +// */ +// private PageSegment currentPageSegment = null; /** * Construct a new page object for the specified name argument, the page @@ -91,56 +91,58 @@ public class PageObject extends AbstractResourceGroupContainer { * the orientation required for the overlay */ public void createIncludePageOverlay(String name, int x, int y, int orientation) { - addObject(new IncludePageOverlay(name, x, y, orientation)); + getActiveEnvironmentGroup().createOverlay(name); + IncludePageOverlay ipo = new IncludePageOverlay(name, x, y, orientation); + addObject(ipo); } - /** - * @return a new page segment object - */ - private PageSegment createPageSegment() { - String name = PAGE_SEGMENT_NAME_PREFIX - + StringUtils.lpad(String.valueOf(++pageSegmentCount), '0', 5); - PageSegment pageSegment = new PageSegment(name); - return pageSegment; - } - - /** - * @return the current page segment - */ - private PageSegment getCurrentPageSegment() { - if (currentPageSegment == null) { - this.currentPageSegment = createPageSegment(); - super.addObject(currentPageSegment); - } - return this.currentPageSegment; - } +// /** +// * @return a new page segment object +// */ +// private PageSegment createPageSegment() { +// String name = PAGE_SEGMENT_NAME_PREFIX +// + StringUtils.lpad(String.valueOf(++pageSegmentCount), '0', 5); +// PageSegment pageSegment = new PageSegment(name); +// return pageSegment; +// } - private static final String PAGE_SEGMENT_NAME_PREFIX = "PSG"; +// /** +// * @return the current page segment +// */ +// private PageSegment getCurrentPageSegment() { +// if (currentPageSegment == null) { +// this.currentPageSegment = createPageSegment(); +// super.addObject(currentPageSegment); +// } +// return this.currentPageSegment; +// } +// +// private static final String PAGE_SEGMENT_NAME_PREFIX = "PSG"; - /** - * Starts a new page segment and makes it current. - */ - public void startPageSegment() { - getCurrentPageSegment(); - } - - /** - * Ends the current page segment. - */ - public void endPageSegment() { - this.currentPageSegment = null; - } +// /** +// * Starts a new page segment and makes it current. +// */ +// public void startPageSegment() { +// getCurrentPageSegment(); +// } +// +// /** +// * Ends the current page segment. +// */ +// public void endPageSegment() { +// this.currentPageSegment = null; +// } - /** - * {@inheritDoc} - */ - protected void addObject(AbstractAFPObject obj) { - if (currentPageSegment != null) { - getCurrentPageSegment().addObject(obj); - } else { - super.addObject(obj); - } - } +// /** +// * {@inheritDoc} +// */ +// protected void addObject(AbstractAFPObject obj) { +//// if (currentPageSegment != null) { +//// getCurrentPageSegment().addObject(obj); +//// } else { +// super.addObject(obj); +//// } +// } /** * This method will create shading on the page using the specified diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java index aff5cc6eb..219dfd8cb 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java @@ -91,15 +91,15 @@ public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup { super(name); } - /** - * Adds an AFP object mapping reference to this resource environment group - * @param obj the object to add - */ - public void addObject(AbstractStructuredAFPObject obj) { - // TODO: AC - fix +// /** +// * Adds an AFP object mapping reference to this resource environment group +// * @param obj the object to add +// */ +// public void addObject(AbstractStructuredAFPObject obj) { // getMapDataResources().add(new MapDataResource(obj)); - getPreprocessPresentationObjects().add(new PreprocessPresentationObject(obj)); - } +// createOverlay(obj.get); +// getPreprocessPresentationObjects().add(new PreprocessPresentationObject(obj)); +// } /** * Returns an indication if the resource environment group is complete diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java index f8c9d5fc0..cd369b876 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java @@ -28,6 +28,8 @@ import java.util.Map; import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.ImageObjectInfo; import org.apache.fop.render.afp.ResourceInfo; +import org.apache.fop.render.afp.ResourceLevel; +import org.apache.fop.render.afp.tools.StringUtils; /** * A Resource Group contains a set of overlays. @@ -72,6 +74,14 @@ public final class ResourceGroup extends AbstractNamedAFPObject { return this.container; } + private static final String OBJECT_CONTAINER_NAME_PREFIX = "OC"; + + private ObjectContainer createObjectContainer() { + String name = OBJECT_CONTAINER_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 6); + return new ObjectContainer(name); + } + /** * Creates a data object in this resource group * @param dataObjectInfo the data object info @@ -81,6 +91,7 @@ public final class ResourceGroup extends AbstractNamedAFPObject { DataObjectAccessor dataObjectAccessor = (DataObjectAccessor)getResourceMap().get(dataObjectInfo.getUri()); ResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + ResourceLevel resourceLevel = resourceInfo.getLevel(); AbstractDataObject dataObj; if (dataObjectAccessor == null) { if (dataObjectInfo instanceof ImageObjectInfo) { @@ -94,27 +105,31 @@ public final class ResourceGroup extends AbstractNamedAFPObject { dataObjectInfo.getWidthRes(), dataObjectInfo.getHeightRes(), dataObjectInfo.getRotation()); + ObjectContainer objectContainer = null; String resourceName = resourceInfo.getName(); - ObjectContainer objectContainer = new ObjectContainer(resourceName); + if (resourceName != null) { + objectContainer = new ObjectContainer(resourceName); + } else { + objectContainer = createObjectContainer(); + resourceName = objectContainer.getName(); + } objectContainer.setDataObject(dataObj); objectContainer.setDataObjectInfo(dataObjectInfo); // When externally located, wrap the object container in a resource object - if (resourceInfo.isExternal()) { + if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) { ResourceObject resourceObject = new ResourceObject(resourceName); resourceObject.setDataObject(objectContainer); + resourceObject.setDataObjectInfo(dataObjectInfo); dataObjectAccessor = resourceObject; } else { // Access data object through container dataObjectAccessor = objectContainer; } - dataObjectAccessor.setDataObjectInfo(dataObjectInfo); // Add to resource map getResourceMap().put(dataObjectInfo.getUri(), dataObjectAccessor); } - // Return include object - AbstractNamedAFPObject dataObject = dataObjectAccessor.getDataObject(); - String name = dataObject.getName(); + String name = dataObjectAccessor.getName(); IncludeObject includeObj = new IncludeObject(name, dataObjectAccessor); return includeObj; } @@ -126,13 +141,15 @@ public final class ResourceGroup extends AbstractNamedAFPObject { */ private boolean isValidObjectType(AbstractNamedAFPObject namedObj) { return (namedObj instanceof Overlay + || namedObj instanceof ResourceObject || namedObj instanceof PageSegment - // || namedObj instanceof FormMap - // || namedObj instanceof BarcodeObject || namedObj instanceof GraphicsObject || namedObj instanceof ImageObject || namedObj instanceof ObjectContainer - || namedObj instanceof Document); + || namedObj instanceof Document + // || namedObj instanceof FormMap + // || namedObj instanceof BarcodeObject + ); } /** * Adds a named object to this resource group diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java index 58c61fc58..e0ba1b4b7 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; import org.apache.fop.render.afp.modca.triplets.Triplet; import org.apache.fop.render.afp.tools.BinaryUtils; @@ -54,10 +55,37 @@ public class ResourceObject extends AbstractPreparedAFPObject implements DataObj /** * Sets the data object referenced by this resource object - * @param namedObject the named data object + * @param obj the named data object */ - public void setDataObject(AbstractNamedAFPObject namedObject) { - this.namedObject = namedObject; + public void setDataObject(AbstractNamedAFPObject obj) { + this.namedObject = obj; + + String fqn = obj.getFullyQualifiedName(); + if (fqn != null) { + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_REPLACE_FIRST_GID_NAME, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, + fqn); + } + + byte type; + if (obj instanceof ObjectContainer) { + type = ResourceObjectTypeTriplet.OBJECT_CONTAINER; + } else if (obj instanceof ImageObject) { + type = ResourceObjectTypeTriplet.IMAGE_OBJECT; + } else if (obj instanceof GraphicsObject) { + type = ResourceObjectTypeTriplet.GRAPHICS_OBJECT; + } else if (obj instanceof Document) { + type = ResourceObjectTypeTriplet.DOCUMENT_OBJECT; + } else if (obj instanceof PageSegment) { + type = ResourceObjectTypeTriplet.PAGE_SEGMENT_OBJECT; + } else if (obj instanceof Overlay) { + type = ResourceObjectTypeTriplet.OVERLAY_OBJECT; + } else { + throw new UnsupportedOperationException( + "Unsupported resource object type " + obj); + } + getTriplets().add(new ResourceObjectTypeTriplet(type)); } /** @@ -80,34 +108,12 @@ public class ResourceObject extends AbstractPreparedAFPObject implements DataObj public void setDataObjectInfo(DataObjectInfo dataObjectInfo) { this.dataObjectInfo = dataObjectInfo; - byte type; if (namedObject instanceof ObjectContainer) { - type = ResourceObjectTypeTriplet.OBJECT_CONTAINER; - -// ObjectContainer objectContainer = (ObjectContainer)namedObject; -// DataObjectInfo dataObjectInfo = objectContainer.getDataObjectInfo(); Registry.ObjectType objectType = dataObjectInfo.getObjectType(); super.setObjectClassification( ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT, objectType); - - } else if (namedObject instanceof ImageObject) { - type = ResourceObjectTypeTriplet.IMAGE_OBJECT; - } else if (namedObject instanceof GraphicsObject) { - type = ResourceObjectTypeTriplet.GRAPHICS_OBJECT; - } else if (namedObject instanceof Document) { - type = ResourceObjectTypeTriplet.DOCUMENT_OBJECT; - } else if (namedObject instanceof PageSegment) { - type = ResourceObjectTypeTriplet.PAGE_SEGMENT_OBJECT; - } else if (namedObject instanceof Overlay) { - type = ResourceObjectTypeTriplet.OVERLAY_OBJECT; - } else { - throw new UnsupportedOperationException( - "Unsupported resource object type " + namedObject); } - - getTriplets().add(new ResourceObjectTypeTriplet(type)); - } /** diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java index 2be37b818..705a8d41d 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java @@ -160,13 +160,17 @@ public class FullyQualifiedNameTriplet extends Triplet { super(FULLY_QUALIFIED_NAME); this.fqName = fqName; - + byte[] fqNameBytes; + String encoding = AFPConstants.EBCIDIC_ENCODING; + if (format == FORMAT_URL) { + encoding = AFPConstants.US_ASCII_ENCODING; + } try { - fqNameBytes = fqName.getBytes(AFPConstants.ASCII_ENCODING); + fqNameBytes = fqName.getBytes(encoding); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException( - AFPConstants.ASCII_ENCODING + " encoding failed"); + encoding + " encoding failed"); } byte[] data = new byte[2 + fqNameBytes.length]; diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/MappingOptionTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/MappingOptionTriplet.java new file mode 100644 index 000000000..daebb6183 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/MappingOptionTriplet.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.afp.modca.triplets; + +/** + * Specifies the mapping of data object presentation space to object area + */ +public class MappingOptionTriplet extends Triplet { + /** + * the data object is placed in the upper left corner, all data must be presented + * within the object area extents + */ + public static final byte POSITION = 0x00; + + /** + * the data object is placed in the upper left corner, all data that falls within + * the object area extents will be presented but data that falls outside will not be presented + */ + public static final byte POSITION_AND_TRIM = 0x10; + + /** + * the data object is centred and symmetrically scaled up or down + * while preserving aspect ratio + */ + public static final byte SCALE_TO_FIT = 0x20; + + /** + * the data object is centred, all data that falls within the object area extents + * will be presented but data that falls outside will not be presented + */ + public static final byte CENTER_AND_TRIM = 0x30; + +// public static final byte MIGRATION_MAPPING_1 = 0x41; +// public static final byte MIGRATION_MAPPING_2 = 0x42; +// public static final byte MIGRATION_MAPPING_3 = 0x50; + + /** the data object is centred, aspect ratio is not always preserved */ + public static final byte SCALE_TO_FILL = 0x60; + + /** used to map ip3i print data objects */ + public static final byte UP3I_PRINT_DATA = 0x70; + + /** + * Main constructor + * + * @param mapValue the mapping option to use + */ + public MappingOptionTriplet(byte mapValue) { + super(Triplet.MAPPING_OPTION, mapValue); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java index 7350db27f..71da6e059 100644 --- a/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java +++ b/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java @@ -32,12 +32,15 @@ public class MeasurementUnitsTriplet extends Triplet { /** * Main constructor + * + * @param xRes units per base on the x-axis + * @param yRes units per base on the y-axis */ - public MeasurementUnitsTriplet() { + public MeasurementUnitsTriplet(int xRes, int yRes) { super(MEASUREMENT_UNITS); //TODO: units correct? - byte[] xUnits = BinaryUtils.convert(1, 2); - byte[] yUnits = BinaryUtils.convert(1, 2); + byte[] xUnits = BinaryUtils.convert(xRes * 10, 2); + byte[] yUnits = BinaryUtils.convert(yRes * 10, 2); byte[] data = new byte[] { TEN_INCHES, // XoaBase TEN_INCHES, // YoaBase -- cgit v1.2.3 From 4a4ec49722df7527eb3084b742f5d21c8b33fbd5 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 10:11:09 +0000 Subject: finalised log and cleanup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660891 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/IDTracker.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/IDTracker.java b/src/java/org/apache/fop/area/IDTracker.java index e8b53b20c..a701af70b 100644 --- a/src/java/org/apache/fop/area/IDTracker.java +++ b/src/java/org/apache/fop/area/IDTracker.java @@ -20,8 +20,6 @@ package org.apache.fop.area; import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -36,20 +34,20 @@ import org.apache.commons.logging.LogFactory; */ public class IDTracker { - private static Log log = LogFactory.getLog(IDTracker.class); + private static final Log log = LogFactory.getLog(IDTracker.class); // HashMap of ID's whose area is located on one or more consecutive // PageViewports. Each ID has an arraylist of PageViewports that // form the defined area of this ID - private Map idLocations = new HashMap(); + private Map idLocations = new java.util.HashMap(); // idref's whose target PageViewports have yet to be identified // Each idref has a HashSet of Resolvable objects containing that idref - private Map unresolvedIDRefs = new HashMap(); + private Map unresolvedIDRefs = new java.util.HashMap(); - private Set unfinishedIDs = new HashSet(); + private Set unfinishedIDs = new java.util.HashSet(); - private Set alreadyResolvedIDs = new HashSet(); + private Set alreadyResolvedIDs = new java.util.HashSet(); /** * Tie a PageViewport with an ID found on a child area of the PV. Note that @@ -198,7 +196,7 @@ public class IDTracker { public void addUnresolvedIDRef(String idref, Resolvable res) { Set todo = (Set) unresolvedIDRefs.get(idref); if (todo == null) { - todo = new HashSet(); + todo = new java.util.HashSet(); unresolvedIDRefs.put(idref, todo); } // add Resolvable object to this HashSet -- cgit v1.2.3 From 680ceef6585738608946e725ca2959df85b5cebc Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 10:14:26 +0000 Subject: fixed some small checkstyle problems and commented out unused offDocumentItems member variable git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660893 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/AreaTreeModel.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/AreaTreeModel.java b/src/java/org/apache/fop/area/AreaTreeModel.java index c43db31bb..544ff612a 100644 --- a/src/java/org/apache/fop/area/AreaTreeModel.java +++ b/src/java/org/apache/fop/area/AreaTreeModel.java @@ -36,11 +36,11 @@ import org.apache.commons.logging.LogFactory; * the life of the area tree model. */ public class AreaTreeModel { - private List pageSequenceList = null; + private List/**/ pageSequenceList = null; private int currentPageSequenceIndex = -1; /** the current page sequence */ protected PageSequence currentPageSequence; - private List offDocumentItems = new java.util.ArrayList(); +// private List offDocumentItems = new java.util.ArrayList(); /** logger instance */ protected static Log log = LogFactory.getLog(AreaTreeModel.class); @@ -48,7 +48,7 @@ public class AreaTreeModel { * Create a new store pages model */ public AreaTreeModel() { - pageSequenceList = new java.util.ArrayList(); + pageSequenceList = new java.util.ArrayList/**/(); } /** @@ -83,13 +83,13 @@ public class AreaTreeModel { * Handle an OffDocumentItem * @param ext the extension to handle */ - public void handleOffDocumentItem(OffDocumentItem ext) {}; + public void handleOffDocumentItem(OffDocumentItem ext) { }; /** * Signal the end of the document for any processing. * @throws SAXException if a problem was encountered. */ - public void endDocument() throws SAXException {}; + public void endDocument() throws SAXException { }; /** * Returns the currently active page-sequence. -- cgit v1.2.3 From 81b174b68556a575308eb84ebe2c976f19be5b0a Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 10:18:47 +0000 Subject: explicitly "this" referenced member variables git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660895 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/inline/Viewport.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/inline/Viewport.java b/src/java/org/apache/fop/area/inline/Viewport.java index fadeb6e97..0dc0112bd 100644 --- a/src/java/org/apache/fop/area/inline/Viewport.java +++ b/src/java/org/apache/fop/area/inline/Viewport.java @@ -45,7 +45,7 @@ public class Viewport extends InlineArea { * @param child the child content area of this viewport */ public Viewport(Area child) { - content = child; + this.content = child; } /** @@ -54,7 +54,7 @@ public class Viewport extends InlineArea { * @param c true if this viewport should clip */ public void setClip(boolean c) { - clip = c; + this.clip = c; } /** @@ -63,7 +63,7 @@ public class Viewport extends InlineArea { * @return true if this viewport should clip */ public boolean getClip() { - return clip; + return this.clip; } /** @@ -72,7 +72,7 @@ public class Viewport extends InlineArea { * @param cp the position and size to place the content */ public void setContentPosition(Rectangle2D cp) { - contentPosition = cp; + this.contentPosition = cp; } /** @@ -81,7 +81,7 @@ public class Viewport extends InlineArea { * @return the position and size to place the content */ public Rectangle2D getContentPosition() { - return contentPosition; + return this.contentPosition; } /** @@ -98,7 +98,7 @@ public class Viewport extends InlineArea { * @return the content area */ public Area getContent() { - return content; + return this.content; } private void writeObject(java.io.ObjectOutputStream out) @@ -123,9 +123,9 @@ public class Viewport extends InlineArea { in.readFloat(), in.readFloat()); } - clip = in.readBoolean(); - props = (HashMap) in.readObject(); - content = (Area) in.readObject(); + this.clip = in.readBoolean(); + this.props = (HashMap) in.readObject(); + this.content = (Area) in.readObject(); } } -- cgit v1.2.3 From 4251cfe084fb0f9782b455b461cbcbff88a3bb37 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 10:23:10 +0000 Subject: cleanup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660896 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/extensions/AFPElement.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java index 7d32c90d7..2fdd32649 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java @@ -46,15 +46,12 @@ public class AFPElement extends AbstractAFPExtensionObject { /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); - //if (!AFPElementMapping.NAMESPACE.equals(parent.getNamespaceURI()) - // || !AFPElementMapping.PAGE.equals(parent.getLocalName())) { - // throw new ValidationException(getName() + " must be a child of afp:page."); - //} if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) { throw new ValidationException(getName() + " must be a child of fo:simple-page-master."); } } + /** {@inheritDoc} */ protected ExtensionAttachment instantiateExtensionAttachment() { return new AFPPageSetup(getName()); } -- cgit v1.2.3 From 7c3df5221ff420d9b476921f9233a58a637f44b2 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 12:48:11 +0000 Subject: small cleanup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660923 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/inline/Image.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/inline/Image.java b/src/java/org/apache/fop/area/inline/Image.java index 1e0a65114..1689dd6c5 100644 --- a/src/java/org/apache/fop/area/inline/Image.java +++ b/src/java/org/apache/fop/area/inline/Image.java @@ -28,14 +28,14 @@ import org.apache.fop.area.Area; */ public class Image extends Area { private String url; - + /** * Create a new image with the given url. * - * @param u the url of the image + * @param url the url of the image */ - public Image(String u) { - url = u; + public Image(String url) { + this.url = url; } /** @@ -45,7 +45,7 @@ public class Image extends Area { * @return the url of this image */ public String getURL() { - return url; + return this.url; } } -- cgit v1.2.3 From 78e587370e9f1013bc14027a7eaf932e8a400aaa Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 12:49:15 +0000 Subject: hasExtensionAttachments() convenience method added git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660926 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/FObj.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/java') diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index 0bbec4d47..150abda24 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -573,6 +573,11 @@ public abstract class FObj extends FONode implements Constants { } } + /** @return true if this FObj has extension attachments */ + public boolean hasExtensionAttachments() { + return extensionAttachments != null; + } + /** * Adds a foreign attribute to this FObj. * @param attributeName the attribute name as a QName instance -- cgit v1.2.3 From ef73102888547c46c287b051112861c5d19a96eb Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 12:50:23 +0000 Subject: Generics comments added in preparation for java 1.5 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660927 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/RenderPagesModel.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java index 64159cca7..39a188bde 100644 --- a/src/java/org/apache/fop/area/RenderPagesModel.java +++ b/src/java/org/apache/fop/area/RenderPagesModel.java @@ -50,9 +50,9 @@ public class RenderPagesModel extends AreaTreeModel { /** * Pages that have been prepared but not rendered yet. */ - protected List prepared = new java.util.ArrayList(); - private List pendingODI = new java.util.ArrayList(); - private List endDocODI = new java.util.ArrayList(); + protected List/**/ prepared = new java.util.ArrayList/**/(); + private List/**/ pendingODI = new java.util.ArrayList/**/(); + private List/**/ endDocODI = new java.util.ArrayList/**/(); /** * Create a new render pages model with the given renderer. @@ -66,7 +66,7 @@ public class RenderPagesModel extends AreaTreeModel { FontInfo fontInfo, OutputStream stream) throws FOPException { super(); - renderer = userAgent.getRendererFactory().createRenderer( + this.renderer = userAgent.getRendererFactory().createRenderer( userAgent, outputFormat); try { -- cgit v1.2.3 From faee0f13f0e61bd537dd18a221e8fa7650b05a5d Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 12:51:07 +0000 Subject: Generics comments added in preparation for java 1.5 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660928 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/PageViewport.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java index 745160d44..a69925ebb 100644 --- a/src/java/org/apache/fop/area/PageViewport.java +++ b/src/java/org/apache/fop/area/PageViewport.java @@ -89,7 +89,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl //Arbitrary attachments to the page from extensions that need to pass information //down to the renderers. - private List extensionAttachments = null; + private List/**/ extensionAttachments = null; /** * logging instance @@ -122,7 +122,8 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl */ public PageViewport(PageViewport original) { if (original.extensionAttachments != null) { - this.extensionAttachments = new java.util.ArrayList(original.extensionAttachments); + this.extensionAttachments + = new java.util.ArrayList/**/(original.extensionAttachments); } this.pageIndex = original.pageIndex; this.pageNumber = original.pageNumber; @@ -588,7 +589,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl */ public void addExtensionAttachment(ExtensionAttachment attachment) { if (this.extensionAttachments == null) { - this.extensionAttachments = new java.util.ArrayList(); + this.extensionAttachments = new java.util.ArrayList/**/(); } extensionAttachments.add(attachment); } -- cgit v1.2.3 From aea517e9d3c81ad85e0e7563d6aa57b333a36228 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 12:53:15 +0000 Subject: Added the ability for an implementing AreaTreeObject to contain child extension attachments git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660929 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/AreaTreeObject.java | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/AreaTreeObject.java b/src/java/org/apache/fop/area/AreaTreeObject.java index 1c2269a01..7fa30aee9 100644 --- a/src/java/org/apache/fop/area/AreaTreeObject.java +++ b/src/java/org/apache/fop/area/AreaTreeObject.java @@ -21,6 +21,7 @@ package org.apache.fop.area; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.apache.xmlgraphics.util.QName; @@ -33,6 +34,9 @@ public abstract class AreaTreeObject { /** Foreign attributes */ protected Map foreignAttributes = null; + /** Extension attachments */ + protected List/**/ extensionAttachments = null; + /** * Sets a foreign attribute. * @param name the qualified name of the attribute @@ -84,5 +88,20 @@ public abstract class AreaTreeObject { } } - + /** + * Set extension attachments from a List + * @param extensionAttachments a List with extension attachments + */ + public void setExtensionAttachments(List extensionAttachments) { + this.extensionAttachments = extensionAttachments; + } + + /** @return the extension attachments associated with this area */ + public List getExtensionAttachments() { + if (this.foreignAttributes != null) { + return Collections.unmodifiableList(this.extensionAttachments); + } else { + return Collections.EMPTY_LIST; + } + } } -- cgit v1.2.3 From 942c8245764c786f2eca11638d46d3264147c2f1 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 12:54:48 +0000 Subject: javadoc corrections, minor cleaups git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660930 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/AreaTreeHandler.java | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java index d3ea41554..3c89fd3d9 100644 --- a/src/java/org/apache/fop/area/AreaTreeHandler.java +++ b/src/java/org/apache/fop/area/AreaTreeHandler.java @@ -101,12 +101,12 @@ public class AreaTreeHandler extends FOEventHandler { setupModel(userAgent, outputFormat, stream); - lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride(); + this.lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride(); if (lmMaker == null) { lmMaker = new LayoutManagerMapping(); } - idTracker = new IDTracker(); + this.idTracker = new IDTracker(); if (log.isDebugEnabled()) { statistics = new Statistics(); @@ -124,7 +124,7 @@ public class AreaTreeHandler extends FOEventHandler { */ protected void setupModel(FOUserAgent userAgent, String outputFormat, OutputStream stream) throws FOPException { - model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream); + this.model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream); } /** @@ -133,7 +133,7 @@ public class AreaTreeHandler extends FOEventHandler { * @return AreaTreeModel the model being used for this area tree */ public AreaTreeModel getAreaTreeModel() { - return model; + return this.model; } /** @@ -143,7 +143,7 @@ public class AreaTreeHandler extends FOEventHandler { * area tree */ public LayoutManagerMaker getLayoutManagerMaker() { - return lmMaker; + return this.lmMaker; } /** @@ -152,7 +152,7 @@ public class AreaTreeHandler extends FOEventHandler { * @return IDTracker used to track reference ids for items in this area tree */ public IDTracker getIDTracker() { - return idTracker; + return this.idTracker; } /** @@ -207,9 +207,9 @@ public class AreaTreeHandler extends FOEventHandler { } private void wrapAndAddExtensionAttachments(List list) { - Iterator i = list.iterator(); - while (i.hasNext()) { - ExtensionAttachment attachment = (ExtensionAttachment) i.next(); + Iterator it = list.iterator(); + while (it.hasNext()) { + ExtensionAttachment attachment = (ExtensionAttachment) it.next(); addOffDocumentItem(new OffDocumentExtensionAttachment(attachment)); } } @@ -357,7 +357,7 @@ public class AreaTreeHandler extends FOEventHandler { * * @param id the property ID of the area * @param pv a page viewport that contains the area with this ID - * @deprecated use getIdTracker().associateIDWithPageViewport(id, pv) instead + * @deprecated use getIDTracker().associateIDWithPageViewport(id, pv) instead */ public void associateIDWithPageViewport(String id, PageViewport pv) { idTracker.associateIDWithPageViewport(id, pv); @@ -369,7 +369,7 @@ public class AreaTreeHandler extends FOEventHandler { * know when an id can be resolved. * * @param id the id of the object being processed - * @deprecated use getIdTracker().signalPendingID(id) instead + * @deprecated use getIDTracker().signalPendingID(id) instead */ public void signalPendingID(String id) { idTracker.signalPendingID(id); @@ -381,7 +381,7 @@ public class AreaTreeHandler extends FOEventHandler { * ref-ids can be resolved. * * @param id the id of the formatting object which was just finished - * @deprecated use getIdTracker().signalIDProcessed(id) instead + * @deprecated use getIDTracker().signalIDProcessed(id) instead */ public void signalIDProcessed(String id) { idTracker.signalIDProcessed(id); @@ -392,7 +392,7 @@ public class AreaTreeHandler extends FOEventHandler { * * @param id the id to check * @return true if the ID has been resolved - * @deprecated use getIdTracker().alreadyResolvedID(id) instead + * @deprecated use getIDTracker().alreadyResolvedID(id) instead */ public boolean alreadyResolvedID(String id) { return idTracker.alreadyResolvedID(id); @@ -402,7 +402,7 @@ public class AreaTreeHandler extends FOEventHandler { * Tries to resolve all unresolved ID references on the given page. * * @param pv page viewport whose ID refs to resolve - * @deprecated use getIdTracker().tryIDResolution(pv) instead + * @deprecated use getIDTracker().tryIDResolution(pv) instead */ public void tryIDResolution(PageViewport pv) { idTracker.tryIDResolution(pv); @@ -413,7 +413,7 @@ public class AreaTreeHandler extends FOEventHandler { * * @param id the id to lookup * @return the list of PageViewports - * @deprecated use getIdTracker().getPageViewportsContainingID(id) instead + * @deprecated use getIDTracker().getPageViewportsContainingID(id) instead */ public List getPageViewportsContainingID(String id) { return idTracker.getPageViewportsContainingID(id); @@ -424,7 +424,7 @@ public class AreaTreeHandler extends FOEventHandler { * * @param idref the idref whose target id has not yet been located * @param res the Resolvable object needing the idref to be resolved - * @deprecated use getIdTracker().addUnresolvedIDRef(idref, res) instead + * @deprecated use getIDTracker().addUnresolvedIDRef(idref, res) instead */ public void addUnresolvedIDRef(String idref, Resolvable res) { idTracker.addUnresolvedIDRef(idref, res); -- cgit v1.2.3 From 34d7c97ca26d4b018226c03784cbaaba3dce24a9 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 12:56:24 +0000 Subject: Warning given when mimetype provided is missing/null for whatever reason git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660931 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/modca/Registry.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/modca/Registry.java b/src/java/org/apache/fop/render/afp/modca/Registry.java index c81b4a289..5287f1a2b 100644 --- a/src/java/org/apache/fop/render/afp/modca/Registry.java +++ b/src/java/org/apache/fop/render/afp/modca/Registry.java @@ -21,6 +21,8 @@ package org.apache.fop.render.afp.modca; import java.util.Collections; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.ImageObjectInfo; import org.apache.xmlgraphics.util.MimeConstants; @@ -29,6 +31,8 @@ import org.apache.xmlgraphics.util.MimeConstants; * MOD:CA Registry of object types */ public final class Registry { + /** logging instance */ + private static final Log log = LogFactory.getLog("org.apache.fop.afp"); /** IOB supported object types */ private static final byte COMPID_GIF = 22; @@ -131,7 +135,11 @@ public final class Registry { if (dataObjectInfo instanceof ImageObjectInfo) { ImageObjectInfo imageInfo = (ImageObjectInfo)dataObjectInfo; String mimeType = imageInfo.getMimeType(); - entry = (Registry.ObjectType)mimeEntryMap.get(mimeType); + if (mimeType != null) { + entry = (Registry.ObjectType)mimeEntryMap.get(mimeType); + } else { + log.info("mimetype for " + dataObjectInfo + " is null"); + } } return entry; } -- cgit v1.2.3 From edb9d893010417f714bfe8698521959f7f0a490e Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 28 May 2008 12:59:15 +0000 Subject: Improved comment git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@660938 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/modca/ResourceGroup.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java index cd369b876..9f8af3d9d 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java @@ -116,7 +116,8 @@ public final class ResourceGroup extends AbstractNamedAFPObject { objectContainer.setDataObject(dataObj); objectContainer.setDataObjectInfo(dataObjectInfo); - // When externally located, wrap the object container in a resource object + // When located at print-file level or externally, + // wrap the object container in a resource object if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) { ResourceObject resourceObject = new ResourceObject(resourceName); resourceObject.setDataObject(objectContainer); -- cgit v1.2.3 From df16894515e5927bc1442225fb0210d2db4c11c9 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Thu, 29 May 2008 14:44:56 +0000 Subject: Added accessor/instantiator method for ObjectEnvironmentGroup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@661340 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/afp/modca/AbstractDataObject.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/java') 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 a57526a04..9bf713127 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java @@ -62,11 +62,19 @@ public abstract class AbstractDataObject extends AbstractPreparedObjectContainer */ public void setViewport(int x, int y, int width, int height, int widthRes, int heightRes, int rotation) { + getObjectEnvironmentGroup().setObjectArea(x, y, width, height, + widthRes, heightRes, rotation); + } + + /** + * Gets the ObjectEnvironmentGroup + * @return the object environment group + */ + protected ObjectEnvironmentGroup getObjectEnvironmentGroup() { if (objectEnvironmentGroup == null) { objectEnvironmentGroup = new ObjectEnvironmentGroup(); } - objectEnvironmentGroup.setObjectArea(x, y, width, height, - widthRes, heightRes, rotation); + return objectEnvironmentGroup; } /** -- cgit v1.2.3 From 92f144a66ef5f789019687047756ac870782ef0a Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 2 Jun 2008 14:05:52 +0000 Subject: Merged revisions 660979,660998,661276,661310,661999,662009,662203 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r660979 | vhennebert | 2008-05-28 16:24:23 +0100 (Wed, 28 May 2008) | 3 lines 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. ........ r660998 | maxberger | 2008-05-28 17:10:32 +0100 (Wed, 28 May 2008) | 1 line Implemented Font auto-selection word-by-word ........ r661276 | vhennebert | 2008-05-29 10:58:06 +0100 (Thu, 29 May 2008) | 2 lines Set svn:keywords and svn:eol-style properties for files added in revision 660998 ........ r661310 | maxberger | 2008-05-29 13:03:48 +0100 (Thu, 29 May 2008) | 1 line Added docs for my recent commit (word-by-word character selection) ........ r661999 | adelmelle | 2008-05-31 11:56:05 +0100 (Sat, 31 May 2008) | 3 lines Bugzilla 45097: Leading/trailing white-space not removed from nested inline-content when there is no preceding/following text. ........ r662009 | maxberger | 2008-05-31 12:45:55 +0100 (Sat, 31 May 2008) | 1 line Code Cleanups (no functional change) ........ r662203 | maxberger | 2008-06-01 12:57:33 +0100 (Sun, 01 Jun 2008) | 1 line More code Cleanups (no functional changes) ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@662442 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/fonts.xml | 50 +- src/java/org/apache/fop/fo/FOText.java | 2 +- .../org/apache/fop/fo/XMLWhiteSpaceHandler.java | 144 ++- src/java/org/apache/fop/fonts/FontSelector.java | 142 +++ .../layoutmgr/inline/CharacterLayoutManager.java | 32 +- .../fop/layoutmgr/inline/TextLayoutManager.java | 1223 ++++++++++---------- .../fop/layoutmgr/list/ListItemLayoutManager.java | 30 +- .../org/apache/fop/layoutmgr/table/ActiveCell.java | 25 +- .../apache/fop/layoutmgr/table/TableStepper.java | 11 +- status.xml | 7 + test/layoutengine/disabled-testcases.xml | 18 - .../standard-testcases/block_font-autoselect.xml | 54 + .../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 +++ .../inline_white-space-treatment_bugzilla45097.xml | 79 ++ 17 files changed, 1376 insertions(+), 755 deletions(-) create mode 100644 src/java/org/apache/fop/fonts/FontSelector.java create mode 100644 test/layoutengine/standard-testcases/block_font-autoselect.xml create mode 100644 test/layoutengine/standard-testcases/footnote_in_list_2.xml create mode 100644 test/layoutengine/standard-testcases/footnote_in_table_2.xml create mode 100644 test/layoutengine/standard-testcases/inline_white-space-treatment_bugzilla45097.xml (limited to 'src/java') 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 @@

      - - +
      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/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/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/src/java/org/apache/fop/fonts/FontSelector.java b/src/java/org/apache/fop/fonts/FontSelector.java new file mode 100644 index 000000000..ec5ea26bf --- /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$ */ + +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..6ae909cd7 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. @@ -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; @@ -31,8 +30,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.FontTriplet; +import org.apache.fop.fonts.FontSelector; import org.apache.fop.layoutmgr.InlineKnuthSequence; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -62,23 +60,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; - - AreaInfo(short startIndex, - short breakIndex, - short wordSpaceCount, - short letterSpaceCount, - MinOptMax areaIPD, - boolean isHyphenated, - boolean isSpace, - boolean breakOppAfter) { + private final 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; @@ -87,16 +87,18 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.isHyphenated = isHyphenated; this.isSpace = isSpace; this.breakOppAfter = breakOppAfter; + this.font = font; } public String toString() { - return "[ lscnt=" + letterSpaceCount - + ", wscnt=" + wordSpaceCount - + ", ipd=" + areaIPD.toString() - + ", sidx=" + startIndex - + ", bidx=" + breakIndex - + ", hyph=" + isHyphenated - + ", space=" + isSpace + 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 + "]"; } @@ -104,11 +106,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; } @@ -117,10 +119,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 = "-/"; @@ -128,18 +130,19 @@ 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'; - 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,16 +153,12 @@ 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; private short thisStart = 0; private short tempStart = 0; - private LinkedList changeList = null; + private List changeList = null; private AlignmentContext alignmentContext = null; @@ -175,24 +174,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); } @@ -200,29 +199,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() { - FontInfo fi = foText.getFOEventHandler().getFontInfo(); - FontTriplet[] fontkeys = foText.getCommonFont().getFontState(fi); - font = fi.getFontInstance(fontkeys[0], foText.getCommonFont().fontSize.getValue(this)); + + this.spaceFont = FontSelector.selectFontForCharacterInText(' ', this.foText, this); // With CID fonts, space isn't neccesary currentFontState.width(32) - spaceCharIPD = font.getCharWidth(' '); + this.spaceCharIPD = this.spaceFont.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()); + // TODO: Use hyphen based on actual font used! + this.hyphIPD = this.foText.getCommonHyphenation().getHyphIPD(this.spaceFont); + + final SpaceVal ls = SpaceVal.makeLetterSpacing(this.foText.getLetterSpacing()); - 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()); + 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; @@ -235,10 +230,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; } @@ -252,10 +248,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 = null; + AreaInfo ai; int wordSpaceCount = 0; int letterSpaceCount = 0; int firstAreaInfoIndex = -1; @@ -265,36 +261,57 @@ 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(); + final LeafPosition tbpNext = (LeafPosition) posIter.next(); if (tbpNext == null) { continue; //Ignore elements without Positions } if (tbpNext.getLeafPos() != -1) { - ai = (AreaInfo) vecAreaInfo.get(tbpNext.getLeafPos()); - if (firstAreaInfoIndex == -1) { + ai = (AreaInfo) this.vecAreaInfo.get(tbpNext.getLeafPos()); + 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); } - int textLength = ai.breakIndex - ai.startIndex; + } + + 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. + 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++; } @@ -302,60 +319,57 @@ 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, lastAreaInfoIndex, - context.isLastArea()); + 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 // but the renderer needs to know the adjustment in relation @@ -370,14 +384,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); } /** @@ -391,11 +405,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) { + 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 @@ -409,11 +424,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 @@ -421,12 +437,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)); @@ -440,7 +456,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 @@ -448,17 +464,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(); @@ -472,7 +490,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; @@ -480,18 +498,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); } } @@ -507,26 +525,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: @@ -539,253 +558,248 @@ 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) { - //Word boundary found, process widths and kerning - short lastIndex = nextStart; - while (lastIndex > 0 && textArray[lastIndex - 1] == CharUtilities.SOFT_HYPHEN) { - lastIndex--; - } - int wordLength = lastIndex - thisStart; - boolean kerning = font.hasKerning(); - MinOptMax wordIPD = new MinOptMax(0); - for (int i = thisStart; i < lastIndex; i++) { - char c = textArray[i]; - - //character width - int charWidth = font.getCharWidth(c); - wordIPD.add(charWidth); - - //kerning - if (kerning) { - int kern = 0; - if (i > thisStart) { - char previous = 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]; - 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) { - int kern = font.getKernValue(textArray[lastIndex - 1], ch) * font.getFontSize() / 1000; - if (kern != 0) { - 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)) { - iLetterSpaces++; - } - wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); - - // create the AreaInfo object - ai = new AreaInfo(thisStart, lastIndex, (short) 0, - (short) iLetterSpaces, - wordIPD, textArray[lastIndex] == CharUtilities.SOFT_HYPHEN, false, breakOpportunity); - prevAi = ai; - vecAreaInfo.add(ai); - tempStart = nextStart; - - //add the elements - addElementsForAWordFragment(sequence, alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD); - ai = null; - thisStart = nextStart; + if (breakOpportunity || TextLayoutManager.isSpace(ch) + || ch == TextLayoutManager.NEWLINE) { + // 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(thisStart, nextStart, - (short) (nextStart - thisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), - false, true, breakOpportunity); - vecAreaInfo.add(ai); - prevAi = ai; - - // create the elements - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); - ai = null; - - thisStart = nextStart; + prevAi = this.processWhitespace(alignment, sequence, + breakOpportunity); } } else { if (ai != null) { - vecAreaInfo.add(ai); prevAi = ai; - ai.breakOppAfter = (ch == CharUtilities.SPACE) || breakOpportunity; - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); - ai = null; + ai = this.processLeftoverAi(alignment, sequence, ai, ch, + ch == CharUtilities.SPACE || breakOpportunity); } if (breakAction == LineBreakStatus.EXPLICIT_BREAK) { - if (lineEndBAP != 0) { - sequence.add( - new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, true)); - } - sequence.endSequence(); - sequence = new InlineKnuthSequence(); - returnList.add(sequence); + sequence = this.processLinebreak(returnList, sequence); } } - 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); - 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 - MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); - ai = new AreaInfo(nextStart, (short) (nextStart + 1), - (short) 0, (short) 0, - ipd, false, true, breakOpportunity); - thisStart = (short) (nextStart + 1); - } else if (ch == NEWLINE) { + 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, + breakOpportunity, font); + 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) { - lastIndex--; - } - int wordLength = lastIndex - thisStart; - boolean kerning = font.hasKerning(); - MinOptMax wordIPD = new MinOptMax(0); - for (int i = thisStart; i < lastIndex; i++) { - char c = textArray[i]; - - //character width - int charWidth = font.getCharWidth(c); - wordIPD.add(charWidth); - - //kerning - if (kerning) { - int kern = 0; - 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.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; - wordIPD.add(MinOptMax.multiply(letterSpaceIPD, iLetterSpaces)); - - // create the AreaInfo object - ai = new AreaInfo(thisStart, (short)lastIndex, (short) 0, - (short) iLetterSpaces, - wordIPD, false, false, false); - vecAreaInfo.add(ai); - tempStart = nextStart; - - // create the elements - addElementsForAWordFragment(sequence, alignment, ai, - vecAreaInfo.size() - 1, letterSpaceIPD); - ai = null; + this.processWord(alignment, sequence, prevAi, ch, false, false); } else if (inWhitespace) { - ai = new AreaInfo(thisStart, (short) (nextStart), - (short) (nextStart - thisStart), (short) 0, - MinOptMax.multiply(wordSpaceIPD, nextStart - thisStart), - false, true, true); - vecAreaInfo.add(ai); - - // create the elements - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); - ai = null; + this.processWhitespace(alignment, sequence, true); } else if (ai != null) { - vecAreaInfo.add(ai); - ai.breakOppAfter = ch == CharUtilities.ZERO_WIDTH_SPACE; - addElementsForASpace(sequence, alignment, ai, vecAreaInfo.size() - 1); - ai = null; - } else if (ch == NEWLINE) { - if (lineEndBAP != 0) { - sequence.add - (new KnuthGlue(lineEndBAP, 0, 0, - auxiliaryPosition, true)); - } - sequence.endSequence(); - sequence = new InlineKnuthSequence(); - returnList.add(sequence); + ai = this.processLeftoverAi(alignment, sequence, ai, ch, + ch == CharUtilities.ZERO_WIDTH_SPACE); + } else if (ch == TextLayoutManager.NEWLINE) { + sequence = this.processLinebreak(returnList, sequence); } if (((List)returnList.getLast()).size() == 0) { //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; + } + } + + 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(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; @@ -798,10 +812,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(); @@ -812,30 +826,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; @@ -850,12 +865,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; @@ -866,115 +881,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((short) startIndex, (short) stopIndex, - (short) 0, - (short) (isWordEnd - ? (stopIndex - startIndex - 1) - : (stopIndex - startIndex)), - newIPD, hyphenFollows, false, false), - ((LeafPosition) pos).getLeafPos())); + this.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; } - 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 { @@ -984,195 +997,133 @@ 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: - // 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(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - - (lineStartBAP + 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, - 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(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue( - - (lineStartBAP + 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, - 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( - - (lineStartBAP + 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, - 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( - - (lineStartBAP + 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, - 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(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - 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(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - 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 (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(ai.areaIPD.opt - - (lineStartBAP + lineEndBAP), -3 + 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(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - auxiliaryPosition, false)); - } else { - baseList.add(new KnuthGlue(0, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - auxiliaryPosition, false)); - baseList.add(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 (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - 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(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - 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 (lineStartBAP != 0 || lineEndBAP != 0) { - baseList.add(new KnuthGlue(lineEndBAP, 0, 0, - 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(makeAuxiliaryZeroWidthBox()); - baseList.add(makeZeroWidthPenalty(KnuthPenalty.INFINITE)); - baseList.add(new KnuthGlue(lineStartBAP, 0, 0, - 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)); } } } - 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 @@ -1180,138 +1131,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 @@ -1319,11 +1284,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)); } } } - + } } 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/status.xml b/status.xml index 593d1c567..730edccac 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,13 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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. + Support character-by-character font-selection strategy on fo:character element. 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/block_font-autoselect.xml b/test/layoutengine/standard-testcases/block_font-autoselect.xml new file mode 100644 index 000000000..55406ad73 --- /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 + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + +
      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 209279e7e51cde75a3b04c4433aa7c6dd112e389 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 2 Jun 2008 14:12:03 +0000 Subject: Just cleanup. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@662443 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/afp/AFPGraphics2D.java | 90 +++++----------------- 1 file changed, 19 insertions(+), 71 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java index f8737d91a..5b922fd26 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java @@ -34,24 +34,20 @@ import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.PathIterator; import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import java.awt.image.RenderedImage; import java.awt.image.renderable.RenderableImage; import java.io.IOException; import org.apache.batik.ext.awt.geom.ExtendedGeneralPath; -import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.render.afp.goca.GraphicsSetLineType; import org.apache.fop.render.afp.modca.GraphicsObject; -import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; import org.apache.xmlgraphics.java2d.StrokingTextHandler; import org.apache.xmlgraphics.java2d.TextHandler; -import org.apache.xmlgraphics.ps.ImageEncodingHelper; /** * This is a concrete implementation of AbstractGraphics2D (and @@ -78,8 +74,8 @@ public class AFPGraphics2D extends AbstractGraphics2D { /** Current AFP state */ private AFPState afpState = null; - /** The SVG document URI */ - private String documentURI = null; +// /** The SVG document URI */ +// private String documentURI = null; /** * @param textAsShapes @@ -215,10 +211,9 @@ public class AFPGraphics2D extends AbstractGraphics2D { int[] coords = null; if (shape instanceof GeneralPath || shape instanceof ExtendedGeneralPath) { // graphics segment opening coordinates (x,y) - int[] openingCoords = new int[2]; // current position coordinates (x,y) - int[] currCoords = new int[2]; - NEXT_ITER: while (!iter.isDone()) { + for (int[] openingCoords = new int[2], currCoords = new int[2]; + !iter.isDone(); iter.next()) { // round the coordinate values and combine with current position // coordinates int type = iter.currentSegment(vals); @@ -252,8 +247,7 @@ public class AFPGraphics2D extends AbstractGraphics2D { log.debug("Unrecognised path iterator type: " + type); } - iter.next(); - continue NEXT_ITER; + continue; } // combine current position coordinates with new graphics // segment coordinates @@ -273,7 +267,6 @@ public class AFPGraphics2D extends AbstractGraphics2D { currCoords[0] = coords[coords.length - 2]; currCoords[1] = coords[coords.length - 1]; } - iter.next(); } } else if (shape instanceof Line2D) { iter.currentSegment(vals); @@ -412,37 +405,6 @@ public class AFPGraphics2D extends AbstractGraphics2D { log.debug("drawImage(): NYI img=" + img + ", x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + ", obs=" + observer); return false; -// log.debug("drawImage() img=" + img + ", x=" + x + ", y=" + y -// + ", width=" + width + ", height=" + height + ", obs=" + observer); -// if (img instanceof BufferedImage) { -// try { -// BufferedImage bi = (BufferedImage)img; -// ByteArrayOutputStream baout = new ByteArrayOutputStream(); -// -// // Serialize image -// ImageEncodingHelper.encodeRenderedImageAsRGB(bi, baout); -// -// int res = afpInfo.getResolution(); -// ImageObjectParameters params = new ImageObjectParameters( -// //TODO: provide a real url -// img.toString(), x, y, -// width, height, res, res, baout.toByteArray(), -// img.getWidth(observer), img.getHeight(observer), -// afpInfo.isColorSupported(), afpInfo.getBitsPerPixel()); -// -// afpInfo.getAFPDataStream().createImageObject(params); -// -// // Generate image -// } catch (IOException ioe) { -// log.error("Error while serializing bitmap: " + ioe.getMessage(), -// ioe); -// return false; -// } -// return true; -// } else { -// log.debug("drawImage() image type not supported: " + img); -// } -// return false; } /** @@ -486,40 +448,26 @@ public class AFPGraphics2D extends AbstractGraphics2D { this.customTextHandler = handler; } -// /** -// * Sets the SVG document URI -// * @param documentURI the SVG document URI -// */ -// public void setDocumentURI(String documentURI) { -// this.documentURI = documentURI; -// } - /** * @return the GOCA graphics object */ protected GraphicsObject getGraphicsObject() { -// if (this.graphicsObj == null) { -//// DataObjectParameters params = new DataObjectParameters( -//// ((AbstractDocument)doc).getDocumentURI(), -//// afpInfo.getX(), afpInfo.getY(), -//// afpInfo.getWidth(), afpInfo.getHeight(), res, res); -//// -//// afpInfo.getAFPDataStream().createGraphicsObject(params); -// -// int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000); -// int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000); -// int res = afpInfo.getResolution(); -// int width = (int)Math.round((afpInfo.getWidth() * res) / 72000f); -// int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f); -// DataObjectParameters params = new DataObjectParameters( -// this.documentURI, x, y, width, height, res, res); -// IncludeObject includeObj = afpInfo.getAFPDataStream().createGraphicsObject(params); -// this.graphicsObj = (GraphicsObject)includeObj.getReferencedObject(); -// } return this.graphicsObj; } - protected void setGraphicsObject(GraphicsObject graphicsObj) { - this.graphicsObj = graphicsObj; + /** + * Sets the graphics object + * @param obj the graphics object + */ + protected void setGraphicsObject(GraphicsObject obj) { + this.graphicsObj = obj; } + +// /** +// * Sets the SVG document URI +// * @param documentURI the SVG document URI +// */ +// public void setDocumentURI(String documentURI) { +// this.documentURI = documentURI; +// } } \ No newline at end of file -- cgit v1.2.3 From f12468ebca3f5ccb89483380af3b0955bd756622 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 2 Jun 2008 14:12:49 +0000 Subject: Just cleanup. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@662444 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/render/afp/modca/MapCodedFont.java | 42 +++++++++------------- 1 file changed, 16 insertions(+), 26 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java b/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java index d4b868bcb..4518be9f1 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java +++ b/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java @@ -42,7 +42,7 @@ import org.apache.fop.render.afp.tools.BinaryUtils; * * @author Pete Townsend */ -public class MapCodedFont extends AbstractAFPObject { +public class MapCodedFont extends AbstractStructuredAFPObject { /** * The collection of map coded fonts (maximum of 254) @@ -53,32 +53,30 @@ public class MapCodedFont extends AbstractAFPObject { * Constructor for the MapCodedFont */ public MapCodedFont() { - fontList = new java.util.ArrayList(); - } /** - * Accessor method to write the AFP datastream for the Map Coded Font - * @param os The stream to write to - * @throws java.io.IOException an I/O exception of some sort has occurred + * {@inheritDoc} */ public void write(OutputStream os) throws IOException { - + byte[] startData = new byte[] { + 0x5A, + 0x00, // Reserved + 0x00, // Reserved + (byte)0xD3, + (byte)0xAB, // Format 2 + (byte)0x8A, + 0x00, // Reserved + 0x00, // Reserved + 0x00, // Reserved + }; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write(0x5A); - baos.write(new byte[] {0x00, 0x00}); - - // Field identifier for a MapCodedFont - baos.write(new byte[] {(byte) 0xD3, (byte) 0xAB, (byte) 0x8A}); + baos.write(startData); - // Reserved - baos.write(new byte[] {0x00, 0x00, 0x00}); - - Iterator iter = fontList.iterator(); while (iter.hasNext()) { - FontDefinition fd = (FontDefinition) iter.next(); // Start of repeating groups (occurs 1 to 254) @@ -186,9 +184,7 @@ public class MapCodedFont extends AbstractAFPObject { } try { - if (font instanceof RasterFont) { - RasterFont raster = (RasterFont) font; CharacterSet cs = raster.getCharacterSet(size); if (cs == null) { @@ -218,7 +214,6 @@ public class MapCodedFont extends AbstractAFPObject { } } else if (font instanceof OutlineFont) { - OutlineFont outline = (OutlineFont) font; CharacterSet cs = outline.getCharacterSet(); fd.characterSet = cs.getNameBytes(); @@ -236,7 +231,6 @@ public class MapCodedFont extends AbstractAFPObject { AFPConstants.EBCIDIC_ENCODING) + " must have a fixed length of 8 characters."); } - } else { String msg = "Font of type " + font.getClass().getName() + " not recognized."; @@ -245,22 +239,19 @@ public class MapCodedFont extends AbstractAFPObject { } if (fontList.size() > 253) { - // Throw an exception if the size is exceeded throw new MaximumSizeExceededException(); - } else { fontList.add(fd); } } catch (UnsupportedEncodingException ex) { - throw new FontRuntimeException("Failed to create font " + " due to a UnsupportedEncodingException", ex); - } } + /** * Private utility class used as a container for font attributes */ @@ -290,7 +281,6 @@ public class MapCodedFont extends AbstractAFPObject { * The scale (only specified for outline fonts) */ private int scale = 0; - } } \ No newline at end of file -- cgit v1.2.3 From b7afb754ecf4e1d7d242e87cae68499272e827e7 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 2 Jun 2008 14:30:39 +0000 Subject: * getImageUri() implementation provided on Graphics2DAdaptor implementations. * Refactored data object creation abilities from AbstractResourceGroupContainer into a new DataObjectFactory class. * Added mime type to ObjectType inner class in Registry for warn/error logging purposes. * Fixed problem with handling ObjectContainer objects in IncludeObject. * Added documentation for configuring AFP resource group files. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@662448 13f79535-47bb-0310-9956-ffa450edef68 --- conf/fop.xconf | 2 + .../content/xdocs/trunk/configuration.xml | 28 ++++ src/documentation/content/xdocs/trunk/output.xml | 14 +- src/java/org/apache/fop/events/EventFormatter.xml | 1 + .../image/loader/batik/ImageConverterSVG2G2D.java | 5 +- .../image/loader/batik/ImageConverterWMF2G2D.java | 4 + .../inline/ExternalGraphicLayoutManager.java | 8 +- .../fop/render/AbstractGenericSVGHandler.java | 7 +- .../fop/render/AbstractGraphics2DAdapter.java | 8 + .../fop/render/afp/AFPGraphics2DAdapter.java | 16 +- .../org/apache/fop/render/afp/AFPRenderer.java | 109 ++++++------- .../fop/render/afp/AFPRendererConfigurator.java | 63 ++++---- .../org/apache/fop/render/afp/ResourceInfo.java | 4 +- .../render/afp/extensions/AFPElementMapping.java | 15 +- .../apache/fop/render/afp/modca/AFPDataStream.java | 34 ++-- .../afp/modca/AbstractResourceGroupContainer.java | 87 ++-------- .../fop/render/afp/modca/DataObjectFactory.java | 180 +++++++++++++++++++++ .../fop/render/afp/modca/GraphicsObject.java | 2 +- .../apache/fop/render/afp/modca/IncludeObject.java | 10 +- .../org/apache/fop/render/afp/modca/Registry.java | 32 +++- .../apache/fop/render/afp/modca/ResourceGroup.java | 35 +--- .../fop/render/java2d/Java2DGraphics2DAdapter.java | 4 +- .../org/apache/fop/render/pcl/PCLRenderer.java | 8 + .../apache/fop/render/ps/PSGraphics2DAdapter.java | 3 +- 24 files changed, 425 insertions(+), 254 deletions(-) create mode 100644 src/java/org/apache/fop/render/afp/modca/DataObjectFactory.java (limited to 'src/java') diff --git a/conf/fop.xconf b/conf/fop.xconf index 53cd142c9..c1bdc3ffb 100644 --- a/conf/fop.xconf +++ b/conf/fop.xconf @@ -110,7 +110,9 @@ the location of this file. --> 240 + resources.afp + +

      + By default if there is no configuration definition for "resource-group-file" all resources will be placed inline within the containing page. +

      +
      diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index 628df1248..46fcddd71 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -454,7 +454,7 @@ out = proc.getOutputStream();]]>
      Configuration
      - Fonts + 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 @@ -590,7 +590,7 @@ out = proc.getOutputStream();]]>

      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 can be overridden by the <images/> configuration element. Example:

      ]]> @@ -601,6 +601,16 @@ out = proc.getOutputStream();]]>

      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.

      +
      + Resource Group File +

      By default the AFP Renderer will place all data resource objects such as images within + the document of the main output datastream. An external resource group file where document resources + may be specified with the <resource-group-file/> configuration element. Example:

      + external_resources.afp +]]> + Be careful when using this option not to overwrite existing resource files from previous rendering runs. +
      Extensions diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml index 3e6cc181e..dc9321a39 100644 --- a/src/java/org/apache/fop/events/EventFormatter.xml +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -26,6 +26,7 @@ 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. + The element must be a child of fo:instream-foreign-object or fo:external-graphic. 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}} 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 be0995d8c..564eddae6 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -59,7 +59,7 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { private static Log log = LogFactory.getLog(ImageConverterSVG2G2D.class); /** {@inheritDoc} */ - public Image convert(Image src, Map hints) throws ImageException { + public Image convert(final Image src, Map hints) throws ImageException { checkSourceFlavor(src); final ImageXMLDOM svg = (ImageXMLDOM)src; if (!SVGDOMImplementation.SVG_NAMESPACE_URI.equals(svg.getRootNamespace())) { @@ -105,6 +105,9 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { return new Dimension(svg.getSize().getWidthMpt(), svg.getSize().getHeightMpt()); } + public String getImageUri() { + return src.getInfo().getOriginalURI(); + } }; ImageGraphics2D g2dImage = new ImageGraphics2D(src.getInfo(), painter); diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java index 6babe4523..22fe023aa 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java @@ -101,6 +101,10 @@ public class ImageConverterWMF2G2D extends AbstractImageConverter { log.debug("Painting WMF took " + duration + " ms."); } } + + public String getImageUri() { + return wmf.getInfo().getOriginalURI(); + } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java index ab05d60c3..5e3c0e2fa 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java @@ -37,12 +37,16 @@ public class ExternalGraphicLayoutManager extends AbstractGraphicsLayoutManager */ public ExternalGraphicLayoutManager(ExternalGraphic node) { super(node); - fobj = node; + this.fobj = node; } /** {@inheritDoc} */ protected Area getChildArea() { - return new Image(fobj.getSrc()); + Image img = new Image(fobj.getSrc()); + if (fobj.hasExtensionAttachments()) { + img.setExtensionAttachments(fobj.getExtensionAttachments()); + } + return img; } } diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index 185aed817..af3c5ae27 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -84,12 +84,13 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC //Build the GVT tree final GraphicsNode root; + final String uri = getDocumentURI(doc); try { root = builder.build(ctx, doc); } catch (Exception e) { SVGEventProducer eventProducer = SVGEventProducer.Provider.get( context.getUserAgent().getEventBroadcaster()); - eventProducer.svgNotBuilt(this, e, getDocumentURI(doc)); + eventProducer.svgNotBuilt(this, e, uri); return; } @@ -111,6 +112,10 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC public Dimension getImageSize() { return new Dimension(wrappedContext.getWidth(), wrappedContext.getHeight()); } + + public String getImageUri() { + return uri; + } }; diff --git a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java index bc7bb95a1..cc747f9d9 100644 --- a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java @@ -32,9 +32,11 @@ 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; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; /** * Graphics2DAdapter implementation for PCL and HP GL/2. @@ -135,4 +137,10 @@ 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(painter, context, null, x, y, width, height); +// } } diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index 1531e6d86..1dd6782d8 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -28,6 +28,8 @@ import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.RendererContext; @@ -37,6 +39,9 @@ import org.apache.fop.render.RendererContext; */ public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter { + /** logging instance */ + private static Log log = LogFactory.getLog(AFPGraphics2DAdapter.class); + /** * Main constructor */ @@ -57,19 +62,18 @@ public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter { //Paint to a BufferedImage int resolution = (int)Math.round(userAgent.getTargetResolution()); - BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, gray, false); - + BufferedImage bi + = paintToBufferedImage(painter, wrappedContext, resolution, gray, false); ImageManager manager = userAgent.getFactory().getImageManager(); ImageSessionContext sessionContext = userAgent.getImageSessionContext(); - - //TODO: AC - fix - String uri = null; - + try { + String uri = painter.getImageUri(); ImageInfo info = manager.getImageInfo(uri, sessionContext); java.util.Map foreignAttributes = null; afp.drawBufferedImage(info, bi, resolution, x, y, width, height, foreignAttributes); } catch (ImageException e) { + log.error(e); } } } diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index fbcd368fd..6a628235f 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -169,12 +169,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * The map of page segments */ - private Map/**/pageSegmentsMap = null; + private Map/**/pageSegmentsMap = null; /** * The fonts on the current page */ - private Map/**/getCurrentPageFonts() { if (currentPageFontMap == null) { - this.currentPageFontMap = new java.util.HashMap/* - * */(); } return this.currentPageFontMap; } @@ -492,42 +489,41 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } - /** - * {@inheritDoc} - */ - // TODO - AC fix - protected void drawBackAndBorders(Area area, float startx, float starty, - float width, float height) { - super.drawBackAndBorders(area, startx, starty, width, height); - Trait.Background back = (Trait.Background) area - .getTrait(Trait.BACKGROUND); - - // the current block has a background so its contents are placed inside - // an overlay - // after drawing the background and borders - if (back != null) { - int x = pts2units(startx); - int y = pts2units(starty); - int w = mpts2units(width); - int h = mpts2units(height); - int res = getResolution(); - final int rotation = 0; - getAFPDataStream().startOverlay(x, y, w, h, res, res, rotation); -// Color col = back.getColor(); -// getAFPDataStream().createShading(x, y, w, h, col); - } - } - // /** // * {@inheritDoc} // */ - protected void renderBlock(Block block) { -// // new block so start page segment -//// getAFPDataStream().startPageSegment(); - super.renderBlock(block); - getAFPDataStream().endOverlay(); -//// getAFPDataStream().endPageSegment(); - } +// protected void drawBackAndBorders(Area area, float startx, float starty, +// float width, float height) { +// super.drawBackAndBorders(area, startx, starty, width, height); +// Trait.Background back = (Trait.Background) area +// .getTrait(Trait.BACKGROUND); +// +// // the current block has a background so its contents are placed inside +// // an overlay +// // after drawing the background and borders +// if (back != null) { +// int x = pts2units(startx); +// int y = pts2units(starty); +// int w = mpts2units(width); +// int h = mpts2units(height); +// int res = getResolution(); +// final int rotation = 0; +// getAFPDataStream().startOverlay(x, y, w, h, res, res, rotation); +//// Color col = back.getColor(); +//// getAFPDataStream().createShading(x, y, w, h, col); +// } +// } +// +//// /** +//// * {@inheritDoc} +//// */ +// protected void renderBlock(Block block) { +//// // new block so start page segment +////// getAFPDataStream().startPageSegment(); +// super.renderBlock(block); +// getAFPDataStream().endOverlay(); +////// getAFPDataStream().endPageSegment(); +// } /** * {@inheritDoc} @@ -765,12 +761,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ public void fillRect(float x, float y, float width, float height) { - getAFPDataStream().createShading( - pts2units(x), pts2units(y), pts2units(width), pts2units(height), - currentColor); -// getAFPDataStream().createLine(pts2units(x), pts2units(y), -// pts2units(x + width), pts2units(y), pts2units(height), +// getAFPDataStream().createShading( +// pts2units(x), pts2units(y), pts2units(width), pts2units(height), // currentColor); + getAFPDataStream().createLine(pts2units(x), pts2units(y), + pts2units(x + width), pts2units(y), pts2units(height), + currentColor); } /** @@ -966,11 +962,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int afpw = mpts2units(posInt.getWidth()); int afph = mpts2units(posInt.getHeight()); int afpres = getResolution(); - + String mimeType = info.getMimeType(); // create image object parameters ImageObjectInfo imageObjectInfo = new ImageObjectInfo(); imageObjectInfo.setUri(uri); - imageObjectInfo.setMimeType(info.getMimeType()); + imageObjectInfo.setMimeType(mimeType); imageObjectInfo.setX(afpx); imageObjectInfo.setY(afpy); imageObjectInfo.setWidth(afpw); @@ -978,14 +974,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { imageObjectInfo.setWidthRes(afpres); imageObjectInfo.setHeightRes(afpres); imageObjectInfo.setData(buf); - imageObjectInfo - .setDataHeight(ccitt.getSize().getHeightPx()); + imageObjectInfo.setDataHeight(ccitt.getSize().getHeightPx()); imageObjectInfo.setDataWidth(ccitt.getSize().getWidthPx()); imageObjectInfo.setColor(colorImages); imageObjectInfo.setBitsPerPixel(bitsPerPixel); imageObjectInfo.setCompression(ccitt.getCompression()); - imageObjectInfo - .setResourceInfoFromForeignAttributes(foreignAttributes); + imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); getAFPDataStream().createObject(imageObjectInfo); } else if (img instanceof ImageXMLDOM) { ImageXMLDOM imgXML = (ImageXMLDOM) img; @@ -1074,8 +1068,10 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // create image object parameters ImageObjectInfo imageObjectInfo = new ImageObjectInfo(); - imageObjectInfo.setUri(imageInfo.getOriginalURI()); - imageObjectInfo.setMimeType(imageInfo.getMimeType()); + if (imageInfo != null) { + imageObjectInfo.setUri(imageInfo.getOriginalURI()); + imageObjectInfo.setMimeType(imageInfo.getMimeType()); + } imageObjectInfo.setX(mpts2units(x)); imageObjectInfo.setY(mpts2units(y)); imageObjectInfo.setWidth(mpts2units(w)); @@ -1373,9 +1369,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { && pageViewport.getExtensionAttachments().size() > 0) { // Extract all AFPPageSetup instances from the attachment list on // the s-p-m - Iterator i = pageViewport.getExtensionAttachments().iterator(); - while (i.hasNext()) { - ExtensionAttachment attachment = (ExtensionAttachment) i.next(); + Iterator it = pageViewport.getExtensionAttachments().iterator(); + while (it.hasNext()) { + ExtensionAttachment attachment = (ExtensionAttachment) it.next(); if (AFPPageSetup.CATEGORY.equals(attachment.getCategory())) { AFPPageSetup aps = (AFPPageSetup) attachment; String element = aps.getElementName(); @@ -1702,5 +1698,4 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { protected boolean isGOCAEnabled() { return this.gocaEnabled; } - } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index c75205c12..8277418d4 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -242,42 +242,39 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240)); } + // TODO: provide support for different MO:DCA interchange sets // the MO:DCA interchange set in use (defaults to MO:DCA-L) - Configuration interchangeSetCfg = cfg.getChild("interchange-set", false); - if (interchangeSetCfg != null) { - String interchangeSetString = interchangeSetCfg.getAttribute( - "name", InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2); - AFPDataStream afpDatastream = afpRenderer.getAFPDataStream(); - InterchangeSet interchangeSet = InterchangeSet.valueOf(interchangeSetString); - afpDatastream.setInterchangeSet(interchangeSet); +// Configuration modcaCfg = cfg.getChild("modca", false); +// if (modcaCfg != null) { +// String interchangeSetString = cfg.getAttribute( +// "interchange-set", InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2); +// InterchangeSet interchangeSet = InterchangeSet.valueOf(interchangeSetString); +// afpRenderer.getAFPDataStream().setInterchangeSet(interchangeSet); +// } - if (interchangeSet.supportsLevel2()) { - - // a default external resource group file setting - Configuration resourceGroupFileCfg - = interchangeSetCfg.getChild("resource-group-file", false); - if (resourceGroupFileCfg != null) { - String resourceGroupDest = null; - try { - resourceGroupDest = resourceGroupFileCfg.getValue(); - } catch (ConfigurationException e) { - LogUtil.handleException(log, e, - userAgent.getFactory().validateUserConfigStrictly()); - } - File resourceGroupFile = new File(resourceGroupDest); - if (resourceGroupFile.canWrite()) { - afpDatastream.setDefaultResourceGroupFile(resourceGroupFile); - } else { - log.warn("Unable to write to default external resource group file '" - + resourceGroupDest); - } - } - } + // goca enabled + Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false); + if (gocaSupportCfg != null) { + afpRenderer.setGOCAEnabled(true); + } - // goca enabled - Configuration gocaSupportCfg = interchangeSetCfg.getChild("goca-enabled", false); - if (gocaSupportCfg != null) { - afpRenderer.setGOCAEnabled(true); + // a default external resource group file setting + Configuration resourceGroupFileCfg + = cfg.getChild("resource-group-file", false); + if (resourceGroupFileCfg != null) { + String resourceGroupDest = null; + try { + resourceGroupDest = resourceGroupFileCfg.getValue(); + } catch (ConfigurationException e) { + LogUtil.handleException(log, e, + userAgent.getFactory().validateUserConfigStrictly()); + } + File resourceGroupFile = new File(resourceGroupDest); + if (resourceGroupFile.canWrite()) { + afpRenderer.getAFPDataStream().setDefaultResourceGroupFile(resourceGroupFile); + } else { + log.warn("Unable to write to default external resource group file '" + + resourceGroupDest); } } } diff --git a/src/java/org/apache/fop/render/afp/ResourceInfo.java b/src/java/org/apache/fop/render/afp/ResourceInfo.java index 3c95b2f65..5bdc9c674 100644 --- a/src/java/org/apache/fop/render/afp/ResourceInfo.java +++ b/src/java/org/apache/fop/render/afp/ResourceInfo.java @@ -34,7 +34,6 @@ public class ResourceInfo { */ private ResourceLevel level = new ResourceLevel(ResourceLevel.PRINT_FILE); - /** * Sets the resource reference name * @param resourceName the resource reference name @@ -54,7 +53,8 @@ public class ResourceInfo { * {@inheritDoc} */ public String toString() { - return "ResourceInfo(" + (name != null ? "name=" + name : "" ) + ", level=" + level + ")"; + return "ResourceInfo(" + (name != null ? "name=" + name + + ", " : "") + "level=" + level + ")"; } /** diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java index 44ba63aca..c3ba2c43b 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java @@ -48,12 +48,12 @@ public class AFPElementMapping extends ElementMapping { /** include page segment element */ public static final String INCLUDE_PAGE_SEGMENT = "include-page-segment"; -// /** include resource element (external) */ -// public static final String RESOURCE = "resource"; - /** NOP */ public static final String NO_OPERATION = "no-operation"; + /** resource information (name, level, dest) */ +// public static final String RESOURCE_INFO = "resource-info"; + /** * The namespace used for AFP extensions */ @@ -94,6 +94,9 @@ public class AFPElementMapping extends ElementMapping { foObjs.put( NO_OPERATION, new AFPNoOperationMaker()); +// foObjs.put( +// RESOURCE_INFO, +// new AFPResourceInfoMaker()); } } @@ -127,6 +130,12 @@ public class AFPElementMapping extends ElementMapping { } } +// static class AFPResourceInfoMaker extends ElementMapping.Maker { +// public FONode make(FONode parent) { +// return new AFPResourceInfoElement(parent); +// } +// } + // static class AFPPageGroupMaker extends ElementMapping.Maker { // public FONode make(FONode parent) { // return new AFPElement(parent, PAGE_GROUP); diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java index fdb0e5cc3..92a5b99f2 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java @@ -41,7 +41,7 @@ import org.apache.fop.render.afp.tools.StringUtils; * conforming to a given format. Application programs can generate data streams * destined for a presentation service, archive library, presentation device or * another application program. The strategic presentation data stream - * architectures used is Mixed Object Document Content Architecture (MO:DCA�). + * architectures used is Mixed Object Document Content Architecture (MO:DCA). * * The MO:DCA architecture defines the data stream used by applications to * describe documents and object envelopes for interchange with other @@ -50,7 +50,6 @@ import org.apache.fop.render.afp.tools.StringUtils; * printed in local or distributed systems environments. Presentation fidelity * is accommodated by including resource objects in the documents that reference * them. - * */ public class AFPDataStream extends AbstractResourceGroupContainer { @@ -144,10 +143,10 @@ public class AFPDataStream extends AbstractResourceGroupContainer { private int instreamObjectCount = 0; /** - * The MO:DCA interchange set in use (default to MO:DCA-L resource set) + * The MO:DCA interchange set in use (default to MO:DCA-P IS/2 set) */ private InterchangeSet interchangeSet - = InterchangeSet.valueOf(InterchangeSet.MODCA_RESOURCE_INTERCHANGE_SET); + = InterchangeSet.valueOf(InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2); /** * The external resource group manager @@ -311,8 +310,6 @@ public class AFPDataStream extends AbstractResourceGroupContainer { resourceObject.setDataObject(currentOverlay); getResourceGroup().addObject(resourceObject); } -// currentPageGroup.getResourceEnvironmentGroup().addObject(currentOverlay); -// currentPageObject.getActiveEnvironmentGroup().createOverlay(overlayName); currentPageObject.createIncludePageOverlay(overlayName, x, y, 0); currentPage = currentOverlay; @@ -458,6 +455,9 @@ public class AFPDataStream extends AbstractResourceGroupContainer { public AbstractNamedAFPObject createObject(DataObjectInfo dataObjectInfo) { String uri = dataObjectInfo.getUri(); + if (uri == null) { + uri = "/"; + } // if this is an instream data object adjust uri to ensure that it is // unique if (uri.endsWith("/")) { @@ -486,8 +486,9 @@ public class AFPDataStream extends AbstractResourceGroupContainer { getCurrentPage().addObject(includeObject); return includeObject.getDataObject(); } else { - log.warn("data object located at '" + uri - + "' cannot be referenced with an include so it will be embedded directly"); + log.warn("data object located at '" + uri + "'" + + " of type '" + objectType.getMimeType() + "'" + + " cannot be included with an IOB so it will be embedded directly"); } } else { if (resourceLevel.isExternal()) { @@ -495,7 +496,6 @@ public class AFPDataStream extends AbstractResourceGroupContainer { + ": not available, object " + getName() + " will reside inline"); } } - } // unrecognised/unsupported object type so create/embed data object // directly in current page @@ -925,7 +925,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { .getExternalResourceGroupFile(); resourceGroup = (ResourceGroup)getExternalResourceGroups().get(resourceGroupFile); if (resourceGroup == null) { - resourceGroup = new ResourceGroup(container); + resourceGroup = new ResourceGroup(); externalResourceGroups .put(resourceGroupFile, resourceGroup); } @@ -941,20 +941,6 @@ public class AFPDataStream extends AbstractResourceGroupContainer { } } -// /** -// * Starts a new page segment. -// */ -// public void startPageSegment() { -// currentPageObject.startPageSegment(); -// } -// -// /** -// * Ends the current page segment. -// */ -// public void endPageSegment() { -// currentPageObject.endPageSegment(); -// } - /** * Sets the MO:DCA interchange set to use * @param interchangeSet the MO:DCA interchange set diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java index 5df2ed3e8..b8c1b10c1 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java @@ -23,10 +23,6 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.fop.render.afp.DataObjectInfo; -import org.apache.fop.render.afp.ImageObjectInfo; -import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; -import org.apache.fop.render.afp.tools.StringUtils; -import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; /** * An abstract container of resource objects @@ -37,6 +33,11 @@ public abstract class AbstractResourceGroupContainer extends AbstractPageObject */ private ResourceGroup resourceGroup = null; + /** + * The data object factory + */ + private DataObjectFactory dataObjectFactory = new DataObjectFactory(); + /** * Default constructor */ @@ -96,7 +97,7 @@ public abstract class AbstractResourceGroupContainer extends AbstractPageObject */ protected ResourceGroup getResourceGroup() { if (resourceGroup == null) { - resourceGroup = new ResourceGroup(this); + resourceGroup = new ResourceGroup(); } return resourceGroup; } @@ -164,84 +165,14 @@ public abstract class AbstractResourceGroupContainer extends AbstractPageObject io.setImageIDESize((byte) bitsPerPixel); io.setImageData(bw); } - - private static final String IMAGE_NAME_PREFIX = "IMG"; - private static final String GRAPHIC_NAME_PREFIX = "GRA"; - - // not currently used/implemented -// private static final String BARCODE_NAME_PREFIX = "BAR"; -// private static final String OTHER_NAME_PREFIX = "OTH"; - - /** - * Helper method to create an image on the current container and to return - * the object. - * @param info the image object info - * @return a newly created image object - */ - protected ImageObject createImage(ImageObjectInfo info) { - String name = IMAGE_NAME_PREFIX - + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); - ImageObject imageObj = new ImageObject(name); - if (info.hasCompression()) { - int compression = info.getCompression(); - switch (compression) { - case TIFFImage.COMP_FAX_G3_1D: - imageObj.setImageEncoding(ImageContent.COMPID_G3_MH); - break; - case TIFFImage.COMP_FAX_G3_2D: - imageObj.setImageEncoding(ImageContent.COMPID_G3_MR); - break; - case TIFFImage.COMP_FAX_G4_2D: - imageObj.setImageEncoding(ImageContent.COMPID_G3_MMR); - break; - default: - throw new IllegalStateException( - "Invalid compression scheme: " + compression); - } - } - imageObj.setImageParameters(info.getWidthRes(), info.getHeightRes(), - info.getDataWidth(), info.getDataHeight()); - if (info.isColor()) { - imageObj.setImageIDESize((byte)24); - imageObj.setImageData(info.getData()); - } else { - convertToGrayScaleImage(imageObj, info.getData(), - info.getDataWidth(), info.getDataHeight(), - info.getBitsPerPixel()); - } - return imageObj; - } - /** - * Helper method to create a graphic in the current container and to return - * the object. - * @param info the data object info - * @return a newly created graphics object - */ - protected GraphicsObject createGraphic(DataObjectInfo info) { - String name = GRAPHIC_NAME_PREFIX - + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); - GraphicsObject graphicsObj = new GraphicsObject(name); - return graphicsObj; - } - /** * Creates and returns a new data object - * @param info the data object parameters + * @param dataObjectInfo the data object info * @return a newly created data object */ - public AbstractNamedAFPObject createObject(DataObjectInfo info) { - AbstractNamedAFPObject dataObject; - if (info instanceof ImageObjectInfo) { - dataObject = createImage((ImageObjectInfo)info); - } else { - dataObject = createGraphic(info); - } - dataObject.setFullyQualifiedName( - FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, - FullyQualifiedNameTriplet.FORMAT_CHARSTR, dataObject.getName()); - - return dataObject; + public AbstractNamedAFPObject createObject(DataObjectInfo dataObjectInfo) { + return dataObjectFactory.create(dataObjectInfo); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/DataObjectFactory.java b/src/java/org/apache/fop/render/afp/modca/DataObjectFactory.java new file mode 100644 index 000000000..bcb506dee --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/DataObjectFactory.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.ImageObjectInfo; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.tools.StringUtils; +import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; + +/** + * Creator of MO;DCA data objects + */ +public class DataObjectFactory { + private static final String IMAGE_NAME_PREFIX = "IMG"; + private static final String GRAPHIC_NAME_PREFIX = "GRA"; +// private static final String BARCODE_NAME_PREFIX = "BAR"; +// private static final String OTHER_NAME_PREFIX = "OTH"; + + private int imageCount = 0; + private int graphicCount = 0; + + /** + * Converts a byte array containing 24 bit RGB image data to a grayscale + * image. + * + * @param io + * the target image object + * @param raw + * the buffer containing the RGB image data + * @param width + * the width of the image in pixels + * @param height + * the height of the image in pixels + * @param bitsPerPixel + * the number of bits to use per pixel + * + * TODO: move this method somewhere appropriate in commons + */ + private static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, + int height, int bitsPerPixel) { + int pixelsPerByte = 8 / bitsPerPixel; + int bytewidth = (width / pixelsPerByte); + if ((width % pixelsPerByte) != 0) { + bytewidth++; + } + byte[] bw = new byte[height * bytewidth]; + byte ib; + for (int y = 0; y < height; y++) { + ib = 0; + int i = 3 * y * width; + for (int x = 0; x < width; x++, i += 3) { + + // see http://www.jguru.com/faq/view.jsp?EID=221919 + double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d + * ((int) raw[i + 1] & 0xff) + 0.072169d + * ((int) raw[i + 2] & 0xff); + switch (bitsPerPixel) { + case 1: + if (greyVal < 128) { + ib |= (byte) (1 << (7 - (x % 8))); + } + break; + case 4: + greyVal /= 16; + ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4)); + break; + case 8: + ib = (byte) greyVal; + break; + default: + throw new UnsupportedOperationException( + "Unsupported bits per pixel: " + bitsPerPixel); + } + + if ((x % pixelsPerByte) == (pixelsPerByte - 1) + || ((x + 1) == width)) { + bw[(y * bytewidth) + (x / pixelsPerByte)] = ib; + ib = 0; + } + } + } + io.setImageIDESize((byte) bitsPerPixel); + io.setImageData(bw); + } + + /** + * Helper method to create an image on the current container and to return + * the object. + * @param info the image object info + * @return a newly created image object + */ + protected ImageObject createImage(ImageObjectInfo info) { + String name = IMAGE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++imageCount), '0', 5); + ImageObject imageObj = new ImageObject(name); + if (info.hasCompression()) { + int compression = info.getCompression(); + switch (compression) { + case TIFFImage.COMP_FAX_G3_1D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MH); + break; + case TIFFImage.COMP_FAX_G3_2D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MR); + break; + case TIFFImage.COMP_FAX_G4_2D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MMR); + break; + default: + throw new IllegalStateException( + "Invalid compression scheme: " + compression); + } + } + imageObj.setImageParameters(info.getWidthRes(), info.getHeightRes(), + info.getDataWidth(), info.getDataHeight()); + if (info.isColor()) { + imageObj.setImageIDESize((byte)24); + imageObj.setImageData(info.getData()); + } else { + convertToGrayScaleImage(imageObj, info.getData(), + info.getDataWidth(), info.getDataHeight(), + info.getBitsPerPixel()); + } + return imageObj; + } + + /** + * Helper method to create a graphic in the current container and to return + * the object. + * @param info the data object info + * @return a newly created graphics object + */ + protected GraphicsObject createGraphic(DataObjectInfo info) { + String name = GRAPHIC_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++graphicCount), '0', 5); + GraphicsObject graphicsObj = new GraphicsObject(name); + return graphicsObj; + } + + /** + * Creates and returns a new data object + * @param dataObjectInfo the data object info + * @return a newly created data object + */ + public AbstractDataObject create(DataObjectInfo dataObjectInfo) { + AbstractDataObject dataObject; + if (dataObjectInfo instanceof ImageObjectInfo) { + dataObject = createImage((ImageObjectInfo)dataObjectInfo); + } else { + dataObject = createGraphic(dataObjectInfo); + } + dataObject.setViewport(dataObjectInfo.getX(), dataObjectInfo.getY(), + dataObjectInfo.getWidth(), dataObjectInfo.getHeight(), + dataObjectInfo.getWidthRes(), dataObjectInfo.getHeightRes(), + dataObjectInfo.getRotation()); + + dataObject.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, dataObject.getName()); + + return dataObject; + } +} 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 823353375..0c260db90 100644 --- a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java @@ -67,7 +67,7 @@ public class GraphicsObject extends AbstractDataObject { public void setViewport(int x, int y, int width, int height, int widthRes, int heightRes, int rotation) { super.setViewport(x, y, width, height, widthRes, heightRes, rotation); - objectEnvironmentGroup.setGraphicsData( + getObjectEnvironmentGroup().setGraphicsData( widthRes, heightRes, 0, x + width, 0, y + height); } diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java index 1b1b6c1ed..188664264 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java @@ -117,11 +117,6 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA this.dataObjectAccessor = dataObjectAccessor; AbstractNamedAFPObject dataObject = dataObjectAccessor.getDataObject(); - // Strip any object container - if (dataObject instanceof ObjectContainer) { - ObjectContainer objectContainer = (ObjectContainer)dataObject; - dataObject = objectContainer.getDataObject(); - } if (dataObject instanceof ImageObject) { this.dataObjectType = TYPE_IMAGE; } else if (dataObject instanceof GraphicsObject) { @@ -130,6 +125,11 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA this.dataObjectType = TYPE_PAGE_SEGMENT; } else { this.dataObjectType = TYPE_OTHER; + // Strip any object container + if (dataObject instanceof ObjectContainer) { + ObjectContainer objectContainer = (ObjectContainer)dataObject; + dataObject = objectContainer.getDataObject(); + } } DataObjectInfo dataObjectInfo = dataObjectAccessor.getDataObjectInfo(); diff --git a/src/java/org/apache/fop/render/afp/modca/Registry.java b/src/java/org/apache/fop/render/afp/modca/Registry.java index 5287f1a2b..fcff8060c 100644 --- a/src/java/org/apache/fop/render/afp/modca/Registry.java +++ b/src/java/org/apache/fop/render/afp/modca/Registry.java @@ -75,7 +75,8 @@ public final class Registry { COMPID_EPS, new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D}, "Encapsulated Postscript", - false + false, + MimeConstants.MIME_EPS ) ); mimeEntryMap.put( @@ -84,7 +85,8 @@ public final class Registry { COMPID_TIFF, new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E}, "TIFF", - false + false, + MimeConstants.MIME_TIFF ) ); mimeEntryMap.put( @@ -93,7 +95,8 @@ public final class Registry { COMPID_GIF, new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16}, "GIF", - true + true, + MimeConstants.MIME_GIF ) ); mimeEntryMap.put( @@ -102,7 +105,8 @@ public final class Registry { COMPID_JFIF, new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17}, "JFIF", - true + true, + MimeConstants.MIME_JPEG ) ); mimeEntryMap.put(MimeConstants.MIME_PDF, @@ -110,7 +114,8 @@ public final class Registry { COMPID_PDF_SINGLE_PAGE, new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19}, "PDF Single-page Object", - true + true, + MimeConstants.MIME_PDF ) ); mimeEntryMap.put( @@ -119,7 +124,8 @@ public final class Registry { COMPID_PCL_PAGE_OBJECT, new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22}, "PCL Page Object", - true + true, + MimeConstants.MIME_PCL ) ); } @@ -152,6 +158,7 @@ public final class Registry { private byte[] oid; private String name; private boolean canBeIncluded; + private String mimeType; /** * Main constructor @@ -159,13 +166,15 @@ public final class Registry { * @param oid the object id of this object type * @param name the object type name * @param canBeIncluded true if this object can be included with an IOB structured field + * @param mimeType the mime type associated with this object type */ public ObjectType(byte componentId, byte[] oid, String name, - boolean canBeIncluded) { + boolean canBeIncluded, String mimeType) { this.componentId = componentId; this.oid = oid; this.name = name; this.canBeIncluded = canBeIncluded; + this.mimeType = mimeType; } /** @@ -197,7 +206,14 @@ public final class Registry { public boolean canBeIncluded() { return this.canBeIncluded; } - + + /** + * @return the mime type associated with this object type + */ + public String getMimeType() { + return this.mimeType; + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java index 9f8af3d9d..1860d8ce7 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java @@ -26,7 +26,6 @@ import java.util.Iterator; import java.util.Map; import org.apache.fop.render.afp.DataObjectInfo; -import org.apache.fop.render.afp.ImageObjectInfo; import org.apache.fop.render.afp.ResourceInfo; import org.apache.fop.render.afp.ResourceLevel; import org.apache.fop.render.afp.tools.StringUtils; @@ -44,34 +43,22 @@ public final class ResourceGroup extends AbstractNamedAFPObject { /** * Mapping of resource uri to data resource object (image/graphic) */ - private Map/**/ resourceMap = null; - - /** - * This resource groups container - */ - private AbstractResourceGroupContainer container = null; + private Map/**/ resourceMap = null; /** * Default constructor - * @param container the resource group container */ - public ResourceGroup(AbstractResourceGroupContainer container) { - this(DEFAULT_NAME, container); + public ResourceGroup() { + this(DEFAULT_NAME); } /** * Constructor for the ResourceGroup, this takes a * name parameter which must be 8 characters long. * @param name the resource group name - * @param container the parent resource group container */ - public ResourceGroup(String name, AbstractResourceGroupContainer container) { + public ResourceGroup(String name) { super(name); - this.container = container; - } - - private AbstractResourceGroupContainer getContainer() { - return this.container; } private static final String OBJECT_CONTAINER_NAME_PREFIX = "OC"; @@ -82,6 +69,8 @@ public final class ResourceGroup extends AbstractNamedAFPObject { return new ObjectContainer(name); } + private DataObjectFactory dataObjectFactory = new DataObjectFactory(); + /** * Creates a data object in this resource group * @param dataObjectInfo the data object info @@ -94,17 +83,7 @@ public final class ResourceGroup extends AbstractNamedAFPObject { ResourceLevel resourceLevel = resourceInfo.getLevel(); AbstractDataObject dataObj; if (dataObjectAccessor == null) { - if (dataObjectInfo instanceof ImageObjectInfo) { - dataObj = getContainer().createImage((ImageObjectInfo)dataObjectInfo); - } else { - dataObj = getContainer().createGraphic(dataObjectInfo); - } - - dataObj.setViewport(dataObjectInfo.getX(), dataObjectInfo.getY(), - dataObjectInfo.getWidth(), dataObjectInfo.getHeight(), - dataObjectInfo.getWidthRes(), dataObjectInfo.getHeightRes(), - dataObjectInfo.getRotation()); - + dataObj = dataObjectFactory.create(dataObjectInfo); ObjectContainer objectContainer = null; String resourceName = resourceInfo.getName(); if (resourceName != null) { 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 007ce4828..324c3558d 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -700,6 +700,10 @@ public class PCLRenderer extends PrintRenderer { public Dimension getImageSize() { return paintRect.getSize(); } + + public String getImageUri() { + return null; + } }; g2a.paintImage(painter, rc, @@ -1560,6 +1564,10 @@ public class PCLRenderer extends PrintRenderer { return paintRect.getSize(); } + public String getImageUri() { + return null; + } + }; try { g2a.paintImage(painter, rc, diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java index a592b4f44..717153b3b 100644 --- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java @@ -28,13 +28,14 @@ import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; import org.apache.xmlgraphics.ps.PSGenerator; +import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.Graphics2DAdapter; 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; -- cgit v1.2.3 From 46d76cd4f13d9da7216c4ce15359f6c75c2e00bb Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 3 Jun 2008 11:12:52 +0000 Subject: Moved image uri storing from AbstractGenericSVGHandler to AFPState as requested/suggested :). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@662738 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.4svn.jar | Bin 516681 -> 517088 bytes .../image/loader/batik/ImageConverterSVG2G2D.java | 3 -- .../image/loader/batik/ImageConverterWMF2G2D.java | 4 --- .../fop/render/AbstractGenericSVGHandler.java | 4 --- .../fop/render/AbstractGraphics2DAdapter.java | 9 ----- .../fop/render/afp/AFPGraphics2DAdapter.java | 7 ++-- .../org/apache/fop/render/afp/AFPRenderer.java | 2 +- src/java/org/apache/fop/render/afp/AFPState.java | 40 ++++++++++++++++++++- .../org/apache/fop/render/pcl/PCLRenderer.java | 8 ----- 9 files changed, 43 insertions(+), 34 deletions(-) (limited to 'src/java') diff --git a/lib/xmlgraphics-commons-1.4svn.jar b/lib/xmlgraphics-commons-1.4svn.jar index efa709c39..3f068fbd9 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/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java index 564eddae6..c8e031405 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -105,9 +105,6 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { return new Dimension(svg.getSize().getWidthMpt(), svg.getSize().getHeightMpt()); } - public String getImageUri() { - return src.getInfo().getOriginalURI(); - } }; ImageGraphics2D g2dImage = new ImageGraphics2D(src.getInfo(), painter); diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java index 22fe023aa..6babe4523 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java @@ -101,10 +101,6 @@ public class ImageConverterWMF2G2D extends AbstractImageConverter { log.debug("Painting WMF took " + duration + " ms."); } } - - public String getImageUri() { - return wmf.getInfo().getOriginalURI(); - } } diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index af3c5ae27..26b63079f 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -113,10 +113,6 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC return new Dimension(wrappedContext.getWidth(), wrappedContext.getHeight()); } - public String getImageUri() { - return uri; - } - }; //Let the painter paint the SVG on the Graphics2D instance diff --git a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java index cc747f9d9..dd1a4dd7c 100644 --- a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java @@ -32,11 +32,9 @@ 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; -import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; /** * Graphics2DAdapter implementation for PCL and HP GL/2. @@ -136,11 +134,4 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); } - -// /** {@inheritDoc} */ -// public void paintImage(Graphics2DImagePainter painter, -// RendererContext context, -// int x, int y, int width, int height) throws IOException { -// paintImage(painter, context, null, x, y, width, height); -// } } diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index 1dd6782d8..d4c1ff365 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -65,11 +65,10 @@ public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter { BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, gray, false); ImageManager manager = userAgent.getFactory().getImageManager(); - ImageSessionContext sessionContext = userAgent.getImageSessionContext(); - + ImageSessionContext sessionContext = userAgent.getImageSessionContext(); + AFPState state = (AFPState)context.getProperty(AFPRendererContextConstants.AFP_STATE); try { - String uri = painter.getImageUri(); - ImageInfo info = manager.getImageInfo(uri, sessionContext); + ImageInfo info = manager.getImageInfo(state.getImageUri(), sessionContext); java.util.Map foreignAttributes = null; afp.drawBufferedImage(info, bi, resolution, x, y, width, height, foreignAttributes); } catch (ImageException e) { diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 6a628235f..763f9dafb 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -52,7 +52,6 @@ import org.apache.xmlgraphics.ps.ImageEncodingHelper; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; -import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; @@ -912,6 +911,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** {@inheritDoc} */ public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { uri = URISpecification.getURL(uri); + getState().setImageUri(uri); Rectangle posInt = new Rectangle((int) pos.getX(), (int) pos.getY(), (int) pos.getWidth(), (int) pos.getHeight()); Point origin = new Point(currentIPPosition, currentBPPosition); diff --git a/src/java/org/apache/fop/render/afp/AFPState.java b/src/java/org/apache/fop/render/afp/AFPState.java index 5977d0de2..7c28e8bf0 100644 --- a/src/java/org/apache/fop/render/afp/AFPState.java +++ b/src/java/org/apache/fop/render/afp/AFPState.java @@ -20,7 +20,6 @@ package org.apache.fop.render.afp; import java.awt.Color; -import java.awt.geom.AffineTransform; import java.io.Serializable; import java.util.Arrays; import java.util.List; @@ -187,6 +186,27 @@ public class AFPState { return getData().pageFonts; } + /** + * Sets the image uri of the current image being processed + * @param uri the image uri of the current image being processed + * @return true if the image uri has changed + */ + public boolean setImageUri(String uri) { + if (!uri.equals(getData().imageUri)) { + getData().imageUri = uri; + return true; + } + return false; + } + + /** + * Returns the image uri of the current image being processed + * @return the image uri of the current image being processed + */ + protected String getImageUri() { + return getData().imageUri; + } + /** * Push the current state onto the stack. * This call should be used when the q operator is used @@ -234,6 +254,7 @@ public class AFPState { return data; } + /** the state data instance */ public class Data implements Cloneable, Serializable { private static final long serialVersionUID = -1789481244175275686L; @@ -261,6 +282,9 @@ public class AFPState { /** The fonts on the current page */ private AFPPageFonts pageFonts = null; + /** The current image uri */ + private String imageUri = null; + /** {@inheritDoc} */ public Object clone() throws CloneNotSupportedException { Data obj = new Data(); @@ -272,7 +296,21 @@ public class AFPState { obj.dashArray = this.dashArray; obj.filled = this.filled; obj.pageFonts = this.pageFonts; + obj.imageUri = this.imageUri; return obj; } + + /** {@inheritDoc} */ + public String toString() { + return "color=" + color + + ", backColor=" + backColor + + ", fontName=" + fontName + + ", fontSize=" + fontSize + + ", lineWidth=" + lineWidth + + ", dashArray=" + dashArray + + ", filled=" + filled + + ", pageFonts=" + pageFonts + + ", imageUri=" + imageUri; + } } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 324c3558d..e1818c84b 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -701,10 +701,6 @@ public class PCLRenderer extends PrintRenderer { return paintRect.getSize(); } - public String getImageUri() { - return null; - } - }; g2a.paintImage(painter, rc, paintRect.x, paintRect.y, paintRect.width, paintRect.height); @@ -1564,10 +1560,6 @@ public class PCLRenderer extends PrintRenderer { return paintRect.getSize(); } - public String getImageUri() { - return null; - } - }; try { g2a.paintImage(painter, rc, -- cgit v1.2.3 From a812cf1529e6bce8cdca92674f9baf3b8d8934d1 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 4 Jun 2008 10:41:55 +0000 Subject: Fix for wrong data arraycopy on OCD. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@663056 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/afp/modca/ObjectContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java index 2e06c1b2c..599cb0b40 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectContainer.java @@ -214,7 +214,7 @@ public class ObjectContainer extends AbstractNamedAFPObject implements DataObjec data[8] = 0x00; // Reserved // copy object data chunk - System.arraycopy(data, startIndex, data, 9, dataLen); + System.arraycopy(objData, startIndex, data, 9, dataLen); super.setData(data); } -- cgit v1.2.3 From 9a5c592c3adc9e66d3681f4cb63664eab9b83ea7 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 4 Jun 2008 14:27:42 +0000 Subject: Unused. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@663121 13f79535-47bb-0310-9956-ffa450edef68 --- .../afp/modca/AbstractResourceGroupContainer.java | 64 ---------------------- 1 file changed, 64 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java index b8c1b10c1..71cc4698b 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java @@ -101,70 +101,6 @@ public abstract class AbstractResourceGroupContainer extends AbstractPageObject } return resourceGroup; } - - /** - * Converts a byte array containing 24 bit RGB image data to a grayscale - * image. - * - * @param io - * the target image object - * @param raw - * the buffer containing the RGB image data - * @param width - * the width of the image in pixels - * @param height - * the height of the image in pixels - * @param bitsPerPixel - * the number of bits to use per pixel - * - * TODO: move this method somewhere appropriate in commons - */ - private static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, - int height, int bitsPerPixel) { - int pixelsPerByte = 8 / bitsPerPixel; - int bytewidth = (width / pixelsPerByte); - if ((width % pixelsPerByte) != 0) { - bytewidth++; - } - byte[] bw = new byte[height * bytewidth]; - byte ib; - for (int y = 0; y < height; y++) { - ib = 0; - int i = 3 * y * width; - for (int x = 0; x < width; x++, i += 3) { - - // see http://www.jguru.com/faq/view.jsp?EID=221919 - double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d - * ((int) raw[i + 1] & 0xff) + 0.072169d - * ((int) raw[i + 2] & 0xff); - switch (bitsPerPixel) { - case 1: - if (greyVal < 128) { - ib |= (byte) (1 << (7 - (x % 8))); - } - break; - case 4: - greyVal /= 16; - ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4)); - break; - case 8: - ib = (byte) greyVal; - break; - default: - throw new UnsupportedOperationException( - "Unsupported bits per pixel: " + bitsPerPixel); - } - - if ((x % pixelsPerByte) == (pixelsPerByte - 1) - || ((x + 1) == width)) { - bw[(y * bytewidth) + (x / pixelsPerByte)] = ib; - ib = 0; - } - } - } - io.setImageIDESize((byte) bitsPerPixel); - io.setImageData(bw); - } /** * Creates and returns a new data object -- cgit v1.2.3 From 2665e6b83c40656cc728ef356bb932387ca9207e Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 6 Jun 2008 10:38:05 +0000 Subject: Cleanup of variable names. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@663884 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/render/afp/modca/ImageContent.java | 81 ++++++++++------------ 1 file changed, 36 insertions(+), 45 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java index 7a86fdddb..65e312cb0 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageContent.java @@ -18,6 +18,7 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; import org.apache.fop.render.afp.tools.BinaryUtils; @@ -53,27 +54,27 @@ public class ImageContent extends AbstractStructuredAFPObject { /** * The image size parameter */ - private ImageSizeParameter _imageSizeParameter = null; + private ImageSizeParameter imageSizeParameter = null; /** * The image encoding */ - private byte _encoding = 0x03; + private byte encoding = (byte)0x03; /** * The image ide size */ - private byte _size = 1; + private byte size = 1; /** * The image compression */ - private byte _compression = (byte)0xC0; + private byte compression = (byte)0xC0; /** * The image color model */ - private byte _colorModel = 0x01; + private byte colorModel = (byte)0x01; /** * The image data @@ -95,7 +96,7 @@ public class ImageContent extends AbstractStructuredAFPObject { * @param vsize The vertival size of the image. */ public void setImageSize(int hresol, int vresol, int hsize, int vsize) { - _imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize); + imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize); } /** @@ -103,7 +104,7 @@ public class ImageContent extends AbstractStructuredAFPObject { * @param encoding The image encoding. */ public void setImageEncoding(byte encoding) { - _encoding = encoding; + this.encoding = encoding; } /** @@ -111,7 +112,7 @@ public class ImageContent extends AbstractStructuredAFPObject { * @param compression The image compression. */ public void setImageCompression(byte compression) { - _compression = compression; + this.compression = compression; } /** @@ -119,7 +120,7 @@ public class ImageContent extends AbstractStructuredAFPObject { * @param size The IDE size. */ public void setImageIDESize(byte size) { - _size = size; + this.size = size; } /** @@ -127,7 +128,7 @@ public class ImageContent extends AbstractStructuredAFPObject { * @param colorModel the IDE color model. */ public void setImageIDEColorModel(byte colorModel) { - _colorModel = colorModel; + this.colorModel = colorModel; } /** @@ -142,8 +143,8 @@ public class ImageContent extends AbstractStructuredAFPObject { * {@inheritDoc} */ protected void writeContent(OutputStream os) throws IOException { - if (_imageSizeParameter != null) { - _imageSizeParameter.write(os); + if (imageSizeParameter != null) { + imageSizeParameter.write(os); } os.write(getImageEncodingParameter()); os.write(getImageIDESizeParameter()); @@ -166,7 +167,7 @@ public class ImageContent extends AbstractStructuredAFPObject { protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[] { (byte)0x91, // ID - 0x01, // Length + 0x01, // Length (byte)0xff, // Object Type = IOCA Image Object }; os.write(data); @@ -178,7 +179,7 @@ public class ImageContent extends AbstractStructuredAFPObject { protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[] { (byte)0x93, // ID - 0x00, // Length + 0x00, // Length }; os.write(data); } @@ -192,17 +193,15 @@ public class ImageContent extends AbstractStructuredAFPObject { byte[] data = new byte[] { (byte)0xFE, // ID (byte)0x92, // ID - 0x00, // Length - 0x00, // Length + 0x00, // Length + 0x00, // Length }; byte[] l = BinaryUtils.convert(len, 2); data[2] = l[0]; data[3] = l[1]; - return data; - } /** @@ -210,16 +209,13 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getImageEncodingParameter() { - byte[] data = new byte[] { (byte)0x95, // ID - 0x02, // Length - _encoding, - 0x01, // RECID + 0x02, // Length + encoding, + 0x01, // RECID }; - return data; - } /** @@ -227,8 +223,7 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getExternalAlgorithmParameter() { - - if (_encoding == (byte)0x83 && _compression != 0) { + if (encoding == (byte)0x83 && compression != 0) { byte[] data = new byte[] { (byte)0x95, // ID 0x00, // Length @@ -238,7 +233,7 @@ public class ImageContent extends AbstractStructuredAFPObject { 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved - _compression, // MARKER + compression, // MARKER 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved @@ -254,15 +249,12 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getImageIDESizeParameter() { - byte[] data = new byte[] { (byte)0x96, // ID - 0x01, // Length - _size, + 0x01, // Length + size, }; - return data; - } /** @@ -270,21 +262,20 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getIDEStructureParameter() { - - if (_colorModel != 0 && _size == 24) { - byte bits = (byte)(_size / 3); + if (colorModel != 0 && size == 24) { + byte bits = (byte)(size / 3); byte[] data = new byte[] { (byte)0x9B, // ID - 0x00, // Length - 0x00, // FLAGS - 0x00, // Reserved - _colorModel, // COLOR MODEL - 0x00, // Reserved - 0x00, // Reserved - 0x00, // Reserved - bits, - bits, - bits, + 0x00, // Length + 0x00, // FLAGS + 0x00, // Reserved + colorModel, // COLOR MODEL + 0x00, // Reserved + 0x00, // Reserved + 0x00, // Reserved + bits, + bits, + bits, }; data[1] = (byte)(data.length - 2); return data; -- cgit v1.2.3 From 1dbe17e5b2edc0639f92cbb7644107dae8f6ad7e Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 9 Jun 2008 11:19:44 +0000 Subject: * Created new AreaObjectInfo class POJO to cleanup all this long parameter passingthat seems to be going on. * convertToGrayscale() method changed so that it is performing an atomic function, again simplified/cleaned up parameter passing. * Fixed bug with handling TIFF images. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@664679 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/afp/AFPRenderer.java | 37 +++--- .../fop/render/afp/AFPRendererConfigurator.java | 2 +- .../org/apache/fop/render/afp/AFPSVGHandler.java | 25 ++-- .../org/apache/fop/render/afp/DataObjectInfo.java | 141 +++----------------- .../org/apache/fop/render/afp/ImageObjectInfo.java | 19 ++- .../org/apache/fop/render/afp/ObjectAreaInfo.java | 147 +++++++++++++++++++++ .../apache/fop/render/afp/modca/AFPDataStream.java | 126 +++++++++--------- .../fop/render/afp/modca/AbstractDataObject.java | 24 +--- .../fop/render/afp/modca/DataObjectFactory.java | 65 +++++---- .../fop/render/afp/modca/GraphicsObject.java | 13 +- .../apache/fop/render/afp/modca/IncludeObject.java | 9 +- .../render/afp/modca/ObjectEnvironmentGroup.java | 22 ++- 12 files changed, 348 insertions(+), 282 deletions(-) create mode 100644 src/java/org/apache/fop/render/afp/ObjectAreaInfo.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 763f9dafb..bfdf56d2b 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -923,8 +923,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { getAFPDataStream().createIncludePageSegment(name, mpts2units(x), mpts2units(y)); } else { - ImageManager manager = getUserAgent().getFactory() - .getImageManager(); + ImageManager manager = getUserAgent().getFactory().getImageManager(); ImageInfo info = null; InputStream in = null; try { @@ -967,12 +966,16 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { ImageObjectInfo imageObjectInfo = new ImageObjectInfo(); imageObjectInfo.setUri(uri); imageObjectInfo.setMimeType(mimeType); - imageObjectInfo.setX(afpx); - imageObjectInfo.setY(afpy); - imageObjectInfo.setWidth(afpw); - imageObjectInfo.setHeight(afph); - imageObjectInfo.setWidthRes(afpres); - imageObjectInfo.setHeightRes(afpres); + + ObjectAreaInfo objectAreaInfo = new ObjectAreaInfo(); + objectAreaInfo.setX(afpx); + objectAreaInfo.setY(afpy); + objectAreaInfo.setWidth(afpw); + objectAreaInfo.setHeight(afph); + objectAreaInfo.setWidthRes(afpres); + objectAreaInfo.setHeightRes(afpres); + imageObjectInfo.setObjectAreaInfo(objectAreaInfo); + imageObjectInfo.setData(buf); imageObjectInfo.setDataHeight(ccitt.getSize().getHeightPx()); imageObjectInfo.setDataWidth(ccitt.getSize().getWidthPx()); @@ -1068,23 +1071,27 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // create image object parameters ImageObjectInfo imageObjectInfo = new ImageObjectInfo(); + imageObjectInfo.setBuffered(true); if (imageInfo != null) { imageObjectInfo.setUri(imageInfo.getOriginalURI()); imageObjectInfo.setMimeType(imageInfo.getMimeType()); } - imageObjectInfo.setX(mpts2units(x)); - imageObjectInfo.setY(mpts2units(y)); - imageObjectInfo.setWidth(mpts2units(w)); - imageObjectInfo.setHeight(mpts2units(h)); - imageObjectInfo.setWidthRes(imageRes); - imageObjectInfo.setHeightRes(imageRes); + + ObjectAreaInfo objectAreaInfo = new ObjectAreaInfo(); + objectAreaInfo.setX(mpts2units(x)); + objectAreaInfo.setY(mpts2units(y)); + objectAreaInfo.setWidth(mpts2units(w)); + objectAreaInfo.setHeight(mpts2units(h)); + objectAreaInfo.setWidthRes(imageRes); + objectAreaInfo.setHeightRes(imageRes); + imageObjectInfo.setObjectAreaInfo(objectAreaInfo); + imageObjectInfo.setData(baout.toByteArray()); imageObjectInfo.setDataHeight(image.getHeight()); imageObjectInfo.setDataWidth(image.getWidth()); imageObjectInfo.setColor(colorImages); imageObjectInfo.setBitsPerPixel(bitsPerPixel); imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); - getAFPDataStream().createObject(imageObjectInfo); } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index 8277418d4..660ac4332 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -274,7 +274,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { afpRenderer.getAFPDataStream().setDefaultResourceGroupFile(resourceGroupFile); } else { log.warn("Unable to write to default external resource group file '" - + resourceGroupDest); + + resourceGroupDest + "'"); } } } diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 86c26d74f..b0d155cd9 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -153,23 +153,28 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f); // set the data object parameters - DataObjectInfo info = new DataObjectInfo(); + DataObjectInfo dataObjectInfo = new DataObjectInfo(); String docUri = ((AbstractDocument)doc).getDocumentURI(); - info.setUri(docUri); - info.setX(x); - info.setY(y); - info.setWidth(width); - info.setHeight(height); - info.setWidthRes(res); - info.setHeightRes(res); + dataObjectInfo.setUri(docUri); + + ObjectAreaInfo objectAreaInfo = new ObjectAreaInfo(); + objectAreaInfo.setX(x); + objectAreaInfo.setY(y); + objectAreaInfo.setWidth(width); + objectAreaInfo.setHeight(height); + objectAreaInfo.setWidthRes(res); + objectAreaInfo.setHeightRes(res); + + dataObjectInfo.setObjectAreaInfo(objectAreaInfo); + Map/**/ foreignAttributes = (Map/**/)context.getProperty( RendererContextConstants.FOREIGN_ATTRIBUTES); - info.setResourceInfoFromForeignAttributes(foreignAttributes); + dataObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes); AFPDataStream afpDataStream = afpInfo.getAFPDataStream(); - GraphicsObject graphicsObj = (GraphicsObject)afpDataStream.createObject(info); + GraphicsObject graphicsObj = (GraphicsObject)afpDataStream.createObject(dataObjectInfo); graphics.setGraphicsObject(graphicsObj); try { diff --git a/src/java/org/apache/fop/render/afp/DataObjectInfo.java b/src/java/org/apache/fop/render/afp/DataObjectInfo.java index 00044da96..b25470551 100644 --- a/src/java/org/apache/fop/render/afp/DataObjectInfo.java +++ b/src/java/org/apache/fop/render/afp/DataObjectInfo.java @@ -42,13 +42,9 @@ public class DataObjectInfo { private static final ResourceInfo DEFAULT_RESOURCE_INFO = new ResourceInfo(); private String uri; - private int x; - private int y; - private int width; - private int height; - private int widthRes; - private int heightRes; - private int rotation = 0; + + /** the object area info */ + private ObjectAreaInfo objectAreaInfo; /** object type entry */ private ObjectType objectType; @@ -70,53 +66,6 @@ public class DataObjectInfo { this.uri = uri; } - /** - * Sets the x position of the data object - * @param x the x position of the data object - */ - protected void setX(int x) { - this.x = x; - } - - /** - * Sets the y position of the data object - * @param y the y position of the data object - */ - protected void setY(int y) { - this.y = y; - } - - /** - * Sets the data object width - * @param width the width of the data object - */ - protected void setWidth(int width) { - this.width = width; - } - - /** - * Sets the data object height - * @param height the height of the data object - */ - protected void setHeight(int height) { - this.height = height; - } - - /** - * Sets the width resolution - * @param widthRes the width resolution - */ - protected void setWidthRes(int widthRes) { - this.widthRes = widthRes; - } - - /** - * Sets the height resolution - * @param heightRes the height resolution - */ - protected void setHeightRes(int heightRes) { - this.heightRes = heightRes; - } /** * @return the uri of this data object @@ -125,63 +74,6 @@ public class DataObjectInfo { return uri; } - /** - * @return the x coordinate of this data object - */ - public int getX() { - return x; - } - - /** - * @return the y coordinate of this data object - */ - public int getY() { - return y; - } - - /** - * @return the width of this data object - */ - public int getWidth() { - return width; - } - - /** - * @return the height of this data object - */ - public int getHeight() { - return height; - } - - /** - * @return the width resolution of this data object - */ - public int getWidthRes() { - return widthRes; - } - - /** - * @return the height resolution of this data object - */ - public int getHeightRes() { - return heightRes; - } - - /** - * @return the rotation of this data object - */ - public int getRotation() { - return rotation; - } - - /** - * Sets the data object rotation - * @param rotation the data object rotation - */ - protected void setRotation(int rotation) { - this.rotation = rotation; - } - /** * Sets the object type * @param objectType the object type @@ -212,6 +104,21 @@ public class DataObjectInfo { this.resourceInfo = resourceInfo; } + /** + * Sets the object area info + * @param objectAreaInfo the object area info + */ + public void setObjectAreaInfo(ObjectAreaInfo objectAreaInfo) { + this.objectAreaInfo = objectAreaInfo; + } + + /** + * @return the object area info + */ + public ObjectAreaInfo getObjectAreaInfo() { + return this.objectAreaInfo; + } + /** * Sets the resource group settings using the given foreign attributes * @param foreignAttributes a mapping of element attributes names to values @@ -278,14 +185,8 @@ public class DataObjectInfo { */ public String toString() { return "uri=" + uri - + ", x=" + x - + ", y=" + y - + ", width=" + width - + ", height=" + height - + ", widthRes=" + widthRes - + ", heightRes=" + heightRes - + ", rotation=" + rotation - + (resourceInfo != null ? ", resourceInfo=" + resourceInfo : "") - + (objectType != null ? ", objectTypeEntry=" + objectType : ""); + + (objectAreaInfo != null ? "objectAreaInfo=" + objectAreaInfo : "") + + (objectType != null ? ", objectType=" + objectType : "") + + (resourceInfo != null ? ", resourceInfo=" + resourceInfo : ""); } } diff --git a/src/java/org/apache/fop/render/afp/ImageObjectInfo.java b/src/java/org/apache/fop/render/afp/ImageObjectInfo.java index cf5e7f951..f9bbc82cf 100644 --- a/src/java/org/apache/fop/render/afp/ImageObjectInfo.java +++ b/src/java/org/apache/fop/render/afp/ImageObjectInfo.java @@ -29,7 +29,8 @@ public class ImageObjectInfo extends DataObjectInfo { private byte[] data; private int dataWidth; private int dataHeight; - private String mimeType; + private String mimeType; + private boolean buffered; /** * Default constructor @@ -150,6 +151,21 @@ public class ImageObjectInfo extends DataObjectInfo { return mimeType; } + /** + * Sets whether or not this is info about a buffered image + * @param buffered true if this is info about a buffered image + */ + public void setBuffered(boolean buffered) { + this.buffered = buffered; + } + + /** + * @return true if this image info is about a buffered image + */ + public boolean isBuffered() { + return this.buffered; + } + /** * {@inheritDoc} */ @@ -161,4 +177,5 @@ public class ImageObjectInfo extends DataObjectInfo { + ", color=" + color + ", bitPerPixel=" + bitsPerPixel; } + } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/ObjectAreaInfo.java b/src/java/org/apache/fop/render/afp/ObjectAreaInfo.java new file mode 100644 index 000000000..85da1a8e2 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/ObjectAreaInfo.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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; + +public class ObjectAreaInfo { + private int x; + private int y; + private int width; + private int height; + private int widthRes; + private int heightRes; + private int rotation = 0; + + /** + * Sets the x position of the data object + * @param x the x position of the data object + */ + protected void setX(int x) { + this.x = x; + } + + /** + * Sets the y position of the data object + * @param y the y position of the data object + */ + protected void setY(int y) { + this.y = y; + } + + /** + * Sets the data object width + * @param width the width of the data object + */ + protected void setWidth(int width) { + this.width = width; + } + + /** + * Sets the data object height + * @param height the height of the data object + */ + protected void setHeight(int height) { + this.height = height; + } + + /** + * Sets the width resolution + * @param widthRes the width resolution + */ + protected void setWidthRes(int widthRes) { + this.widthRes = widthRes; + } + + /** + * Sets the height resolution + * @param heightRes the height resolution + */ + protected void setHeightRes(int heightRes) { + this.heightRes = heightRes; + } + + /** + * @return the x coordinate of this data object + */ + public int getX() { + return x; + } + + /** + * @return the y coordinate of this data object + */ + public int getY() { + return y; + } + + /** + * @return the width of this data object + */ + public int getWidth() { + return width; + } + + /** + * @return the height of this data object + */ + public int getHeight() { + return height; + } + + /** + * @return the width resolution of this data object + */ + public int getWidthRes() { + return widthRes; + } + + /** + * @return the height resolution of this data object + */ + public int getHeightRes() { + return heightRes; + } + + /** + * @return the rotation of this data object + */ + public int getRotation() { + return rotation; + } + + /** + * Sets the data object rotation + * @param rotation the data object rotation + */ + protected void setRotation(int rotation) { + this.rotation = rotation; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "x=" + x + + ", y=" + y + + ", width=" + width + + ", height=" + height + + ", widthRes=" + widthRes + + ", heightRes=" + heightRes + + ", rotation=" + rotation; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java index 92a5b99f2..c2d11bef2 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java @@ -492,7 +492,7 @@ public class AFPDataStream extends AbstractResourceGroupContainer { } } else { if (resourceLevel.isExternal()) { - log.warn( interchangeSet + log.warn(interchangeSet + ": not available, object " + getName() + " will reside inline"); } } @@ -504,68 +504,68 @@ public class AFPDataStream extends AbstractResourceGroupContainer { return dataObj; } - /** - * Sets the object view port taking into account rotation. - * - * @param x - * the x position of the object - * @param y - * the y position of the object - * @param w - * the width of the object - * @param h - * the height of the object - * @param wr - * the resolution width of the object - * @param hr - * the resolution height of the object - * @return a new graphics object - */ - private void setObjectViewPort(AbstractDataObject dataObj, int x, int y, - int w, int h, int wr, int hr) { - int xOrigin; - int yOrigin; - int width; - int height; - int widthRes; - int heightRes; - switch (this.rotation) { - case 90: - xOrigin = getCurrentPage().getWidth() - y - yOffset; - yOrigin = x + xOffset; - width = h; - height = w; - widthRes = hr; - heightRes = wr; - break; - case 180: - xOrigin = getCurrentPage().getWidth() - x - xOffset; - yOrigin = getCurrentPage().getHeight() - y - yOffset; - width = w; - height = h; - widthRes = wr; - heightRes = hr; - break; - case 270: - xOrigin = y + yOffset; - yOrigin = getCurrentPage().getHeight() - x - xOffset; - width = h; - height = w; - widthRes = hr; - heightRes = wr; - break; - default: - xOrigin = x + xOffset; - yOrigin = y + yOffset; - width = w; - height = h; - widthRes = wr; - heightRes = hr; - break; - } - dataObj.setViewport(xOrigin, yOrigin, width, height, widthRes, - heightRes, rotation); - } +// /** +// * Sets the object view port taking into account rotation. +// * +// * @param x +// * the x position of the object +// * @param y +// * the y position of the object +// * @param w +// * the width of the object +// * @param h +// * the height of the object +// * @param wr +// * the resolution width of the object +// * @param hr +// * the resolution height of the object +// * @return a new graphics object +// */ +// private void setObjectViewPort(AbstractDataObject dataObj, int x, int y, +// int w, int h, int wr, int hr) { +// int xOrigin; +// int yOrigin; +// int width; +// int height; +// int widthRes; +// int heightRes; +// switch (this.rotation) { +// case 90: +// xOrigin = getCurrentPage().getWidth() - y - yOffset; +// yOrigin = x + xOffset; +// width = h; +// height = w; +// widthRes = hr; +// heightRes = wr; +// break; +// case 180: +// xOrigin = getCurrentPage().getWidth() - x - xOffset; +// yOrigin = getCurrentPage().getHeight() - y - yOffset; +// width = w; +// height = h; +// widthRes = wr; +// heightRes = hr; +// break; +// case 270: +// xOrigin = y + yOffset; +// yOrigin = getCurrentPage().getHeight() - x - xOffset; +// width = h; +// height = w; +// widthRes = hr; +// heightRes = wr; +// break; +// default: +// xOrigin = x + xOffset; +// yOrigin = y + yOffset; +// width = w; +// height = h; +// widthRes = wr; +// heightRes = hr; +// break; +// } +// dataObj.setViewport(xOrigin, yOrigin, width, height, widthRes, +// heightRes, rotation); +// } /** * Method to create a line on the current page. 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 9bf713127..f52047b62 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java @@ -22,6 +22,8 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.ObjectAreaInfo; + /** * Abstract base class used by the ImageObject and GraphicsObject which both @@ -45,25 +47,11 @@ public abstract class AbstractDataObject extends AbstractPreparedObjectContainer /** * Sets the object display area position and size. * - * @param x - * the x position of the object - * @param y - * the y position of the object - * @param width - * the width of the object - * @param height - * the height of the object - * @param widthRes - * the resolution width - * @param heightRes - * the resolution height - * @param rotation - * the rotation of the object + * @param objectAreaInfo + * the object area info */ - public void setViewport(int x, int y, int width, int height, - int widthRes, int heightRes, int rotation) { - getObjectEnvironmentGroup().setObjectArea(x, y, width, height, - widthRes, heightRes, rotation); + public void setViewport(ObjectAreaInfo objectAreaInfo) { + getObjectEnvironmentGroup().setObjectArea(objectAreaInfo); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/DataObjectFactory.java b/src/java/org/apache/fop/render/afp/modca/DataObjectFactory.java index bcb506dee..7e3f41a53 100644 --- a/src/java/org/apache/fop/render/afp/modca/DataObjectFactory.java +++ b/src/java/org/apache/fop/render/afp/modca/DataObjectFactory.java @@ -21,6 +21,7 @@ package org.apache.fop.render.afp.modca; import org.apache.fop.render.afp.DataObjectInfo; import org.apache.fop.render.afp.ImageObjectInfo; +import org.apache.fop.render.afp.ObjectAreaInfo; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.tools.StringUtils; import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; @@ -43,25 +44,23 @@ public class DataObjectFactory { * * @param io * the target image object - * @param raw - * the buffer containing the RGB image data - * @param width - * the width of the image in pixels - * @param height - * the height of the image in pixels - * @param bitsPerPixel - * the number of bits to use per pixel - * - * TODO: move this method somewhere appropriate in commons + * @param info + * the image object info + * + * @return the converted image data */ - private static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, - int height, int bitsPerPixel) { + private static byte[] convertToGrayScaleImage(ImageObject io, ImageObjectInfo info) { + byte[] raw = info.getData(); + int width = info.getDataWidth(); + int height = info.getDataHeight(); + int bitsPerPixel = info.getBitsPerPixel(); + int pixelsPerByte = 8 / bitsPerPixel; int bytewidth = (width / pixelsPerByte); if ((width % pixelsPerByte) != 0) { bytewidth++; } - byte[] bw = new byte[height * bytewidth]; + byte[] data = new byte[height * bytewidth]; byte ib; for (int y = 0; y < height; y++) { ib = 0; @@ -92,27 +91,26 @@ public class DataObjectFactory { if ((x % pixelsPerByte) == (pixelsPerByte - 1) || ((x + 1) == width)) { - bw[(y * bytewidth) + (x / pixelsPerByte)] = ib; + data[(y * bytewidth) + (x / pixelsPerByte)] = ib; ib = 0; } } } - io.setImageIDESize((byte) bitsPerPixel); - io.setImageData(bw); + return data; } /** * Helper method to create an image on the current container and to return * the object. - * @param info the image object info + * @param imageObjectInfo the image object info * @return a newly created image object */ - protected ImageObject createImage(ImageObjectInfo info) { + protected ImageObject createImage(ImageObjectInfo imageObjectInfo) { String name = IMAGE_NAME_PREFIX + StringUtils.lpad(String.valueOf(++imageCount), '0', 5); ImageObject imageObj = new ImageObject(name); - if (info.hasCompression()) { - int compression = info.getCompression(); + if (imageObjectInfo.hasCompression()) { + int compression = imageObjectInfo.getCompression(); switch (compression) { case TIFFImage.COMP_FAX_G3_1D: imageObj.setImageEncoding(ImageContent.COMPID_G3_MH); @@ -128,15 +126,19 @@ public class DataObjectFactory { "Invalid compression scheme: " + compression); } } - imageObj.setImageParameters(info.getWidthRes(), info.getHeightRes(), - info.getDataWidth(), info.getDataHeight()); - if (info.isColor()) { - imageObj.setImageIDESize((byte)24); - imageObj.setImageData(info.getData()); - } else { - convertToGrayScaleImage(imageObj, info.getData(), - info.getDataWidth(), info.getDataHeight(), - info.getBitsPerPixel()); + ObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo(); + imageObj.setImageParameters(objectAreaInfo.getWidthRes(), objectAreaInfo.getHeightRes(), + imageObjectInfo.getDataWidth(), imageObjectInfo.getDataHeight()); + if (imageObjectInfo.isBuffered()) { + if (imageObjectInfo.isColor()) { + imageObj.setImageIDESize((byte)24); + imageObj.setImageData(imageObjectInfo.getData()); + } else { + int bitsPerPixel = imageObjectInfo.getBitsPerPixel(); + imageObj.setImageIDESize((byte)bitsPerPixel); + byte[] data = convertToGrayScaleImage(imageObj, imageObjectInfo); + imageObj.setImageData(data); + } } return imageObj; } @@ -166,10 +168,7 @@ public class DataObjectFactory { } else { dataObject = createGraphic(dataObjectInfo); } - dataObject.setViewport(dataObjectInfo.getX(), dataObjectInfo.getY(), - dataObjectInfo.getWidth(), dataObjectInfo.getHeight(), - dataObjectInfo.getWidthRes(), dataObjectInfo.getHeightRes(), - dataObjectInfo.getRotation()); + dataObject.setViewport(dataObjectInfo.getObjectAreaInfo()); dataObject.setFullyQualifiedName( FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF, 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 0c260db90..a73c9fc70 100644 --- a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java @@ -23,6 +23,7 @@ import java.awt.Color; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.ObjectAreaInfo; import org.apache.fop.render.afp.goca.GraphicsBox; import org.apache.fop.render.afp.goca.GraphicsData; import org.apache.fop.render.afp.goca.GraphicsFillet; @@ -64,11 +65,15 @@ public class GraphicsObject extends AbstractDataObject { /** * {@inheritDoc} */ - public void setViewport(int x, int y, int width, int height, - int widthRes, int heightRes, int rotation) { - super.setViewport(x, y, width, height, widthRes, heightRes, rotation); + public void setViewport(ObjectAreaInfo objectAreaInfo) { + super.setViewport(objectAreaInfo); getObjectEnvironmentGroup().setGraphicsData( - widthRes, heightRes, 0, x + width, 0, y + height); + objectAreaInfo.getWidthRes(), + objectAreaInfo.getHeightRes(), + 0, + objectAreaInfo.getX() + objectAreaInfo.getWidth(), + 0, + objectAreaInfo.getY() + objectAreaInfo.getHeight()); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java index 188664264..85cb283a8 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.fop.render.afp.DataObjectInfo; +import org.apache.fop.render.afp.ObjectAreaInfo; import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.modca.triplets.MappingOptionTriplet; import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; @@ -133,8 +134,8 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA } DataObjectInfo dataObjectInfo = dataObjectAccessor.getDataObjectInfo(); - - setObjectArea(dataObjectInfo.getX(), dataObjectInfo.getY()); + ObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); + setObjectArea(objectAreaInfo.getX(), objectAreaInfo.getY()); super.setFullyQualifiedName( FullyQualifiedNameTriplet.TYPE_REPLACE_FIRST_GID_NAME, @@ -147,11 +148,11 @@ public class IncludeObject extends AbstractNamedAFPObject implements DataObjectA ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT, objectType); - super.setMeasurementUnits(dataObjectInfo.getWidthRes(), dataObjectInfo.getHeightRes()); + super.setMeasurementUnits(objectAreaInfo.getWidthRes(), objectAreaInfo.getHeightRes()); super.setMappingOption(MappingOptionTriplet.SCALE_TO_FIT); - super.setObjectAreaSize(dataObjectInfo.getWidth(), dataObjectInfo.getHeight()); + super.setObjectAreaSize(objectAreaInfo.getWidth(), objectAreaInfo.getHeight()); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java index b673dec46..4b31da1f1 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java @@ -22,6 +22,8 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.render.afp.ObjectAreaInfo; + /** * An Object Environment Group (OEG) may be associated with an object and is contained @@ -79,20 +81,14 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject { /** * Sets the object area parameters. - * @param x the x position of the object - * @param y the y position of the object - * @param width the object width - * @param height the object height - * @param rotation the object orientation - * @param widthRes the object resolution width - * @param heightRes the object resolution height + * @param info the object area info */ - public void setObjectArea(int x, int y, int width, int height, - int widthRes, int heightRes, int rotation) { - this.objectAreaDescriptor = new ObjectAreaDescriptor(width, height, - widthRes, heightRes); - this.objectAreaPosition = new ObjectAreaPosition(x, y, rotation); - + public void setObjectArea(ObjectAreaInfo info) { + this.objectAreaDescriptor = new ObjectAreaDescriptor( + info.getWidth(), info.getHeight(), + info.getWidthRes(), info.getHeightRes()); + this.objectAreaPosition = new ObjectAreaPosition( + info.getX(), info.getY(), info.getRotation()); } /** -- cgit v1.2.3 From 7d7910f72b18167d0f5cbc441a99aeeaa97e0838 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 9 Jun 2008 11:24:36 +0000 Subject: Merged revisions 662417,662807,662991,663045,663493,664347,664349-664350 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r662417 | jeremias | 2008-06-02 13:50:55 +0100 (Mon, 02 Jun 2008) | 1 line Integer keeps inside multi-line blocks and in between block-paragraphs. ........ r662807 | jeremias | 2008-06-03 15:13:27 +0100 (Tue, 03 Jun 2008) | 3 lines Bugzilla #45115: Added a PCL-specific extension attribute on simple-page-master for controlling the simplex/duplex mode. Submitted by: Martin Edge ........ r662991 | jeremias | 2008-06-04 07:10:37 +0100 (Wed, 04 Jun 2008) | 1 line ApacheCon EU 2008 is long over. ........ r663045 | adelmelle | 2008-06-04 10:53:15 +0100 (Wed, 04 Jun 2008) | 1 line Minor cleanup: remove spurious white-space ........ r663493 | jeremias | 2008-06-05 08:41:06 +0100 (Thu, 05 Jun 2008) | 1 line Restored lost overflow warning in static-content. ........ r664347 | adelmelle | 2008-06-07 15:49:42 +0100 (Sat, 07 Jun 2008) | 5 lines 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) ........ r664349 | adelmelle | 2008-06-07 15:54:13 +0100 (Sat, 07 Jun 2008) | 1 line Minor cleanup: remove unneeded constant ........ r664350 | adelmelle | 2008-06-07 16:09:42 +0100 (Sat, 07 Jun 2008) | 1 line Improve code-readability; add some clarifying comments ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@664680 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/trunk/output.xml | 25 ++++ src/documentation/skinconf.xml | 2 + .../fop/layoutmgr/StaticContentLayoutManager.java | 6 + .../fop/layoutmgr/inline/LineLayoutManager.java | 31 +++-- .../fop/layoutmgr/inline/TextLayoutManager.java | 31 +++-- .../org/apache/fop/render/pcl/PCLGenerator.java | 13 ++ .../org/apache/fop/render/pcl/PCLRenderer.java | 11 +- .../apache/fop/text/linebreak/LineBreakStatus.java | 139 ++++++++++++--------- src/java/org/apache/fop/util/CharUtilities.java | 49 +++++--- status.xml | 4 + .../block_keep-together_integers_1.xml | 17 +++ .../block_uax14_explicit-breaks.xml | 64 ++++++++++ 12 files changed, 288 insertions(+), 104 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block_uax14_explicit-breaks.xml (limited to 'src/java') diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index b485cdb21..d03041f19 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/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/ 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(); 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/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 6ae909cd7..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 */ @@ -523,7 +521,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 +559,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 +600,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 +620,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 +628,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; @@ -1000,14 +1001,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 +1047,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 +1060,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)); } 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 e1818c84b..11e78ea97 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/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; } } 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/status.xml b/status.xml index 730edccac..665bc47dc 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,10 @@ Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + 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. 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 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 2ab4f01d9a5bf07e5f2b6ee4bb93dc107ef86eff Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 9 Jun 2008 14:11:16 +0000 Subject: Merged revisions 665691 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ................ r665691 | jeremias | 2008-06-09 15:01:53 +0100 (Mon, 09 Jun 2008) | 82 lines 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/branches/Temp_AFPGOCAResources@665697 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 | 147 +++++++++------ .../org/apache/fop/render/pcl/PCLRenderer.java | 74 ++++++++ .../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 +++- 42 files changed, 1303 insertions(+), 110 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/java') 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 dd1a4dd7c..19796eada 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 { @@ -134,4 +135,12 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 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 0c5732ac7..86210b07a 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; @@ -520,6 +521,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 bfdf56d2b..790732c12 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -57,6 +57,7 @@ import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; import org.apache.fop.area.CTM; import org.apache.fop.area.LineArea; +import org.apache.fop.area.NormalFlow; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; @@ -488,45 +489,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } } -// /** -// * {@inheritDoc} -// */ -// protected void drawBackAndBorders(Area area, float startx, float starty, -// float width, float height) { -// super.drawBackAndBorders(area, startx, starty, width, height); -// Trait.Background back = (Trait.Background) area -// .getTrait(Trait.BACKGROUND); -// -// // the current block has a background so its contents are placed inside -// // an overlay -// // after drawing the background and borders -// if (back != null) { -// int x = pts2units(startx); -// int y = pts2units(starty); -// int w = mpts2units(width); -// int h = mpts2units(height); -// int res = getResolution(); -// final int rotation = 0; -// getAFPDataStream().startOverlay(x, y, w, h, res, res, rotation); -//// Color col = back.getColor(); -//// getAFPDataStream().createShading(x, y, w, h, col); -// } -// } -// -//// /** -//// * {@inheritDoc} -//// */ -// protected void renderBlock(Block block) { -//// // new block so start page segment -////// getAFPDataStream().startPageSegment(); -// super.renderBlock(block); -// getAFPDataStream().endOverlay(); -////// getAFPDataStream().endPageSegment(); -// } - - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void renderBlockViewport(BlockViewport bv, List children) { // clip and position viewport if necessary @@ -658,6 +621,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() @@ -1104,23 +1137,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. */ @@ -1609,13 +1643,14 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { getAFPDataStream().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); getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot); } + return current; } /** diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 11e78ea97..10d66fb4e 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/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 665bc47dc..d8e09fa79 100644 --- a/status.xml +++ b/status.xml @@ -147,7 +147,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 07ee324b35a7a7bf5d7cb8f704a0a2b62a89df5d Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 9 Jun 2008 14:33:04 +0000 Subject: Merged revisions 665699 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r665699 | maxberger | 2008-06-09 15:15:38 +0100 (Mon, 09 Jun 2008) | 1 line Replaced LinkedList with generic List interface ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@665703 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/java') 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 f25d75a80cbb96a31e6d5b5a4da9d5e95d164cd8 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 10 Jun 2008 09:52:27 +0000 Subject: Merged revisions 665740,665793,665995 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r665740 | adelmelle | 2008-06-09 17:20:08 +0100 (Mon, 09 Jun 2008) | 1 line Minor update: make the codegen-unicode target create LineBreakUtils.java at the appropriate place in the source tree ........ r665793 | adelmelle | 2008-06-09 18:27:51 +0100 (Mon, 09 Jun 2008) | 9 lines 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 ........ r665995 | maxberger | 2008-06-10 08:52:36 +0100 (Tue, 10 Jun 2008) | 1 line Replaced getLast() calls with calls to listUtil ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@666048 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 11 +- src/codegen/unicode/data/LineBreakPairTable.txt | 56 +- .../fop/text/linebreak/GenerateLineBreakUtils.java | 160 ++- .../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 +- .../apache/fop/text/linebreak/LineBreakUtils.java | 1278 +++++++++++--------- src/java/org/apache/fop/util/ListUtil.java | 55 + 13 files changed, 939 insertions(+), 759 deletions(-) create mode 100644 src/java/org/apache/fop/util/ListUtil.java (limited to 'src/java') diff --git a/build.xml b/build.xml index d744c16c1..54356e0ab 100644 --- a/build.xml +++ b/build.xml @@ -1418,9 +1418,10 @@ NOTE: - - - + + + + @@ -1429,7 +1430,9 @@ NOTE: source="${javac.source}" target="${javac.target}"> - + + + 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/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/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]; } -}; +} 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 08f0da8adadb9fda358992ad204948570ad41d11 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 17 Jun 2008 10:30:54 +0000 Subject: Merged revisions 666596,666967,667367,667831,667862,667864,667893,668177,668576 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r666596 | vhennebert | 2008-06-11 10:52:04 +0100 (Wed, 11 Jun 2008) | 2 lines Fixed typo ........ r666967 | maxberger | 2008-06-12 07:07:28 +0100 (Thu, 12 Jun 2008) | 1 line Added PMD and Findbugs report, 'reports' target' ........ r667367 | maxberger | 2008-06-13 07:03:30 +0100 (Fri, 13 Jun 2008) | 1 line Disabled retroweaver task definition, because it breaks gump ........ r667831 | maxberger | 2008-06-14 17:21:15 +0100 (Sat, 14 Jun 2008) | 1 line minor spelling fixes ........ r667862 | maxberger | 2008-06-14 19:18:14 +0100 (Sat, 14 Jun 2008) | 1 line minor spelling fixes ........ r667864 | maxberger | 2008-06-14 19:23:28 +0100 (Sat, 14 Jun 2008) | 1 line minor spelling & checkstyle fixes ........ r667893 | maxberger | 2008-06-14 23:20:42 +0100 (Sat, 14 Jun 2008) | 1 line removed double storage of 'fobj' ........ r668177 | lfurini | 2008-06-16 15:52:14 +0100 (Mon, 16 Jun 2008) | 2 lines 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. ........ r668576 | jeremias | 2008-06-17 10:04:05 +0100 (Tue, 17 Jun 2008) | 1 line Wrong line number reported in the case of a line overflow. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@668608 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 689 +++++++-------------- lib/build/asm-3.1.jar | Bin 0 -> 43033 bytes lib/build/asm-commons-3.1.jar | Bin 0 -> 32694 bytes lib/build/asm-util-3.1.jar | Bin 0 -> 34444 bytes lib/build/asm.LICENSE.txt | 28 + lib/build/backport-util-concurrent-3.1.jar | Bin 0 -> 331716 bytes lib/build/backport-util-concurrent.LICENSE.txt | 2 + lib/build/jaxen-1.1.1.jar | Bin 0 -> 226915 bytes lib/build/jaxen.LICENSE.txt | 33 + lib/build/pmd.LICENSE.txt | 31 + lib/build/pmd14-4.2.2.jar | Bin 0 -> 1124295 bytes lib/build/retroweaver-2.0.5.jar | Bin 0 -> 91990 bytes lib/build/retroweaver-rt-2.0.5.jar | Bin 0 -> 122274 bytes lib/build/retroweaver.LICENSE.txt | 25 + .../fop/layoutmgr/AbstractBaseLayoutManager.java | 34 +- .../org/apache/fop/layoutmgr/LayoutManager.java | 4 +- .../fop/layoutmgr/PageBreakingAlgorithm.java | 8 +- .../inline/AbstractGraphicsLayoutManager.java | 35 +- .../inline/ExternalGraphicLayoutManager.java | 16 +- .../layoutmgr/inline/InstreamForeignObjectLM.java | 11 +- .../layoutmgr/inline/LeafNodeLayoutManager.java | 4 +- .../fop/layoutmgr/inline/LineLayoutManager.java | 3 +- status.xml | 5 + .../footnote_changing-page-bpd.xml | 97 +++ .../footnote_changing-page-bpd_2.xml | 102 +++ 25 files changed, 603 insertions(+), 524 deletions(-) create mode 100644 lib/build/asm-3.1.jar create mode 100644 lib/build/asm-commons-3.1.jar create mode 100644 lib/build/asm-util-3.1.jar create mode 100644 lib/build/asm.LICENSE.txt create mode 100644 lib/build/backport-util-concurrent-3.1.jar create mode 100644 lib/build/backport-util-concurrent.LICENSE.txt create mode 100644 lib/build/jaxen-1.1.1.jar create mode 100644 lib/build/jaxen.LICENSE.txt create mode 100644 lib/build/pmd.LICENSE.txt create mode 100644 lib/build/pmd14-4.2.2.jar create mode 100644 lib/build/retroweaver-2.0.5.jar create mode 100644 lib/build/retroweaver-rt-2.0.5.jar create mode 100644 lib/build/retroweaver.LICENSE.txt 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/java') diff --git a/build.xml b/build.xml index 54356e0ab..ff76686b6 100644 --- a/build.xml +++ b/build.xml @@ -52,15 +52,12 @@ list of possible build targets. ============================================================================ --> - - - + + - - - + @@ -72,7 +69,6 @@ list of possible build targets. - @@ -87,7 +83,6 @@ list of possible build targets. - @@ -108,58 +103,45 @@ list of possible build targets. - - - - - - - + - - - - - - - @@ -174,7 +156,6 @@ list of possible build targets. - @@ -182,48 +163,38 @@ list of possible build targets. - - - - - + + - - - - - + - - - - + + + - - - + @@ -233,9 +204,7 @@ list of possible build targets. - - + @@ -245,12 +214,9 @@ list of possible build targets. - - - + @@ -260,7 +226,6 @@ list of possible build targets. - @@ -276,28 +241,22 @@ list of possible build targets. - - - - - + + + - - - - + + + - - - - + - + - + - + - + - + - + - + - + - + - + - + - - - + + - - - - + + + - + - + @@ -377,11 +317,8 @@ list of possible build targets. - - + @@ -391,12 +328,9 @@ list of possible build targets. - - + @@ -409,75 +343,57 @@ list of possible build targets. - - + - - + - + - + - + - + - + - + - @@ -498,21 +414,17 @@ list of possible build targets. - - + - - - - - - + + + @@ -526,13 +438,11 @@ list of possible build targets. - - @@ -546,27 +456,31 @@ list of possible build targets. - - - - - - + + + + + + + - + - - + - - - @@ -585,14 +499,12 @@ list of possible build targets. - - + - + - - + @@ -603,14 +515,12 @@ list of possible build targets. - - @@ -634,12 +544,10 @@ list of possible build targets. - - - - + + + - @@ -655,9 +563,8 @@ list of possible build targets. - - + @@ -680,7 +587,7 @@ list of possible build targets. - + @@ -688,42 +595,36 @@ list of possible build targets. - + - - - - + - - + - - - + @@ -734,8 +635,7 @@ list of possible build targets. - - + @@ -748,7 +648,7 @@ list of possible build targets. - + @@ -776,12 +676,11 @@ list of possible build targets. - - - - - - + + + + + @@ -790,15 +689,11 @@ list of possible build targets. - - + @@ -814,7 +709,6 @@ list of possible build targets. - @@ -831,9 +725,7 @@ list of possible build targets. - - @@ -852,7 +744,7 @@ list of possible build targets. - + + @@ -934,7 +824,6 @@ list of possible build targets. - @@ -952,7 +841,6 @@ list of possible build targets. - @@ -970,9 +858,7 @@ list of possible build targets. - - - + @@ -992,7 +878,6 @@ list of possible build targets. - @@ -1013,7 +898,6 @@ list of possible build targets. - @@ -1032,18 +916,8 @@ list of possible build targets. - - - - - - - - - - - + NOTE: ************************************************************************** * One or more of the Junit tests had Failures or Errors or were skipped! * @@ -1054,8 +928,7 @@ NOTE: All Junit tests passed! Use the "junit-reports" target to generate HTML test reports - - + @@ -1066,12 +939,11 @@ NOTE: JUnit HTML test reports should be available in ${junit.html.reports.dir} - - - - + + + - - + @@ -1096,22 +968,7 @@ NOTE: - - +

      @@ -1173,7 +1030,6 @@ NOTE: - @@ -1183,134 +1039,103 @@ NOTE: - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - + + + - - + + - - - + + + + + + + + + + + + basic + braces + codesize + clone + design + finalizers + imports + strings + rulesets/migrating_to_14.xml + optimizations + sunsecure + unusedcode + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + - - @@ -1327,10 +1152,8 @@ NOTE: - - + @@ -1342,7 +1165,6 @@ NOTE: - @@ -1350,10 +1172,8 @@ NOTE: - - + @@ -1365,12 +1185,11 @@ NOTE: - - - - + + + - + @@ -1386,66 +1205,55 @@ NOTE: - - - - + + + - + - + - - - - - - - - -
      Latest ReleaseLatest Stable Release
      Repository URL
      Latest Release
      Repository URL + + http://svn.apache.org/repos/asf/xmlgraphics/fop/tags/fop-0_95beta/ + +
      Web view + + http://svn.apache.org/viewvc/xmlgraphics/fop/tags/fop-0_95beta/ + +
      Trunk
      Image Supportstable, but in need of a redesignbeta (recently rewritten)
      Hyphenation Subsystem - + X @@ -298,6 +303,19 @@
      AFP + + + + + + + + + +
      Forrest 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 e12527fe3..423eaad11 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,132 @@

      - 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:

      -

      Windows (on JDK 1.4 and later):

      + To use it, run the class org.apache.fop.fonts.apps.PFMReader:

      +

      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):

      + org.apache.fop.fonts.apps.PFMReader [options] pfm-file xml-file +

      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 + 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 +301,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 +330,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 +355,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/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 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/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 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 @@ - + - + diff --git a/src/documentation/sitemap.xmap b/src/documentation/sitemap.xmap index bfc1e2bbe..470db0b7b 100644 --- a/src/documentation/sitemap.xmap +++ b/src/documentation/sitemap.xmap @@ -20,44 +20,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -65,13 +34,13 @@ - + - + @@ -80,7 +49,7 @@ - + @@ -88,13 +57,13 @@ - + - + diff --git a/src/documentation/skinconf.xml b/src/documentation/skinconf.xml index 65a271a64..e87baab34 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/ @@ -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;} @@ -311,8 +312,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 - - -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/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/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/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..e8ca88c1c 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)) { @@ -249,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(); @@ -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()); @@ -388,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); @@ -411,7 +412,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 +445,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } } else { - int maxbpd = context.getStackLimit().opt; + int maxbpd = context.getStackLimitBP().opt; allocBPD = maxbpd; if (!switchedProgressionDirection) { autoHeight = true; @@ -601,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() { @@ -625,7 +622,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()); @@ -707,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()); @@ -736,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) { @@ -772,7 +769,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } - getPSLM().addIDToPage(getBlockContainerFO().getId()); + addId(); addMarkersToPage(true, isFirst(firstPos), isLast(lastPos)); @@ -854,7 +851,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); } @@ -873,7 +870,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager referenceArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(((BlockContainer)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** @@ -992,30 +989,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..f5270107c 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; @@ -146,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); } /** @@ -249,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()); @@ -279,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 @@ -308,7 +309,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } } - getPSLM().addIDToPage(getBlockFO().getId()); + addId(); addMarkersToPage(true, isFirst(firstPos), isLast(lastPos)); @@ -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..67ed1de9f 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); } @@ -293,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; @@ -392,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/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..79b5e232f 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -74,18 +74,29 @@ 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; /** 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; @@ -145,7 +156,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 +177,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; } @@ -273,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; } /** @@ -306,14 +314,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 +577,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/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/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/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/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/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java index 841a94705..dfc8c99f2 100644 --- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java +++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java @@ -29,6 +29,7 @@ import org.apache.fop.datatypes.SimplePercentBaseContext; 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.CommonMarginBlock; import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.fonts.Font; @@ -280,6 +281,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 +397,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/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/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/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 b449b6689..e9919e02f 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; @@ -296,7 +297,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { ); } - while ((curLM = (LayoutManager) getChildLM()) != null) { + while ((curLM = getChildLM()) != null) { if (!(curLM instanceof InlineLevelLayoutManager)) { // A block LM @@ -435,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()) { @@ -599,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/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 6df7ac00c..9a818232c 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; @@ -582,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.getStackLimit(); - clearPrevIPD(); //PHASE 1: Create Knuth elements @@ -646,7 +644,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 +1685,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 +1699,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 +1768,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/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 470cbbe9c..c17ddc711 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 @@ -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; } @@ -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); } @@ -218,7 +218,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager curBlockArea = null; resetSpaces(); - getPSLM().notifyEndOfLayout(((ListBlock)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** @@ -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..8b0028a8f 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. @@ -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; } @@ -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); } @@ -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 dc28e98e2..c6b5b8cf9 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. @@ -72,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; @@ -83,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; @@ -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:"); @@ -301,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; @@ -413,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()); @@ -459,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; @@ -478,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()); } } @@ -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); } @@ -554,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/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index c1e4ae619..61d0f8e6f 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,23 +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 -= 2 * tableLM.getHalfBorderSeparationBPD(); - 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); @@ -182,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; } @@ -265,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; } @@ -394,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 @@ -445,13 +529,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, @@ -463,20 +540,9 @@ 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). - */ - 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 c2e26e18d..9c97ca827 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -19,16 +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; @@ -94,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.setStackLimit(context.getStackLimit()); //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 022ff0589..bed9c53ae 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -23,25 +23,27 @@ 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; +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 +73,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 +94,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 +155,6 @@ class RowPainter { currentRow = row; } } - rowFO = currentRow.getTableRow(); if (firstRowIndex < 0) { firstRowIndex = currentRow.getIndex(); if (firstRowOnPageIndex < 0) { @@ -148,7 +194,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 +228,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 @@ -255,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; } @@ -278,8 +326,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 +379,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 +435,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/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 289785d68..8acfebca0 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -23,16 +23,19 @@ 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; 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,9 +74,8 @@ 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; /** @@ -96,31 +98,11 @@ 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 */ public Table getTable() { - FONode node = fobj.getParent(); - while (!(node instanceof Table)) { - node = node.getParent(); - } - return (Table)node; + return getTableCell().getTable(); } @@ -148,13 +130,13 @@ 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; cellIPD -= getIPIndents(); - LinkedList returnedList = null; + LinkedList returnedList; LinkedList contentList = new LinkedList(); LinkedList returnList = new LinkedList(); @@ -163,8 +145,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 @@ -260,7 +242,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager p.setP(0); } - getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); setFinished(true); return returnList; @@ -303,7 +285,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * @param h the height of cell */ public void setTotalHeight(int h) { - rowHeight = h; + totalHeight = h; } /** @@ -330,6 +312,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 +325,25 @@ 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()); + addId(); int borderBeforeWidth = primaryGridUnit.getBeforeBorderWidth(startRow, borderBeforeWhich); int borderAfterWidth = primaryGridUnit.getAfterBorderWidth(endRow, borderAfterWhich); + + CommonBorderPaddingBackground padding = primaryGridUnit.getCell() + .getCommonBorderPaddingBackground(); + 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, paddingRectBPD); + if (isSeparateBorderModel()) { if (!emptyCell || getTableCell().showEmptyCells()) { if (borderBeforeWidth > 0) { @@ -421,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); @@ -437,18 +435,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 +460,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 +470,33 @@ 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 paddingRectBPD) { + TableColumn column = getTable().getColumn(primaryGridUnit.getColIndex()); + if (column.getCommonBorderPaddingBackground().hasBackground()) { + Block colBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); + ((TableLayoutManager) parentLM).registerColumnBackgroundArea(column, colBackgroundArea, + -startIndent); + } + + TableBody body = primaryGridUnit.getTableBody(); + if (body.getCommonBorderPaddingBackground().hasBackground()) { + painter.registerPartBackgroundArea( + getBackgroundArea(paddingRectBPD, borderBeforeWidth)); + } + + TableRow row = primaryGridUnit.getRow(); + if (row != null && row.getCommonBorderPaddingBackground().hasBackground()) { + Block rowBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); + ((TableLayoutManager) parentLM).addBackgroundArea(rowBackgroundArea); + TraitSetter.addBackground(rowBackgroundArea, row.getCommonBorderPaddingBackground(), + 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 +525,21 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager block.setBPD(block.getBPD() + amount); } + private Block getBackgroundArea(int bpd, int borderBeforeWidth) { + CommonBorderPaddingBackground padding = getTableCell().getCommonBorderPaddingBackground(); + int paddingStart = padding.getPaddingStart(false, this); + int paddingEnd = padding.getPaddingEnd(false, this); + + Block block = new Block(); + TraitSetter.setProducerID(block, getTable().getId()); + block.setPositioning(Block.ABSOLUTE); + block.setIPD(cellIPD + paddingStart + paddingEnd); + block.setBPD(bpd); + block.setXOffset(xoffset + startIndent - paddingStart); + 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 b9a118e28..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.getBody(); - } - 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..260b8cfdf 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 @@ -101,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/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 1cbc3e50a..d6bba5cb5 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 @@ -211,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); /* @@ -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. @@ -274,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) { @@ -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(), @@ -323,7 +379,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager resetSpaces(); curBlockArea = null; - getPSLM().notifyEndOfLayout(((Table)getFObj()).getId()); + getPSLM().notifyEndOfLayout(fobj.getId()); } /** @@ -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/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/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index f74699fd5..c0c9ce88c 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -47,7 +47,7 @@ import org.apache.fop.svg.SVGUserAgent; public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererContextConstants { /** logging instance */ - private static Log log = LogFactory.getLog(AbstractGenericSVGHandler.class); + protected static Log log = LogFactory.getLog(AbstractGenericSVGHandler.class); /** {@inheritDoc} */ public void handleXML(RendererContext context, diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index b10f4b30f..cb3d3a433 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -940,10 +940,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int x = origin.x + posInt.x; int y = origin.y + posInt.y; - String name = null; - if (pageSegmentsMap != null) { - name = (String) pageSegmentsMap.get(uri); - } + String name = (String)getPageSegments().get(uri); if (name != null) { afpDataStream.createIncludePageSegment(name, mpts2units(x), mpts2units(y)); } else { @@ -1543,6 +1540,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { return MimeConstants.MIME_AFP; } + private Map getPageSegments() { + if (pageSegmentsMap == null) { + pageSegmentsMap = new java.util.HashMap(); + } + return pageSegmentsMap; + } + /** * Method to render the page extension. *

      @@ -1571,17 +1575,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { .equals(element)) { String name = aps.getName(); String source = aps.getValue(); - if (pageSegmentsMap == null) { - pageSegmentsMap = new java.util.HashMap(); - } - pageSegmentsMap.put(source, name); + getPageSegments().put(source, name); } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT .equals(element)) { String name = aps.getName(); String value = aps.getValue(); - if (pageSegmentsMap == null) { - pageSegmentsMap = new java.util.HashMap(); - } afpDataStream.createTagLogicalElement(name, value); } else if (AFPElementMapping.NO_OPERATION.equals(element)) { String content = aps.getContent(); @@ -1589,7 +1587,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { afpDataStream.createNoOperation(content); } } else if (AFPElementMapping.RESOURCE.equals(element)) { - System.out.println("resource: " + attachment); + log.info("resource: " + attachment); } } } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index 4c8a3dc9f..cde464ba5 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -234,8 +234,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false); if (rendererResolutionCfg != null) { - afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger( - AFPRenderer.DPI_240_RESOLUTION)); + afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240)); } Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false); diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 2641e6fbe..1d469ea94 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -49,9 +49,6 @@ import org.w3c.dom.Document; */ public class AFPSVGHandler extends AbstractGenericSVGHandler { - /** logging instance */ - private static Log log = LogFactory.getLog(AFPSVGHandler.class); - /** {@inheritDoc} */ public void handleXML(RendererContext context, Document doc, String ns) throws Exception { @@ -196,7 +193,10 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { } /** {@inheritDoc} */ - public String getNamespace() { - return SVGDOMImplementation.SVG_NAMESPACE_URI; + protected void updateRendererContext(RendererContext context) { + //Work around a problem in Batik: Gradients cannot be done in ColorSpace.CS_GRAY + context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, + Boolean.FALSE); } + } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java index 808cd88f1..659c79a8e 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java @@ -55,7 +55,8 @@ public class AFPElement extends AbstractAFPExtensionObject { } } - protected ExtensionAttachment instantiateExtensionAttachment() { - return null; - } + protected ExtensionAttachment instantiateExtensionAttachment() { + return new AFPPageSetup(getName()); + } + } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java index 8d4b0ae5e..ad80399e3 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java @@ -19,8 +19,6 @@ package org.apache.fop.render.afp.extensions; -import java.util.HashMap; - import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.FONode; @@ -39,7 +37,7 @@ public class AFPElementMapping extends ElementMapping { public static final String PAGE = "page"; /** page group element */ - public static final String PAGE_GROUP = "page-group"; +// public static final String PAGE_GROUP = "page-group"; /** tag logical element */ public static final String TAG_LOGICAL_ELEMENT = "tag-logical-element"; @@ -78,9 +76,12 @@ public class AFPElementMapping extends ElementMapping { protected void initialize() { if (foObjs == null) { - foObjs = new HashMap(); + super.foObjs = new java.util.HashMap(); foObjs.put(PAGE, new AFPPageSetupMaker()); - // foObjs.put(PAGE_GROUP, new AFPMaker()); +// foObjs.put( +// PAGE_GROUP, +// new AFPPageGroupMaker() +// ); foObjs.put( TAG_LOGICAL_ELEMENT, new AFPTagLogicalElementMaker()); @@ -94,7 +95,6 @@ public class AFPElementMapping extends ElementMapping { NO_OPERATION, new AFPNoOperationMaker()); } - } static class AFPPageSetupMaker extends ElementMapping.Maker { @@ -126,4 +126,10 @@ public class AFPElementMapping extends ElementMapping { return new AFPElement(parent, NO_OPERATION); } } + +// static class AFPPageGroupMaker extends ElementMapping.Maker { +// public FONode make(FONode parent) { +// return new AFPElement(parent, PAGE_GROUP); +// } +// } } 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 7fdf7cd11..fca486279 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java @@ -54,7 +54,7 @@ public class AFPExtensionHandler extends DefaultHandler || localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) || localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) || localName.equals(AFPElementMapping.PAGE) - || localName.equals(AFPElementMapping.PAGE_GROUP)) { + /*|| localName.equals(AFPElementMapping.PAGE_GROUP)*/) { //handled in endElement } else { handled = false; 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..44dcd0e9f 100644 --- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java @@ -229,11 +229,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/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java index 26d42b2d4..106454ad6 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java @@ -44,7 +44,7 @@ public abstract class AbstractAFPObject { * DataStream objects must implement the writeDataStream() * method to write its data to the given OutputStream * @param os The outputsteam stream - * @throws java.io.IOException in the event that an I/O exception occurred + * @throws java.io.IOException */ public abstract void writeDataStream(OutputStream os) throws IOException; @@ -52,10 +52,10 @@ public abstract class AbstractAFPObject { * Help method to write a set of AFPObjects to the AFP datastream. * @param objects a list of AFPObjects * @param os The stream to write to - * @throws java.io.IOException in the event that an I/O exception occurred + * @throws java.io.IOException */ protected void writeObjects(Collection/**/ objects, OutputStream os) - throws IOException { + throws IOException { if (objects != null) { for (Iterator it = objects.iterator(); it.hasNext();) { Object obj1 = it.next(); @@ -63,5 +63,7 @@ public abstract class AbstractAFPObject { obj.writeDataStream(os); } } + } -} \ No newline at end of file +} + diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java b/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java index 29c619d32..6d827766e 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java @@ -28,22 +28,22 @@ public abstract class AbstractDescriptor extends AbstractAFPObject { /** height of this descriptor */ protected int height = 0; /** width resolution of this descriptor */ - protected int widthRes = 0; + protected int widthResolution = 0; /** height resolution of this descriptor */ - protected int heightRes = 0; + protected int heightResolution = 0; /** * Constructor a PresentationTextDescriptor for the specified * width and height. * @param width The width of the page. * @param height The height of the page. - * @param widthRes The width resolution of the page. - * @param heightRes The height resolution of the page. + * @param widthResolution The width resolution of the page. + * @param heightResolution The height resolution of the page. */ - public AbstractDescriptor(int width, int height, int widthRes, int heightRes) { + public AbstractDescriptor(int width, int height, int widthResolution, int heightResolution) { this.width = width; this.height = height; - this.widthRes = widthRes; - this.heightRes = heightRes; + this.widthResolution = widthResolution; + this.heightResolution = heightResolution; } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java index 393cff84b..09fa33f8f 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java @@ -38,7 +38,7 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject * The name of the object in EBCIDIC bytes */ protected byte[] nameBytes; - + /** * Default constructor */ @@ -51,19 +51,17 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject * @param name the object name */ protected AbstractNamedAFPObject(String name) { - int nameLen = getNameLength(); - if (name.length() < nameLen) { - this.name = (name + " ").substring(0, nameLen); - } else if (name.length() > nameLen) { - log.warn("Constructor:: name truncated to " + nameLen + " chars: " + name); - this.name = name.substring(0, nameLen); - } else { - this.name = name; + this.name = name; + if (name.length() < 8) { + name = (name + " ").substring(0, 8); + } else if (name.length() > 8) { + log.warn("Constructor:: name truncated to 8 chars" + name); + name = name.substring(0, 8); } try { - this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); + nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); } catch (UnsupportedEncodingException usee) { - this.nameBytes = name.getBytes(); + nameBytes = name.getBytes(); log.warn( "Constructor:: UnsupportedEncodingException translating the name " + name); @@ -82,5 +80,6 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject */ public String getName() { return name; - } + } + } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java index f373b5bf7..984aa44c9 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java @@ -310,7 +310,7 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer private PresentationTextObject getPresentationTextObject() { if (presentationTextObject == null) { this.presentationTextObject = new PresentationTextObject(); - addObject(this.presentationTextObject); + super.addObject(this.presentationTextObject); } return presentationTextObject; } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java index 4aea02901..726c58762 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageContent.java @@ -18,13 +18,11 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; - import java.io.IOException; import java.io.OutputStream; import org.apache.fop.render.afp.tools.BinaryUtils; /** - * Image content IOCA object */ public class ImageContent extends AbstractStructuredAFPObject { @@ -55,27 +53,27 @@ public class ImageContent extends AbstractStructuredAFPObject { /** * The image size parameter */ - private ImageSizeParameter imageSizeParam = null; + private ImageSizeParameter _imageSizeParameter = null; /** * The image encoding */ - private byte encoding = 0x03; + private byte _encoding = 0x03; /** * The image ide size */ - private byte size = 1; + private byte _size = 1; /** * The image compression */ - private byte compression = (byte)0xC0; + private byte _compression = (byte)0xC0; /** * The image color model */ - private byte colorModel = 0x01; + private byte _colorModel = 0x01; /** * The image data @@ -97,39 +95,39 @@ public class ImageContent extends AbstractStructuredAFPObject { * @param vsize The vertival size of the image. */ public void setImageSize(int hresol, int vresol, int hsize, int vsize) { - this.imageSizeParam = new ImageSizeParameter(hresol, vresol, hsize, vsize); + _imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize); } /** * Sets the image encoding. - * @param enc The image encoding. + * @param encoding The image encoding. */ - public void setImageEncoding(byte enc) { - this.encoding = enc; + public void setImageEncoding(byte encoding) { + _encoding = encoding; } /** * Sets the image compression. - * @param comp The image compression. + * @param compression The image compression. */ - public void setImageCompression(byte comp) { - this.compression = comp; + public void setImageCompression(byte compression) { + _compression = compression; } /** * Sets the image IDE size. - * @param siz The IDE size. + * @param size The IDE size. */ - public void setImageIDESize(byte siz) { - this.size = siz; + public void setImageIDESize(byte size) { + _size = size; } /** * Sets the image IDE color model. - * @param model the IDE color model. + * @param colorModel the IDE color model. */ - public void setImageIDEColorModel(byte model) { - this.colorModel = model; + public void setImageIDEColorModel(byte colorModel) { + _colorModel = colorModel; } /** @@ -144,8 +142,8 @@ public class ImageContent extends AbstractStructuredAFPObject { * {@inheritDoc} */ protected void writeContent(OutputStream os) throws IOException { - if (imageSizeParam != null) { - imageSizeParam.writeDataStream(os); + if (_imageSizeParameter != null) { + _imageSizeParameter.writeDataStream(os); } os.write(getImageEncodingParameter()); os.write(getImageIDESizeParameter()); @@ -190,16 +188,21 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getImageDataStart(int len) { - byte[] imageDataStartData = new byte[] { + + byte[] data = new byte[] { (byte)0xFE, // ID (byte)0x92, // ID 0x00, // Length 0x00, // Length }; + byte[] l = BinaryUtils.convert(len, 2); - imageDataStartData[2] = l[0]; - imageDataStartData[3] = l[1]; - return imageDataStartData; + data[2] = l[0]; + data[3] = l[1]; + + + return data; + } /** @@ -207,13 +210,16 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getImageEncodingParameter() { - byte[] imageEncParamData = new byte[] { + + byte[] data = new byte[] { (byte)0x95, // ID 0x02, // Length - encoding, + _encoding, 0x01, // RECID }; - return imageEncParamData; + + return data; + } /** @@ -221,8 +227,9 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getExternalAlgorithmParameter() { - if (encoding == (byte)0x83 && compression != 0) { - byte[] extAlgParamData = new byte[] { + + if (_encoding == (byte)0x83 && _compression != 0) { + byte[] data = new byte[] { (byte)0x95, // ID 0x00, // Length 0x10, // ALGTYPE = Compression Algorithm @@ -231,13 +238,13 @@ public class ImageContent extends AbstractStructuredAFPObject { 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved - compression, // MARKER + _compression, // MARKER 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved }; - extAlgParamData[1] = (byte)(extAlgParamData.length - 2); - return extAlgParamData; + data[1] = (byte)(data.length - 2); + return data; } return new byte[0]; } @@ -247,12 +254,15 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getImageIDESizeParameter() { - byte[] imageIDESizeParamData = new byte[] { + + byte[] data = new byte[] { (byte)0x96, // ID 0x01, // Length - size, + _size, }; - return imageIDESizeParamData; + + return data; + } /** @@ -260,14 +270,15 @@ public class ImageContent extends AbstractStructuredAFPObject { * @return byte[] The data stream. */ private byte[] getIDEStructureParameter() { - if (colorModel != 0 && size == 24) { - byte bits = (byte)(size / 3); - byte[] ideStructParamData = new byte[] { + + if (_colorModel != 0 && _size == 24) { + byte bits = (byte)(_size / 3); + byte[] data = new byte[] { (byte)0x9B, // ID 0x00, // Length 0x00, // FLAGS 0x00, // Reserved - colorModel, // COLOR MODEL + _colorModel, // COLOR MODEL 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved @@ -275,9 +286,10 @@ public class ImageContent extends AbstractStructuredAFPObject { bits, bits, }; - ideStructParamData[1] = (byte)(ideStructParamData.length - 2); - return ideStructParamData; + data[1] = (byte)(data.length - 2); + return data; } return new byte[0]; } + } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java index d1c2c11c7..9250f0c7f 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java @@ -27,17 +27,10 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class ImageDataDescriptor extends AbstractAFPObject { - /** x resolution */ - private int xresol = 0; - - /** y resolution */ - private int yresol = 0; - - /** width */ - private int width = 0; - - /** height */ - private int height = 0; + private int _xresol = 0; + private int _yresol = 0; + private int _width = 0; + private int _height = 0; /** * Constructor for a ImageDataDescriptor for the specified @@ -48,25 +41,26 @@ public class ImageDataDescriptor extends AbstractAFPObject { * @param height The height of the height. */ public ImageDataDescriptor(int xresol, int yresol, int width, int height) { - this.xresol = xresol; - this.yresol = yresol; - this.width = width; - this.height = height; + + _xresol = xresol; + _yresol = yresol; + _width = width; + _height = height; + } /** - * {@inheritDoc} + * Accessor method to write the AFP datastream for the Image Data Descriptor + * @param os The stream to write to + * @throws java.io.IOException */ - public void writeDataStream(OutputStream os) throws IOException { - byte[] len = BinaryUtils.convert(21, 2); - byte[] xres = BinaryUtils.convert(xresol, 2); - byte[] yres = BinaryUtils.convert(yresol, 2); - byte[] w = BinaryUtils.convert(width, 2); - byte[] h = BinaryUtils.convert(height, 2); + public void writeDataStream(OutputStream os) + throws IOException { + byte[] data = new byte[] { 0x5A, - len[0], - len[1], + 0x00, + 0x20, (byte) 0xD3, (byte) 0xA6, (byte) 0xFB, @@ -74,19 +68,42 @@ public class ImageDataDescriptor extends AbstractAFPObject { 0x00, // Reserved 0x00, // Reserved 0x00, // Unit base - 10 Inches - xres[0], // XRESOL - xres[1], // - yres[0], // YRESOL - yres[1], // - w[0], // XSIZE - w[1], // - h[0], // YSIZE - h[1], // + 0x00, // XRESOL + 0x00, // + 0x00, // YRESOL + 0x00, // + 0x00, // XSIZE + 0x00, // + 0x00, // YSIZE + 0x00, // (byte)0xF7, // ID = Set IOCA Function Set 0x02, // Length 0x01, // Category = Function set identifier 0x0B, // FCNSET = IOCA FS 11 }; + + byte[] l = BinaryUtils.convert(data.length - 1, 2); + data[1] = l[0]; + data[2] = l[1]; + + byte[] x = BinaryUtils.convert(_xresol, 2); + data[10] = x[0]; + data[11] = x[1]; + + byte[] y = BinaryUtils.convert(_yresol, 2); + data[12] = y[0]; + data[13] = y[1]; + + byte[] w = BinaryUtils.convert(_width, 2); + data[14] = w[0]; + data[15] = w[1]; + + byte[] h = BinaryUtils.convert(_height, 2); + data[16] = h[0]; + data[17] = h[1]; + os.write(data); + } + } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java index 2876e8348..ea8eb334b 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java @@ -18,7 +18,6 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; - import java.io.IOException; import java.io.OutputStream; @@ -165,6 +164,7 @@ public class ImageSegment extends AbstractNamedAFPObject { * {@inheritDoc} */ protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[] { 0x71, // ID 0x00, // Length diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java index aa35db10e..7c940148b 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java @@ -35,11 +35,11 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { * and object height. * @param width The page width. * @param height The page height. - * @param widthRes The page width resolution. - * @param heightRes The page height resolution. + * @param widthResolution The page width resolution. + * @param heightResolution The page height resolution. */ - public ObjectAreaDescriptor(int width, int height, int widthRes, int heightRes) { - super(width, height, widthRes, heightRes); + public ObjectAreaDescriptor(int width, int height, int widthResolution, int heightResolution) { + super(width, height, widthResolution, heightResolution); } /** @@ -47,7 +47,8 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { * @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 { + public void writeDataStream(OutputStream os) + throws IOException { byte[] data = new byte[29]; data[0] = 0x5A; @@ -71,12 +72,12 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { data[15] = 0x00; // YaoBase = 10 inches // XaoUnits - byte[] xdpi = BinaryUtils.convert(this.widthRes * 10, 2); + byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); data[16] = xdpi[0]; data[17] = xdpi[1]; // YaoUnits - byte[] ydpi = BinaryUtils.convert(this.heightRes * 10, 2); + byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); data[18] = ydpi[0]; data[19] = ydpi[1]; @@ -84,16 +85,18 @@ public class ObjectAreaDescriptor extends AbstractDescriptor { data[21] = 0x4C; // tid = Object Area Size data[22] = 0x02; // Size Type - byte[] x = BinaryUtils.convert(this.width, 3); + byte[] x = BinaryUtils.convert(width, 3); data[23] = x[0]; data[24] = x[1]; data[25] = x[2]; - byte[] y = BinaryUtils.convert(this.height, 3); + byte[] y = BinaryUtils.convert(height, 3); data[26] = y[0]; data[27] = y[1]; data[28] = y[2]; os.write(data); + } + } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java index ffa5f3c85..1cdec7616 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java @@ -35,11 +35,11 @@ public class PageDescriptor extends AbstractDescriptor { * and page height. * @param width The page width. * @param height The page height. - * @param widthRes The page width resolution - * @param heightRes The page height resolution + * @param widthResolution The page width resolution + * @param heightResolution The page height resolution */ - public PageDescriptor(int width, int height, int widthRes, int heightRes) { - super(width, height, widthRes, heightRes); + public PageDescriptor(int width, int height, int widthResolution, int heightResolution) { + super(width, height, widthResolution, heightResolution); } /** @@ -68,12 +68,12 @@ public class PageDescriptor extends AbstractDescriptor { data[10] = 0x00; // YpgBase = 10 inches // XpgUnits - byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2); + byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); data[11] = xdpi[0]; data[12] = xdpi[1]; // YpgUnits - byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2); + byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); data[13] = ydpi[0]; data[14] = ydpi[1]; diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java index bad80bcc1..9a8646ba0 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PageObject.java @@ -56,14 +56,14 @@ public class PageObject extends AbstractPageObject { * the height of the page. * @param rotation * the rotation of the page. - * @param widthRes + * @param widthResolution * the width resolution of the page. - * @param heightRes + * @param heightResolution * the height resolution of the page. */ public PageObject(String name, int width, int height, int rotation, - int widthRes, int heightRes) { - super(name, width, height, rotation, widthRes, heightRes); + int widthResolution, int heightResolution) { + super(name, width, height, rotation, widthResolution, heightResolution); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java index 30a78d6c9..98beb96f7 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java @@ -56,42 +56,42 @@ public class PresentationTextData extends AbstractAFPObject { /** * The afp data relating to this presentaion text data. */ - private ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + private ByteArrayOutputStream _baos = new ByteArrayOutputStream(1024); /** * The current x coordinate. */ - private int currentXCoordinate = -1; + private int _currentXCoordinate = -1; /** * The current y cooridnate */ - private int currentYCoordinate = -1; + private int _currentYCoordinate = -1; /** * The current font */ - private String currentFont = ""; + private String _currentFont = ""; /** * The current orientation */ - private int currentOrientation = 0; + private int _currentOrientation = 0; /** * The current color */ - private Color currentColor = new Color(0, 0, 0); + private Color _currentColor = new Color(0, 0, 0); /** * The current variable space increment */ - private int currentVariableSpaceCharacterIncrement = 0; + private int _currentVariableSpaceCharacterIncrement = 0; /** * The current inter character adjustment */ - private int currentInterCharacterAdjustment = 0; + private int _currentInterCharacterAdjustment = 0; /** * Default constructor for the PresentationTextData. @@ -112,7 +112,7 @@ public class PresentationTextData extends AbstractAFPObject { */ public PresentationTextData(boolean controlInd) { - baos.write(new byte[] {0x5A, // Structured field identifier + _baos.write(new byte[] { 0x5A, // Structured field identifier 0x00, // Record length byte 1 0x00, // Record length byte 2 (byte) 0xD3, // PresentationTextData identifier byte 1 @@ -124,7 +124,7 @@ public class PresentationTextData extends AbstractAFPObject { }, 0, 9); if (controlInd) { - baos.write(new byte[] {0x2B, (byte) 0xD3}, 0, 2); + _baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2); } } @@ -142,13 +142,13 @@ public class PresentationTextData extends AbstractAFPObject { private void setCodedFont(byte font, ByteArrayOutputStream afpdata) { // Avoid unnecessary specification of the font - if (String.valueOf(font).equals(currentFont)) { + if (String.valueOf(font).equals(_currentFont)) { return; } else { - currentFont = String.valueOf(font); + _currentFont = String.valueOf(font); } - afpdata.write(new byte[] {0x03, (byte) 0xF1, font}, 0, 3); + afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3); } @@ -167,9 +167,9 @@ public class PresentationTextData extends AbstractAFPObject { byte[] b = BinaryUtils.convert(coordinate, 2); - afpdata.write(new byte[] {0x04, (byte) 0xC7, b[0], b[1]}, 0, 4); + afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4); - currentXCoordinate = coordinate; + _currentXCoordinate = coordinate; } @@ -188,9 +188,9 @@ public class PresentationTextData extends AbstractAFPObject { byte[] b = BinaryUtils.convert(coordinate, 2); - afpdata.write(new byte[] {0x04, (byte) 0xD3, b[0], b[1]}, 0, 4); + afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4); - currentYCoordinate = coordinate; + _currentYCoordinate = coordinate; } @@ -214,7 +214,7 @@ public class PresentationTextData extends AbstractAFPObject { "Transparent data is longer than 253 bytes: " + data); } - afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB}, + afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, }, 0, 2); afpdata.write(data, 0, data.length); @@ -236,7 +236,7 @@ public class PresentationTextData extends AbstractAFPObject { private void drawBaxisRule(int length, int width, ByteArrayOutputStream afpdata) { - afpdata.write(new byte[] {0x07, // Length + afpdata.write(new byte[] { 0x07, // Length (byte) 0xE7, // Type }, 0, 2); @@ -266,7 +266,7 @@ public class PresentationTextData extends AbstractAFPObject { private void drawIaxisRule(int length, int width, ByteArrayOutputStream afpdata) { - afpdata.write(new byte[] {0x07, // Length + afpdata.write(new byte[] { 0x07, // Length (byte) 0xE5, // Type }, 0, 2); @@ -284,7 +284,7 @@ public class PresentationTextData extends AbstractAFPObject { /** * Create the presentation text data for the byte array of data. * - * @param fontReference + * @param fontNumber * The font resource identifier. * @param x * The x coordinate for the text data. @@ -300,64 +300,64 @@ public class PresentationTextData extends AbstractAFPObject { * The inter character adjustment. * @param data * The text data to be created. - * @throws MaximumSizeExceededException if the maximum size is exceeded + * @throws MaximumSizeExceededException */ - public void createTextData(int fontReference, int x, int y, int orientation, + public void createTextData(int fontNumber, int x, int y, int orientation, Color col, int vsci, int ica, byte[] data) throws MaximumSizeExceededException { ByteArrayOutputStream afpdata = new ByteArrayOutputStream(); - if (currentOrientation != orientation) { + if (_currentOrientation != orientation) { setTextOrientation(orientation, afpdata); - currentOrientation = orientation; - currentXCoordinate = -1; - currentYCoordinate = -1; + _currentOrientation = orientation; + _currentXCoordinate = -1; + _currentYCoordinate = -1; } // Avoid unnecessary specification of the Y co-ordinate - if (y != currentYCoordinate) { + if (y != _currentYCoordinate) { absoluteMoveBaseline(y, afpdata); - currentXCoordinate = -1; + _currentXCoordinate = -1; } // Avoid unnecessary specification of the X co-ordinate - if (x != currentXCoordinate) { + if (x != _currentXCoordinate) { absoluteMoveInline(x, afpdata); } // Avoid unnecessary specification of the variable space increment - if (vsci != currentVariableSpaceCharacterIncrement) { + if (vsci != _currentVariableSpaceCharacterIncrement) { setVariableSpaceCharacterIncrement(vsci, afpdata); - currentVariableSpaceCharacterIncrement = vsci; + _currentVariableSpaceCharacterIncrement = vsci; } // Avoid unnecessary specification of the inter character adjustment - if (ica != currentInterCharacterAdjustment) { + if (ica != _currentInterCharacterAdjustment) { setInterCharacterAdjustment(ica, afpdata); - currentInterCharacterAdjustment = ica; + _currentInterCharacterAdjustment = ica; } // Avoid unnecessary specification of the text color - if (!col.equals(currentColor)) { + if (!col.equals(_currentColor)) { setExtendedTextColor(col, afpdata); - currentColor = col; + _currentColor = col; } - setCodedFont(BinaryUtils.convert(fontReference)[0], afpdata); + setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata); addTransparentData(data, afpdata); - currentXCoordinate = -1; + _currentXCoordinate = -1; int s = afpdata.size(); - if (baos.size() + s > MAX_SIZE) { - currentXCoordinate = -1; - currentYCoordinate = -1; + if (_baos.size() + s > MAX_SIZE) { + _currentXCoordinate = -1; + _currentYCoordinate = -1; throw new MaximumSizeExceededException(); } byte[] outputdata = afpdata.toByteArray(); - baos.write(outputdata, 0, outputdata.length); + _baos.write(outputdata, 0, outputdata.length); } @@ -379,31 +379,30 @@ public class PresentationTextData extends AbstractAFPObject { * The orientation of the text data. * @param col * The text color. - * @throws MaximumSizeExceededException if the maximum size is exceeded */ public void createLineData(int x1, int y1, int x2, int y2, int thickness, int orientation, Color col) throws MaximumSizeExceededException { ByteArrayOutputStream afpdata = new ByteArrayOutputStream(); - if (currentOrientation != orientation) { + if (_currentOrientation != orientation) { setTextOrientation(orientation, afpdata); - currentOrientation = orientation; + _currentOrientation = orientation; } // Avoid unnecessary specification of the Y coordinate - if (y1 != currentYCoordinate) { + if (y1 != _currentYCoordinate) { absoluteMoveBaseline(y1, afpdata); } // Avoid unnecessary specification of the X coordinate - if (x1 != currentXCoordinate) { + if (x1 != _currentXCoordinate) { absoluteMoveInline(x1, afpdata); } - if (!col.equals(currentColor)) { + if (!col.equals(_currentColor)) { setExtendedTextColor(col, afpdata); - currentColor = col; + _currentColor = col; } if (y1 == y2) { @@ -416,14 +415,14 @@ public class PresentationTextData extends AbstractAFPObject { int s = afpdata.size(); - if (baos.size() + s > MAX_SIZE) { - currentXCoordinate = -1; - currentYCoordinate = -1; + if (_baos.size() + s > MAX_SIZE) { + _currentXCoordinate = -1; + _currentYCoordinate = -1; throw new MaximumSizeExceededException(); } byte[] outputdata = afpdata.toByteArray(); - baos.write(outputdata, 0, outputdata.length); + _baos.write(outputdata, 0, outputdata.length); } @@ -444,7 +443,7 @@ public class PresentationTextData extends AbstractAFPObject { private void setTextOrientation(int orientation, ByteArrayOutputStream afpdata) { - afpdata.write(new byte[] {0x06, (byte) 0xF7}, 0, 2); + afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2); switch (orientation) { case 90: @@ -560,11 +559,12 @@ public class PresentationTextData extends AbstractAFPObject { * Accessor method to write the AFP datastream for * the text data. * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred + * @throws java.io.IOException */ - public void writeDataStream(OutputStream os) throws IOException { + public void writeDataStream(OutputStream os) + throws IOException { - byte[] data = baos.toByteArray(); + byte[] data = _baos.toByteArray(); byte[] size = BinaryUtils.convert(data.length - 1, 2); data[1] = size[0]; data[2] = size[1]; @@ -580,7 +580,7 @@ public class PresentationTextData extends AbstractAFPObject { * presentation text data objects, but must eventually be terminated. This * method terminates the control sequence. * - * @throws MaximumSizeExceededException if the maximum size is exceeded + * @throws MaximumSizeExceededException */ public void endControlSequence() throws MaximumSizeExceededException { @@ -588,10 +588,12 @@ public class PresentationTextData extends AbstractAFPObject { data[0] = 0x02; data[1] = (byte) 0xF8; - if (data.length + baos.size() > MAX_SIZE) { + if (data.length + _baos.size() > MAX_SIZE) { throw new MaximumSizeExceededException(); } - baos.write(data, 0, data.length); + + _baos.write(data, 0, data.length); + } } \ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java index 27b3de5ca..3858f4169 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java @@ -52,11 +52,12 @@ public class PresentationTextDescriptor extends AbstractDescriptor { * width and height. * @param width The width of the page. * @param height The height of the page. - * @param widthRes The width resolution of the page. - * @param heightRes The height resolution of the page. + * @param widthResolution The width resolution of the page. + * @param heightResolution The height resolution of the page. */ - public PresentationTextDescriptor(int width, int height, int widthRes, int heightRes) { - super(width, height, widthRes, heightRes); + public PresentationTextDescriptor(int width, int height, + int widthResolution, int heightResolution) { + super(width, height, widthResolution, heightResolution); } /** @@ -80,11 +81,11 @@ public class PresentationTextDescriptor extends AbstractDescriptor { data[9] = 0x00; data[10] = 0x00; - byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2); + byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); data[11] = xdpi[0]; // xdpi data[12] = xdpi[1]; - byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2); + byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); data[13] = ydpi[0]; // ydpi data[14] = ydpi[1]; diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java index 49f7c81a8..5df9fdb4c 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java @@ -117,7 +117,6 @@ public class PresentationTextObject extends AbstractNamedAFPObject { startPresentationTextData(); } try { - currentPresentationTextData.createTextData(fontRef, x, y, orientation, col, vsci, ica, data); } catch (MaximumSizeExceededException msee) { @@ -279,4 +278,4 @@ public class PresentationTextObject extends AbstractNamedAFPObject { endControlSequence(); } } -} \ No newline at end of file +} diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java b/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java index 99f31ba14..29ac9eb5d 100644 --- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java +++ b/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java @@ -47,7 +47,7 @@ public class TagLogicalElementBean { * @return the key */ public String getKey() { - return this.key; + return key; } /** @@ -55,7 +55,7 @@ public class TagLogicalElementBean { * @return the value */ public String getValue() { - return this.value; + return value; } } 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/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 8442af229..583d2ad2f 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -312,6 +312,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); } + graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_PURE); // transform page based on scale factor supplied AffineTransform at = graphics.getTransform(); 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/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/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 19f274902..55524534e 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); @@ -1803,9 +1730,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/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/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/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/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 f618b0074..a008177c1 100644 --- a/status.xml +++ b/status.xml @@ -16,25 +16,159 @@ limitations under the License. --> + - + + + + + + + - - - - + + + + + + + + + + + - + + + Added SVG support for AFP (GOCA). + + + Added de-duplication and externalization support for IOCA and GOCA data resource objects. + + + 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. + + + + +

      + Notes +

      + Besides the important changes listed below, the most important areas with + improvements in this release are: +

      +
        +
      • + 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 + auto-detection/-registration. +
      • +
      • + Performance improvements and memory optimizations for the property handling + in the FO tree. +
      • +
      +

      + 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) 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. + + + 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. + + + 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. + Added full support for keep-with-previous on fo:table-row and in fo:table-cell elements. 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. @@ -64,7 +198,7 @@ Bugfix for date formatting with negative time zones in the PDF's Info object. This affected PDF/A compliance. - + 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. @@ -134,7 +268,7 @@ 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 will make up an entire page. See the documentation for details. @@ -143,15 +277,12 @@ 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). Bugfix: content of a row with zero height overriding the previous row - - Added SVG support for AFP (GOCA). - Bugfix: allow multiple bookmarks to point at the same destination. @@ -232,7 +363,7 @@ Added support for fo:markers in fo:inline and fo:basic-link. - + PDF Transcoder (SVG) text painting has been completely rewritten. Except for some special cases (with filters for example), all text (including flow text) is now painted using PDF text operators. @@ -279,31 +410,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 @@ -463,33 +584,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 @@ -1064,9 +1188,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. + + + + 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/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 diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index 15ac8aa48..b4de16ef4 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/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/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. + + + + + + + + + + + + + + +
      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/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 + + + + + +
      diff --git a/test/layoutengine/standard-testcases/table-body_background-image.xml b/test/layoutengine/standard-testcases/table-body_background-image.xml deleted file mode 100644 index 2a9aa9362..000000000 --- a/test/layoutengine/standard-testcases/table-body_background-image.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - -

      - 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_block_keep-with-previous.xml b/test/layoutengine/standard-testcases/table-cell_block_keep-with-previous.xml deleted file mode 100644 index 00257a10a..000000000 --- a/test/layoutengine/standard-testcases/table-cell_block_keep-with-previous.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - -

      - This test checks keep-with-previous on content inside tables. -

      -
      - - - - - - - - - - block1 - - - - - - - line1 - line2 - - - line1 - - - - - line1 - - - line1 - - - - - block2 - - - - - - - - - - - - - - - - - - - - - - - - 3 - - -
      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_background-image.xml b/test/layoutengine/standard-testcases/table-header_background-image.xml deleted file mode 100644 index f74c13b0d..000000000 --- a/test/layoutengine/standard-testcases/table-header_background-image.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - -

      - 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-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-row_keep-with-previous.xml b/test/layoutengine/standard-testcases/table-row_keep-with-previous.xml index 34a8be4c1..e6131308a 100644 --- a/test/layoutengine/standard-testcases/table-row_keep-with-previous.xml +++ b/test/layoutengine/standard-testcases/table-row_keep-with-previous.xml @@ -19,66 +19,236 @@

      - This test checks keep-with-previous on table-rows. + This test checks that keep-with-previous works on table-row.

      - + - - + + - + + + - block1 - - + 1. Before the table + + - - - line1 - line2 + + + 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 + + + Cell 3.1 Line 1 + Cell 3.1 Line 2 + + + + + After the table + + + + + + + 2. Before the table + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 + + + Cell 1.2 Line 1 + Cell 1.2 Line 2 - - line1 + + + + Cell 2.1 Line 1 + Cell 2.1 Line 2 - - - line1 + + + After the table + + + + + + + 3. Before the table + Before the table + + + + + + Cell 1.1 Line 1 + Cell 1.1 Line 2 - - line1 + + Cell 1.2 Line 1 + Cell 1.2 Line 2 + + + + + Cell 2.1 Line 1 + Cell 2.1 Line 2 - block2 + After the table + - - - - - - - - - - - - - - - - - - - 3 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      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
      +
      nonopartial  +
        +
      • [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.

      • +
      +
      nonoyes  
      nonoyes  
      nonoyes  
      nonoyes  
      yes (used for layout but not for output) no