git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_Accessibility@829138 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_0
@@ -156,10 +156,14 @@ list of possible build targets. | |||
<property name="fo.examples.userconfig" value="conf/fop.xconf"/> | |||
<property name="fo.examples.include" value="**/*.fo"/> | |||
<property name="fo.examples.force" value="false"/> | |||
<property name="xml.tests.include" value="**/*.xml"/> | |||
<property name="xml.tests.force" value="false"/> | |||
<property name="xml.tests.userconfig" value="conf/fop.xconf"/> | |||
<property name="lib.dir" value="${basedir}/lib"/> | |||
<property name="user.hyph.dir" value="${basedir}/hyph"/> | |||
<property name="unidata.dir" value="${basedir}/UNIDATA"/> | |||
<property name="hyph.stacksize" value="512k"/> | |||
<property name="test.dir" value="${basedir}/test"/> | |||
<property name="build.dir" value="${basedir}/build"/> | |||
<property name="build.gensrc.dir" value="${build.dir}/gensrc"/> | |||
<property name="build.classes.dir" value="${build.dir}/classes"/> | |||
@@ -167,9 +171,11 @@ list of possible build targets. | |||
<property name="build.codegen-classes.dir" value="${build.dir}/codegen-classes"/> | |||
<property name="build.javadocs.dir" value="${build.dir}/javadocs"/> | |||
<property name="build.examples.dir" value="${build.dir}/examples"/> | |||
<property name="build.tests.dir" value="${build.dir}/tests"/> | |||
<property name="build.viewer.resources.dir" value="${build.classes.dir}/org/apache/fop/render/awt/viewer/resources"/> | |||
<property name="build.viewer.images.dir" value="${build.classes.dir}/org/apache/fop/render/awt/viewer/images"/> | |||
<property name="build.property.examples.mime.type" value="application/pdf"/> | |||
<property name="build.property.tests.mime.type" value="application/pdf"/> | |||
<!--property name="layoutengine.disabled" value="test/layoutengine/disabled-testcases.txt"/--> | |||
<!--property name="fotree.disabled" value="test/fotree/disabled-testcases.txt"/--> | |||
<property name="layoutengine.disabled" value="test/layoutengine/disabled-testcases.xml"/> | |||
@@ -755,7 +761,7 @@ list of possible build targets. | |||
<mkdir dir="${build.dir}/test-gensrc"/> | |||
<mkdir dir="${junit.reports.dir}"/> | |||
<javac destdir="${build.dir}/test-classes" fork="${javac.fork}" debug="${javac.debug}" deprecation="${javac.deprecation}" optimize="${javac.optimize}" source="${javac.source}" target="${javac.target}"> | |||
<src path="${basedir}/test/java"/> | |||
<src path="${test.dir}/java"/> | |||
<patternset refid="test-sources"/> | |||
<classpath> | |||
<path refid="libs-build-tools-classpath"/> | |||
@@ -765,19 +771,19 @@ list of possible build targets. | |||
</classpath> | |||
</javac> | |||
<copy todir="${build.dir}/test-classes"> | |||
<fileset dir="${basedir}/test/java"> | |||
<fileset dir="${test.dir}/java"> | |||
<include name="**/*.xsl"/> | |||
</fileset> | |||
</copy> | |||
</target> | |||
<target name="junit-compile-copy-resources" if="junit.present"> | |||
<eventResourceGenerator modelfile="${build.dir}/test-gensrc/org/apache/fop/events/test-event-model.xml"> | |||
<fileset dir="${basedir}/test/java"> | |||
<fileset dir="${test.dir}/java"> | |||
<include name="**/*.java"/> | |||
</fileset> | |||
</eventResourceGenerator> | |||
<copy todir="${build.dir}/test-classes"> | |||
<fileset dir="${basedir}/test/java"> | |||
<fileset dir="${test.dir}/java"> | |||
<include name="META-INF/**"/> | |||
<include name="**/*.xml"/> | |||
</fileset> | |||
@@ -1336,9 +1342,9 @@ NOTE: | |||
</jar> | |||
</target> | |||
<!-- =================================================================== --> | |||
<!-- Generate example PDFs --> | |||
<!-- Generate examples --> | |||
<!-- =================================================================== --> | |||
<target name="examples" depends="package" description="Generates example PDF files"> | |||
<target name="examples" depends="package" description="Generates the example files"> | |||
<taskdef name="fop" classname="org.apache.fop.tools.anttasks.Fop" classpathref="libs-run-classpath"/> | |||
<mkdir dir="${build.examples.dir}"/> | |||
<fop format="${build.property.examples.mime.type}" outdir="${build.examples.dir}" messagelevel="debug" basedir="${fo.examples.dir}" userconfig="${fo.examples.userconfig}" force="${fo.examples.force}"> | |||
@@ -1347,6 +1353,20 @@ NOTE: | |||
</fileset> | |||
</fop> | |||
</target> | |||
<!-- =================================================================== --> | |||
<!-- Generate unit tests --> | |||
<!-- =================================================================== --> | |||
<target name="tests" depends="package" description="Generates the test files"> | |||
<taskdef name="fop" classname="org.apache.fop.tools.anttasks.Fop" classpathref="libs-run-classpath"/> | |||
<mkdir dir="${build.tests.dir}"/> | |||
<fop format="${build.property.tests.mime.type}" xsltfile="${test.dir}/layoutengine/testcase2fo.xsl" outdir="${build.tests.dir}" messagelevel="debug" basedir="${test.dir}" userconfig="${fo.examples.userconfig}" force="${xml.tests.force}"> | |||
<fileset dir="${test.dir}"> | |||
<include name="${xml.tests.include}"/> | |||
</fileset> | |||
</fop> | |||
</target> | |||
<!-- =================================================================== --> | |||
<!-- Helper task to generate source files that have already been --> | |||
<!-- checked into CVS. For these files, CVS version is the official one --> |
@@ -68,6 +68,16 @@ | |||
<td>XSL-FO file to be rendered</td> | |||
<td>Yes, if no fileset nested element is used</td> | |||
</tr> | |||
<tr> | |||
<td>xmlfile</td> | |||
<td>XML input file</td> | |||
<td>Yes, if no fofile is specified</td> | |||
</tr> | |||
<tr> | |||
<td>xsltfile</td> | |||
<td>XSLT input file</td> | |||
<td>Yes, if no fofile is specified</td> | |||
</tr> | |||
<tr> | |||
<td>outfile</td> | |||
<td>Output filename</td> | |||
@@ -194,6 +204,31 @@ | |||
<include name="*.fo"/> | |||
</fileset> | |||
</fop> | |||
</target> | |||
]]></source> | |||
<p> | |||
The following example transforms and converts a single XML and XSLT file to an AFP document: | |||
</p> | |||
<source><![CDATA[ | |||
<target name="generate-afp-from-transform" description="Generates a single AFP file from an XSLT stylesheet"> | |||
<fop format="application/x-afp" | |||
xmlfile="c:\working\foDirectory\Document.xml" | |||
xsltfile="c:\working\foDirectory\Document.xslt" | |||
outfile="c:\working\afpDirectory\Document.afp" /> | |||
</target> | |||
]]></source> | |||
<p> | |||
This example transforms and converts all XML files within an entire directory to PostScript: | |||
</p> | |||
<source><![CDATA[ | |||
<target name="generate-multiple-ps-from-transform" description="Generates multiple PostScript files using an XSLT stylesheet"> | |||
<fop format="application/postscript" | |||
xsltfile="c:\working\foDirectory\Document.xslt" | |||
outdir="${build.dir}" messagelevel="debug"> | |||
<fileset dir="${test.dir}"> | |||
<include name="*.xml"/> | |||
</fileset> | |||
</fop> | |||
</target> | |||
]]></source> | |||
</section> |
@@ -24,6 +24,7 @@ import java.awt.geom.Rectangle2D; | |||
import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; | |||
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; | |||
import org.apache.fop.afp.ioca.IDEStructureParameter; | |||
import org.apache.fop.afp.ioca.ImageContent; | |||
import org.apache.fop.afp.modca.AbstractDataObject; | |||
import org.apache.fop.afp.modca.AbstractNamedAFPObject; | |||
@@ -113,12 +114,35 @@ public class AFPDataObjectFactory { | |||
} | |||
} | |||
if (imageObjectInfo.isColor()) { | |||
imageObj.setIDESize((byte) 24); | |||
} else { | |||
imageObj.setIDESize((byte) imageObjectInfo.getBitsPerPixel()); | |||
ImageContent content = imageObj.getImageSegment().getImageContent(); | |||
int bitsPerPixel = imageObjectInfo.getBitsPerPixel(); | |||
imageObj.setIDESize((byte) bitsPerPixel); | |||
IDEStructureParameter ideStruct; | |||
switch (bitsPerPixel) { | |||
case 1: | |||
//Skip IDE Structure Parameter | |||
break; | |||
case 4: | |||
case 8: | |||
ideStruct = content.needIDEStructureParameter(); | |||
ideStruct.setBitsPerComponent(new int[] {bitsPerPixel}); | |||
break; | |||
case 24: | |||
ideStruct = content.needIDEStructureParameter(); | |||
ideStruct.setDefaultRGBColorModel(); | |||
break; | |||
case 32: | |||
ideStruct = content.needIDEStructureParameter(); | |||
ideStruct.setDefaultCMYKColorModel(); | |||
break; | |||
default: | |||
throw new IllegalArgumentException("Unsupported number of bits per pixel: " | |||
+ bitsPerPixel); | |||
} | |||
if (imageObjectInfo.isSubtractive()) { | |||
ideStruct = content.needIDEStructureParameter(); | |||
ideStruct.setSubtractive(imageObjectInfo.isSubtractive()); | |||
} | |||
imageObj.setSubtractive(imageObjectInfo.isSubtractive()); | |||
imageObj.setData(imageObjectInfo.getData()); | |||
@@ -46,8 +46,10 @@ implements Cloneable { | |||
/** color image support */ | |||
private boolean colorImages = false; | |||
/** images are supported in this AFP environment */ | |||
/** true if certain image formats may be embedded unchanged in their native format. */ | |||
private boolean nativeImagesSupported = false; | |||
/** true if CMYK images (requires IOCA FS45 suppport on the target platform) may be generated */ | |||
private boolean cmykImagesSupported; | |||
/** default value for image depth */ | |||
private int bitsPerPixel = 8; | |||
@@ -64,6 +66,7 @@ implements Cloneable { | |||
/** a unit converter */ | |||
private final transient AFPUnitConverter unitConv = new AFPUnitConverter(this); | |||
/** | |||
* Sets the rotation to be used for portrait pages, valid values are 0 | |||
* (default), 90, 180, 270. | |||
@@ -185,6 +188,24 @@ implements Cloneable { | |||
return this.nativeImagesSupported; | |||
} | |||
/** | |||
* Controls whether CMYK images (IOCA FS45) are enabled. By default, support is disabled | |||
* for wider compatibility. When disabled, any CMYK image is converted to the selected | |||
* color format. | |||
* @param value true to enabled CMYK images | |||
*/ | |||
public void setCMYKImagesSupported(boolean value) { | |||
this.cmykImagesSupported = value; | |||
} | |||
/** | |||
* Indicates whether CMYK images (IOCA FS45) are enabled. | |||
* @return true if IOCA FS45 is enabled | |||
*/ | |||
public boolean isCMYKImagesSupported() { | |||
return this.cmykImagesSupported; | |||
} | |||
/** | |||
* Sets the output/device resolution | |||
* |
@@ -45,7 +45,7 @@ public class GraphicsCharacterString extends AbstractGraphicsCoord { | |||
*/ | |||
public GraphicsCharacterString(String str, int x, int y) { | |||
super(x, y); | |||
this.str = truncate(str); | |||
this.str = truncate(str, MAX_STR_LEN); | |||
} | |||
/** | |||
@@ -57,7 +57,7 @@ public class GraphicsCharacterString extends AbstractGraphicsCoord { | |||
*/ | |||
public GraphicsCharacterString(String str) { | |||
super(null); | |||
this.str = truncate(str); | |||
this.str = truncate(str, MAX_STR_LEN); | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -82,20 +82,6 @@ public class GraphicsCharacterString extends AbstractGraphicsCoord { | |||
os.write(data); | |||
} | |||
/** | |||
* Truncates the string as necessary | |||
* | |||
* @param str a character string | |||
* @return a possibly truncated string | |||
*/ | |||
private String truncate(String str) { | |||
if (str.length() > MAX_STR_LEN) { | |||
str = str.substring(0, MAX_STR_LEN); | |||
log.warn("truncated character string, longer than " + MAX_STR_LEN + " chars"); | |||
} | |||
return str; | |||
} | |||
/** | |||
* Returns the text string as an encoded byte array | |||
* |
@@ -0,0 +1,151 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.afp.ioca; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import org.apache.fop.afp.Streamable; | |||
/** | |||
* This class represents the IOCA IDE Structure parameter (X'9B'). | |||
*/ | |||
public class IDEStructureParameter implements Streamable { | |||
/** The RGB color model used by the IDE Structure parameter */ | |||
public static final byte COLOR_MODEL_RGB = (byte)0x01; | |||
/** The YCrCb color model used by the IDE Structure parameter */ | |||
public static final byte COLOR_MODEL_YCRCB = (byte)0x02; | |||
/** The CMYK color model used by the IDE Structure parameter */ | |||
public static final byte COLOR_MODEL_CMYK = (byte)0x04; | |||
/** The YCbCr color model used by the IDE Structure parameter */ | |||
public static final byte COLOR_MODEL_YCBCR = (byte)0x12; | |||
/** additive/subtractive setting for ASFLAG */ | |||
private boolean subtractive = false; | |||
/** setting for GRAYCODE flag */ | |||
private boolean grayCoding = false; | |||
/** the image color model */ | |||
private byte colorModel = COLOR_MODEL_RGB; | |||
/** the array with the number of bits/IDE for each component */ | |||
private byte[] bitsPerIDE = new byte[] {(byte)1}; //1-bit by default | |||
/** | |||
* Creates a new IDE Structure parameter. The values are initialized for a bi-level image | |||
* using the RGB color model. | |||
*/ | |||
public IDEStructureParameter() { | |||
//nop | |||
} | |||
/** | |||
* Sets the image IDE color model. | |||
* | |||
* @param color the IDE color model. | |||
*/ | |||
public void setColorModel(byte color) { | |||
this.colorModel = color; | |||
} | |||
/** | |||
* Establishes the parameter values for the normal RGB 24bit color model. | |||
*/ | |||
public void setDefaultRGBColorModel() { | |||
this.colorModel = COLOR_MODEL_RGB; | |||
setUniformBitsPerComponent(3, 8); | |||
} | |||
/** | |||
* Establishes the parameter values for the normal CMYK 32bit color model. | |||
*/ | |||
public void setDefaultCMYKColorModel() { | |||
this.colorModel = COLOR_MODEL_CMYK; | |||
setUniformBitsPerComponent(4, 8); | |||
} | |||
/** | |||
* Sets | |||
* @param numComponents | |||
* @param bitsPerComponent | |||
*/ | |||
public void setUniformBitsPerComponent(int numComponents, int bitsPerComponent) { | |||
if (bitsPerComponent < 0 || bitsPerComponent >= 256) { | |||
throw new IllegalArgumentException( | |||
"The number of bits per component must be between 0 and 255"); | |||
} | |||
this.bitsPerIDE = new byte[numComponents]; | |||
for (int i = 0; i < numComponents; i++) { | |||
this.bitsPerIDE[i] = (byte)bitsPerComponent; | |||
} | |||
} | |||
/** | |||
* Sets the array for the bits/IDE, one entry per component. | |||
* @param bitsPerComponent the | |||
*/ | |||
public void setBitsPerComponent(int[] bitsPerComponent) { | |||
int numComponents = bitsPerComponent.length; | |||
this.bitsPerIDE = new byte[numComponents]; | |||
for (int i = 0; i < numComponents; i++) { | |||
int bits = bitsPerComponent[i]; | |||
if (bits < 0 || bits >= 256) { | |||
throw new IllegalArgumentException( | |||
"The number of bits per component must be between 0 and 255"); | |||
} | |||
this.bitsPerIDE[i] = (byte)bits; | |||
} | |||
} | |||
/** | |||
* Set either additive or subtractive mode (used for ASFLAG). | |||
* @param subtractive true for subtractive mode, false for additive mode | |||
*/ | |||
public void setSubtractive(boolean subtractive) { | |||
this.subtractive = subtractive; | |||
} | |||
/** {@inheritDoc} */ | |||
public void writeToStream(OutputStream os) throws IOException { | |||
int length = 7 + bitsPerIDE.length; | |||
byte flags = 0x00; | |||
if (subtractive) { | |||
flags |= 1 << 7; | |||
} | |||
if (grayCoding) { | |||
flags |= 1 << 6; | |||
} | |||
DataOutputStream dout = new DataOutputStream(os); | |||
dout.writeByte(0x9B); //ID | |||
dout.writeByte(length - 2); //LENGTH | |||
dout.writeByte(flags); //FLAGS | |||
dout.writeByte(this.colorModel); //FORMAT | |||
for (int i = 0; i < 3; i++) { | |||
dout.writeByte(0); //RESERVED | |||
} | |||
dout.write(this.bitsPerIDE); //component sizes | |||
} | |||
} |
@@ -56,21 +56,18 @@ public class ImageContent extends AbstractStructuredObject { | |||
/** the image size parameter */ | |||
private ImageSizeParameter imageSizeParameter = null; | |||
/** the IDE Structure parameter */ | |||
private IDEStructureParameter ideStructureParameter = null; | |||
/** the image encoding */ | |||
private byte encoding = (byte)0x03; | |||
/** the image ide size */ | |||
private byte size = 1; | |||
/** the image IDE (Image Data Element, Sample) size */ | |||
private byte ideSize = 1; | |||
/** the image compression */ | |||
private byte compression = (byte)0xC0; | |||
/** the image color model */ | |||
private byte colorModel = (byte)0x01; | |||
/** additive/subtractive setting for ASFLAG */ | |||
private boolean subtractive = false; | |||
/** the image data */ | |||
private byte[] data; | |||
@@ -89,6 +86,34 @@ public class ImageContent extends AbstractStructuredObject { | |||
this.imageSizeParameter = imageSizeParameter; | |||
} | |||
/** | |||
* Sets the IDE Structure parameter. | |||
* @param parameter the IDE Structure parameter | |||
*/ | |||
public void setIDEStructureParameter(IDEStructureParameter parameter) { | |||
this.ideStructureParameter = parameter; | |||
} | |||
/** | |||
* Returns the (optional) IDE Structure parameter | |||
* @return the IDE Structure parameter or null if none is set | |||
*/ | |||
public IDEStructureParameter getIDEStructureParameter() { | |||
return this.ideStructureParameter; | |||
} | |||
/** | |||
* Returns the (optional) IDE Structure parameter. If none is set an instance is prepared | |||
* with defaults for a bi-level image. | |||
* @return the IDE Structure parameter | |||
*/ | |||
public IDEStructureParameter needIDEStructureParameter() { | |||
if (this.ideStructureParameter == null) { | |||
setIDEStructureParameter(new IDEStructureParameter()); | |||
} | |||
return getIDEStructureParameter(); | |||
} | |||
/** | |||
* Sets the image encoding. | |||
* | |||
@@ -113,24 +138,26 @@ public class ImageContent extends AbstractStructuredObject { | |||
* @param s The IDE size. | |||
*/ | |||
public void setImageIDESize(byte s) { | |||
this.size = s; | |||
this.ideSize = s; | |||
} | |||
/** | |||
* Sets the image IDE color model. | |||
* | |||
* @param color the IDE color model. | |||
* @deprecated use {@link #setIDEStructureParameter(IDEStructureParameter)} instead | |||
*/ | |||
public void setImageIDEColorModel(byte color) { | |||
this.colorModel = color; | |||
needIDEStructureParameter().setColorModel(color); | |||
} | |||
/** | |||
* Set either additive or subtractive mode (used for ASFLAG). | |||
* @param subtractive true for subtractive mode, false for additive mode | |||
* @deprecated use {@link #setIDEStructureParameter(IDEStructureParameter)} instead | |||
*/ | |||
public void setSubtractive(boolean subtractive) { | |||
this.subtractive = subtractive; | |||
needIDEStructureParameter().setSubtractive(subtractive); | |||
} | |||
/** | |||
@@ -155,10 +182,12 @@ public class ImageContent extends AbstractStructuredObject { | |||
os.write(getImageIDESizeParameter()); | |||
boolean useFS10 = (this.size == 1); | |||
if (!useFS10) { | |||
os.write(getIDEStructureParameter()); | |||
if (getIDEStructureParameter() != null) { | |||
getIDEStructureParameter().writeToStream(os); | |||
} | |||
boolean useFS10 = (this.ideSize == 1); | |||
if (!useFS10) { | |||
os.write(getExternalAlgorithmParameter()); | |||
} | |||
@@ -243,58 +272,15 @@ public class ImageContent extends AbstractStructuredObject { | |||
* @return byte[] The data stream. | |||
*/ | |||
private byte[] getImageIDESizeParameter() { | |||
if (size != 1) { | |||
if (ideSize != 1) { | |||
final byte[] ideSizeData = new byte[] { | |||
(byte)0x96, // ID | |||
0x01, // Length | |||
size}; | |||
ideSize}; | |||
return ideSizeData; | |||
} else { | |||
return new byte[0]; | |||
} | |||
} | |||
/** | |||
* Helper method to return the external algorithm parameter. | |||
* | |||
* @return byte[] The data stream. | |||
*/ | |||
private byte[] getIDEStructureParameter() { | |||
byte flags = 0x00; | |||
if (subtractive) { | |||
flags |= 1 << 7; | |||
} | |||
if (colorModel != 0 && size == 24) { | |||
final byte bits = (byte)(size / 3); | |||
final byte[] ideStructData = new byte[] { | |||
(byte)0x9B, // ID | |||
0x00, // Length | |||
flags, // FLAGS | |||
colorModel, // COLOR MODEL | |||
0x00, // Reserved | |||
0x00, // Reserved | |||
0x00, // Reserved | |||
bits, | |||
bits, | |||
bits, | |||
}; | |||
ideStructData[1] = (byte)(ideStructData.length - 2); | |||
return ideStructData; | |||
} else if (size == 1) { | |||
final byte[] ideStructData = new byte[] { | |||
(byte)0x9B, // ID | |||
0x00, // Length | |||
flags, // FLAGS | |||
colorModel, // COLOR MODEL | |||
0x00, // Reserved | |||
0x00, // Reserved | |||
0x00, // Reserved | |||
0x01 | |||
}; | |||
ideStructData[1] = (byte)(ideStructData.length - 2); | |||
return ideStructData; | |||
} | |||
return new byte[0]; | |||
} | |||
} |
@@ -56,7 +56,11 @@ public class ImageSegment extends AbstractNamedAFPObject { | |||
this.factory = factory; | |||
} | |||
private ImageContent getImageContent() { | |||
/** | |||
* Returns the image content object associated with this image segment. | |||
* @return the image content | |||
*/ | |||
public ImageContent getImageContent() { | |||
if (imageContent == null) { | |||
this.imageContent = factory.createImageContent(); | |||
} | |||
@@ -108,6 +112,7 @@ public class ImageSegment extends AbstractNamedAFPObject { | |||
* Sets the image IDE color model. | |||
* | |||
* @param colorModel the IDE color model. | |||
* @deprecated Use {@link IDEStructureParameter#setColorModel(byte)} instead. | |||
*/ | |||
public void setIDEColorModel(byte colorModel) { | |||
getImageContent().setImageIDEColorModel(colorModel); | |||
@@ -116,6 +121,7 @@ public class ImageSegment extends AbstractNamedAFPObject { | |||
/** | |||
* Set either additive or subtractive mode (used for ASFLAG). | |||
* @param subtractive true for subtractive mode, false for additive mode | |||
* @deprecated Use {@link IDEStructureParameter#setSubtractive(boolean)} instead. | |||
*/ | |||
public void setSubtractive(boolean subtractive) { | |||
getImageContent().setSubtractive(subtractive); | |||
@@ -124,7 +130,7 @@ public class ImageSegment extends AbstractNamedAFPObject { | |||
/** | |||
* Set the data image data. | |||
* | |||
* @param data the image data | |||
* @param imageData the image data | |||
*/ | |||
public void setData(byte[] imageData) { | |||
getImageContent().setImageData(imageData); |
@@ -43,7 +43,7 @@ public abstract class AbstractAFPObject implements Streamable { | |||
/** the structured field class id */ | |||
protected static final byte SF_CLASS = (byte)0xD3; | |||
private static final byte[] SF_HEADER = new byte[] { | |||
protected static final byte[] SF_HEADER = new byte[] { | |||
0x5A, // Structured field identifier | |||
0x00, // Length byte 1 | |||
0x10, // Length byte 2 | |||
@@ -177,6 +177,21 @@ public abstract class AbstractAFPObject implements Streamable { | |||
} | |||
} | |||
/** | |||
* Truncates the string as necessary | |||
* | |||
* @param str a character string | |||
* @param maxLength the maximum length allowed for the string | |||
* @return a possibly truncated string | |||
*/ | |||
protected String truncate(String str, int maxLength) { | |||
if (str.length() > maxLength) { | |||
str = str.substring(0, maxLength); | |||
log.warn("truncated character string '" + str + "', longer than " + maxLength + " chars"); | |||
} | |||
return str; | |||
} | |||
/** structured field type codes */ | |||
public interface Type { | |||
@@ -27,9 +27,12 @@ import java.util.List; | |||
import org.apache.fop.afp.modca.Registry.ObjectType; | |||
import org.apache.fop.afp.modca.triplets.AbstractTriplet; | |||
import org.apache.fop.afp.modca.triplets.AttributeQualifierTriplet; | |||
import org.apache.fop.afp.modca.triplets.AttributeValueTriplet; | |||
import org.apache.fop.afp.modca.triplets.CommentTriplet; | |||
import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet; | |||
import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet; | |||
import org.apache.fop.afp.modca.triplets.Triplet; | |||
/** | |||
* A MODCA structured object base class providing support for Triplets | |||
@@ -37,7 +40,7 @@ import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet; | |||
public class AbstractTripletStructuredObject extends AbstractStructuredObject { | |||
/** list of object triplets */ | |||
protected List/*<AbstractTriplet>*/ triplets = new java.util.ArrayList/*<AbstractTriplet>*/(); | |||
protected List/*<Triplet>*/ triplets = new java.util.ArrayList/*<Triplet>*/(); | |||
/** | |||
* Returns the triplet data length | |||
@@ -109,7 +112,7 @@ public class AbstractTripletStructuredObject extends AbstractStructuredObject { | |||
* | |||
* @param triplet the triplet to add | |||
*/ | |||
protected void addTriplet(AbstractTriplet triplet) { | |||
protected void addTriplet(Triplet triplet) { | |||
triplets.add(triplet); | |||
} | |||
@@ -130,7 +133,7 @@ public class AbstractTripletStructuredObject extends AbstractStructuredObject { | |||
} | |||
/** | |||
* Sets the fully qualified name of this resource | |||
* Sets the fully qualified name of this structured field | |||
* | |||
* @param fqnType the fully qualified name type of this resource | |||
* @param fqnFormat the fully qualified name format of this resource |
@@ -79,6 +79,8 @@ public class ContainerDataDescriptor extends AbstractDescriptor { | |||
data[18] = ysize[0]; | |||
data[19] = ysize[1]; | |||
data[20] = ysize[2]; | |||
os.write(data); | |||
} | |||
} |
@@ -31,6 +31,7 @@ public class ImageDataDescriptor extends AbstractDescriptor { | |||
public static final byte FUNCTION_SET_FS10 = 0x0A; | |||
public static final byte FUNCTION_SET_FS11 = 0x0B; | |||
public static final byte FUNCTION_SET_FS45 = 45; | |||
private byte functionSet = FUNCTION_SET_FS11; // FCNSET = IOCA FS 11 | |||
@@ -24,9 +24,12 @@ import java.io.OutputStream; | |||
import org.apache.commons.io.output.ByteArrayOutputStream; | |||
import org.apache.xmlgraphics.util.MimeConstants; | |||
import org.apache.fop.afp.AFPDataObjectInfo; | |||
import org.apache.fop.afp.AFPImageObjectInfo; | |||
import org.apache.fop.afp.Factory; | |||
import org.apache.fop.afp.ioca.IDEStructureParameter; | |||
import org.apache.fop.afp.ioca.ImageSegment; | |||
/** | |||
@@ -50,7 +53,11 @@ public class ImageObject extends AbstractDataObject { | |||
super(factory, name); | |||
} | |||
private ImageSegment getImageSegment() { | |||
/** | |||
* Returns the image segment object associated with this image object. | |||
* @return the image segment | |||
*/ | |||
public ImageSegment getImageSegment() { | |||
if (imageSegment == null) { | |||
this.imageSegment = factory.createImageSegment(); | |||
} | |||
@@ -71,6 +78,8 @@ public class ImageObject extends AbstractDataObject { | |||
= factory.createImageDataDescriptor(dataWidth, dataHeight, dataWidthRes, dataHeightRes); | |||
if (imageObjectInfo.getBitsPerPixel() == 1) { | |||
imageDataDescriptor.setFunctionSet(ImageDataDescriptor.FUNCTION_SET_FS10); | |||
} else if (MimeConstants.MIME_AFP_IOCA_FS45.equals(imageObjectInfo.getMimeType())) { | |||
imageDataDescriptor.setFunctionSet(ImageDataDescriptor.FUNCTION_SET_FS45); | |||
} | |||
getObjectEnvironmentGroup().setDataDescriptor(imageDataDescriptor); | |||
getObjectEnvironmentGroup().setMapImageObject( | |||
@@ -110,6 +119,7 @@ public class ImageObject extends AbstractDataObject { | |||
* Sets the image IDE color model. | |||
* | |||
* @param colorModel the IDE color model. | |||
* @deprecated Use {@link IDEStructureParameter#setColorModel(byte)} instead. | |||
*/ | |||
public void setIDEColorModel(byte colorModel) { | |||
getImageSegment().setIDEColorModel(colorModel); | |||
@@ -118,6 +128,7 @@ public class ImageObject extends AbstractDataObject { | |||
/** | |||
* Set either additive or subtractive mode (used for ASFLAG). | |||
* @param subtractive true for subtractive mode, false for additive mode | |||
* @deprecated Use {@link IDEStructureParameter#setSubtractive(boolean)} instead. | |||
*/ | |||
public void setSubtractive(boolean subtractive) { | |||
getImageSegment().setSubtractive(subtractive); |
@@ -21,9 +21,10 @@ package org.apache.fop.afp.modca; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.UnsupportedEncodingException; | |||
import org.apache.fop.afp.AFPConstants; | |||
import org.apache.fop.afp.modca.triplets.AttributeQualifierTriplet; | |||
import org.apache.fop.afp.modca.triplets.AttributeValueTriplet; | |||
import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet; | |||
import org.apache.fop.afp.util.BinaryUtils; | |||
/** | |||
@@ -45,7 +46,7 @@ import org.apache.fop.afp.util.BinaryUtils; | |||
* effect on the appearance of a document when it is presented. | |||
* <p/> | |||
*/ | |||
public class TagLogicalElement extends AbstractAFPObject { | |||
public class TagLogicalElement extends AbstractTripletStructuredObject { | |||
/** | |||
* Name of the key, used within the TLE | |||
@@ -75,77 +76,43 @@ public class TagLogicalElement extends AbstractAFPObject { | |||
this.tleID = tleID; | |||
} | |||
/** {@inheritDoc} */ | |||
public void writeToStream(OutputStream os) throws IOException { | |||
// convert name and value to ebcdic | |||
byte[] tleByteName = null; | |||
byte[] tleByteValue = null; | |||
try { | |||
tleByteName = name.getBytes(AFPConstants.EBCIDIC_ENCODING); | |||
tleByteValue = value.getBytes(AFPConstants.EBCIDIC_ENCODING); | |||
} catch (UnsupportedEncodingException usee) { | |||
tleByteName = name.getBytes(); | |||
tleByteValue = value.getBytes(); | |||
log.warn( | |||
"Constructor:: UnsupportedEncodingException translating the name " | |||
+ name); | |||
} | |||
byte[] data = new byte[27 + tleByteName.length + tleByteValue.length]; | |||
data[0] = 0x5A; | |||
// Set the total record length | |||
byte[] rl1 | |||
= BinaryUtils.convert(26 + tleByteName.length + tleByteValue.length, 2); | |||
//Ignore first byte | |||
data[1] = rl1[0]; | |||
data[2] = rl1[1]; | |||
// Structured field ID for a TLE | |||
data[3] = (byte) 0xD3; | |||
data[4] = (byte) Type.ATTRIBUTE; | |||
data[5] = (byte) Category.PROCESS_ELEMENT; | |||
data[6] = 0x00; // Reserved | |||
data[7] = 0x00; // Reserved | |||
data[8] = 0x00; // Reserved | |||
//Use 2 triplets, attribute name and value (the key for indexing) | |||
byte[] rl2 = BinaryUtils.convert(tleByteName.length + 4, 1); | |||
data[9] = rl2[0]; // length of the triplet, including this field | |||
data[10] = 0x02; //Identifies it as a FQN triplet | |||
data[11] = 0x0B; // GID format | |||
data[12] = 0x00; | |||
// write out TLE name | |||
int pos = 13; | |||
for (int i = 0; i < tleByteName.length; i++) { | |||
data[pos++] = tleByteName[i]; | |||
} | |||
byte[] rl3 = BinaryUtils.convert(tleByteValue.length + 4, 1); | |||
data[pos++] = rl3[0]; // length of the triplet, including this field | |||
data[pos++] = 0x36; //Identifies the triplet, attribute value | |||
data[pos++] = 0x00; // Reserved | |||
data[pos++] = 0x00; // Reserved | |||
/** | |||
* Sets the attribute value of this structured field | |||
* | |||
* @param value the attribute value | |||
*/ | |||
public void setAttributeValue(String value) { | |||
addTriplet(new AttributeValueTriplet(value)); | |||
} | |||
for (int i = 0; i < tleByteValue.length; i++) { | |||
data[pos++] = tleByteValue[i]; | |||
} | |||
// attribute qualifier | |||
data[pos++] = 0x0A; | |||
data[pos++] = (byte)0x80; | |||
byte[] id = BinaryUtils.convert(tleID, 4); | |||
for (int i = 0; i < id.length; i++) { | |||
data[pos++] = id[i]; | |||
} | |||
byte[] level = BinaryUtils.convert(1, 4); | |||
for (int i = 0; i < level.length; i++) { | |||
data[pos++] = level[i]; | |||
} | |||
/** | |||
* Sets the attribute qualifier of this structured field | |||
* | |||
* @param seqNumber the attribute sequence number | |||
* @param levNumber the attribute level number | |||
*/ | |||
public void setAttributeQualifier(int seqNumber, int levNumber) { | |||
addTriplet(new AttributeQualifierTriplet(seqNumber, levNumber)); | |||
} | |||
/** {@inheritDoc} */ | |||
public void writeToStream(OutputStream os) throws IOException { | |||
setFullyQualifiedName( | |||
FullyQualifiedNameTriplet.TYPE_ATTRIBUTE_GID, | |||
FullyQualifiedNameTriplet.FORMAT_CHARSTR, | |||
name); | |||
setAttributeQualifier(tleID, 1); | |||
setAttributeValue(value); | |||
byte[] data = new byte[SF_HEADER.length]; | |||
copySF(data, Type.ATTRIBUTE, Category.PROCESS_ELEMENT); | |||
int tripletDataLength = getTripletDataLength(); | |||
byte[] l = BinaryUtils.convert(data.length + tripletDataLength - 1, 2); | |||
data[1] = l[0]; | |||
data[2] = l[1]; | |||
os.write(data); | |||
writeTriplets(os); | |||
} | |||
} |
@@ -19,70 +19,12 @@ | |||
package org.apache.fop.afp.modca.triplets; | |||
import org.apache.fop.afp.Streamable; | |||
import org.apache.fop.afp.StructuredData; | |||
import org.apache.fop.afp.modca.AbstractAFPObject; | |||
/** | |||
* A simple implementation of a MOD:CA triplet | |||
*/ | |||
public abstract class AbstractTriplet implements Streamable, StructuredData { | |||
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; | |||
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; | |||
public abstract class AbstractTriplet extends AbstractAFPObject implements Triplet { | |||
/** the triplet identifier */ | |||
protected final byte id; |
@@ -0,0 +1,67 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.afp.modca.triplets; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import org.apache.fop.afp.util.BinaryUtils; | |||
/** | |||
* The attribute qualifier triplet is used to specify a qualifier for a document | |||
* attribute. | |||
*/ | |||
public class AttributeQualifierTriplet extends AbstractTriplet { | |||
private int seqNumber; | |||
private int levNumber; | |||
/** | |||
* Main constructor | |||
* | |||
* @param seqNumber the attribute qualifier sequence number | |||
* @param levNumber the attribute qualifier level number | |||
*/ | |||
public AttributeQualifierTriplet(int seqNumber, int levNumber) { | |||
super(ATTRIBUTE_QUALIFIER); | |||
this.seqNumber = seqNumber; | |||
this.levNumber = levNumber; | |||
} | |||
/** {@inheritDoc} */ | |||
public void writeToStream(OutputStream os) throws IOException { | |||
byte[] data = getData(); | |||
byte[] id = BinaryUtils.convert(seqNumber, 4); | |||
System.arraycopy(id, 0, data, 2, id.length); | |||
byte[] level = BinaryUtils.convert(levNumber, 4); | |||
System.arraycopy(level, 0, data, 6, level.length); | |||
os.write(data); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getDataLength() { | |||
return 10; | |||
} | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
return "seqNumber=" + seqNumber + ", levNumber=" + levNumber; | |||
} | |||
} |
@@ -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.afp.modca.triplets; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.UnsupportedEncodingException; | |||
import org.apache.fop.afp.AFPConstants; | |||
/** | |||
* The attribute value triplet is used to specify a value for a document | |||
* attribute. | |||
*/ | |||
public class AttributeValueTriplet extends AbstractTriplet { | |||
private String attVal; | |||
/** | |||
* Main constructor | |||
* | |||
* @param attVal an attribute value | |||
*/ | |||
public AttributeValueTriplet(String attVal) { | |||
super(ATTRIBUTE_VALUE); | |||
this.attVal = truncate(attVal, MAX_LENGTH - 4); | |||
} | |||
/** {@inheritDoc} */ | |||
public void writeToStream(OutputStream os) throws IOException { | |||
byte[] data = super.getData(); | |||
data[2] = 0x00; // Reserved | |||
data[3] = 0x00; // Reserved | |||
// convert name and value to ebcdic | |||
byte[] tleByteValue = null; | |||
try { | |||
tleByteValue = attVal.getBytes(AFPConstants.EBCIDIC_ENCODING); | |||
} catch (UnsupportedEncodingException usee) { | |||
tleByteValue = attVal.getBytes(); | |||
throw new IllegalArgumentException(attVal + " encoding failed"); | |||
} | |||
System.arraycopy(tleByteValue, 0, data, 4, tleByteValue.length); | |||
os.write(data); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getDataLength() { | |||
return 4 + attVal.length(); | |||
} | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
return attVal; | |||
} | |||
} |
@@ -0,0 +1,85 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.afp.modca.triplets; | |||
import org.apache.fop.afp.Streamable; | |||
import org.apache.fop.afp.StructuredData; | |||
public interface Triplet extends Streamable, StructuredData { | |||
int MAX_LENGTH = 254; | |||
byte CODED_GRAPHIC_CHARACTER_SET_GLOBAL_IDENTIFIER = 0x01; | |||
/** Triplet identifiers */ | |||
byte FULLY_QUALIFIED_NAME = 0x02; | |||
byte MAPPING_OPTION = 0x04; | |||
byte OBJECT_CLASSIFICATION = 0x10; | |||
byte MODCA_INTERCHANGE_SET = 0x18; | |||
byte FONT_DESCRIPTOR_SPECIFICATION = 0x1F; | |||
byte OBJECT_FUNCTION_SET_SPECIFICATION = 0x21; | |||
byte EXTENDED_RESOURCE_LOCAL_IDENTIFIER = 0x22; | |||
byte RESOURCE_LOCAL_IDENTIFIER = 0x24; | |||
byte RESOURCE_SECTION_NUMBER = 0x25; | |||
byte CHARACTER_ROTATION = 0x26; | |||
byte OBJECT_BYTE_OFFSET = 0x2D; | |||
byte ATTRIBUTE_VALUE = 0x36; | |||
byte DESCRIPTOR_POSITION = 0x43; | |||
byte MEDIA_EJECT_CONTROL = 0x45; | |||
byte PAGE_OVERLAY_CONDITIONAL_PROCESSING = 0x46; | |||
byte RESOURCE_USAGE_ATTRIBUTE = 0x47; | |||
byte MEASUREMENT_UNITS = 0x4B; | |||
byte OBJECT_AREA_SIZE = 0x4C; | |||
byte AREA_DEFINITION = 0x4D; | |||
byte COLOR_SPECIFICATION = 0x4E; | |||
byte ENCODING_SCHEME_ID = 0x50; | |||
byte MEDIUM_MAP_PAGE_NUMBER = 0x56; | |||
byte OBJECT_BYTE_EXTENT = 0x57; | |||
byte OBJECT_STRUCTURED_FIELD_OFFSET = 0x58; | |||
byte OBJECT_STRUCTURED_FIELD_EXTENT = 0x59; | |||
byte OBJECT_OFFSET = 0x5A; | |||
byte FONT_HORIZONTAL_SCALE_FACTOR = 0x5D; | |||
byte OBJECT_COUNT = 0x5E; | |||
byte OBJECT_DATE_AND_TIMESTAMP = 0x62; | |||
byte COMMENT = 0x65; | |||
byte MEDIUM_ORIENTATION = 0x68; | |||
byte RESOURCE_OBJECT_INCLUDE = 0x6C; | |||
byte PRESENTATION_SPACE_RESET_MIXING = 0x70; | |||
byte PRESENTATION_SPACE_MIXING_RULE = 0x71; | |||
byte UNIVERSAL_DATE_AND_TIMESTAMP = 0x72; | |||
byte TONER_SAVER = 0x74; | |||
byte COLOR_FIDELITY = 0x75; | |||
byte FONT_FIDELITY = 0x78; | |||
byte ATTRIBUTE_QUALIFIER = (byte)0x80; | |||
byte PAGE_POSITION_INFORMATION = (byte)0x81; | |||
byte PARAMETER_VALUE = (byte)0x82; | |||
byte PRESENTATION_CONTROL = (byte)0x83; | |||
byte FONT_RESOLUTION_AND_METRIC_TECHNOLOGY = (byte)0x84; | |||
byte FINISHING_OPERATION = (byte)0x85; | |||
byte TEXT_FIDELITY = (byte)0x86; | |||
byte MEDIA_FIDELITY = (byte)0x87; | |||
byte FINISHING_FIDELITY = (byte)0x88; | |||
byte DATA_OBJECT_FONT_DESCRIPTOR = (byte)0x8B; | |||
byte LOCALE_SELECTOR = (byte)0x8C; | |||
byte UP3I_FINISHING_OPERATION = (byte)0x8E; | |||
byte COLOR_MANAGEMENT_RESOURCE_DESCRIPTOR = (byte)0x91; | |||
byte RENDERING_INTENT = (byte)0x95; | |||
byte CMR_TAG_FIDELITY = (byte)0x96; | |||
byte DEVICE_APPEARANCE = (byte)0x97; | |||
} |
@@ -109,6 +109,8 @@ public class CommandLineOptions { | |||
private boolean useStdIn = false; | |||
/* true if System.out (stdout) should be used for the output file */ | |||
private boolean useStdOut = false; | |||
/* true if a catalog resolver should be used for entity and uri resolution */ | |||
private boolean useCatalogResolver = false; | |||
/* rendering options (for the user agent) */ | |||
private Map renderingOptions = new java.util.HashMap(); | |||
/* target resolution (for the user agent) */ | |||
@@ -354,6 +356,8 @@ public class CommandLineOptions { | |||
} else { | |||
throw new FOPException("invalid param usage: use -param <name> <value>"); | |||
} | |||
} else if (args[i].equals("-catalog")) { | |||
useCatalogResolver = true; | |||
} else if (args[i].equals("-o")) { | |||
i = i + parsePDFOwnerPassword(args, i); | |||
} else if (args[i].equals("-u")) { | |||
@@ -1024,7 +1028,7 @@ public class CommandLineOptions { | |||
case IF_INPUT: | |||
return new IFInputHandler(iffile); | |||
case XSLT_INPUT: | |||
return new InputHandler(xmlfile, xsltfile, xsltParams); | |||
return new InputHandler(xmlfile, xsltfile, xsltParams, useCatalogResolver); | |||
case IMAGE_INPUT: | |||
return new ImageInputHandler(imagefile, xsltfile, xsltParams); | |||
default: | |||
@@ -1166,6 +1170,7 @@ public class CommandLineOptions { | |||
+ " -xsl stylesheet xslt stylesheet \n \n" | |||
+ " -param name value <value> to use for parameter <name> in xslt stylesheet\n" | |||
+ " (repeat '-param name value' for each parameter)\n \n" | |||
+ " -catalog use catalog resolver for input XML and XSLT files\n" | |||
+ " [OUTPUT] \n" | |||
+ " outfile input will be rendered as PDF into outfile\n" | |||
+ " (use '-' for outfile to pipe output to stdout)\n" |
@@ -19,7 +19,6 @@ | |||
package org.apache.fop.cli; | |||
// Imported java.io classes | |||
import java.io.File; | |||
import java.io.FileNotFoundException; | |||
import java.io.InputStream; | |||
@@ -34,11 +33,13 @@ import javax.xml.transform.Source; | |||
import javax.xml.transform.Transformer; | |||
import javax.xml.transform.TransformerException; | |||
import javax.xml.transform.TransformerFactory; | |||
import javax.xml.transform.URIResolver; | |||
import javax.xml.transform.sax.SAXResult; | |||
import javax.xml.transform.sax.SAXSource; | |||
import javax.xml.transform.stream.StreamResult; | |||
import javax.xml.transform.stream.StreamSource; | |||
import org.xml.sax.EntityResolver; | |||
import org.xml.sax.InputSource; | |||
import org.xml.sax.SAXException; | |||
import org.xml.sax.XMLReader; | |||
@@ -51,27 +52,27 @@ import org.apache.fop.apps.FOUserAgent; | |||
import org.apache.fop.apps.Fop; | |||
import org.apache.fop.apps.FopFactory; | |||
import org.apache.fop.render.awt.viewer.Renderable; | |||
import org.xml.sax.InputSource; | |||
import org.xml.sax.SAXException; | |||
import org.xml.sax.XMLReader; | |||
/** | |||
* Class for handling files input from command line | |||
* either with XML and XSLT files (and optionally xsl | |||
* parameters) or FO File input alone | |||
* parameters) or FO File input alone. | |||
*/ | |||
public class InputHandler implements ErrorListener, Renderable { | |||
/** original source file */ | |||
protected File sourcefile = null; | |||
private File stylesheet = null; // for XML/XSLT usage | |||
private Vector xsltParams = null; // for XML/XSLT usage | |||
protected File sourcefile; | |||
private File stylesheet; // for XML/XSLT usage | |||
private Vector xsltParams; // for XML/XSLT usage | |||
private EntityResolver entityResolver; | |||
private URIResolver uriResolver; | |||
/** the logger */ | |||
protected Log log = LogFactory.getLog(InputHandler.class); | |||
/** | |||
* Constructor for XML->XSLT->FO input | |||
* | |||
* @param xmlfile XML file | |||
* @param xsltfile XSLT file | |||
* @param params Vector of command-line parameters (name, value, | |||
@@ -83,6 +84,23 @@ public class InputHandler implements ErrorListener, Renderable { | |||
xsltParams = params; | |||
} | |||
/** | |||
* Constructor for XML->XSLT->FO input | |||
* | |||
* @param xmlfile XML file | |||
* @param xsltfile XSLT file | |||
* @param params Vector of command-line parameters (name, value, | |||
* name, value, ...) for XSL stylesheet, null if none | |||
* @param useCatalogResolver if true, use a catalog resolver | |||
* for XML parsing and XSLT URI resolution | |||
*/ | |||
public InputHandler(File xmlfile, File xsltfile, Vector params, boolean useCatalogResolver) { | |||
this(xmlfile, xsltfile, params); | |||
if (useCatalogResolver) { | |||
createCatalogResolver(); | |||
} | |||
} | |||
/** | |||
* Constructor for FO input | |||
* @param fofile the file to read the FO document. | |||
@@ -151,7 +169,7 @@ public class InputHandler implements ErrorListener, Renderable { | |||
* @return the Source for the main input file | |||
*/ | |||
protected Source createMainSource() { | |||
Source result; | |||
Source source; | |||
InputStream in; | |||
String uri; | |||
if (this.sourcefile != null) { | |||
@@ -169,37 +187,91 @@ public class InputHandler implements ErrorListener, Renderable { | |||
try { | |||
InputSource is = new InputSource(in); | |||
is.setSystemId(uri); | |||
SAXParserFactory spf = SAXParserFactory.newInstance(); | |||
spf.setFeature("http://xml.org/sax/features/namespaces", true); | |||
spf.setFeature("http://apache.org/xml/features/xinclude", true); | |||
XMLReader xr = spf.newSAXParser().getXMLReader(); | |||
result = new SAXSource(xr, is); | |||
XMLReader xr = getXMLReader(); | |||
if (entityResolver != null) { | |||
xr.setEntityResolver(entityResolver); | |||
} | |||
source = new SAXSource(xr, is); | |||
} catch (SAXException e) { | |||
if (this.sourcefile != null) { | |||
result = new StreamSource(this.sourcefile); | |||
source = new StreamSource(this.sourcefile); | |||
} else { | |||
result = new StreamSource(in, uri); | |||
source = new StreamSource(in, uri); | |||
} | |||
} catch (ParserConfigurationException e) { | |||
if (this.sourcefile != null) { | |||
result = new StreamSource(this.sourcefile); | |||
source = new StreamSource(this.sourcefile); | |||
} else { | |||
result = new StreamSource(in, uri); | |||
source = new StreamSource(in, uri); | |||
} | |||
} | |||
return source; | |||
} | |||
/** | |||
* Creates a catalog resolver and uses it for XML parsing and XSLT URI resolution. | |||
* Tries the Apache Commons Resolver, and if unsuccessful, | |||
* tries the same built into Java 6. | |||
*/ | |||
private void createCatalogResolver() { | |||
String[] classNames = new String[] { | |||
"org.apache.xml.resolver.tools.CatalogResolver", | |||
"com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver"}; | |||
Class resolverClass = null; | |||
for (int i = 0; i < classNames.length && resolverClass == null; ++i) { | |||
try { | |||
resolverClass = Class.forName(classNames[i]); | |||
} catch (ClassNotFoundException e) { | |||
// No worries | |||
} | |||
} | |||
return result; | |||
if (resolverClass == null) { | |||
log.error("Could not find catalog resolver in class path"); | |||
return; | |||
} | |||
try { | |||
entityResolver = (EntityResolver) resolverClass.newInstance(); | |||
uriResolver = (URIResolver) resolverClass.newInstance(); | |||
} catch (InstantiationException e) { | |||
log.error("Error creating the catalog resolver: " + e.getMessage()); | |||
} catch (IllegalAccessException e) { | |||
log.error("Error creating the catalog resolver: " + e.getMessage()); | |||
} | |||
} | |||
/** | |||
* Creates a Source for the selected stylesheet. | |||
* | |||
* @return the Source for the selected stylesheet or null if there's no stylesheet | |||
*/ | |||
protected Source createXSLTSource() { | |||
Source xslt = null; | |||
if (this.stylesheet != null) { | |||
return new StreamSource(this.stylesheet); | |||
} else { | |||
return null; | |||
if (entityResolver != null) { | |||
try { | |||
InputSource is = new InputSource(this.stylesheet.getPath()); | |||
XMLReader xr = getXMLReader(); | |||
xr.setEntityResolver(entityResolver); | |||
xslt = new SAXSource(xr, is); | |||
} catch (SAXException e) { | |||
// return StreamSource | |||
} catch (ParserConfigurationException e) { | |||
// return StreamSource | |||
} | |||
} | |||
if (xslt == null) { | |||
xslt = new StreamSource(this.stylesheet); | |||
} | |||
} | |||
return xslt; | |||
} | |||
private XMLReader getXMLReader() throws ParserConfigurationException, SAXException { | |||
SAXParserFactory spf = SAXParserFactory.newInstance(); | |||
spf.setFeature("http://xml.org/sax/features/namespaces", true); | |||
spf.setFeature("http://apache.org/xml/features/xinclude", true); | |||
XMLReader xr = spf.newSAXParser().getXMLReader(); | |||
return xr; | |||
} | |||
/** | |||
@@ -226,6 +298,9 @@ public class InputHandler implements ErrorListener, Renderable { | |||
(String) xsltParams.elementAt(i + 1)); | |||
} | |||
} | |||
if (uriResolver != null) { | |||
transformer.setURIResolver(uriResolver); | |||
} | |||
} | |||
transformer.setErrorListener(this); | |||
@@ -56,7 +56,7 @@ public abstract class FObj extends FONode implements Constants { | |||
private List/*<ExtensionAttachment>*/ extensionAttachments = null; | |||
/** The map of foreign attributes, null if none */ | |||
private Map foreignAttributes = null; | |||
private Map/*<QName,String>*/ foreignAttributes = null; | |||
/** Used to indicate if this FO is either an Out Of Line FO (see rec) | |||
* or a descendant of one. Used during FO validation. | |||
@@ -591,7 +591,7 @@ public abstract class FObj extends FONode implements Constants { | |||
throw new NullPointerException("Parameter attributeName must not be null"); | |||
} | |||
if (foreignAttributes == null) { | |||
foreignAttributes = new java.util.HashMap(); | |||
foreignAttributes = new java.util.HashMap/*<QName,String>*/(); | |||
} | |||
foreignAttributes.put(attributeName, value); | |||
} |
@@ -161,12 +161,12 @@ public class CIDSubset { | |||
} | |||
/** | |||
* Returns a BitSet with bits set for each available glyph index. | |||
* Returns a BitSet with bits set for each available glyph index in the subset. | |||
* @return a BitSet indicating available glyph indices | |||
*/ | |||
public BitSet getGlyphIndexBitSet() { | |||
BitSet bitset = new BitSet(); | |||
Iterator iter = usedGlyphs.keySet().iterator(); | |||
Iterator iter = usedGlyphsIndex.keySet().iterator(); | |||
while (iter.hasNext()) { | |||
Integer cid = (Integer)iter.next(); | |||
bitset.set(cid.intValue()); |
@@ -170,6 +170,9 @@ public class Font { | |||
/** | |||
* Returns the amount of kerning between two characters. | |||
* | |||
* The value returned measures in pt. So it is already adjusted for font size. | |||
* | |||
* @param ch1 first character | |||
* @param ch2 second character | |||
* @return the distance to adjust for kerning, 0 if there's no kerning | |||
@@ -179,7 +182,7 @@ public class Font { | |||
if (kernPair != null) { | |||
Integer width = (Integer)kernPair.get(new Integer(ch2)); | |||
if (width != null) { | |||
return width.intValue(); | |||
return width.intValue() * getFontSize() / 1000; | |||
} | |||
} | |||
return 0; |
@@ -367,7 +367,7 @@ public abstract class AbstractBreaker { | |||
alg.setConstantLineWidth(flowBPD); | |||
int optimalPageCount = alg.findBreakingPoints(effectiveList, 1, true, | |||
BreakingAlgorithm.ALL_BREAKS); | |||
if (alg.ipdChanged()) { | |||
if (alg.getIPDdifference() != 0) { | |||
KnuthNode optimalBreak = alg.getBestNodeBeforeIPDChange(); | |||
int positionIndex = optimalBreak.position; | |||
KnuthElement elementAtBreak = alg.getElement(positionIndex); | |||
@@ -381,14 +381,19 @@ public abstract class AbstractBreaker { | |||
LayoutManager restartAtLM = null; | |||
List firstElements = Collections.EMPTY_LIST; | |||
if (containsNonRestartableLM(positionAtBreak)) { | |||
if (alg.getIPDdifference() > 0) { | |||
log.warn("Content that cannot handle IPD changes is flowing to a" | |||
+ " narrower page. Part of it may be clipped" | |||
+ " by the page border."); | |||
} | |||
firstElements = new LinkedList(); | |||
boolean boxFound = false; | |||
Iterator iter = effectiveList.listIterator(++positionIndex); | |||
Iterator iter = effectiveList.listIterator(positionIndex + 1); | |||
Position position = null; | |||
while (iter.hasNext() | |||
&& (position == null || containsNonRestartableLM(position))) { | |||
KnuthElement element = (KnuthElement) iter.next(); | |||
positionIndex++; | |||
KnuthElement element = (KnuthElement) iter.next(); | |||
position = element.getPosition(); | |||
if (element.isBox()) { | |||
boxFound = true; | |||
@@ -400,9 +405,11 @@ public abstract class AbstractBreaker { | |||
if (position instanceof SpaceResolver.SpaceHandlingBreakPosition) { | |||
/* Retrieve the original position wrapped into this space position */ | |||
positionAtBreak = position.getPosition(); | |||
} else { | |||
positionAtBreak = null; | |||
} | |||
} | |||
if (positionAtBreak.getIndex() == -1) { | |||
if (positionAtBreak != null && positionAtBreak.getIndex() == -1) { | |||
/* | |||
* This is an indication that we are between two blocks | |||
* (possibly surrounded by another block), not inside a | |||
@@ -588,7 +595,7 @@ public abstract class AbstractBreaker { | |||
.listIterator(startElementIndex); | |||
while (effectiveListIterator.nextIndex() <= endElementIndex) { | |||
KnuthElement tempEl = (KnuthElement)effectiveListIterator.next(); | |||
if (tempEl.isBox() && tempEl.getW() > 0) { | |||
if (tempEl.isBox() && tempEl.getWidth() > 0) { | |||
boxCount++; | |||
} | |||
} | |||
@@ -678,8 +685,23 @@ public abstract class AbstractBreaker { | |||
BlockSequence blockList; | |||
List returnedList; | |||
if (positionAtIPDChange == null) { | |||
if (firstElements == null) { | |||
returnedList = getNextKnuthElements(childLC, alignment); | |||
} else if (positionAtIPDChange == null) { | |||
/* | |||
* No restartable element found after changing IPD break. Simply add the | |||
* non-restartable elements found after the break. | |||
*/ | |||
returnedList = firstElements; | |||
/* | |||
* Remove the last 3 penalty-filler-forced break elements that were added by | |||
* the Knuth algorithm. They will be re-added later on. | |||
*/ | |||
ListIterator iter = returnedList.listIterator(returnedList.size()); | |||
for (int i = 0; i < 3; i++) { | |||
iter.previous(); | |||
iter.remove(); | |||
} | |||
} else { | |||
returnedList = getNextKnuthElements(childLC, alignment, positionAtIPDChange, | |||
restartAtLM); | |||
@@ -861,9 +883,9 @@ public abstract class AbstractBreaker { | |||
case BlockLevelLayoutManager.LINE_NUMBER_ADJUSTMENT: | |||
// potential line number adjustment | |||
lineNumberMaxAdjustment.max += ((KnuthGlue) thisElement) | |||
.getY(); | |||
.getStretch(); | |||
lineNumberMaxAdjustment.min -= ((KnuthGlue) thisElement) | |||
.getZ(); | |||
.getShrink(); | |||
adjustableLinesList.add(thisElement); | |||
break; | |||
case BlockLevelLayoutManager.LINE_HEIGHT_ADJUSTMENT: | |||
@@ -885,9 +907,9 @@ public abstract class AbstractBreaker { | |||
KnuthGlue blockSpace = (KnuthGlue) unconfirmedList | |||
.removeFirst(); | |||
spaceMaxAdjustment.max += ((KnuthGlue) blockSpace) | |||
.getY(); | |||
.getStretch(); | |||
spaceMaxAdjustment.min -= ((KnuthGlue) blockSpace) | |||
.getZ(); | |||
.getShrink(); | |||
blockSpacesList.add(blockSpace); | |||
} | |||
} | |||
@@ -898,11 +920,11 @@ public abstract class AbstractBreaker { | |||
log.debug("| space adj = " | |||
+ spaceMaxAdjustment); | |||
if (thisElement.isPenalty() && thisElement.getW() > 0) { | |||
if (thisElement.isPenalty() && thisElement.getWidth() > 0) { | |||
log.debug(" mandatory variation to the number of lines!"); | |||
((BlockLevelLayoutManager) thisElement | |||
.getLayoutManager()).negotiateBPDAdjustment( | |||
thisElement.getW(), thisElement); | |||
thisElement.getWidth(), thisElement); | |||
} | |||
if (thisBreak.bpdAdjust != 0 | |||
@@ -967,7 +989,7 @@ public abstract class AbstractBreaker { | |||
int partial = 0; | |||
while (spaceListIterator.hasNext()) { | |||
KnuthGlue blockSpace = (KnuthGlue)spaceListIterator.next(); | |||
partial += (difference > 0 ? blockSpace.getY() : blockSpace.getZ()); | |||
partial += (difference > 0 ? blockSpace.getStretch() : blockSpace.getShrink()); | |||
if (log.isDebugEnabled()) { | |||
log.debug("available = " + partial + " / " + total); | |||
log.debug("competenza = " | |||
@@ -990,7 +1012,7 @@ public abstract class AbstractBreaker { | |||
int partial = 0; | |||
while (lineListIterator.hasNext()) { | |||
KnuthGlue line = (KnuthGlue)lineListIterator.next(); | |||
partial += (difference > 0 ? line.getY() : line.getZ()); | |||
partial += (difference > 0 ? line.getStretch() : line.getShrink()); | |||
int newAdjust = ((BlockLevelLayoutManager) line.getLayoutManager()).negotiateBPDAdjustment(((int) ((float) partial * difference / total)) - adjustedDiff, line); | |||
adjustedDiff += newAdjust; | |||
} |
@@ -1133,7 +1133,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager | |||
// by this BlockLM, and must be ignored | |||
if (element.getLayoutManager() != this) { | |||
splitList.add(element); | |||
splitLength += element.getW(); | |||
splitLength += element.getWidth(); | |||
lastLM = element.getLayoutManager(); | |||
} | |||
} |
@@ -339,7 +339,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager | |||
// by this BlockLM, and must be ignored | |||
if (element.getLayoutManager() != this) { | |||
splitList.add(element); | |||
splitLength += element.getW(); | |||
splitLength += element.getWidth(); | |||
lastLM = element.getLayoutManager(); | |||
} | |||
} |
@@ -695,11 +695,11 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
/*LF*/ //log.debug(" BLM.negotiateBPDAdjustment> bpunit con penalty"); | |||
KnuthPenalty storedPenalty = (KnuthPenalty) | |||
storedList.get(mappingPos.getLastIndex()); | |||
if (storedPenalty.getW() > 0) { | |||
if (storedPenalty.getWidth() > 0) { | |||
// the original penalty has width > 0 | |||
/*LF*/ //log.debug(" BLM.negotiateBPDAdjustment> chiamata passata"); | |||
return ((BlockLevelLayoutManager)storedPenalty.getLayoutManager()) | |||
.negotiateBPDAdjustment(storedPenalty.getW(), | |||
.negotiateBPDAdjustment(storedPenalty.getWidth(), | |||
storedPenalty); | |||
} else { | |||
// the original penalty has width = 0 | |||
@@ -1406,17 +1406,18 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
while (oldListIterator.hasNext()) { | |||
KnuthElement element = (KnuthElement) oldListIterator.next(); | |||
if (element.isBox()) { | |||
totalLength.add(new MinOptMax(element.getW())); | |||
//log.debug("box " + element.getW()); | |||
totalLength.add(new MinOptMax(element.getWidth())); | |||
//log.debug("box " + element.getWidth()); | |||
} else if (element.isGlue()) { | |||
totalLength.min -= element.getZ(); | |||
totalLength.max += element.getY(); | |||
totalLength.min -= element.getShrink(); | |||
totalLength.max += element.getStretch(); | |||
//leafValue = ((LeafPosition) element.getPosition()).getLeafPos(); | |||
//log.debug("glue " + element.getW() + " + " | |||
// + ((KnuthGlue) element).getY() + " - " + ((KnuthGlue) element).getZ()); | |||
//log.debug("glue " + element.getWidth() + " + " | |||
// + ((KnuthGlue) element).getStretch() + " - " | |||
// + ((KnuthGlue) element).getShrink()); | |||
} else { | |||
//log.debug((((KnuthPenalty)element).getP() == KnuthElement.INFINITE | |||
// ? "PENALTY " : "penalty ") + element.getW()); | |||
//log.debug((((KnuthPenalty)element).getPenalty() == KnuthElement.INFINITE | |||
// ? "PENALTY " : "penalty ") + element.getWidth()); | |||
} | |||
} | |||
// compute the total amount of "units" | |||
@@ -1443,22 +1444,22 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
KnuthElement element = (KnuthElement) oldListIterator.next(); | |||
lastIndex++; | |||
if (element.isBox()) { | |||
lengthBeforeBreak.add(new MinOptMax(element.getW())); | |||
lengthAfterBreak.subtract(new MinOptMax(element.getW())); | |||
lengthBeforeBreak.add(new MinOptMax(element.getWidth())); | |||
lengthAfterBreak.subtract(new MinOptMax(element.getWidth())); | |||
bPrevIsBox = true; | |||
} else if (element.isGlue()) { | |||
lengthBeforeBreak.min -= element.getZ(); | |||
lengthAfterBreak.min += element.getZ(); | |||
lengthBeforeBreak.max += element.getY(); | |||
lengthAfterBreak.max -= element.getY(); | |||
lengthBeforeBreak.min -= element.getShrink(); | |||
lengthAfterBreak.min += element.getShrink(); | |||
lengthBeforeBreak.max += element.getStretch(); | |||
lengthAfterBreak.max -= element.getStretch(); | |||
bPrevIsBox = false; | |||
} else { | |||
lengthBeforeBreak.add(new MinOptMax(element.getW())); | |||
lengthBeforeBreak.add(new MinOptMax(element.getWidth())); | |||
bPrevIsBox = false; | |||
} | |||
// create the new elements | |||
if (element.isPenalty() && element.getP() < KnuthElement.INFINITE | |||
if (element.isPenalty() && element.getPenalty() < KnuthElement.INFINITE | |||
|| element.isGlue() && bPrevIsBox | |||
|| !oldListIterator.hasNext()) { | |||
// suppress elements after the breaking point | |||
@@ -1468,8 +1469,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
iStepsForward++; | |||
if (el.isGlue()) { | |||
// suppressed glue | |||
lengthAfterBreak.min += el.getZ(); | |||
lengthAfterBreak.max -= el.getY(); | |||
lengthAfterBreak.min += el.getShrink(); | |||
lengthAfterBreak.max -= el.getStretch(); | |||
} else if (el.isPenalty()) { | |||
// suppressed penalty, do nothing | |||
} else { | |||
@@ -1489,8 +1490,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
for (int i = 0; i < iStepsForward; i++) { | |||
KnuthElement el = (KnuthElement) oldListIterator.previous(); | |||
if (el.isGlue()) { | |||
lengthAfterBreak.min -= el.getZ(); | |||
lengthAfterBreak.max += el.getY(); | |||
lengthAfterBreak.min -= el.getShrink(); | |||
lengthAfterBreak.max += el.getStretch(); | |||
} | |||
} | |||
@@ -1611,7 +1612,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
} | |||
if (element.isPenalty()) { | |||
lengthBeforeBreak.add(new MinOptMax(-element.getW())); | |||
lengthBeforeBreak.add(new MinOptMax(-element.getWidth())); | |||
} | |||
} | |||
@@ -1640,14 +1641,14 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
- neededUnits(totalLength.opt - adjustedSpaceBefore)) | |||
* bpUnit; | |||
// insert the correct elements | |||
newList.addFirst(new KnuthBox(wrongBox.getW() - decreasedLength, | |||
newList.addFirst(new KnuthBox(wrongBox.getWidth() - decreasedLength, | |||
wrongBox.getPosition(), false)); | |||
newList.addFirst(new KnuthGlue(decreasedLength, 0, 0, SPACE_BEFORE_ADJUSTMENT, | |||
wrongBox.getPosition(), false)); | |||
//log.debug(" rimosso box " + neededUnits(wrongBox.getW())); | |||
//log.debug(" rimosso box " + neededUnits(wrongBox.getWidth())); | |||
//log.debug(" aggiunto glue " + neededUnits(decreasedLength) + " 0 0"); | |||
//log.debug(" aggiunto box " + neededUnits( | |||
// wrongBox.getW() - decreasedLength)); | |||
// wrongBox.getWidth() - decreasedLength)); | |||
} | |||
// if space-after.conditionality is "discard", correct newList | |||
@@ -1663,7 +1664,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
// (it cannot be parted and has some stretch or shrink) | |||
// the wrong box is the first one, not the last one | |||
LinkedList preserveList = new LinkedList(); | |||
if (wrongBox.getW() == 0) { | |||
if (wrongBox.getWidth() == 0) { | |||
preserveList.add(wrongBox); | |||
preserveList.addFirst((KnuthGlue) newList.removeLast()); | |||
preserveList.addFirst((KnuthPenalty) newList.removeLast()); | |||
@@ -1676,7 +1677,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
- neededUnits(totalLength.opt - adjustedSpaceAfter)) | |||
* bpUnit; | |||
// insert the correct box | |||
newList.addLast(new KnuthBox(wrongBox.getW() - decreasedLength, | |||
newList.addLast(new KnuthBox(wrongBox.getWidth() - decreasedLength, | |||
wrongBox.getPosition(), false)); | |||
// add preserved elements | |||
if (!preserveList.isEmpty()) { | |||
@@ -1685,9 +1686,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
// insert the correct glue | |||
newList.addLast(new KnuthGlue(decreasedLength, 0, 0, SPACE_AFTER_ADJUSTMENT, | |||
wrongBox.getPosition(), false)); | |||
//log.debug(" rimosso box " + neededUnits(wrongBox.getW())); | |||
//log.debug(" rimosso box " + neededUnits(wrongBox.getWidth())); | |||
//log.debug(" aggiunto box " + neededUnits( | |||
// wrongBox.getW() - decreasedLength)); | |||
// wrongBox.getWidth() - decreasedLength)); | |||
//log.debug(" aggiunto glue " + neededUnits(decreasedLength) + " 0 0"); | |||
} | |||
@@ -491,7 +491,7 @@ public abstract class BreakingAlgorithm { | |||
elementIndex, previousIsBox, allowedBreaks).isBox(); | |||
if (activeNodeCount == 0) { | |||
if (ipdChanged()) { | |||
if (getIPDdifference() != 0) { | |||
return handleIpdChange(); | |||
} | |||
if (!force) { | |||
@@ -538,8 +538,8 @@ public abstract class BreakingAlgorithm { | |||
return line; | |||
} | |||
protected boolean ipdChanged() { | |||
return false; | |||
protected int getIPDdifference() { | |||
return 0; | |||
} | |||
protected int handleIpdChange() { | |||
@@ -676,7 +676,7 @@ public abstract class BreakingAlgorithm { | |||
protected void handleBox(KnuthBox box) { | |||
// a KnuthBox object is not a legal line break, | |||
// just add the width to the total | |||
totalWidth += box.getW(); | |||
totalWidth += box.getWidth(); | |||
} | |||
/** | |||
@@ -697,9 +697,9 @@ public abstract class BreakingAlgorithm { | |||
&& !(allowedBreaks == ONLY_FORCED_BREAKS)) { | |||
considerLegalBreak(glue, position); | |||
} | |||
totalWidth += glue.getW(); | |||
totalStretch += glue.getY(); | |||
totalShrink += glue.getZ(); | |||
totalWidth += glue.getWidth(); | |||
totalStretch += glue.getStretch(); | |||
totalShrink += glue.getShrink(); | |||
} | |||
/** | |||
@@ -716,8 +716,8 @@ public abstract class BreakingAlgorithm { | |||
// only if its penalty is not infinite; | |||
// consider all penalties, non-flagged penalties or non-forcing penalties | |||
// according to the value of allowedBreaks | |||
if (((penalty.getP() < KnuthElement.INFINITE) | |||
&& (!(allowedBreaks == NO_FLAGGED_PENALTIES) || !penalty.isFlagged()) | |||
if (((penalty.getPenalty() < KnuthElement.INFINITE) | |||
&& (!(allowedBreaks == NO_FLAGGED_PENALTIES) || !penalty.isPenaltyFlagged()) | |||
&& (!(allowedBreaks == ONLY_FORCED_BREAKS) | |||
|| penalty.isForcedBreak()))) { | |||
considerLegalBreak(penalty, position); | |||
@@ -880,7 +880,7 @@ public abstract class BreakingAlgorithm { | |||
*/ | |||
protected boolean elementCanEndLine(KnuthElement element, int line, int difference) { | |||
return (!element.isPenalty() | |||
|| element.getP() < KnuthElement.INFINITE); | |||
|| element.getPenalty() < KnuthElement.INFINITE); | |||
} | |||
/** | |||
@@ -921,9 +921,9 @@ public abstract class BreakingAlgorithm { | |||
if (tempElement.isBox()) { | |||
break; | |||
} else if (tempElement.isGlue()) { | |||
newWidth += tempElement.getW(); | |||
newStretch += tempElement.getY(); | |||
newShrink += tempElement.getZ(); | |||
newWidth += tempElement.getWidth(); | |||
newStretch += tempElement.getStretch(); | |||
newShrink += tempElement.getShrink(); | |||
} else if (tempElement.isForcedBreak() && i != elementIdx) { | |||
break; | |||
} | |||
@@ -1034,9 +1034,9 @@ public abstract class BreakingAlgorithm { | |||
if (tempElement.isBox()) { | |||
break; | |||
} else if (tempElement.isGlue()) { | |||
newWidth += tempElement.getW(); | |||
newStretch += tempElement.getY(); | |||
newShrink += tempElement.getZ(); | |||
newWidth += tempElement.getWidth(); | |||
newStretch += tempElement.getStretch(); | |||
newShrink += tempElement.getShrink(); | |||
} else if (tempElement.isForcedBreak() && i != elementIdx) { | |||
break; | |||
} | |||
@@ -1075,7 +1075,7 @@ public abstract class BreakingAlgorithm { | |||
// compute the adjustment ratio | |||
int actualWidth = totalWidth - activeNode.totalWidth; | |||
if (element.isPenalty()) { | |||
actualWidth += element.getW(); | |||
actualWidth += element.getWidth(); | |||
} | |||
return getLineWidth() - actualWidth; | |||
} | |||
@@ -1133,7 +1133,7 @@ public abstract class BreakingAlgorithm { | |||
double f = Math.abs(r); | |||
f = 1 + 100 * f * f * f; | |||
if (element.isPenalty()) { | |||
double penalty = element.getP(); | |||
double penalty = element.getPenalty(); | |||
if (penalty >= 0) { | |||
f += penalty; | |||
demerits = f * f; | |||
@@ -1146,9 +1146,9 @@ public abstract class BreakingAlgorithm { | |||
demerits = f * f; | |||
} | |||
if (element.isPenalty() && ((KnuthPenalty) element).isFlagged() | |||
if (element.isPenalty() && ((KnuthPenalty) element).isPenaltyFlagged() | |||
&& getElement(activeNode.position).isPenalty() | |||
&& ((KnuthPenalty) getElement(activeNode.position)).isFlagged()) { | |||
&& ((KnuthPenalty) getElement(activeNode.position)).isPenaltyFlagged()) { | |||
// add demerit for consecutive breaks at flagged penalties | |||
demerits += repeatedFlaggedDemerit; | |||
// there are at least two consecutive lines ending with a flagged penalty; | |||
@@ -1160,7 +1160,7 @@ public abstract class BreakingAlgorithm { | |||
prevNode = prevNode.previous) { | |||
KnuthElement prevElement = getElement(prevNode.position); | |||
if (prevElement.isPenalty() | |||
&& ((KnuthPenalty) prevElement).isFlagged()) { | |||
&& ((KnuthPenalty) prevElement).isPenaltyFlagged()) { | |||
// the previous line ends with a flagged penalty too | |||
flaggedPenaltiesCount++; | |||
} else { |
@@ -62,13 +62,14 @@ public final class ElementListUtils { | |||
if (el.isPenalty()) { | |||
KnuthPenalty penalty = (KnuthPenalty)el; | |||
//Convert all penalties to break inhibitors | |||
if (penalty.getP() < KnuthPenalty.INFINITE) { | |||
iter.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, | |||
penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary())); | |||
if (penalty.getPenalty() < KnuthPenalty.INFINITE) { | |||
iter.set(new KnuthPenalty(penalty.getWidth(), KnuthPenalty.INFINITE, | |||
penalty.isPenaltyFlagged(), penalty.getPosition(), | |||
penalty.isAuxiliary())); | |||
} | |||
} else if (el.isGlue()) { | |||
KnuthGlue glue = (KnuthGlue)el; | |||
len += glue.getW(); | |||
len += glue.getWidth(); | |||
iter.previous(); | |||
el = (ListElement)iter.previous(); | |||
iter.next(); | |||
@@ -84,7 +85,7 @@ public final class ElementListUtils { | |||
} | |||
} else { | |||
KnuthElement kel = (KnuthElement)el; | |||
len += kel.getW(); | |||
len += kel.getWidth(); | |||
} | |||
if (len >= constraint) { | |||
return false; | |||
@@ -109,13 +110,14 @@ public final class ElementListUtils { | |||
if (el.isPenalty()) { | |||
KnuthPenalty penalty = (KnuthPenalty)el; | |||
//Convert all penalties to break inhibitors | |||
if (penalty.getP() < KnuthPenalty.INFINITE) { | |||
i.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, | |||
penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary())); | |||
if (penalty.getPenalty() < KnuthPenalty.INFINITE) { | |||
i.set(new KnuthPenalty(penalty.getWidth(), KnuthPenalty.INFINITE, | |||
penalty.isPenaltyFlagged(), penalty.getPosition(), | |||
penalty.isAuxiliary())); | |||
} | |||
} else if (el.isGlue()) { | |||
KnuthGlue glue = (KnuthGlue)el; | |||
len += glue.getW(); | |||
len += glue.getWidth(); | |||
el = (ListElement)i.previous(); | |||
i.next(); | |||
if (el.isBox()) { | |||
@@ -134,7 +136,7 @@ public final class ElementListUtils { | |||
} | |||
} else { | |||
KnuthElement kel = (KnuthElement)el; | |||
len += kel.getW(); | |||
len += kel.getWidth(); | |||
} | |||
if (len >= constraint) { | |||
return false; | |||
@@ -158,9 +160,9 @@ public final class ElementListUtils { | |||
while (iter.hasNext()) { | |||
ListElement el = (ListElement)iter.next(); | |||
if (el.isBox()) { | |||
len += ((KnuthElement)el).getW(); | |||
len += ((KnuthElement)el).getWidth(); | |||
} else if (el.isGlue()) { | |||
len += ((KnuthElement)el).getW(); | |||
len += ((KnuthElement)el).getWidth(); | |||
} else { | |||
//log.debug("Ignoring penalty: " + el); | |||
//ignore penalties | |||
@@ -210,7 +212,7 @@ public final class ElementListUtils { | |||
*/ | |||
public static boolean endsWithNonInfinitePenalty(List elems) { | |||
ListElement last = (ListElement) ListUtil.getLast(elems); | |||
if (last.isPenalty() && ((KnuthPenalty)last).getP() < KnuthElement.INFINITE) { | |||
if (last.isPenalty() && ((KnuthPenalty)last).getPenalty() < KnuthElement.INFINITE) { | |||
return true; | |||
} else if (last instanceof BreakElement | |||
&& ((BreakElement)last).getPenaltyValue() < KnuthElement.INFINITE) { | |||
@@ -230,7 +232,7 @@ public final class ElementListUtils { | |||
int prevBreak = startIndex - 1; | |||
while (prevBreak >= 0) { | |||
KnuthElement el = (KnuthElement)elems.get(prevBreak); | |||
if (el.isPenalty() && el.getP() < KnuthElement.INFINITE) { | |||
if (el.isPenalty() && el.getPenalty() < KnuthElement.INFINITE) { | |||
break; | |||
} | |||
prevBreak--; |
@@ -72,7 +72,7 @@ public class InlineKnuthSequence extends KnuthSequence { | |||
lastOldElement = getLast(); | |||
firstNewElement = sequence.getElement(0); | |||
if (firstNewElement.isBox() && !((KnuthElement) firstNewElement).isAuxiliary() | |||
&& lastOldElement.isBox() && ((KnuthElement) lastOldElement).getW() != 0) { | |||
&& lastOldElement.isBox() && ((KnuthElement) lastOldElement).getWidth() != 0) { | |||
addALetterSpace(); | |||
} | |||
addAll(sequence); |
@@ -37,12 +37,12 @@ public class KnuthBox extends KnuthElement { | |||
/** | |||
* Create a new KnuthBox. | |||
* | |||
* @param w the width of this box | |||
* @param width the width of this box | |||
* @param pos the Position stored in this box | |||
* @param bAux is this box auxiliary? | |||
* @param auxiliary is this box auxiliary? | |||
*/ | |||
public KnuthBox(int w, Position pos, boolean bAux) { | |||
super(w, pos, bAux); | |||
public KnuthBox(int width, Position pos, boolean auxiliary) { | |||
super(width, pos, auxiliary); | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -52,14 +52,14 @@ public class KnuthBox extends KnuthElement { | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(64); | |||
StringBuffer buffer = new StringBuffer(64); | |||
if (isAuxiliary()) { | |||
sb.append("aux. "); | |||
buffer.append("aux. "); | |||
} | |||
sb.append("box"); | |||
sb.append(" w="); | |||
sb.append(getW()); | |||
return sb.toString(); | |||
buffer.append("box"); | |||
buffer.append(" w="); | |||
buffer.append(getWidth()); | |||
return buffer.toString(); | |||
} | |||
} |
@@ -33,44 +33,44 @@ public abstract class KnuthElement extends ListElement { | |||
public static final int INFINITE = 1000; | |||
private int width; | |||
private boolean bIsAuxiliary; | |||
private boolean auxiliary; | |||
/** | |||
* Create a new KnuthElement. | |||
* This class being abstract, this can be called only by subclasses. | |||
* | |||
* @param w the width of this element | |||
* @param width the width of this element | |||
* @param pos the Position stored in this element | |||
* @param bAux is this an auxiliary element? | |||
* @param auxiliary is this an auxiliary element? | |||
*/ | |||
protected KnuthElement(int w, Position pos, boolean bAux) { | |||
protected KnuthElement(int width, Position pos, boolean auxiliary) { | |||
super(pos); | |||
width = w; | |||
bIsAuxiliary = bAux; | |||
this.width = width; | |||
this.auxiliary = auxiliary; | |||
} | |||
/** @return true if this element is an auxiliary one. */ | |||
public boolean isAuxiliary() { | |||
return bIsAuxiliary; | |||
return auxiliary; | |||
} | |||
/** @return the width of this element. */ | |||
public int getW() { | |||
public int getWidth() { | |||
return width; | |||
} | |||
/** @return the penalty value of this element, if applicable. */ | |||
public int getP() { | |||
public int getPenalty() { | |||
throw new RuntimeException("Element is not a penalty"); | |||
} | |||
/** @return the stretch value of this element, if applicable. */ | |||
public int getY() { | |||
public int getStretch() { | |||
throw new RuntimeException("Element is not a glue"); | |||
} | |||
/** @return the shrink value of this element, if applicable. */ | |||
public int getZ() { | |||
public int getShrink() { | |||
throw new RuntimeException("Element is not a glue"); | |||
} | |||
@@ -54,24 +54,25 @@ public class KnuthGlue extends KnuthElement { | |||
/** | |||
* Create a new KnuthGlue. | |||
* | |||
* @param w the width of this glue | |||
* @param y the stretchability of this glue | |||
* @param z the shrinkability of this glue | |||
* @param width the width of this glue | |||
* @param stretchability the stretchability of this glue | |||
* @param shrinkability the shrinkability of this glue | |||
* @param pos the Position stored in this glue | |||
* @param bAux is this glue auxiliary? | |||
* @param auxiliary is this glue auxiliary? | |||
*/ | |||
public KnuthGlue(int w, int y, int z, Position pos, boolean bAux) { | |||
super(w, pos, bAux); | |||
stretchability = y; | |||
shrinkability = z; | |||
public KnuthGlue(int width, int stretchability, int shrinkability, Position pos, | |||
boolean auxiliary) { | |||
super(width, pos, auxiliary); | |||
this.stretchability = stretchability; | |||
this.shrinkability = shrinkability; | |||
} | |||
public KnuthGlue(int w, int y, int z, | |||
int iAdjClass, Position pos, boolean bAux) { | |||
super(w, pos, bAux); | |||
stretchability = y; | |||
shrinkability = z; | |||
adjustmentClass = iAdjClass; | |||
public KnuthGlue(int width, int stretchability, int shrinkability, int adjustmentClass, | |||
Position pos, boolean auxiliary) { | |||
super(width, pos, auxiliary); | |||
this.stretchability = stretchability; | |||
this.shrinkability = shrinkability; | |||
this.adjustmentClass = adjustmentClass; | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -80,12 +81,12 @@ public class KnuthGlue extends KnuthElement { | |||
} | |||
/** @return the stretchability of this glue. */ | |||
public int getY() { | |||
public int getStretch() { | |||
return stretchability; | |||
} | |||
/** @return the shrinkability of this glue. */ | |||
public int getZ() { | |||
public int getShrink() { | |||
return shrinkability; | |||
} | |||
@@ -96,18 +97,18 @@ public class KnuthGlue extends KnuthElement { | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(64); | |||
StringBuffer buffer = new StringBuffer(64); | |||
if (isAuxiliary()) { | |||
sb.append("aux. "); | |||
buffer.append("aux. "); | |||
} | |||
sb.append("glue"); | |||
sb.append(" w=").append(getW()); | |||
sb.append(" stretch=").append(getY()); | |||
sb.append(" shrink=").append(getZ()); | |||
buffer.append("glue"); | |||
buffer.append(" w=").append(getWidth()); | |||
buffer.append(" stretch=").append(getStretch()); | |||
buffer.append(" shrink=").append(getShrink()); | |||
if (getAdjustmentClass() >= 0) { | |||
sb.append(" adj-class=").append(getAdjustmentClass()); | |||
buffer.append(" adj-class=").append(getAdjustmentClass()); | |||
} | |||
return sb.toString(); | |||
return buffer.toString(); | |||
} | |||
} |
@@ -45,39 +45,40 @@ public class KnuthPenalty extends KnuthElement { | |||
public static final int FLAGGED_PENALTY = 50; | |||
private int penalty; | |||
private boolean isFlagged; | |||
private boolean penaltyFlagged; | |||
private int breakClass = -1; | |||
/** | |||
* Create a new KnuthPenalty. | |||
* | |||
* @param w the width of this penalty | |||
* @param p the penalty value of this penalty | |||
* @param f is this penalty flagged? | |||
* @param width the width of this penalty | |||
* @param penalty the penalty value of this penalty | |||
* @param penaltyFlagged is this penalty flagged? | |||
* @param pos the Position stored in this penalty | |||
* @param isAuxiliary is this penalty auxiliary? | |||
* @param auxiliary is this penalty auxiliary? | |||
*/ | |||
public KnuthPenalty(int w, int p, boolean f, Position pos, boolean isAuxiliary) { | |||
super(w, pos, isAuxiliary); | |||
penalty = p; | |||
isFlagged = f; | |||
public KnuthPenalty(int width, int penalty, boolean penaltyFlagged, Position pos, | |||
boolean auxiliary) { | |||
super(width, pos, auxiliary); | |||
this.penalty = penalty; | |||
this.penaltyFlagged = penaltyFlagged; | |||
} | |||
/** | |||
* Create a new KnuthPenalty. | |||
* | |||
* @param w the width of this penalty | |||
* @param p the penalty value of this penalty | |||
* @param f is this penalty flagged? | |||
* @param width the width of this penalty | |||
* @param penalty the penalty value of this penalty | |||
* @param penaltyFlagged is this penalty flagged? | |||
* @param breakClass the break class of this penalty (one of | |||
* {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, | |||
* {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}) | |||
* @param pos the Position stored in this penalty | |||
* @param isAuxiliary is this penalty auxiliary? | |||
*/ | |||
public KnuthPenalty(int w, int p, boolean f, | |||
int breakClass, Position pos, boolean isAuxiliary) { | |||
this(w, p, f, pos, isAuxiliary); | |||
public KnuthPenalty(int width, int penalty, boolean penaltyFlagged, int breakClass, | |||
Position pos, boolean isAuxiliary) { | |||
this(width, penalty, penaltyFlagged, pos, isAuxiliary); | |||
this.breakClass = breakClass; | |||
} | |||
@@ -90,6 +91,8 @@ public class KnuthPenalty extends KnuthElement { | |||
* (Mainly used in {@link #toString()} methods, to improve readability | |||
* of the trace logs.) | |||
* | |||
* TODO: shouldn't be penalty a class of its own? | |||
* | |||
* @param penaltyValue the penalty value | |||
* @return the penalty value as a {@link java.lang.String} | |||
*/ | |||
@@ -110,21 +113,21 @@ public class KnuthPenalty extends KnuthElement { | |||
/** | |||
* @return the penalty value of this penalty. | |||
*/ | |||
public int getP() { | |||
public int getPenalty() { | |||
return penalty; | |||
} | |||
/** | |||
* Sets a new penalty value. | |||
* @param p the new penalty value | |||
* @param penalty the new penalty value | |||
*/ | |||
public void setP(int p) { | |||
this.penalty = p; | |||
public void setPenalty(int penalty) { | |||
this.penalty = penalty; | |||
} | |||
/** @return true is this penalty is a flagged one. */ | |||
public boolean isFlagged() { | |||
return isFlagged; | |||
public boolean isPenaltyFlagged() { | |||
return penaltyFlagged; | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -142,28 +145,28 @@ public class KnuthPenalty extends KnuthElement { | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(64); | |||
StringBuffer buffer = new StringBuffer(64); | |||
if (isAuxiliary()) { | |||
sb.append("aux. "); | |||
buffer.append("aux. "); | |||
} | |||
sb.append("penalty"); | |||
sb.append(" p="); | |||
sb.append(valueOf(this.penalty)); | |||
if (this.isFlagged) { | |||
sb.append(" [flagged]"); | |||
buffer.append("penalty"); | |||
buffer.append(" p="); | |||
buffer.append(valueOf(this.penalty)); | |||
if (this.penaltyFlagged) { | |||
buffer.append(" [flagged]"); | |||
} | |||
sb.append(" w="); | |||
sb.append(getW()); | |||
buffer.append(" w="); | |||
buffer.append(getWidth()); | |||
if (isForcedBreak()) { | |||
sb.append(" (forced break, ") | |||
buffer.append(" (forced break, ") | |||
.append(getBreakClassName(this.breakClass)) | |||
.append(")"); | |||
} else if (this.penalty >= 0 && this.breakClass != -1) { | |||
//penalty corresponding to a keep constraint | |||
sb.append(" (keep constraint, ") | |||
buffer.append(" (keep constraint, ") | |||
.append(getBreakClassName(this.breakClass)) | |||
.append(")"); | |||
} | |||
return sb.toString(); | |||
return buffer.toString(); | |||
} | |||
} |
@@ -26,9 +26,12 @@ import java.util.List; | |||
import java.util.ListIterator; | |||
/** | |||
* Represents a list of Knuth elements. | |||
* Represents a list of {@link KnuthElement Knuth elements}. | |||
*/ | |||
public abstract class KnuthSequence extends ArrayList { | |||
//TODO: do not extend ArrayList | |||
/** | |||
* Creates a new and empty list. | |||
*/ |
@@ -96,7 +96,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
//Controls whether a single part should be forced if possible (ex. block-container) | |||
private boolean favorSinglePart = false; | |||
private boolean ipdChange; | |||
private int ipdDifference; | |||
private KnuthNode bestNodeForIPDChange; | |||
//Used to keep track of switches in keep-context | |||
@@ -320,7 +320,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
* will not have considered it a legal break, but it could still | |||
* be one. | |||
*/ | |||
if (penalty.getP() == KnuthPenalty.INFINITE) { | |||
if (penalty.getPenalty() == KnuthPenalty.INFINITE) { | |||
int breakClass = penalty.getBreakClass(); | |||
if (breakClass == Constants.EN_PAGE | |||
|| breakClass == Constants.EN_COLUMN) { | |||
@@ -363,7 +363,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
noteListIterator.hasNext();) { | |||
final KnuthElement element = (KnuthElement) noteListIterator.next(); | |||
if (element.isBox() || element.isGlue()) { | |||
noteLength += element.getW(); | |||
noteLength += element.getWidth(); | |||
} | |||
} | |||
int prevLength = (lengthList == null || lengthList.isEmpty()) | |||
@@ -445,22 +445,22 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
return true; | |||
} else { | |||
KnuthPenalty p = (KnuthPenalty) element; | |||
if (p.getP() <= 0) { | |||
if (p.getPenalty() <= 0) { | |||
return true; | |||
} else { | |||
int context = p.getBreakClass(); | |||
switch (context) { | |||
case Constants.EN_LINE: | |||
case Constants.EN_COLUMN: | |||
return p.getP() < KnuthPenalty.INFINITE; | |||
return p.getPenalty() < KnuthPenalty.INFINITE; | |||
case Constants.EN_PAGE: | |||
return p.getP() < KnuthPenalty.INFINITE | |||
return p.getPenalty() < KnuthPenalty.INFINITE | |||
|| !pageProvider.endPage(line - 1); | |||
case Constants.EN_AUTO: | |||
log.debug("keep is not auto but context is"); | |||
return true; | |||
default: | |||
if (p.getP() < KnuthPenalty.INFINITE) { | |||
if (p.getPenalty() < KnuthPenalty.INFINITE) { | |||
log.debug("Non recognized keep context:" + context); | |||
return true; | |||
} else { | |||
@@ -479,7 +479,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
int footnoteSplit = 0; | |||
boolean canDeferOldFootnotes; | |||
if (element.isPenalty()) { | |||
actualWidth += element.getW(); | |||
actualWidth += element.getWidth(); | |||
} | |||
if (footnotesPending) { | |||
// compute the total length of the footnotes not yet inserted | |||
@@ -588,7 +588,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
index++) { | |||
if (par.getElement(index).isGlue() && par.getElement(index - 1).isBox() | |||
|| par.getElement(index).isPenalty() | |||
&& ((KnuthElement) par.getElement(index)).getP() < KnuthElement.INFINITE) { | |||
&& ((KnuthElement) par.getElement(index)).getPenalty() < KnuthElement.INFINITE) { | |||
// break found | |||
break; | |||
} | |||
@@ -711,7 +711,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
element = (KnuthElement) noteListIterator.next(); | |||
if (element.isBox()) { | |||
// element is a box | |||
splitLength += element.getW(); | |||
splitLength += element.getWidth(); | |||
boxPreceding = true; | |||
} else if (element.isGlue()) { | |||
// element is a glue | |||
@@ -721,10 +721,10 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
break; | |||
} | |||
boxPreceding = false; | |||
splitLength += element.getW(); | |||
splitLength += element.getWidth(); | |||
} else { | |||
// element is a penalty | |||
if (element.getP() < KnuthElement.INFINITE) { | |||
if (element.getPenalty() < KnuthElement.INFINITE) { | |||
// end of the sub-sequence | |||
index = noteListIterator.previousIndex(); | |||
break; | |||
@@ -792,7 +792,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
double f = Math.abs(r); | |||
f = 1 + 100 * f * f * f; | |||
if (element.isPenalty()) { | |||
double penalty = element.getP(); | |||
double penalty = element.getPenalty(); | |||
if (penalty >= 0) { | |||
f += penalty; | |||
demerits = f * f; | |||
@@ -805,9 +805,9 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
demerits = f * f; | |||
} | |||
if (element.isPenalty() && ((KnuthPenalty) element).isFlagged() | |||
if (element.isPenalty() && ((KnuthPenalty) element).isPenaltyFlagged() | |||
&& getElement(activeNode.position).isPenalty() | |||
&& ((KnuthPenalty) getElement(activeNode.position)).isFlagged()) { | |||
&& ((KnuthPenalty) getElement(activeNode.position)).isPenaltyFlagged()) { | |||
// add demerit for consecutive breaks at flagged penalties | |||
demerits += repeatedFlaggedDemerit; | |||
} | |||
@@ -1077,8 +1077,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
} | |||
/** {@inheritDoc} */ | |||
protected boolean ipdChanged() { | |||
return ipdChange; | |||
protected int getIPDdifference() { | |||
return ipdDifference; | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -1104,9 +1104,9 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
* @param node the active node to add | |||
*/ | |||
protected void addNode(int line, KnuthNode node) { | |||
if (node.position < par.size() - 1 && line > 0 && ipdChange(line - 1)) { | |||
if (node.position < par.size() - 1 && line > 0 | |||
&& (ipdDifference = compareIPDs(line - 1)) != 0) { | |||
log.trace("IPD changes at page " + line); | |||
ipdChange = true; | |||
if (bestNodeForIPDChange == null | |||
|| node.totalDemerits < bestNodeForIPDChange.totalDemerits) { | |||
bestNodeForIPDChange = node; | |||
@@ -1117,7 +1117,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
* The whole sequence could actually fit on the last page before | |||
* the IPD change. No need to do any special handling. | |||
*/ | |||
ipdChange = false; | |||
ipdDifference = 0; | |||
} | |||
super.addNode(line, node); | |||
} | |||
@@ -1127,12 +1127,11 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
return bestNodeForIPDChange; | |||
} | |||
/** {@inheritDoc} */ | |||
protected boolean ipdChange(int line) { | |||
private int compareIPDs(int line) { | |||
if (pageProvider == null) { | |||
return false; | |||
return 0; | |||
} | |||
return pageProvider.ipdChange(line); | |||
return pageProvider.compareIPDs(line); | |||
} | |||
} |
@@ -161,12 +161,13 @@ public class PageProvider implements Constants { | |||
} | |||
/** | |||
* Returns true if the part following the given one has a different IPD. | |||
* Compares the IPD of the given part with the following one. | |||
* | |||
* @param index index of the current part | |||
* @return true if the following part has a different IPD, false otherwise | |||
* @return a negative integer, zero or a positive integer as the current IPD is less | |||
* than, equal to or greater than the IPD of the following part | |||
*/ | |||
public boolean ipdChange(int index) { | |||
public int compareIPDs(int index) { | |||
int columnCount = 0; | |||
int colIndex = startColumnOfCurrentElementList + index; | |||
int pageIndex = -1; | |||
@@ -179,11 +180,11 @@ public class PageProvider implements Constants { | |||
} while (colIndex >= columnCount); | |||
if (colIndex + 1 < columnCount) { | |||
// Next part is a column on same page => same IPD | |||
return false; | |||
return 0; | |||
} else { | |||
Page nextPage = getPage(false, pageIndex + 1, RELTO_CURRENT_ELEMENT_LIST); | |||
return page.getPageViewport().getBodyRegion().getIPD() | |||
!= nextPage.getPageViewport().getBodyRegion().getIPD(); | |||
- nextPage.getPageViewport().getBodyRegion().getIPD(); | |||
} | |||
} | |||
@@ -266,12 +266,12 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager | |||
KnuthSequence ks = (KnuthSequence)obj; | |||
for (Iterator it = ks.iterator(); it.hasNext(); ) { | |||
contentElement = (KnuthElement)it.next(); | |||
stackSize += contentElement.getW(); | |||
stackSize += contentElement.getWidth(); | |||
contentList.add(contentElement); | |||
} | |||
} else { | |||
contentElement = (KnuthElement)obj; | |||
stackSize += contentElement.getW(); | |||
stackSize += contentElement.getWidth(); | |||
contentList.add(contentElement); | |||
} | |||
} |
@@ -680,7 +680,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager | |||
assert lastElement != null; | |||
previousIsBox = lastElement.isBox() | |||
&& !((KnuthElement) lastElement).isAuxiliary() | |||
&& ((KnuthElement) lastElement).getW() != 0; | |||
&& ((KnuthElement) lastElement).getWidth() != 0; | |||
// if last paragraph is open, add the new elements to the paragraph | |||
// else this is the last paragraph | |||
@@ -705,7 +705,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager | |||
// finish last paragraph if it was closed with a linefeed | |||
if (lastElement.isPenalty() | |||
&& ((KnuthPenalty) lastElement).getP() == -KnuthPenalty.INFINITE) { | |||
&& ((KnuthPenalty) lastElement).getPenalty() == -KnuthPenalty.INFINITE) { | |||
// a penalty item whose value is -inf | |||
// represents a preserved linefeed, | |||
// which forces a line break | |||
@@ -1172,7 +1172,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager | |||
LeafPosition pos = (LeafPosition)lastElement.getPosition(); | |||
int totalAdj = adj; | |||
//if (lastElement.isPenalty()) { | |||
// totalAdj += lastElement.getW(); | |||
// totalAdj += lastElement.getWidth(); | |||
//} | |||
//int lineNumberDifference = (int)((double) totalAdj / constantLineHeight); | |||
int lineNumberDifference = (int) Math.round((double) totalAdj / constantLineHeight |
@@ -57,6 +57,8 @@ import org.apache.fop.util.ListUtil; | |||
*/ | |||
public class TextLayoutManager extends LeafNodeLayoutManager { | |||
//TODO: remove all final modifiers at local variables | |||
/** | |||
* Store information about each potential text area. | |||
* Index of character which ends the area, IPD of area, including | |||
@@ -703,39 +705,39 @@ public class TextLayoutManager extends LeafNodeLayoutManager { | |||
} | |||
private AreaInfo processWord(final int alignment, final KnuthSequence sequence, | |||
AreaInfo prevAi, final char ch, final boolean breakOpportunity, | |||
AreaInfo prevAreaInfo, final char ch, final boolean breakOpportunity, | |||
final boolean checkEndsWithHyphen) { | |||
AreaInfo ai; | |||
//Word boundary found, process widths and kerning | |||
int lastIndex = this.nextStart; | |||
while (lastIndex > 0 | |||
&& this.foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { | |||
&& foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { | |||
lastIndex--; | |||
} | |||
final boolean endsWithHyphen = checkEndsWithHyphen | |||
&& this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; | |||
&& foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; | |||
final Font font = FontSelector | |||
.selectFontForCharactersInText(this.foText, | |||
this.thisStart, lastIndex, this.foText, this); | |||
.selectFontForCharactersInText(foText, | |||
this.thisStart, lastIndex, 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.foText.charAt(i); | |||
final char currentChar = foText.charAt(i); | |||
//character width | |||
final int charWidth = font.getCharWidth(c); | |||
final int charWidth = font.getCharWidth(currentChar); | |||
wordIPD.add(charWidth); | |||
//kerning | |||
if (kerning) { | |||
int kern = 0; | |||
if (i > this.thisStart) { | |||
final char previous = this.foText.charAt(i - 1); | |||
kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; | |||
} else if (prevAi != null && !prevAi.isSpace && prevAi.breakIndex > 0) { | |||
final char previous = this.foText.charAt(prevAi.breakIndex - 1); | |||
kern = font.getKernValue(previous, c) * font.getFontSize() / 1000; | |||
final char previousChar = foText.charAt(i - 1); | |||
kern = font.getKernValue(previousChar, currentChar); | |||
} else if (prevAreaInfo != null && !prevAreaInfo.isSpace && prevAreaInfo.breakIndex > 0) { | |||
final char previousChar = foText.charAt(prevAreaInfo.breakIndex - 1); | |||
kern = font.getKernValue(previousChar, currentChar); | |||
} | |||
if (kern != 0) { | |||
this.addToLetterAdjust(i, kern); | |||
@@ -748,11 +750,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { | |||
&& !TextLayoutManager.isSpace(ch) | |||
&& lastIndex > 0 | |||
&& endsWithHyphen) { | |||
final int kern = font.getKernValue( | |||
this.foText.charAt(lastIndex - 1), ch) | |||
* font.getFontSize() / 1000; | |||
final int kern = font.getKernValue(foText.charAt(lastIndex - 1), ch); | |||
if (kern != 0) { | |||
this.addToLetterAdjust(lastIndex, kern); | |||
//TODO: add kern to wordIPD? | |||
} | |||
} | |||
int iLetterSpaces = wordLength - 1; | |||
@@ -765,20 +766,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager { | |||
wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); | |||
// create the AreaInfo object | |||
ai = new AreaInfo(this.thisStart, lastIndex, 0, | |||
AreaInfo areaInfo = new AreaInfo(this.thisStart, lastIndex, 0, | |||
iLetterSpaces, wordIPD, | |||
endsWithHyphen, | |||
false, breakOpportunity, font); | |||
prevAi = ai; | |||
this.vecAreaInfo.add(ai); | |||
prevAreaInfo = areaInfo; | |||
this.vecAreaInfo.add(areaInfo); | |||
this.tempStart = this.nextStart; | |||
//add the elements | |||
this.addElementsForAWordFragment(sequence, alignment, ai, | |||
this.addElementsForAWordFragment(sequence, alignment, areaInfo, | |||
this.vecAreaInfo.size() - 1, this.letterSpaceIPD); | |||
ai = null; | |||
this.thisStart = this.nextStart; | |||
return prevAi; | |||
return prevAreaInfo; | |||
} | |||
/** {@inheritDoc} */ |
@@ -298,14 +298,14 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
int stepPenalty = 0; | |||
KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]); | |||
if (endEl instanceof KnuthPenalty) { | |||
additionalPenaltyHeight = endEl.getW(); | |||
stepPenalty = Math.max(stepPenalty, endEl.getP()); | |||
additionalPenaltyHeight = endEl.getWidth(); | |||
stepPenalty = Math.max(stepPenalty, endEl.getPenalty()); | |||
} | |||
endEl = (KnuthElement)elementLists[1].get(end[1]); | |||
if (endEl instanceof KnuthPenalty) { | |||
additionalPenaltyHeight = Math.max( | |||
additionalPenaltyHeight, endEl.getW()); | |||
stepPenalty = Math.max(stepPenalty, endEl.getP()); | |||
additionalPenaltyHeight, endEl.getWidth()); | |||
stepPenalty = Math.max(stepPenalty, endEl.getPenalty()); | |||
} | |||
int boxHeight = step - addedBoxHeight - penaltyHeight; | |||
@@ -367,7 +367,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
end[i]++; | |||
KnuthElement el = (KnuthElement)elementLists[i].get(end[i]); | |||
if (el.isPenalty()) { | |||
if (el.getP() < KnuthElement.INFINITE) { | |||
if (el.getPenalty() < KnuthElement.INFINITE) { | |||
//First legal break point | |||
break; | |||
} | |||
@@ -379,9 +379,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
break; | |||
} | |||
} | |||
partialHeights[i] += el.getW(); | |||
partialHeights[i] += el.getWidth(); | |||
} else { | |||
partialHeights[i] += el.getW(); | |||
partialHeights[i] += el.getWidth(); | |||
} | |||
} | |||
if (end[i] < start[i]) { |
@@ -158,9 +158,9 @@ class ActiveCell { | |||
private int contentLength; | |||
FillerPenalty(KnuthPenalty p, int length) { | |||
super(length, p.getP(), p.isFlagged(), p.getBreakClass(), | |||
super(length, p.getPenalty(), p.isPenaltyFlagged(), p.getBreakClass(), | |||
p.getPosition(), p.isAuxiliary()); | |||
contentLength = p.getW(); | |||
contentLength = p.getWidth(); | |||
} | |||
FillerPenalty(int length) { | |||
@@ -190,7 +190,7 @@ class ActiveCell { | |||
} else if (el instanceof FillerBox) { | |||
return 0; | |||
} else { | |||
return el.getW(); | |||
return el.getWidth(); | |||
} | |||
} | |||
@@ -248,17 +248,17 @@ class ActiveCell { | |||
KnuthElement el = (KnuthElement) iter.next(); | |||
if (el.isBox()) { | |||
prevIsBox = true; | |||
cumulateLength += el.getW(); | |||
cumulateLength += el.getWidth(); | |||
} else if (el.isGlue()) { | |||
if (prevIsBox) { | |||
elementList.add(iter.nextIndex() - 1, | |||
new FillerPenalty(minBPD - cumulateLength)); | |||
} | |||
prevIsBox = false; | |||
cumulateLength += el.getW(); | |||
cumulateLength += el.getWidth(); | |||
} else { | |||
prevIsBox = false; | |||
if (cumulateLength + el.getW() < minBPD) { | |||
if (cumulateLength + el.getWidth() < minBPD) { | |||
iter.set(new FillerPenalty((KnuthPenalty) el, minBPD - cumulateLength)); | |||
} | |||
} | |||
@@ -314,7 +314,7 @@ class ActiveCell { | |||
KnuthElement el = (KnuthElement) knuthIter.next(); | |||
if (el.isPenalty()) { | |||
prevIsBox = false; | |||
if (el.getP() < KnuthElement.INFINITE | |||
if (el.getPenalty() < KnuthElement.INFINITE | |||
|| ((KnuthPenalty) el).getBreakClass() == Constants.EN_PAGE) { | |||
// TODO too much is being done in that test, only to handle | |||
// keep.within-column properly. | |||
@@ -322,8 +322,8 @@ class ActiveCell { | |||
// First legal break point | |||
breakFound = true; | |||
KnuthPenalty p = (KnuthPenalty) el; | |||
afterNextStep.penaltyLength = p.getW(); | |||
afterNextStep.penaltyValue = p.getP(); | |||
afterNextStep.penaltyLength = p.getWidth(); | |||
afterNextStep.penaltyValue = p.getPenalty(); | |||
if (p.isForcedBreak()) { | |||
afterNextStep.breakClass = p.getBreakClass(); | |||
} | |||
@@ -333,9 +333,9 @@ class ActiveCell { | |||
// Second legal break point | |||
breakFound = true; | |||
} else { | |||
afterNextStep.contentLength += el.getW(); | |||
afterNextStep.contentLength += el.getWidth(); | |||
if (!boxFound) { | |||
afterNextStep.condBeforeContentLength += el.getW(); | |||
afterNextStep.condBeforeContentLength += el.getWidth(); | |||
} | |||
} | |||
prevIsBox = false; | |||
@@ -348,7 +348,7 @@ class ActiveCell { | |||
} | |||
prevIsBox = true; | |||
boxFound = true; | |||
afterNextStep.contentLength += el.getW(); | |||
afterNextStep.contentLength += el.getWidth(); | |||
} | |||
} | |||
afterNextStep.end = knuthIter.nextIndex() - 1; |
@@ -361,7 +361,7 @@ class RowPainter { | |||
while (iter.nextIndex() < endIndex) { | |||
KnuthElement el = (KnuthElement) iter.next(); | |||
if (el.isBox() || el.isGlue()) { | |||
len += el.getW(); | |||
len += el.getWidth(); | |||
} | |||
} | |||
len += ActiveCell.getElementContentLength((KnuthElement) iter.next()); |
@@ -202,7 +202,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager | |||
if (lastItem.isForcedBreak()) { | |||
KnuthPenalty p = (KnuthPenalty) lastItem; | |||
primaryGridUnit.setBreakAfter(p.getBreakClass()); | |||
p.setP(0); | |||
p.setPenalty(0); | |||
} | |||
setFinished(true); |
@@ -76,7 +76,7 @@ public abstract class PDFFontNonBase14 extends PDFFont { | |||
if (getDocumentSafely().getProfile().isFontEmbeddingRequired()) { | |||
if (this.getDescriptor().getFontFile() == null) { | |||
throw new PDFConformanceException("For " + getDocumentSafely().getProfile() | |||
+ ", all fonts have to be embedded!"); | |||
+ ", all fonts have to be embedded! Offending font: " + getBaseFont()); | |||
} | |||
} | |||
} |
@@ -50,6 +50,14 @@ public interface AFPCustomizable { | |||
*/ | |||
void setNativeImagesSupported(boolean nativeImages); | |||
/** | |||
* Controls whether CMYK images (IOCA FS45) are enabled. By default, support is disabled | |||
* for wider compatibility. When disabled, any CMYK image is converted to the selected | |||
* color format. | |||
* @param value true to enabled CMYK images | |||
*/ | |||
void setCMYKImagesSupported(boolean value); | |||
/** | |||
* Sets the shading mode for painting filled rectangles. | |||
* @param shadingMode the shading mode |
@@ -356,6 +356,11 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler | |||
paintingState.setNativeImagesSupported(nativeImages); | |||
} | |||
/** {@inheritDoc} */ | |||
public void setCMYKImagesSupported(boolean value) { | |||
paintingState.setCMYKImagesSupported(value); | |||
} | |||
/** {@inheritDoc} */ | |||
public void setShadingMode(AFPShadingMode shadingMode) { | |||
this.shadingMode = shadingMode; |
@@ -24,6 +24,7 @@ import org.apache.xmlgraphics.image.loader.ImageFlavor; | |||
import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS; | |||
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; | |||
import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; | |||
import org.apache.xmlgraphics.util.MimeConstants; | |||
import org.apache.fop.afp.AFPDataObjectInfo; | |||
import org.apache.fop.render.RenderingContext; | |||
@@ -35,6 +36,7 @@ public class AFPImageHandlerRawStream extends AbstractAFPImageHandlerRawStream { | |||
private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { | |||
ImageFlavor.RAW_JPEG, | |||
ImageFlavor.RAW_TIFF, | |||
ImageFlavor.RAW_EPS, | |||
}; | |||
@@ -63,7 +65,12 @@ public class AFPImageHandlerRawStream extends AbstractAFPImageHandlerRawStream { | |||
if (targetContext instanceof AFPRenderingContext) { | |||
AFPRenderingContext afpContext = (AFPRenderingContext)targetContext; | |||
return (afpContext.getPaintingState().isNativeImagesSupported()) | |||
&& (image == null || image instanceof ImageRawJPEG || image instanceof ImageRawEPS); | |||
&& (image == null | |||
|| image instanceof ImageRawJPEG | |||
|| image instanceof ImageRawEPS | |||
|| ((image instanceof ImageRawStream) | |||
&& (MimeConstants.MIME_TIFF.equals( | |||
((ImageRawStream)image).getMimeType())))); | |||
} | |||
return false; | |||
} |
@@ -89,7 +89,11 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima | |||
int resolution = paintingState.getResolution(); | |||
int maxPixelSize = paintingState.getBitsPerPixel(); | |||
if (paintingState.isColorImages()) { | |||
maxPixelSize *= 3; //RGB only at the moment | |||
if (paintingState.isCMYKImagesSupported()) { | |||
maxPixelSize *= 4; //CMYK is maximum | |||
} else { | |||
maxPixelSize *= 3; //RGB is maximum | |||
} | |||
} | |||
RenderedImage renderedImage = imageRendered.getRenderedImage(); | |||
@@ -97,6 +101,7 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima | |||
ImageSize intrinsicSize = imageInfo.getSize(); | |||
boolean useFS10 = (maxPixelSize == 1) || BitmapImageUtil.isMonochromeImage(renderedImage); | |||
int functionSet = useFS10 ? 10 : 11; | |||
boolean usePageSegments = useFS10 | |||
&& !imageObjectInfo.getResourceInfo().getLevel().isInline(); | |||
@@ -124,11 +129,6 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima | |||
resampledDim.width, resampledDim.height, resolution); | |||
} | |||
} | |||
if (useFS10) { | |||
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS10); | |||
} else { | |||
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS11); | |||
} | |||
imageObjectInfo.setDataHeightRes((int)Math.round( | |||
effIntrinsicSize.getDpiHorizontal() * 10)); | |||
@@ -156,9 +156,9 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima | |||
byte[] imageData = null; | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
boolean allowDirectEncoding = true; | |||
if (allowDirectEncoding && pixelSize <= maxPixelSize) { | |||
if (allowDirectEncoding && (pixelSize <= maxPixelSize)) { | |||
//Attempt to encode without resampling the image | |||
ImageEncodingHelper helper = new ImageEncodingHelper(renderedImage); | |||
ImageEncodingHelper helper = new ImageEncodingHelper(renderedImage, pixelSize == 32); | |||
ColorModel encodedColorModel = helper.getEncodedColorModel(); | |||
boolean directEncode = true; | |||
if (helper.getEncodedColorModel().getPixelSize() > maxPixelSize) { | |||
@@ -180,6 +180,9 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima | |||
log.trace("set subtractive mode"); | |||
imageObjectInfo.setSubtractive(true); | |||
} | |||
if (pixelSize == 32) { | |||
functionSet = 45; //IOCA FS45 required for CMYK | |||
} | |||
helper.encode(baos); | |||
imageData = baos.toByteArray(); | |||
@@ -191,6 +194,7 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima | |||
//Convert image to 24bit RGB | |||
ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos); | |||
imageData = baos.toByteArray(); | |||
imageObjectInfo.setBitsPerPixel(24); | |||
boolean colorImages = paintingState.isColorImages(); | |||
imageObjectInfo.setColor(colorImages); | |||
@@ -212,6 +216,20 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler implements Ima | |||
} | |||
} | |||
switch (functionSet) { | |||
case 10: | |||
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS10); | |||
break; | |||
case 11: | |||
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS11); | |||
break; | |||
case 45: | |||
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45); | |||
break; | |||
default: | |||
throw new IllegalStateException("Invalid IOCA function set: " + functionSet); | |||
} | |||
imageObjectInfo.setData(imageData); | |||
// set object area info |
@@ -90,8 +90,8 @@ import org.apache.fop.render.afp.extensions.AFPElementMapping; | |||
import org.apache.fop.render.afp.extensions.AFPExtensionAttachment; | |||
import org.apache.fop.render.afp.extensions.AFPIncludeFormMap; | |||
import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap; | |||
import org.apache.fop.render.afp.extensions.AFPPageSetup; | |||
import org.apache.fop.render.afp.extensions.AFPPageOverlay; | |||
import org.apache.fop.render.afp.extensions.AFPPageSetup; | |||
/** | |||
* This is an implementation of a FOP Renderer that renders areas to AFP. | |||
@@ -444,6 +444,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust | |||
ImageFlavor.XML_DOM, | |||
/*ImageFlavor.RAW_PNG, */ // PNG not natively supported in AFP | |||
ImageFlavor.RAW_JPEG, ImageFlavor.RAW_CCITTFAX, ImageFlavor.RAW_EPS, | |||
ImageFlavor.RAW_TIFF, | |||
ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE }; | |||
private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { | |||
@@ -830,6 +831,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust | |||
paintingState.setNativeImagesSupported(nativeImages); | |||
} | |||
/** {@inheritDoc} */ | |||
public void setCMYKImagesSupported(boolean value) { | |||
paintingState.setCMYKImagesSupported(value); | |||
} | |||
/** {@inheritDoc} */ | |||
public void setShadingMode(AFPShadingMode shadingMode) { | |||
this.shadingMode = shadingMode; |
@@ -318,6 +318,9 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator | |||
String imagesMode = imagesCfg.getAttribute("mode", IMAGES_MODE_GRAYSCALE); | |||
if (IMAGES_MODE_COLOR.equals(imagesMode)) { | |||
customizable.setColorImages(true); | |||
boolean cmyk = imagesCfg.getAttributeAsBoolean("cmyk", false); | |||
customizable.setCMYKImagesSupported(cmyk); | |||
} else { | |||
customizable.setColorImages(false); | |||
// default to 8 bits per pixel |
@@ -34,6 +34,7 @@ import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.net.MalformedURLException; | |||
import java.util.List; | |||
import java.util.Vector; | |||
// FOP | |||
import org.apache.fop.apps.FOPException; | |||
@@ -67,7 +68,10 @@ import org.xml.sax.SAXException; | |||
public class Fop extends Task { | |||
private File foFile; | |||
private List filesets = new java.util.ArrayList(); | |||
private File xmlFile; | |||
private File xsltFile; | |||
private String xsltParams; | |||
private List/*<FileSet>*/ filesets = new java.util.ArrayList/*<FileSet>*/(); | |||
private File outFile; | |||
private File outDir; | |||
private String format; //MIME type | |||
@@ -111,6 +115,54 @@ public class Fop extends Task { | |||
return foFile; | |||
} | |||
/** | |||
* Gets the input XML file. | |||
* @return the input XML file. | |||
*/ | |||
public File getXmlFile() { | |||
return xmlFile; | |||
} | |||
/** | |||
* Sets the input XML file. | |||
* @param xmlFile the input XML file. | |||
*/ | |||
public void setXmlFile(File xmlFile) { | |||
this.xmlFile = xmlFile; | |||
} | |||
/** | |||
* Gets the input XSLT file. | |||
* @return the input XSLT file. | |||
*/ | |||
public File getXsltFile() { | |||
return xsltFile; | |||
} | |||
/** | |||
* Sets the input XSLT file. | |||
* @param xsltFile the input XSLT file. | |||
*/ | |||
public void setXsltFile(File xsltFile) { | |||
this.xsltFile = xsltFile; | |||
} | |||
/** | |||
* Gets the XSLT parameters | |||
* @return the XSLT parameters | |||
*/ | |||
public String getXsltParams() { | |||
return xsltParams; | |||
} | |||
/** | |||
* Sets the XSLT parameters | |||
* @param xsltParams the XSLT parameters | |||
*/ | |||
public void setXsltParams(String xsltParams) { | |||
this.xsltParams = xsltParams; | |||
} | |||
/** | |||
* Adds a set of XSL-FO files (nested fileset attribute). | |||
* @param set a fileset | |||
@@ -491,10 +543,39 @@ class FOPTaskStarter { | |||
skippedcount++; | |||
} | |||
} | |||
} else if (task.getXmlFile() != null && task.getXsltFile() != null) { | |||
if (task.getXmlFile().exists() && task.getXsltFile().exists()) { | |||
File outf = task.getOutfile(); | |||
if (outf == null) { | |||
throw new BuildException("outfile is required when fofile is used"); | |||
} | |||
if (task.getOutdir() != null) { | |||
outf = new File(task.getOutdir(), outf.getName()); | |||
} | |||
// Render if "force" flag is set OR | |||
// OR output file doesn't exist OR | |||
// output file is older than input file | |||
if (task.getForce() || !outf.exists() | |||
|| (task.getXmlFile().lastModified() > outf.lastModified() || | |||
task.getXsltFile().lastModified() > outf.lastModified())) { | |||
render(task.getXmlFile(), task.getXsltFile(), outf, outputFormat); | |||
actioncount++; | |||
} else if (outf.exists() | |||
&& (task.getXmlFile().lastModified() <= outf.lastModified() || | |||
task.getXsltFile().lastModified() <= outf.lastModified())) { | |||
skippedcount++; | |||
} | |||
} | |||
} | |||
GlobPatternMapper mapper = new GlobPatternMapper(); | |||
mapper.setFrom("*.fo"); | |||
String inputExtension = ".fo"; | |||
File xsltFile = task.getXsltFile(); | |||
if (xsltFile != null) { | |||
inputExtension = ".xml"; | |||
} | |||
mapper.setFrom("*" + inputExtension); | |||
mapper.setTo("*" + newExtension); | |||
// deal with the filesets | |||
@@ -507,16 +588,19 @@ class FOPTaskStarter { | |||
File f = new File(fs.getDir(task.getProject()), files[j]); | |||
File outf = null; | |||
if (task.getOutdir() != null && files[j].endsWith(".fo")) { | |||
if (task.getOutdir() != null && files[j].endsWith(inputExtension)) { | |||
String[] sa = mapper.mapFileName(files[j]); | |||
outf = new File(task.getOutdir(), sa[0]); | |||
} else { | |||
outf = replaceExtension(f, ".fo", newExtension); | |||
outf = replaceExtension(f, inputExtension, newExtension); | |||
if (task.getOutdir() != null) { | |||
outf = new File(task.getOutdir(), outf.getName()); | |||
} | |||
} | |||
File dir = outf.getParentFile(); | |||
if (!dir.exists()) { | |||
dir.mkdirs(); | |||
} | |||
try { | |||
if (task.getRelativebase()) { | |||
this.baseURL = f.getParentFile().toURI().toURL(). | |||
@@ -536,7 +620,11 @@ class FOPTaskStarter { | |||
// output file is older than input file | |||
if (task.getForce() || !outf.exists() | |||
|| (f.lastModified() > outf.lastModified() )) { | |||
render(f, outf, outputFormat); | |||
if (xsltFile != null) { | |||
render(f, xsltFile, outf, outputFormat); | |||
} else { | |||
render(f, outf, outputFormat); | |||
} | |||
actioncount++; | |||
} else if (outf.exists() && (f.lastModified() <= outf.lastModified() )) { | |||
skippedcount++; | |||
@@ -554,10 +642,7 @@ class FOPTaskStarter { | |||
} | |||
} | |||
private void render(File foFile, File outFile, | |||
String outputFormat) throws FOPException { | |||
InputHandler inputHandler = new InputHandler(foFile); | |||
private void renderInputHandler(InputHandler inputHandler, File outFile, String outputFormat) throws Exception { | |||
OutputStream out = null; | |||
try { | |||
out = new java.io.FileOutputStream(outFile); | |||
@@ -565,11 +650,6 @@ class FOPTaskStarter { | |||
} catch (Exception ex) { | |||
throw new BuildException("Failed to open " + outFile, ex); | |||
} | |||
if (task.getLogFiles()) { | |||
task.log(foFile + " -> " + outFile, Project.MSG_INFO); | |||
} | |||
boolean success = false; | |||
try { | |||
FOUserAgent userAgent = fopFactory.newFOUserAgent(); | |||
@@ -580,7 +660,7 @@ class FOPTaskStarter { | |||
if (task.getThrowexceptions()) { | |||
throw new BuildException(ex); | |||
} | |||
logger.error("Error rendering fo file: " + foFile, ex); | |||
throw ex; | |||
} finally { | |||
try { | |||
out.close(); | |||
@@ -593,5 +673,31 @@ class FOPTaskStarter { | |||
} | |||
} | |||
private void render(File foFile, File outFile, | |||
String outputFormat) throws FOPException { | |||
InputHandler inputHandler = new InputHandler(foFile); | |||
try { | |||
renderInputHandler(inputHandler, outFile, outputFormat); | |||
} catch (Exception ex) { | |||
logger.error("Error rendering fo file: " + foFile, ex); | |||
} | |||
if (task.getLogFiles()) { | |||
task.log(foFile + " -> " + outFile, Project.MSG_INFO); | |||
} | |||
} | |||
private void render(File xmlFile, File xsltFile, File outFile, String outputFormat) { | |||
//TODO: implement support for XSLT params | |||
final Vector xsltParams = null; | |||
InputHandler inputHandler = new InputHandler(xmlFile, xsltFile, xsltParams); | |||
try { | |||
renderInputHandler(inputHandler, outFile, outputFormat); | |||
} catch (Exception ex) { | |||
logger.error("Error rendering xml/xslt files: " + xmlFile + ", " + xsltFile, ex); | |||
} | |||
if (task.getLogFiles()) { | |||
task.log("xml: " + xmlFile + ", xslt: " + xsltFile + " -> " + outFile, Project.MSG_INFO); | |||
} | |||
} | |||
} | |||
@@ -61,6 +61,18 @@ | |||
<action context="Renderers" dev="JM" type="add" fixes-bug="46705" due-to="Jost Klopfstein"> | |||
Added basic accessibility and Tagged PDF support. | |||
</action> | |||
<action context="Code" dev="JM" type="add"> | |||
Added support for encoding CMYK bitmap images (IOCA FS45) and TIFF images as embedded objects. | |||
</action> | |||
<action context="Code" dev="AC" type="add"> | |||
Added support for xmlfile and xsltfile parameters in FOP's Ant Task. | |||
</action> | |||
<action context="Renderers" dev="AC" type="fix" fixes-bug="47941"> | |||
BugFix: Maintain valid AFP by providing TLE truncation on Attribute Value Triplet values that are greater than 250 chars in length. | |||
</action> | |||
<action context="Fonts" dev="JM" type="fix" fixes-bug="47711" due-to="Nicolas Peninguy"> | |||
Fixed generation of CIDSet object in PDF output. | |||
</action> | |||
<action context="Layout" dev="VH" type="fix"> | |||
Fixed handling of percentage values for provisional-label-separation. | |||
</action> |
@@ -83,10 +83,10 @@ public class ElementListCheck implements LayoutEngineCheck { | |||
} | |||
if (domEl.getAttribute("w").length() > 0) { | |||
int w = Integer.parseInt(domEl.getAttribute("w")); | |||
if (w != knuthEl.getW()) { | |||
if (w != knuthEl.getWidth()) { | |||
fail("Expected w=" + w | |||
+ " at position " + pos | |||
+ " but got: " + knuthEl.getW()); | |||
+ " but got: " + knuthEl.getWidth()); | |||
} | |||
} | |||
if ("true".equals(domEl.getAttribute("aux"))) { | |||
@@ -110,24 +110,24 @@ public class ElementListCheck implements LayoutEngineCheck { | |||
KnuthPenalty pen = (KnuthPenalty)knuthEl; | |||
if (domEl.getAttribute("w").length() > 0) { | |||
int w = Integer.parseInt(domEl.getAttribute("w")); | |||
if (w != knuthEl.getW()) { | |||
if (w != knuthEl.getWidth()) { | |||
fail("Expected w=" + w | |||
+ " at position " + pos | |||
+ " but got: " + knuthEl.getW()); | |||
+ " but got: " + knuthEl.getWidth()); | |||
} | |||
} | |||
if (domEl.getAttribute("p").length() > 0) { | |||
if ("<0".equals(domEl.getAttribute("p"))) { | |||
if (knuthEl.getP() >= 0) { | |||
if (knuthEl.getPenalty() >= 0) { | |||
fail("Expected p<0" | |||
+ " at position " + pos | |||
+ " but got: " + knuthEl.getP()); | |||
+ " but got: " + knuthEl.getPenalty()); | |||
} | |||
} else if (">0".equals(domEl.getAttribute("p"))) { | |||
if (knuthEl.getP() <= 0) { | |||
if (knuthEl.getPenalty() <= 0) { | |||
fail("Expected p>0" | |||
+ " at position " + pos | |||
+ " but got: " + knuthEl.getP()); | |||
+ " but got: " + knuthEl.getPenalty()); | |||
} | |||
} else { | |||
int p; | |||
@@ -142,20 +142,20 @@ public class ElementListCheck implements LayoutEngineCheck { | |||
} else { | |||
p = Integer.parseInt(domEl.getAttribute("p")); | |||
} | |||
if (p != knuthEl.getP()) { | |||
if (p != knuthEl.getPenalty()) { | |||
fail("Expected p=" + p | |||
+ " at position " + pos | |||
+ " but got: " + knuthEl.getP()); | |||
+ " but got: " + knuthEl.getPenalty()); | |||
} | |||
} | |||
} | |||
if ("true".equals(domEl.getAttribute("flagged"))) { | |||
if (!pen.isFlagged()) { | |||
if (!pen.isPenaltyFlagged()) { | |||
fail("Expected flagged penalty" | |||
+ " at position " + pos); | |||
} | |||
} else if ("false".equals(domEl.getAttribute("flagged"))) { | |||
if (pen.isFlagged()) { | |||
if (pen.isPenaltyFlagged()) { | |||
fail("Expected non-flagged penalty" | |||
+ " at position " + pos); | |||
} | |||
@@ -180,26 +180,26 @@ public class ElementListCheck implements LayoutEngineCheck { | |||
KnuthGlue glue = (KnuthGlue)knuthEl; | |||
if (domEl.getAttribute("w").length() > 0) { | |||
int w = Integer.parseInt(domEl.getAttribute("w")); | |||
if (w != knuthEl.getW()) { | |||
if (w != knuthEl.getWidth()) { | |||
fail("Expected w=" + w | |||
+ " at position " + pos | |||
+ " but got: " + knuthEl.getW()); | |||
+ " but got: " + knuthEl.getWidth()); | |||
} | |||
} | |||
if (domEl.getAttribute("y").length() > 0) { | |||
int stretch = Integer.parseInt(domEl.getAttribute("y")); | |||
if (stretch != knuthEl.getY()) { | |||
if (stretch != knuthEl.getStretch()) { | |||
fail("Expected y=" + stretch | |||
+ " (stretch) at position " + pos | |||
+ " but got: " + knuthEl.getY()); | |||
+ " but got: " + knuthEl.getStretch()); | |||
} | |||
} | |||
if (domEl.getAttribute("z").length() > 0) { | |||
int shrink = Integer.parseInt(domEl.getAttribute("z")); | |||
if (shrink != knuthEl.getZ()) { | |||
if (shrink != knuthEl.getShrink()) { | |||
fail("Expected z=" + shrink | |||
+ " (shrink) at position " + pos | |||
+ " but got: " + knuthEl.getZ()); | |||
+ " but got: " + knuthEl.getShrink()); | |||
} | |||
} | |||
} else { |
@@ -55,9 +55,9 @@ public class ElementListUtilsTestCase extends TestCase { | |||
assertFalse(res); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(1)).getP()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getP()); | |||
assertEquals(0, ((KnuthPenalty)lst.get(5)).getP()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(1)).getPenalty()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getPenalty()); | |||
assertEquals(0, ((KnuthPenalty)lst.get(5)).getPenalty()); | |||
} | |||
/** | |||
@@ -82,11 +82,11 @@ public class ElementListUtilsTestCase extends TestCase { | |||
assertFalse(res); | |||
//Must insert an INFINITE penalty | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(1)).getP()); | |||
assertEquals(0, ((KnuthGlue)lst.get(2)).getW()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(4)).getP()); | |||
assertEquals(0, ((KnuthGlue)lst.get(5)).getW()); | |||
assertEquals(0, ((KnuthGlue)lst.get(7)).getW()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(1)).getPenalty()); | |||
assertEquals(0, ((KnuthGlue)lst.get(2)).getWidth()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(4)).getPenalty()); | |||
assertEquals(0, ((KnuthGlue)lst.get(5)).getWidth()); | |||
assertEquals(0, ((KnuthGlue)lst.get(7)).getWidth()); | |||
} | |||
/** | |||
@@ -110,9 +110,9 @@ public class ElementListUtilsTestCase extends TestCase { | |||
assertFalse(res); | |||
assertEquals(0, ((KnuthPenalty)lst.get(1)).getP()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getP()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(5)).getP()); | |||
assertEquals(0, ((KnuthPenalty)lst.get(1)).getPenalty()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getPenalty()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(5)).getPenalty()); | |||
} | |||
/** | |||
@@ -137,10 +137,10 @@ public class ElementListUtilsTestCase extends TestCase { | |||
assertFalse(res); | |||
//Must insert an INFINITE penalty | |||
assertEquals(0, ((KnuthPenalty)lst.get(1)).getP()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getP()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(5)).getP()); | |||
assertEquals(0, ((KnuthGlue)lst.get(6)).getW()); | |||
assertEquals(0, ((KnuthPenalty)lst.get(1)).getPenalty()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(3)).getPenalty()); | |||
assertEquals(KnuthElement.INFINITE, ((KnuthPenalty)lst.get(5)).getPenalty()); | |||
assertEquals(0, ((KnuthGlue)lst.get(6)).getWidth()); | |||
} | |||
@@ -0,0 +1,404 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
--> | |||
<!-- $Id$ --> | |||
<testcase> | |||
<info> | |||
<p> | |||
This test checks that the code behaves properly when no restartable element can be found at | |||
all after a changing IPD break. | |||
</p> | |||
</info> | |||
<fo> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" font-size="8pt" line-height="10pt" | |||
provisional-distance-between-starts="6pt" provisional-label-separation="0"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="narrow" | |||
page-height="70pt" page-width="320pt" margin="10pt"> | |||
<fo:region-body background-color="#F0F0F0"/> | |||
</fo:simple-page-master> | |||
<fo:simple-page-master master-name="wide" | |||
page-height="70pt" page-width="420pt" margin="10pt"> | |||
<fo:region-body background-color="#F0F0F0"/> | |||
</fo:simple-page-master> | |||
<fo:page-sequence-master master-name="start-narrow-rest-wide"> | |||
<fo:single-page-master-reference master-reference="narrow"/> | |||
<fo:repeatable-page-master-reference master-reference="wide"/> | |||
</fo:page-sequence-master> | |||
<fo:page-sequence-master master-name="alternate"> | |||
<fo:repeatable-page-master-alternatives> | |||
<fo:conditional-page-master-reference master-reference="narrow" odd-or-even="odd"/> | |||
<fo:conditional-page-master-reference master-reference="wide" odd-or-even="even"/> | |||
</fo:repeatable-page-master-alternatives> | |||
</fo:page-sequence-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="start-narrow-rest-wide"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="30pt">Before the table</fo:block> | |||
<fo:table table-layout="fixed" width="100%"> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block> | |||
<fo:block>Before page break</fo:block> | |||
<fo:block>After page break</fo:block> | |||
</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
<fo:page-sequence master-reference="start-narrow-rest-wide"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="30pt">Before the table</fo:block> | |||
<fo:table table-layout="fixed" width="100%"> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block> | |||
<fo:block>Before page break</fo:block> | |||
<fo:block>After page break</fo:block> | |||
</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 1</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 2</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 3</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 4</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 5</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 6</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 7</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
<fo:page-sequence master-reference="alternate"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="30pt">Before the table</fo:block> | |||
<fo:table table-layout="fixed" width="100%"> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block> | |||
<fo:block>Before page break</fo:block> | |||
<fo:block>After page break</fo:block> | |||
</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 1</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 2</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 3</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 4</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 5</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 6</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Fill 7</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
<fo:page-sequence master-reference="start-narrow-rest-wide"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="30pt">Before the list</fo:block> | |||
<fo:list-block> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Before page break</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>After page break</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
</fo:list-block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
<fo:page-sequence master-reference="start-narrow-rest-wide"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="30pt">Before the list</fo:block> | |||
<fo:list-block> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Before page break</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>After page break</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 1</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 2</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 3</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 4</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 5</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 6</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 7</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
</fo:list-block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
<fo:page-sequence master-reference="alternate"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="30pt">Before the list</fo:block> | |||
<fo:list-block> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Before page break</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>After page break</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 1</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 2</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 3</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 4</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 5</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 6</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Fill 7</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
</fo:list-block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> | |||
</fo> | |||
<checks> | |||
<!-- Tables --> | |||
<eval expected="Before page break" xpath="//pageSequence[1]/pageViewport[1]//flow/block[2]//text"/> | |||
<eval expected="After page break" xpath="//pageSequence[1]/pageViewport[2]//flow/block[1]//text"/> | |||
<eval expected="Before page break" xpath="//pageSequence[2]/pageViewport[1]//flow/block[2]//text"/> | |||
<eval expected="After page break" xpath="//pageSequence[2]/pageViewport[2]//flow/block/block[1]//text"/> | |||
<eval expected="Fill 1" xpath="//pageSequence[2]/pageViewport[2]//flow/block/block[2]//text"/> | |||
<eval expected="Fill 2" xpath="//pageSequence[2]/pageViewport[2]//flow/block/block[3]//text"/> | |||
<eval expected="Fill 3" xpath="//pageSequence[2]/pageViewport[2]//flow/block/block[4]//text"/> | |||
<eval expected="Fill 4" xpath="//pageSequence[2]/pageViewport[2]//flow/block/block[5]//text"/> | |||
<eval expected="Fill 5" xpath="//pageSequence[2]/pageViewport[3]//flow/block/block[1]//text"/> | |||
<eval expected="Fill 6" xpath="//pageSequence[2]/pageViewport[3]//flow/block/block[2]//text"/> | |||
<eval expected="Fill 7" xpath="//pageSequence[2]/pageViewport[3]//flow/block/block[3]//text"/> | |||
<eval expected="Before page break" xpath="//pageSequence[3]/pageViewport[1]//flow/block[2]//text"/> | |||
<eval expected="After page break" xpath="//pageSequence[3]/pageViewport[2]//flow/block/block[1]//text"/> | |||
<eval expected="Fill 1" xpath="//pageSequence[3]/pageViewport[2]//flow/block/block[2]//text"/> | |||
<eval expected="Fill 2" xpath="//pageSequence[3]/pageViewport[2]//flow/block/block[3]//text"/> | |||
<eval expected="Fill 3" xpath="//pageSequence[3]/pageViewport[2]//flow/block/block[4]//text"/> | |||
<eval expected="Fill 4" xpath="//pageSequence[3]/pageViewport[2]//flow/block/block[5]//text"/> | |||
<eval expected="Fill 5" xpath="//pageSequence[3]/pageViewport[3]//flow/block/block[1]//text"/> | |||
<eval expected="Fill 6" xpath="//pageSequence[3]/pageViewport[3]//flow/block/block[2]//text"/> | |||
<eval expected="Fill 7" xpath="//pageSequence[3]/pageViewport[3]//flow/block/block[3]//text"/> | |||
<!-- Lists --> | |||
<eval expected="Before page break" xpath="//pageSequence[4]/pageViewport[1]//flow/block[2]/block/block[2]//text"/> | |||
<eval expected="After page break" xpath="//pageSequence[4]/pageViewport[2]//flow/block[1]/block/block[2]//text"/> | |||
<eval expected="Before page break" xpath="//pageSequence[5]/pageViewport[1]//flow/block[2]/block/block[2]//text"/> | |||
<eval expected="After page break" xpath="//pageSequence[5]/pageViewport[2]//flow/block/block[1]/block[2]//text"/> | |||
<eval expected="Fill 1" xpath="//pageSequence[5]/pageViewport[2]//flow/block/block[2]/block[2]//text"/> | |||
<eval expected="Fill 2" xpath="//pageSequence[5]/pageViewport[2]//flow/block/block[3]/block[2]//text"/> | |||
<eval expected="Fill 3" xpath="//pageSequence[5]/pageViewport[2]//flow/block/block[4]/block[2]//text"/> | |||
<eval expected="Fill 4" xpath="//pageSequence[5]/pageViewport[2]//flow/block/block[5]/block[2]//text"/> | |||
<eval expected="Fill 5" xpath="//pageSequence[5]/pageViewport[3]//flow/block/block[1]/block[2]//text"/> | |||
<eval expected="Fill 6" xpath="//pageSequence[5]/pageViewport[3]//flow/block/block[2]/block[2]//text"/> | |||
<eval expected="Fill 7" xpath="//pageSequence[5]/pageViewport[3]//flow/block/block[3]/block[2]//text"/> | |||
<eval expected="Before page break" xpath="//pageSequence[6]/pageViewport[1]//flow/block[2]/block/block[2]//text"/> | |||
<eval expected="After page break" xpath="//pageSequence[6]/pageViewport[2]//flow/block/block[1]/block[2]//text"/> | |||
<eval expected="Fill 1" xpath="//pageSequence[6]/pageViewport[2]//flow/block/block[2]/block[2]//text"/> | |||
<eval expected="Fill 2" xpath="//pageSequence[6]/pageViewport[2]//flow/block/block[3]/block[2]//text"/> | |||
<eval expected="Fill 3" xpath="//pageSequence[6]/pageViewport[2]//flow/block/block[4]/block[2]//text"/> | |||
<eval expected="Fill 4" xpath="//pageSequence[6]/pageViewport[2]//flow/block/block[5]/block[2]//text"/> | |||
<eval expected="Fill 5" xpath="//pageSequence[6]/pageViewport[3]//flow/block/block[1]/block[2]//text"/> | |||
<eval expected="Fill 6" xpath="//pageSequence[6]/pageViewport[3]//flow/block/block[2]/block[2]//text"/> | |||
<eval expected="Fill 7" xpath="//pageSequence[6]/pageViewport[3]//flow/block/block[3]/block[2]//text"/> | |||
</checks> | |||
</testcase> |
@@ -0,0 +1,80 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
--> | |||
<!-- $Id$ --> | |||
<testcase> | |||
<info> | |||
<p> | |||
This test checks that a table immediately following a changing IPD break is handled properly. | |||
</p> | |||
</info> | |||
<fo> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="narrow" | |||
page-height="220pt" page-width="320pt" margin="10pt"> | |||
<fo:region-body background-color="#F0F0F0"/> | |||
</fo:simple-page-master> | |||
<fo:simple-page-master master-name="wide" | |||
page-height="220pt" page-width="420pt" margin="10pt"> | |||
<fo:region-body background-color="#F0F0F0"/> | |||
</fo:simple-page-master> | |||
<fo:page-sequence-master master-name="pages"> | |||
<fo:single-page-master-reference master-reference="narrow"/> | |||
<fo:repeatable-page-master-reference master-reference="wide"/> | |||
</fo:page-sequence-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="pages" font-size="8pt" line-height="10pt"> | |||
<fo:flow flow-name="xsl-region-body" text-align="justify"> | |||
<fo:block space-after="180pt">Before the table</fo:block> | |||
<fo:table table-layout="fixed" width="100%" id="table"> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block> | |||
<fo:block id="before_break">Block before the page break.</fo:block> | |||
<fo:block id="after_break">Block after the page break.</fo:block> | |||
</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
<fo:table table-layout="fixed" width="100%"> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>After the table 1</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>After the table 2</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> | |||
</fo> | |||
<checks> | |||
<eval expected="Block before the page break." xpath="//pageViewport[1]//flow/block[2]//text"/> | |||
<eval expected="Block after the page break." xpath="//pageViewport[2]//flow/block[1]//text"/> | |||
<eval expected="After the table 1" xpath="//pageViewport[2]//flow/block[2]/block[1]//text"/> | |||
<eval expected="After the table 2" xpath="//pageViewport[2]//flow/block[2]/block[2]//text"/> | |||
</checks> | |||
</testcase> |