Browse Source

Merged changes from Trunk up to revision 829121


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_Accessibility@829138 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Vincent Hennebert 14 years ago
parent
commit
20171ce3b3
58 changed files with 1711 additions and 552 deletions
  1. 26
    6
      build.xml
  2. BIN
      lib/xmlgraphics-commons-1.4svn.jar
  3. 35
    0
      src/documentation/content/xdocs/trunk/anttask.xml
  4. 29
    5
      src/java/org/apache/fop/afp/AFPDataObjectFactory.java
  5. 22
    1
      src/java/org/apache/fop/afp/AFPPaintingState.java
  6. 2
    16
      src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java
  7. 151
    0
      src/java/org/apache/fop/afp/ioca/IDEStructureParameter.java
  8. 45
    59
      src/java/org/apache/fop/afp/ioca/ImageContent.java
  9. 8
    2
      src/java/org/apache/fop/afp/ioca/ImageSegment.java
  10. 16
    1
      src/java/org/apache/fop/afp/modca/AbstractAFPObject.java
  11. 6
    3
      src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java
  12. 2
    0
      src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java
  13. 1
    0
      src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java
  14. 12
    1
      src/java/org/apache/fop/afp/modca/ImageObject.java
  15. 39
    72
      src/java/org/apache/fop/afp/modca/TagLogicalElement.java
  16. 2
    60
      src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java
  17. 67
    0
      src/java/org/apache/fop/afp/modca/triplets/AttributeQualifierTriplet.java
  18. 72
    0
      src/java/org/apache/fop/afp/modca/triplets/AttributeValueTriplet.java
  19. 85
    0
      src/java/org/apache/fop/afp/modca/triplets/Triplet.java
  20. 6
    1
      src/java/org/apache/fop/cli/CommandLineOptions.java
  21. 97
    22
      src/java/org/apache/fop/cli/InputHandler.java
  22. 2
    2
      src/java/org/apache/fop/fo/FObj.java
  23. 2
    2
      src/java/org/apache/fop/fonts/CIDSubset.java
  24. 4
    1
      src/java/org/apache/fop/fonts/Font.java
  25. 36
    14
      src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
  26. 1
    1
      src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
  27. 1
    1
      src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
  28. 31
    30
      src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
  29. 21
    21
      src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java
  30. 16
    14
      src/java/org/apache/fop/layoutmgr/ElementListUtils.java
  31. 1
    1
      src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java
  32. 10
    10
      src/java/org/apache/fop/layoutmgr/KnuthBox.java
  33. 11
    11
      src/java/org/apache/fop/layoutmgr/KnuthElement.java
  34. 25
    24
      src/java/org/apache/fop/layoutmgr/KnuthGlue.java
  35. 36
    33
      src/java/org/apache/fop/layoutmgr/KnuthPenalty.java
  36. 4
    1
      src/java/org/apache/fop/layoutmgr/KnuthSequence.java
  37. 23
    24
      src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
  38. 6
    5
      src/java/org/apache/fop/layoutmgr/PageProvider.java
  39. 2
    2
      src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java
  40. 3
    3
      src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
  41. 23
    22
      src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
  42. 7
    7
      src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
  43. 12
    12
      src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
  44. 1
    1
      src/java/org/apache/fop/layoutmgr/table/RowPainter.java
  45. 1
    1
      src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
  46. 1
    1
      src/java/org/apache/fop/pdf/PDFFontNonBase14.java
  47. 8
    0
      src/java/org/apache/fop/render/afp/AFPCustomizable.java
  48. 5
    0
      src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
  49. 8
    1
      src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java
  50. 26
    8
      src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
  51. 7
    1
      src/java/org/apache/fop/render/afp/AFPRenderer.java
  52. 3
    0
      src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
  53. 122
    16
      src/java/org/apache/fop/tools/anttasks/Fop.java
  54. 12
    0
      status.xml
  55. 18
    18
      test/java/org/apache/fop/layoutengine/ElementListCheck.java
  56. 15
    15
      test/java/org/apache/fop/util/ElementListUtilsTestCase.java
  57. 404
    0
      test/layoutengine/standard-testcases/flow_changing-ipd_no-restartable.xml
  58. 80
    0
      test/layoutengine/standard-testcases/flow_changing-ipd_table-after-break.xml

+ 26
- 6
build.xml View File

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

BIN
lib/xmlgraphics-commons-1.4svn.jar View File


+ 35
- 0
src/documentation/content/xdocs/trunk/anttask.xml View File

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

+ 29
- 5
src/java/org/apache/fop/afp/AFPDataObjectFactory.java View File

@@ -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());


+ 22
- 1
src/java/org/apache/fop/afp/AFPPaintingState.java View File

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

+ 2
- 16
src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java View File

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

