diff options
8 files changed, 143 insertions, 41 deletions
diff --git a/src/java/org/apache/fop/afp/AFPBorderPainter.java b/src/java/org/apache/fop/afp/AFPBorderPainter.java index 42c58aa7d..06f1ecd11 100644 --- a/src/java/org/apache/fop/afp/AFPBorderPainter.java +++ b/src/java/org/apache/fop/afp/AFPBorderPainter.java @@ -22,6 +22,7 @@ package org.apache.fop.afp; import java.awt.geom.AffineTransform; import org.apache.fop.fo.Constants; +import org.apache.fop.render.intermediate.BorderPainter; import org.apache.fop.util.ColorUtil; /** @@ -126,24 +127,27 @@ public class AFPBorderPainter extends AbstractAFPPainter { } break; case Constants.EN_DASHED: - int thick = lineDataInfo.getThickness() * 3; if (borderPaintInfo.isHorizontal()) { - lineDataInfo.setX2 ( lineDataInfo.getX1() + thick ); + int dashWidth = (int) (BorderPainter.dashWidthCalculator(x2 - x1, thickness)); + lineDataInfo.setX2 ( lineDataInfo.getX1() + dashWidth ); lineDataInfo.setY2 ( lineDataInfo.getY1() ); int ex2 = Math.round(x2); - while (lineDataInfo.getX1() + thick < ex2) { + int spaceWidth = (int) (BorderPainter.DASHED_BORDER_SPACE_RATIO * dashWidth); + while (lineDataInfo.getX2() < ex2) { dataStream.createLine(lineDataInfo); - lineDataInfo.setX1 ( lineDataInfo.getX1() + 2 * thick ); - lineDataInfo.setX2 ( lineDataInfo.getX1() + thick ); + lineDataInfo.setX1 ( lineDataInfo.getX2() + spaceWidth ); + lineDataInfo.setX2 ( lineDataInfo.getX1() + dashWidth ); } } else { + int dashWidth = (int) BorderPainter.dashWidthCalculator(y2 - y1, thickness); lineDataInfo.setX2 ( lineDataInfo.getX1() ); - lineDataInfo.setY2 ( lineDataInfo.getY1() + thick ); + lineDataInfo.setY2 ( lineDataInfo.getY1() + dashWidth ); int ey2 = Math.round(y2); - while (lineDataInfo.getY1() + thick < ey2) { + int spaceWidth = (int) (BorderPainter.DASHED_BORDER_SPACE_RATIO * dashWidth); + while (lineDataInfo.getY2() < ey2) { dataStream.createLine(lineDataInfo); - lineDataInfo.setY1 ( lineDataInfo.getY1() + 2 * thick ); - lineDataInfo.setY2 ( lineDataInfo.getY1() + thick ); + lineDataInfo.setY1 ( lineDataInfo.getY2() + spaceWidth ); + lineDataInfo.setY2 ( lineDataInfo.getY1() + dashWidth ); } } break; diff --git a/src/java/org/apache/fop/render/intermediate/BorderPainter.java b/src/java/org/apache/fop/render/intermediate/BorderPainter.java index 19e30b50f..d63c4534b 100644 --- a/src/java/org/apache/fop/render/intermediate/BorderPainter.java +++ b/src/java/org/apache/fop/render/intermediate/BorderPainter.java @@ -56,6 +56,11 @@ public class BorderPainter { /** Convention index of bottom-left border corners */ protected static final int BOTTOM_LEFT = 3; + /** The ratio between a solid dash and the white-space in a dashed-border */ + public static final float DASHED_BORDER_SPACE_RATIO = 0.5f; + /** The length of the dash as a factor of the border width i.e. 4 -> dashWidth = 4*borderWidth */ + protected static final float DASHED_BORDER_LENGTH_FACTOR = 4.0f; + private final GraphicsPainter graphicsPainter; public BorderPainter(GraphicsPainter graphicsPainter) { @@ -274,6 +279,21 @@ public class BorderPainter { return bp != null && bp.isCollapseOuter(); } + /** + * This method calculates the length of the "dash" in a dashed border. The dash satisfies the + * condition that corners start on a dash and end with a dash (rather than ending with a white space). + * @param borderLength The length of the border. + * @param borderWidth The width/thickness of the border. + * @param dashSpaceRatio The ratio between dashes and white-space. + * @return returns the length of the dash such that it fits the criteria above. + */ + public static float dashWidthCalculator(float borderLength, float borderWidth) { + float dashWidth = DASHED_BORDER_LENGTH_FACTOR * borderWidth; + int period = (int) ((borderLength - dashWidth) / dashWidth / (1.0f + DASHED_BORDER_SPACE_RATIO)); + period = period < 0 ? 0 : period; + return borderLength / (period * (1.0f + DASHED_BORDER_SPACE_RATIO) + 1.0f); + } + /** TODO merge with drawRectangularBorders? * @param borderRect the border rectangle * @param bpsBefore the border specification on the before side diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphicsPainter.java b/src/java/org/apache/fop/render/pdf/PDFGraphicsPainter.java index ff1ffb5ff..5e0792696 100644 --- a/src/java/org/apache/fop/render/pdf/PDFGraphicsPainter.java +++ b/src/java/org/apache/fop/render/pdf/PDFGraphicsPainter.java @@ -27,6 +27,7 @@ import java.io.IOException; import org.apache.fop.fo.Constants; import org.apache.fop.render.intermediate.ArcToBezierCurveTransformer; import org.apache.fop.render.intermediate.BezierCurvePainter; +import org.apache.fop.render.intermediate.BorderPainter; import org.apache.fop.render.intermediate.GraphicsPainter; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.ColorUtil; @@ -64,25 +65,15 @@ public class PDFGraphicsPainter implements GraphicsPainter, BezierCurvePainter { case Constants.EN_DASHED: generator.setColor(col); if (horz) { - float unit = Math.abs(2 * h); - int rep = (int) (w / unit); - if (rep % 2 == 0) { - rep++; - } - unit = w / rep; + float dashedWidth = BorderPainter.dashWidthCalculator(w, h); float ym = y1 + (h / 2); - generator.setDashLine(unit) + generator.setDashLine(dashedWidth, dashedWidth * BorderPainter.DASHED_BORDER_SPACE_RATIO) .setLineWidth(h) .strokeLine(x1, ym, x2, ym); } else { - float unit = Math.abs(2 * w); - int rep = (int) (h / unit); - if (rep % 2 == 0) { - rep++; - } - unit = h / rep; + float dashedWidth = BorderPainter.dashWidthCalculator(h, w); float xm = x1 + (w / 2); - generator.setDashLine(unit) + generator.setDashLine(dashedWidth, dashedWidth * BorderPainter.DASHED_BORDER_SPACE_RATIO) .setLineWidth(w) .strokeLine(xm, y1, xm, y2); } diff --git a/src/java/org/apache/fop/render/ps/PSGraphicsPainter.java b/src/java/org/apache/fop/render/ps/PSGraphicsPainter.java index ab766f701..9152d0937 100644 --- a/src/java/org/apache/fop/render/ps/PSGraphicsPainter.java +++ b/src/java/org/apache/fop/render/ps/PSGraphicsPainter.java @@ -31,6 +31,7 @@ import org.apache.xmlgraphics.ps.PSGenerator; import org.apache.fop.fo.Constants; import org.apache.fop.render.intermediate.ArcToBezierCurveTransformer; import org.apache.fop.render.intermediate.BezierCurvePainter; +import org.apache.fop.render.intermediate.BorderPainter; import org.apache.fop.render.intermediate.GraphicsPainter; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.ColorUtil; @@ -87,25 +88,17 @@ public class PSGraphicsPainter implements GraphicsPainter, BezierCurvePainter { case Constants.EN_DASHED: gen.useColor(col); if (horz) { - float unit = Math.abs(2 * h); - int rep = (int) (w / unit); - if (rep % 2 == 0) { - rep++; - } - unit = w / rep; - gen.useDash("[" + unit + "] 0"); + float dashWidth = BorderPainter.dashWidthCalculator(w, h); + gen.useDash("[" + dashWidth + " " + BorderPainter.DASHED_BORDER_SPACE_RATIO + * dashWidth + "] 0"); gen.useLineCap(0); gen.useLineWidth(h); float ym = y1 + (h / 2); drawLine(gen, x1, ym, x2, ym); } else { - float unit = Math.abs(2 * w); - int rep = (int) (h / unit); - if (rep % 2 == 0) { - rep++; - } - unit = h / rep; - gen.useDash("[" + unit + "] 0"); + float dashWidth = BorderPainter.dashWidthCalculator(h, w); + gen.useDash("[" + dashWidth + " " + BorderPainter.DASHED_BORDER_SPACE_RATIO + * dashWidth + "] 0"); gen.useLineCap(0); gen.useLineWidth(w); float xm = x1 + (w / 2); diff --git a/status.xml b/status.xml index e08a24372..f6cb335f6 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,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="Code" dev="MH" type="add" fixes-bug="45822"> + Changed the dashed borders to appear more like dashes and less like dots + </action> <action context="Code" dev="PH" type="add" fixes-bug="54041"> Added support for Rounded Corners on block areas. </action> diff --git a/test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java b/test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java index ab5c18c9e..f0e9522d9 100644 --- a/test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java +++ b/test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java @@ -23,10 +23,6 @@ import java.io.IOException; import org.junit.Test; -import org.apache.fop.fo.Constants; -import org.apache.fop.traits.BorderProps; -import org.apache.fop.traits.BorderProps.Mode; - import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doThrow; @@ -36,6 +32,10 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import org.apache.fop.fo.Constants; +import org.apache.fop.traits.BorderProps; +import org.apache.fop.traits.BorderProps.Mode; + public class BorderPainterTestCase { private static final BorderProps BORDER_PROPS = new BorderProps(Constants.EN_SOLID, 10, 50, 50, diff --git a/test/java/org/apache/fop/render/pdf/PDFBorderPainterTestCase.java b/test/java/org/apache/fop/render/pdf/PDFBorderPainterTestCase.java new file mode 100644 index 000000000..5acad9837 --- /dev/null +++ b/test/java/org/apache/fop/render/pdf/PDFBorderPainterTestCase.java @@ -0,0 +1,47 @@ +package org.apache.fop.render.pdf; + +import java.awt.Color; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +import org.apache.fop.fo.Constants; +import org.apache.fop.pdf.PDFDocument; + +public class PDFBorderPainterTestCase { + + private PDFContentGenerator generator; + private ByteArrayOutputStream outStream; + private PDFGraphicsPainter borderPainter; + + @Before + public void setUp() { + outStream = new ByteArrayOutputStream(); + generator = new PDFContentGenerator(new PDFDocument("test"), outStream, null); + borderPainter = new PDFGraphicsPainter(generator); + } + + /** + * This test will fail if either of the below statements isn't true: + * org.apache.fop.render.intermediate.BorderPainter.DASHED_BORDER_SPACE_RATIO = 0.5f:q + * org.apache.fop.render.intermediate.BorderPainter.DASHED_BORDER_LENGTH_FACTOR = 4.0f. + */ + @Test + public void testDrawBorderLine() throws Exception { + borderPainter.drawBorderLine(0, 0, 40000, 1000, true, true, + Constants.EN_DASHED, Color.BLACK); + generator.flushPDFDoc(); + OutputStream outStream = new ByteArrayOutputStream(); + outStream = generator.getStream().getBufferOutputStream(); + assertTrue(((ByteArrayOutputStream) outStream).toString().contains("[4 2] 0 d 1 w")); + } + + public void tearDown() { + generator = null; + outStream= null; + } +} diff --git a/test/java/org/apache/fop/render/ps/PSBorderPainterTestCase.java b/test/java/org/apache/fop/render/ps/PSBorderPainterTestCase.java new file mode 100644 index 000000000..1ffe87982 --- /dev/null +++ b/test/java/org/apache/fop/render/ps/PSBorderPainterTestCase.java @@ -0,0 +1,44 @@ +package org.apache.fop.render.ps; + +import java.awt.Color; +import java.io.ByteArrayOutputStream; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +import org.apache.xmlgraphics.ps.PSGenerator; + +import org.apache.fop.fo.Constants; + +public class PSBorderPainterTestCase { + + private PSGenerator generator; + private ByteArrayOutputStream outStream; + private PSGraphicsPainter borderPainter; + + @Before + public void setUp() { + outStream = new ByteArrayOutputStream(); + generator = new PSGenerator(outStream); + borderPainter = new PSGraphicsPainter(generator); + } + + /** + * This test will fail if either of the below statements isn't true: + * org.apache.fop.render.intermediate.BorderPainter.DASHED_BORDER_SPACE_RATIO = 0.5f:q + * org.apache.fop.render.intermediate.BorderPainter.DASHED_BORDER_LENGTH_FACTOR = 4.0f. + */ + @Test + public void testDrawBorderLine() throws Exception { + borderPainter.drawBorderLine(0, 0, 40000, 1000, true, true, + Constants.EN_DASHED, Color.BLACK); + assertTrue(outStream.toString().contains("[4.0 2.0] 0 setdash")); + } + + public void tearDown() { + generator = null; + outStream= null; + } +} |