git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1339442 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_1rc1old
@@ -94,6 +94,7 @@ the location of this file. | |||
--> | |||
<images mode="b+w" bits-per-pixel="8"/> | |||
<renderer-resolution>240</renderer-resolution> | |||
<line-width-correction>2.5</line-width-correction> | |||
<resource-group-file>resources.afp</resource-group-file> | |||
<fonts> |
@@ -471,6 +471,7 @@ | |||
<source><![CDATA[<renderer mime="application/x-afp"> | |||
<images mode="b+w" bits-per-pixel="8" native="true"/> | |||
<renderer-resolution>240</renderer-resolution> | |||
<line-width-correction>2.5</line-width-correction> | |||
<!-- a default external resource group file --> | |||
<resource-group-file>resources.afp</resource-group-file> | |||
@@ -482,6 +483,9 @@ | |||
<p> | |||
The default value for the "renderer-resolution" is 240 dpi. | |||
</p> | |||
<p> | |||
The default line width is device dependent and may need to be fine tuned so that the output matches the expected result. The default correction value is 2.5. | |||
</p> | |||
<!-- | |||
<p> | |||
The default value for the MO:DCA "interchange-set" is "MO:DCA-L". Other compliance settings include presentation interchange sets "MO:DCA-P IS/1" and "MO:DCA-P IS/2" (Resource Groups). |
@@ -757,6 +757,14 @@ Note that the value of the encoding attribute in the example is the double-byte | |||
<source><![CDATA[ | |||
<renderer-resolution>240</renderer-resolution>]]></source> | |||
</section> | |||
<section id="afp-line-width-correction-config"> | |||
<title>Line Width Correction</title> | |||
<p>The default line width in AFP is device dependent. This means that a line width specified in, say, | |||
a SVG source file may not render the way it was intended. The output AFP line with can be corrected | |||
by the <line-width-correction/> configuration element. Example:</p> | |||
<source><![CDATA[ | |||
<line-width-correction>2.5</line-width-correction>]]></source> | |||
</section> | |||
<section id="afp-image-config"> | |||
<title>Images</title> | |||
<p>By default the AFP Renderer converts all images to 8 bit grey level. |
@@ -50,4 +50,15 @@ public interface AFPConstants { | |||
* 72dpi in millipoints | |||
*/ | |||
int DPI_72_MPTS = DPI_72 * 1000; | |||
/** | |||
* The line width is set as a multiplier of a default line with; the width of the default | |||
* line width is implementation defined, which probably means different devices use different | |||
* actual widths; this means that the source line width (as specified in, say, a SVG line | |||
* element) needs to be corrected by a fudge factor that depends on the output device so that | |||
* the final output (print to paper, screen viewer) looks as intended. | |||
*/ | |||
float LINE_WIDTH_CORRECTION = 2.5f; | |||
} | |||
@@ -263,14 +263,6 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand | |||
return length * factor; | |||
} | |||
/** IBM's AFP Workbench paints lines that are wider than expected. We correct manually. */ | |||
private static final double GUESSED_WIDTH_CORRECTION = 1.7; | |||
private static final double SPEC_NORMAL_LINE_WIDTH = UnitConv.in2pt(0.01); //"approx" 0.01 inch | |||
private static final double NORMAL_LINE_WIDTH | |||
= SPEC_NORMAL_LINE_WIDTH * GUESSED_WIDTH_CORRECTION; | |||
/** | |||
* Apply the stroke to the AFP graphics object. | |||
* This takes the java stroke and outputs the appropriate settings | |||
@@ -282,17 +274,11 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand | |||
if (stroke instanceof BasicStroke) { | |||
BasicStroke basicStroke = (BasicStroke) stroke; | |||
// set line width | |||
// set line width and correct it; NOTE: apparently we need to correct the width so that the | |||
// output looks OK since the default with depends on the output device | |||
float lineWidth = basicStroke.getLineWidth(); | |||
if (false) { | |||
//Old approach. Retained until verified problems with 1440 resolution | |||
graphicsObj.setLineWidth(Math.round(lineWidth / 2)); | |||
} else { | |||
double absoluteLineWidth = lineWidth * Math.abs(getTransform().getScaleY()); | |||
double multiplier = absoluteLineWidth / NORMAL_LINE_WIDTH; | |||
graphicsObj.setLineWidth((int)Math.round(multiplier)); | |||
//TODO Use GSFLW instead of GSLW for higher accuracy? | |||
} | |||
float correction = paintingState.getLineWidthCorrection(); | |||
graphicsObj.setLineWidth(lineWidth * correction); | |||
//No line join, miter limit and end cap support in GOCA. :-( | |||
@@ -79,6 +79,12 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState | |||
/** the output resolution */ | |||
private int resolution = 240; // 240 dpi | |||
/** | |||
* A configurable value to correct the line width so that the output matches the expected. Different | |||
* devices may need different values. | |||
*/ | |||
private float lineWidthCorrection = AFPConstants.LINE_WIDTH_CORRECTION; | |||
/** determines whether GOCA is enabled or disabled */ | |||
private boolean gocaEnabled = true; | |||
/** determines whether to stroke text in GOCA mode or to use text operators where possible */ | |||
@@ -322,6 +328,18 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState | |||
this.resolution = resolution; | |||
} | |||
/** | |||
* Sets the line width correction | |||
* | |||
* @param correction the line width multiplying factor correction | |||
*/ | |||
public void setLineWidthCorrection(float correction) { | |||
if (log.isDebugEnabled()) { | |||
log.debug("line width correction set to: " + correction); | |||
} | |||
this.lineWidthCorrection = correction; | |||
} | |||
/** | |||
* Returns the output/device resolution. | |||
* | |||
@@ -331,6 +349,14 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState | |||
return this.resolution; | |||
} | |||
/** | |||
* Returns the line width correction. | |||
* @return the correction | |||
*/ | |||
public float getLineWidthCorrection() { | |||
return this.lineWidthCorrection; | |||
} | |||
/** | |||
* Controls whether GOCA is enabled or disabled. | |||
* @param enabled true if GOCA is enabled, false if it is disabled |
@@ -0,0 +1,69 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.afp.goca; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
/** | |||
* Sets the line width to use when stroking GOCA shapes (structured fields) | |||
*/ | |||
public class GraphicsSetFractionalLineWidth extends AbstractGraphicsDrawingOrder { | |||
/** line width multiplier */ | |||
private final float multiplier; | |||
/** | |||
* Main constructor | |||
* | |||
* @param multiplier the line width multiplier | |||
*/ | |||
public GraphicsSetFractionalLineWidth(float multiplier) { | |||
this.multiplier = multiplier; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getDataLength() { | |||
return 4; | |||
} | |||
/** {@inheritDoc} */ | |||
public void writeToStream(OutputStream os) throws IOException { | |||
int integral = (int) multiplier; | |||
int fractional = (int) ((multiplier - (float) integral) * 256); | |||
byte[] data = new byte[] { | |||
getOrderCode(), // GSLW order code | |||
0x02, // two bytes next | |||
(byte) integral, // integral line with | |||
(byte) fractional // and fractional | |||
}; | |||
os.write(data); | |||
} | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
return "GraphicsSetFractionalLineWidth{multiplier=" + multiplier + "}"; | |||
} | |||
/** {@inheritDoc} */ | |||
byte getOrderCode() { | |||
return 0x11; | |||
} | |||
} |
@@ -28,7 +28,7 @@ import java.io.OutputStream; | |||
public class GraphicsSetLineWidth extends AbstractGraphicsDrawingOrder { | |||
/** line width multiplier */ | |||
private int multiplier = 1; | |||
private final int multiplier; | |||
/** | |||
* Main constructor | |||
@@ -48,7 +48,7 @@ public class GraphicsSetLineWidth extends AbstractGraphicsDrawingOrder { | |||
public void writeToStream(OutputStream os) throws IOException { | |||
byte[] data = new byte[] { | |||
getOrderCode(), // GSLW order code | |||
(byte)multiplier // MH (line-width) | |||
(byte) multiplier // MH (line-width) | |||
}; | |||
os.write(data); | |||
} |
@@ -48,6 +48,7 @@ import org.apache.fop.afp.goca.GraphicsLine; | |||
import org.apache.fop.afp.goca.GraphicsSetArcParameters; | |||
import org.apache.fop.afp.goca.GraphicsSetCharacterSet; | |||
import org.apache.fop.afp.goca.GraphicsSetCurrentPosition; | |||
import org.apache.fop.afp.goca.GraphicsSetFractionalLineWidth; | |||
import org.apache.fop.afp.goca.GraphicsSetLineType; | |||
import org.apache.fop.afp.goca.GraphicsSetLineWidth; | |||
import org.apache.fop.afp.goca.GraphicsSetPatternSymbol; | |||
@@ -182,8 +183,20 @@ public class GraphicsObject extends AbstractDataObject { | |||
* @param lineWidth the line width multiplier | |||
*/ | |||
public void setLineWidth(int lineWidth) { | |||
if (lineWidth != graphicsState.lineWidth) { | |||
if ((float) lineWidth != graphicsState.lineWidth) { | |||
addObject(new GraphicsSetLineWidth(lineWidth)); | |||
graphicsState.lineWidth = (float) lineWidth; | |||
} | |||
} | |||
/** | |||
* Sets the line width | |||
* | |||
* @param lineWidth the line width multiplier | |||
*/ | |||
public void setLineWidth(float lineWidth) { | |||
if (lineWidth != graphicsState.lineWidth) { | |||
addObject(new GraphicsSetFractionalLineWidth(lineWidth)); | |||
graphicsState.lineWidth = lineWidth; | |||
} | |||
} | |||
@@ -414,7 +427,7 @@ public class GraphicsObject extends AbstractDataObject { | |||
private byte lineType; | |||
/** the current line width */ | |||
private int lineWidth; | |||
private float lineWidth; | |||
/** the current fill pattern */ | |||
private byte patternSymbol; |
@@ -89,6 +89,13 @@ public interface AFPCustomizable { | |||
*/ | |||
void setResolution(int resolution); | |||
/** | |||
* Sets the line width correction | |||
* | |||
* @param correction the line width multiplying factor correction | |||
*/ | |||
void setLineWidthCorrection(float correction); | |||
/** | |||
* Sets whether FS11 and FS45 non-inline images should be wrapped in a page segment | |||
* @param pSeg true iff images should be wrapped |
@@ -442,6 +442,11 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler | |||
paintingState.setResolution(resolution); | |||
} | |||
/** {@inheritDoc} */ | |||
public void setLineWidthCorrection(float correction) { | |||
paintingState.setLineWidthCorrection(correction); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getResolution() { | |||
return paintingState.getResolution(); |
@@ -29,6 +29,7 @@ import java.util.List; | |||
import org.apache.avalon.framework.configuration.Configuration; | |||
import org.apache.avalon.framework.configuration.ConfigurationException; | |||
import org.apache.fop.afp.AFPConstants; | |||
import org.apache.fop.afp.AFPEventProducer; | |||
import org.apache.fop.afp.AFPResourceLevel; | |||
import org.apache.fop.afp.AFPResourceLevelDefaults; | |||
@@ -446,6 +447,13 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator | |||
customizable.setResolution(rendererResolutionCfg.getValueAsInteger(240)); | |||
} | |||
// renderer resolution | |||
Configuration lineWidthCorrectionCfg = cfg.getChild("line-width-correction", false); | |||
if (lineWidthCorrectionCfg != null) { | |||
customizable.setLineWidthCorrection(lineWidthCorrectionCfg | |||
.getValueAsFloat(AFPConstants.LINE_WIDTH_CORRECTION)); | |||
} | |||
// a default external resource group file setting | |||
Configuration resourceGroupFileCfg | |||
= cfg.getChild("resource-group-file", false); |
@@ -63,6 +63,9 @@ | |||
documents. Example: the fix of marks layering will be such a case when it's done. | |||
--> | |||
<release version="FOP Trunk" date="TBD"> | |||
<action context="Renderers" dev="GA" type="fix" fixes-bug="53242" due-to="Luis Bernardo"> | |||
Support fractional line widths in AFP renderer, fixing problem with SVG line drawing. | |||
</action> | |||
<action context="Config" dev="GA" type="fix" fixes-bug="53248" due-to="Luis Bernardo"> | |||
Fix exception thrown from use of -print option in CLI. | |||
</action> |
@@ -0,0 +1,57 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.afp; | |||
import java.awt.BasicStroke; | |||
import org.junit.Test; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.when; | |||
import org.apache.fop.afp.modca.GraphicsObject; | |||
import org.apache.fop.fonts.FontInfo; | |||
public class AFPGraphics2DTestCase { | |||
private final float lineWidth = 1.0f; | |||
private final float correction = 2.5f; | |||
private final BasicStroke stroke = mock(BasicStroke.class); | |||
private final GraphicsObject gObject = mock(GraphicsObject.class); | |||
private final AFPPaintingState paintingState = mock(AFPPaintingState.class); | |||
private final AFPResourceManager resourceManager = mock(AFPResourceManager.class); | |||
private final AFPResourceInfo resourceInfo = mock(AFPResourceInfo.class); | |||
private final FontInfo fontInfo = mock(FontInfo.class); | |||
private AFPGraphics2D graphics2D = new AFPGraphics2D(false, paintingState, resourceManager, resourceInfo, | |||
fontInfo); | |||
@Test | |||
public void testApplyStroke() { | |||
// note: this only tests the setLineWidth in the GraphicsObject | |||
float correctedLineWidth = lineWidth * correction; | |||
when(stroke.getLineWidth()).thenReturn(lineWidth); | |||
when(paintingState.getLineWidthCorrection()).thenReturn(correction); | |||
graphics2D.setGraphicsObject(gObject); | |||
graphics2D.applyStroke(stroke); | |||
verify(gObject).setLineWidth(correctedLineWidth); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
// $Id$ | |||
package org.apache.fop.afp.goca; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertTrue; | |||
public class GraphicsSetFractionalLineWidthTestCase { | |||
private final float multiplier = 5.25f; | |||
private final GraphicsSetFractionalLineWidth gsflw = new GraphicsSetFractionalLineWidth(multiplier); | |||
@Test | |||
public void testGetDataLength() { | |||
assertEquals(4, gsflw.getDataLength()); | |||
} | |||
@Test | |||
public void testWriteToStream() throws IOException { | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
gsflw.writeToStream(baos); | |||
baos.close(); | |||
// note: 0.25 = 64/256 and 64 = 4*16, so 0x40 | |||
// expected: 0x11 (order code), 0x02 (2 bytes next), 0x05 (integral multiplier), 0x40 (fractional | |||
// multiplier) | |||
byte[] expected = new byte[] {0x11, 0x02, 0x05, 0x40}; | |||
assertTrue(Arrays.equals(expected, baos.toByteArray())); | |||
} | |||
@Test | |||
public void testToString() { | |||
// lets make sure we keep good coverage... | |||
assertEquals("GraphicsSetFractionalLineWidth{multiplier=" + multiplier + "}", gsflw.toString()); | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
// $Id$ | |||
package org.apache.fop.afp.goca; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertTrue; | |||
public class GraphicsSetLineWidthTestCase { | |||
private final int multiplier = 5; | |||
private final GraphicsSetLineWidth gslw = new GraphicsSetLineWidth(multiplier); | |||
@Test | |||
public void testGetDataLength() { | |||
assertEquals(2, gslw.getDataLength()); | |||
} | |||
@Test | |||
public void testWriteToStream() throws IOException { | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
gslw.writeToStream(baos); | |||
baos.close(); | |||
// expected: 0x19 (order code), 0x05 (integral multiplier) | |||
byte[] expected = new byte[] {0x19, 0x05}; | |||
assertTrue(Arrays.equals(expected, baos.toByteArray())); | |||
} | |||
@Test | |||
public void testToString() { | |||
// lets make sure we keep good coverage... | |||
assertEquals("GraphicsSetLineWidth{multiplier=" + multiplier + "}", gslw.toString()); | |||
} | |||
} |