+ 151
- 0
src/java/org/apache/fop/afp/ioca/IDEStructureParameter.java View File

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

}

+ 45
- 59
src/java/org/apache/fop/afp/ioca/ImageContent.java View File

@@ -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];
}

}

+ 8
- 2
src/java/org/apache/fop/afp/ioca/ImageSegment.java View File

@@ -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);

+ 16
- 1
src/java/org/apache/fop/afp/modca/AbstractAFPObject.java View File

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


+ 6
- 3
src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java View File

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

+ 2
- 0
src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java View File

@@ -79,6 +79,8 @@ public class ContainerDataDescriptor extends AbstractDescriptor {
data[18] = ysize[0];
data[19] = ysize[1];
data[20] = ysize[2];

os.write(data);
}

}

+ 1
- 0
src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java View File

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


+ 12
- 1
src/java/org/apache/fop/afp/modca/ImageObject.java View File

@@ -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);

+ 39
- 72
src/java/org/apache/fop/afp/modca/TagLogicalElement.java View File

@@ -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);
}
}

+ 2
- 60
src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java View File

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

+ 67
- 0
src/java/org/apache/fop/afp/modca/triplets/AttributeQualifierTriplet.java View File

@@ -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;
}
}

+ 72
- 0
src/java/org/apache/fop/afp/modca/triplets/AttributeValueTriplet.java View File

@@ -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;
}
}

+ 85
- 0
src/java/org/apache/fop/afp/modca/triplets/Triplet.java View File

@@ -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;
}

+ 6
- 1
src/java/org/apache/fop/cli/CommandLineOptions.java View File

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

+ 97
- 22
src/java/org/apache/fop/cli/InputHandler.java View File

@@ -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);


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

@@ -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);
}

+ 2
- 2
src/java/org/apache/fop/fonts/CIDSubset.java View File

@@ -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());

+ 4
- 1
src/java/org/apache/fop/fonts/Font.java View File

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

+ 36
- 14
src/java/org/apache/fop/layoutmgr/AbstractBreaker.java View File

@@ -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;
}

+ 1
- 1
src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java View File

@@ -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();
}
}

+ 1
- 1
src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java View File

@@ -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();
}
}

+ 31
- 30
src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java View File

@@ -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");
}


+ 21
- 21
src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java View File

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

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

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

+ 1
- 1
src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java View File

@@ -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);

+ 10
- 10
src/java/org/apache/fop/layoutmgr/KnuthBox.java View File

@@ -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();
}

}

+ 11
- 11
src/java/org/apache/fop/layoutmgr/KnuthElement.java View File

@@ -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");
}


+ 25
- 24
src/java/org/apache/fop/layoutmgr/KnuthGlue.java View File

@@ -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();
}

}

+ 36
- 33
src/java/org/apache/fop/layoutmgr/KnuthPenalty.java View File

@@ -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();
}
}

+ 4
- 1
src/java/org/apache/fop/layoutmgr/KnuthSequence.java View File

@@ -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.
*/

+ 23
- 24
src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java View File

@@ -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);
}

}

+ 6
- 5
src/java/org/apache/fop/layoutmgr/PageProvider.java View File

@@ -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();
}
}


+ 2
- 2
src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java View File

@@ -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);
}
}

+ 3
- 3
src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java View File

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

+ 23
- 22
src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java View File

@@ -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} */

+ 7
- 7
src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java View File

@@ -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]) {

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

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

+ 1
- 1
src/java/org/apache/fop/layoutmgr/table/RowPainter.java View File

@@ -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());

+ 1
- 1
src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java View File

@@ -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);

+ 1
- 1
src/java/org/apache/fop/pdf/PDFFontNonBase14.java View File

@@ -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());
}
}
}

+ 8
- 0
src/java/org/apache/fop/render/afp/AFPCustomizable.java View File

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

+ 5
- 0
src/java/org/apache/fop/render/afp/AFPDocumentHandler.java View File

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

+ 8
- 1
src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java View File

@@ -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;
}

+ 26
- 8
src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java View File

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

+ 7
- 1
src/java/org/apache/fop/render/afp/AFPRenderer.java View File

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

+ 3
- 0
src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java View File

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

+ 122
- 16
src/java/org/apache/fop/tools/anttasks/Fop.java View File

@@ -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);
}
}
}


+ 12
- 0
status.xml View File

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

+ 18
- 18
test/java/org/apache/fop/layoutengine/ElementListCheck.java View File

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

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

@@ -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());
}



+ 404
- 0
test/layoutengine/standard-testcases/flow_changing-ipd_no-restartable.xml View File

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

+ 80
- 0
test/layoutengine/standard-testcases/flow_changing-ipd_table-after-break.xml View File

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

Loading…
Cancel
Save