Index: test/java/org/apache/fop/render/ps/PSBorderPainterTest.java
===================================================================
--- test/java/org/apache/fop/render/ps/PSBorderPainterTest.java	(revision 0)
+++ test/java/org/apache/fop/render/ps/PSBorderPainterTest.java	(revision 0)
@@ -0,0 +1,69 @@
+package org.apache.fop.render.ps;
+
+import java.awt.Color;
+import java.io.ByteArrayOutputStream;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.render.intermediate.BorderPainterTestCase;
+import org.apache.xmlgraphics.ps.PSGenerator;
+
+public class PSBorderPainterTest extends BorderPainterTestCase {
+    
+    private PSGenerator generator;
+    private ByteArrayOutputStream outStream;
+    private PSBorderPainter borderPainter;
+    
+    public PSBorderPainterTest(String name) {
+        super(name);
+    }
+    
+    public void setUp() {
+        outStream = new ByteArrayOutputStream();
+        generator = new PSGenerator(outStream);
+        borderPainter = new PSBorderPainter(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.
+     */
+    public void testDrawBorderLine() throws Exception {
+        borderPainter.drawBorderLine(0, 0, 40000, 1000, true, true,
+                Constants.EN_DASHED, Color.BLACK);      
+        assertTrue(((ByteArrayOutputStream) outStream).toString().contains("[4.0 2.0] 0 setdash"));
+    }
+
+    public void testDrawLine() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testMoveTo() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testLineTo() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testClosePath() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testClip() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testSaveGfxState() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testRestoreGfxState() {
+        // TODO Auto-generated method stub
+    }
+    
+    public void tearDown() {
+        generator = null;
+        outStream= null;
+    }
+}
Index: test/java/org/apache/fop/render/pdf/PDFBorderPainterTest.java
===================================================================
--- test/java/org/apache/fop/render/pdf/PDFBorderPainterTest.java	(revision 0)
+++ test/java/org/apache/fop/render/pdf/PDFBorderPainterTest.java	(revision 0)
@@ -0,0 +1,73 @@
+package org.apache.fop.render.pdf;
+
+import java.awt.Color;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.render.intermediate.BorderPainterTestCase;
+
+public class PDFBorderPainterTest extends BorderPainterTestCase {
+    
+    private PDFContentGenerator generator;
+    private ByteArrayOutputStream outStream;
+    private PDFBorderPainter borderPainter;
+    
+    public PDFBorderPainterTest(String name) {
+        super(name);
+    }
+    
+    public void setUp() {
+        outStream = new ByteArrayOutputStream();
+        generator = new PDFContentGenerator(new PDFDocument("test"), outStream, null);
+        borderPainter = new PDFBorderPainter(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.
+     */
+    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 testDrawLine() {
+        // TODO Auto-generated method stub        
+    }
+
+    public void testMoveTo() {
+        // TODO Auto-generated method stub        
+    }
+
+    public void testLineTo() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testClosePath() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testClip() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testSaveGfxState() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testRestoreGfxState() {
+        // TODO Auto-generated method stub
+    }
+    
+    public void tearDown() {
+        generator = null;
+        outStream= null;
+    }
+}
Index: test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java
===================================================================
--- test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java	(revision 0)
+++ test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java	(revision 0)
@@ -0,0 +1,62 @@
+package org.apache.fop.render.intermediate;
+
+import junit.framework.TestCase;
+
+/**
+ * An abstract JUnit class used to test test org.apache.fop.render.intermediate.BorderPainter.java
+ *
+ */
+public abstract class BorderPainterTestCase extends TestCase {
+    
+    public BorderPainterTestCase(String name) {
+        super(name);
+    }
+    
+    public void setUp() {
+        // Currently unused.
+    }
+    
+    public void testDrawBorders() {
+        assertTrue(true);
+    }
+    
+    /**
+     * This test relies upon BorderPainter.DASHED_BORDER_SPACE_RATIO = 0.5f and
+     * BorderPainter.DASHED_BORDER_LENGTH_FACTOR = 2.0f. If these values are changed, the test
+     * will necessarily fail.
+     */
+    public void testDashWidthCalc() {
+        // if the height is 1 and the width is 5, the width should be 2 (this tests a nice round case)
+        assertEquals("Dash-Border dashWidthCalculator fails the first test", 8.0f,
+                BorderPainter.dashWidthCalculator(20.0f, 2.0f), 0.0f);
+        
+        // if the height is 2 and the width is 50, the width should be 100/69
+        float testValue = 100.0f / 11.0f;
+        assertEquals("Dash-Border dashWidthCalculator fails the second test", testValue, 
+                BorderPainter.dashWidthCalculator(50.0f, 2.0f), 0.0f);
+    }
+    
+    /**
+     * This should test each type of border i.e. solid, dashed, dotted etc...
+     * @throws Exception
+     */
+    public abstract void testDrawBorderLine() throws Exception;
+    
+    public abstract void testDrawLine();
+    
+    public abstract void testMoveTo();
+    
+    public abstract void testLineTo();
+    
+    public abstract void testClosePath();
+    
+    public abstract void testClip();
+    
+    public abstract void testSaveGfxState();
+    
+    public abstract void testRestoreGfxState();
+    
+    public void tearDown() {
+        // Currently unused.
+    }
+}
Index: test/java/org/apache/fop/afp/AFPBorderPainterTest.java
===================================================================
--- test/java/org/apache/fop/afp/AFPBorderPainterTest.java	(revision 0)
+++ test/java/org/apache/fop/afp/AFPBorderPainterTest.java	(revision 0)
@@ -0,0 +1,120 @@
+package org.apache.fop.afp;
+
+import java.awt.Color;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.render.intermediate.BorderPainterTestCase;
+
+public class AFPBorderPainterTest extends BorderPainterTestCase {
+    
+    private AFPBorderPainter painter;
+    private DataStream dataStream;
+    private ByteArrayOutputStream outputStream;
+    private AFPUnitConverter unitConv;
+    private AFPPaintingState paintState;
+    
+    public void setUp() {
+        paintState = new AFPPaintingState();
+        unitConv = paintState.getUnitConverter();
+        outputStream = new ByteArrayOutputStream();
+        dataStream = new DataStream(new Factory(), paintState, outputStream);
+        painter = new AFPBorderPainter(paintState, dataStream);
+        unitConv = new AFPUnitConverter(paintState);
+        
+        int pageWidth = Math.round(unitConv.mpt2units(100000));
+        int pageHeight = Math.round(unitConv.mpt2units(100000));
+        int pageRotation = paintState.getRotation();
+        int resolution = paintState.getResolution();
+        
+        try {
+            dataStream.startDocument();
+            dataStream.startPage(pageWidth, pageHeight, pageRotation, resolution, resolution);
+        } catch (IOException ex) {
+            fail("Threw an IOException when performing dataStream.StartDocument() in AFPBorderPainterTest");
+        }
+        
+    }
+
+    public AFPBorderPainterTest(String name) {
+        super(name);
+    }
+    
+    public void testDrawBorderLine() throws Exception {
+        testDrawSolidBorderLine();
+    }
+
+    public void testDrawSolidBorderLine() throws Exception {
+        int x1 = 0; 
+        int y1 = 0;
+        int x2 = 20000;
+        int y2 = 1000;
+        painter.drawBorderLine(x1, y1, x2, y2, true, true, Constants.EN_SOLID, Color.BLACK);
+        dataStream.endPage();
+        dataStream.endDocument();
+        byte[] outputBytes = outputStream.toByteArray();
+        int startIndex = AFPUtils.getSubsetIndex(outputBytes, AFPUtils.PTX_DATA_CODE);
+        int endIndex = AFPUtils.getSubsetIndex(outputBytes, AFPUtils.PTX_END_CODE);
+        endIndex += AFPUtils.PTX_END_CODE.length;
+        
+        byte[] expectedBytes = Arrays.copyOfRange(outputBytes, startIndex, endIndex);
+        
+        ByteArrayOutputStream testBytes = new ByteArrayOutputStream();
+        
+        testBytes.write(AFPUtils.setupPTX());
+        testBytes.write(AFPUtils.drawLine(
+                Math.round(unitConv.mpt2units(x1)), // x1 co-ord
+                Math.round(unitConv.mpt2units(y1)), // y1 co-ord
+                Math.round(unitConv.mpt2units(x2)), // x2 co-ord
+                Math.round(unitConv.mpt2units(y2))));//y2 co-ord
+        testBytes.write(AFPUtils.endPTX());
+        
+        assertEqualsByteArray("test", testBytes.toByteArray(), expectedBytes);
+    }
+    
+    private static void assertEqualsByteArray(String str, byte[] expected, byte[] actual) {
+        if (!Arrays.equals(expected, actual)) {
+            assertEquals(str, AFPUtils.byteArrayToString(expected, true), 
+                    AFPUtils.byteArrayToString(actual, true));
+        }
+    }
+    
+    public void tearDown() {
+        paintState = null;
+        unitConv = null;
+        outputStream = null;
+        dataStream = null;
+        painter = null;
+        unitConv = null;
+    }
+
+    public void testDrawLine() {
+        // TODO Auto-generated method stub        
+    }
+
+    public void testMoveTo() {
+        // TODO Auto-generated method stub        
+    }
+
+    public void testLineTo() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testClosePath() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testClip() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testSaveGfxState() {
+        // TODO Auto-generated method stub
+    }
+
+    public void testRestoreGfxState() {
+        // TODO Auto-generated method stub
+    }
+}
Index: test/java/org/apache/fop/afp/AFPUtils.java
===================================================================
--- test/java/org/apache/fop/afp/AFPUtils.java	(revision 0)
+++ test/java/org/apache/fop/afp/AFPUtils.java	(revision 0)
@@ -0,0 +1,206 @@
+package org.apache.fop.afp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.fop.afp.modca.AbstractAFPObject;
+import org.apache.fop.afp.ptoca.PtocaConstants;
+
+import com.sun.corba.se.impl.ior.ByteBuffer;
+import com.sun.org.apache.xml.internal.security.Init;
+import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader.Array;
+
+/**
+ * This is a utility class for AFP (or other formats) to assist with testing. This differs from
+ * org.apache.fop.afp.util.BinaryUtils in that these are intended for speed and easy to read 
+ * outputs. This class is intended for testing ONLY. This class inherits from AbstractAFPObject
+ * and PtocaConstants merely to take advantage to the static variables and circumvent the access
+ * modifiers.
+ */
+public class AFPUtils extends AbstractAFPObject implements PtocaConstants {
+    
+    /** AFP - Presentation Text Object Begin byte code */
+    public static final byte[] PTX_BEGIN_CODE =
+    { SF_CLASS, Type.BEGIN, Category.PRESENTATION_TEXT };
+    /** AFP - Presentation Text Object Data byte code */
+    public static final byte[] PTX_DATA_CODE = 
+    { SF_CLASS, Type.DATA, Category.PRESENTATION_TEXT };
+    /** AFP - Presentation Text Object End byte code */
+    public static final byte[] PTX_END_CODE = 
+    { SF_CLASS, Type.END, Category.PRESENTATION_TEXT };
+    // All of the actions are in a chained sequence thus the | 0x01
+    /** AFP - Absolute Move Baseline byte code */
+    public static final byte[] AMB_CODE = { (byte) 0x04, AMB | 0x01 };
+    /** AFP - Absolute Move In-line byte code */
+    public static final byte[] AMI_CODE = { (byte) 0x04, AMI | 0x01 };
+    /** AFP - Draw In-line-axis Rule byte code */
+    public static final byte[] DIR_CODE = {(byte) 0x07, DIR | 0x01 };
+    /** AFP - Draw Baseline-axis Rule byte code */
+    public static final byte[] DBR_CODE = {(byte) 0x07, DBR | 0x01 };
+    
+    /**
+     * Converts a byte[] to a String. This also separates each byte with a whitespace to make
+     * the output easy to read.
+     * @param byteArray
+     * @return
+     */
+    public static String byteArrayToString(byte[] byteArray, boolean trim) {
+        StringBuffer strBuffer = new StringBuffer();
+        for (byte b : byteArray) {
+            strBuffer.append(byteToString(b));
+            strBuffer.append(" ");
+        }
+        return trim ? strBuffer.toString().trim() : strBuffer.toString();
+    }
+    
+    /**
+     * Converts a single byte to a String.
+     * @param b
+     * @return
+     */
+    public static String byteToString(byte b) {
+        Integer currentByte = (b & 0xFF) + 0x100;
+        return Integer.toString(currentByte, 16).substring(1);
+    }
+    
+    /**
+     * Converts an int into 2 Bytes (short) String, this is necessary in order to write
+     * many of the parameters to AFP format.
+     * @param number This only accepts positive values.
+     * @return
+     * @throws IllegalArgumentException
+     */
+    public static byte[] intToTwoBytes(int number) throws IllegalArgumentException {
+        if (number < 0) {
+            throw new IllegalArgumentException("You attempted to turn a negative int into a " +
+            		"byte, AFP doesn't support negative ints.");
+        }
+        return new byte[] { (byte) (number >>> 8),
+                            (byte) (number) };
+    }
+    
+    /**
+     * Setup a Presentation Text Object and start a chain sequence.
+     * @return
+     * @throws IOException
+     */
+    public static byte[] setupPTX() throws IOException {
+        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+        byteArray.write(PTX_DATA_CODE);
+        // there are 3 reserved bytes
+        byteArray.write(new byte [] {(byte) 0x00, (byte) 0x00, (byte) 0x00});
+        // This starts a chained sequence i.e. prevents us from having to specify the
+        // class and type for every subsequent action (AMI, AMB, DIR etc..)
+        byteArray.write(startChainSequence());
+        return byteArray.toByteArray();
+    }
+    
+    /**
+     * End a Presentation Text Object and close the chain sequence.
+     * @return
+     * @throws IOException
+     */
+    public static byte[] endPTX() throws IOException {
+        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+        byteArray.write(closeChainSequence());
+        byteArray.write(new byte[] {(byte)0x5A, (byte)0x00, (byte)0x10});
+        byteArray.write(PTX_END_CODE);
+        return byteArray.toByteArray();
+    }
+    
+    /**
+     * Start a chain sequence by writing the returned byte[].
+     * @return
+     */
+    public static byte[] startChainSequence() {
+        return ESCAPE;
+    }
+    
+    /**
+     * End a chain sequence by writing the returned byte[].
+     * @return
+     */
+    public static byte[] closeChainSequence() {
+        return new byte[] {(byte)0x02, (byte)NOP };
+    }
+    
+    /**
+     * This method returns the index of an array that contains a subset. For example:
+     * if byteArray = {0x01,0x01,0x02,0x03,0x04,0x05,0x05}
+     * and subset   =           {0x02,0x03,0x04} the returned value would be 2, the index at which
+     * the subset begins in the byteArray. Returns -1 if byteArray does not contain subset.
+     * @param byteArray
+     * @param subset
+     * @return
+     */
+    public static int getSubsetIndex(byte[] byteArray, byte[] subset) {
+        byte[] window = new byte[subset.length];
+        int winIndex = 0;
+        int lastSameIndex = -1; //using -1 as a null value
+        for (int i = 0; i < byteArray.length; i++) {
+            window[winIndex] = byteArray[i];
+            if (i < subset.length) {
+                winIndex = incrementIndex(winIndex, subset.length);
+                continue;
+            }
+            int tempIndex = 
+                lastSameIndex > 0 ? lastSameIndex : incrementIndex(winIndex, subset.length);
+            
+            for (int j = 0; j < subset.length; j++) {
+                if (window[tempIndex] != subset[j]) {
+                    lastSameIndex = -1;
+                    break;
+                } else if (j == subset.length - 1) {
+                    return i - j;
+                }
+                lastSameIndex = 
+                    lastSameIndex >= 0 ? lastSameIndex : incrementIndex(winIndex, subset.length);
+                tempIndex = incrementIndex(tempIndex, subset.length);
+            }
+            winIndex = incrementIndex(winIndex, subset.length);
+        }
+        return -1;
+    }
+    
+    private static int incrementIndex(int index, int maxValue) {
+        return index >= maxValue - 1 ? 0 : ++index;
+    }
+
+    
+    /**
+     * Draws a line in AFP format given the necessary coordinates.
+     * @param x1
+     * @param y1
+     * @param x2
+     * @param y2
+     * @return
+     */
+    public static byte[] drawLine(int x1, int y1, int x2, int y2) throws IOException {
+        int lineLength = Math.abs(x2 - x1);
+        int lineWidth = Math.abs(y2 - y1);
+        
+        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+        // Position the cursor at y1
+        byteArray.write(AMB_CODE); byteArray.write(intToTwoBytes(y1));
+        // Position the cursor at x1
+        byteArray.write(AMI_CODE); byteArray.write(intToTwoBytes(x1));
+        // Draw In-line (and Baseline) have 1 reserved byte at the end.
+        byteArray.write(DIR_CODE); 
+        // line length parameter
+        byteArray.write(intToTwoBytes(lineLength));
+        // line width + reserved byte
+        byteArray.write(intToTwoBytes(lineWidth)); byteArray.write((byte) 0x00);
+        return byteArray.toByteArray();
+    }
+
+    /**
+     * Not currently supported for this test class.
+     */
+    public void writeToStream(OutputStream os) throws IOException {
+        throw new UnsupportedOperationException("writeToStream isn't supported by this test class");        
+    }
+}
Index: status.xml
===================================================================
--- status.xml	(revision 1026998)
+++ status.xml	(working copy)
@@ -58,9 +58,6 @@
       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="JM" type="add" fixes-bug="42600" due-to="Maximilian Aster">
-        Added some support for break-before/-after for RTF output.
-      </action>
       <action context="Renderers" dev="JM" type="add" fixes-bug="49379" due-to="Peter Hancock">
         Added ability to embed an external AFP page segment resource file (AFP output only).
       </action>
Index: src/java/org/apache/fop/render/intermediate/BorderPainter.java
===================================================================
--- src/java/org/apache/fop/render/intermediate/BorderPainter.java	(revision 1026998)
+++ src/java/org/apache/fop/render/intermediate/BorderPainter.java	(working copy)
@@ -31,7 +31,12 @@
  * This is an abstract base class for handling border painting.
  */
 public abstract class BorderPainter {
-
+    
+    // The ratio between a solid dash and the white-space in a dashed-border
+    protected 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;
+    
     /**
      * Draws borders.
      * @param borderRect the border rectangle
@@ -199,9 +204,23 @@
             restoreGraphicsState();
         }
     }
-
-
+    
     /**
+     * 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.
+     */
+    protected 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);
+    }
+    
+    /**
      * Draws a border line.
      * @param x1 X coordinate of the upper left corner
      *                  of the line's bounding rectangle (in millipoints)
Index: src/java/org/apache/fop/render/ps/PSBorderPainter.java
===================================================================
--- src/java/org/apache/fop/render/ps/PSBorderPainter.java	(revision 1026998)
+++ src/java/org/apache/fop/render/ps/PSBorderPainter.java	(working copy)
@@ -34,7 +34,7 @@
 import org.apache.fop.util.ColorUtil;
 
 /**
- * PostScript-specific implementation of the {@link BorderPainter}.
+ * PostScript-specific implementation of the {@link AdobeBorderPainter}.
  */
 public class PSBorderPainter extends BorderPainter {
 
@@ -86,25 +86,15 @@
             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 = dashWidthCalculator(w, h);
+                    gen.useDash("[" + dashWidth + " " + 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 = dashWidthCalculator(h, w);
+                    gen.useDash("[" + dashWidth + " " + DASHED_BORDER_SPACE_RATIO * dashWidth + "] 0");
                     gen.useLineCap(0);
                     gen.useLineWidth(w);
                     float xm = x1 + (w / 2);
Index: src/java/org/apache/fop/render/afp/AFPPainter.java
===================================================================
--- src/java/org/apache/fop/render/afp/AFPPainter.java	(revision 1026998)
+++ src/java/org/apache/fop/render/afp/AFPPainter.java	(working copy)
@@ -38,8 +38,6 @@
 import org.apache.fop.afp.AFPBorderPainter;
 import org.apache.fop.afp.AFPPaintingState;
 import org.apache.fop.afp.AFPUnitConverter;
-import org.apache.fop.afp.AbstractAFPPainter;
-import org.apache.fop.afp.BorderPaintingInfo;
 import org.apache.fop.afp.DataStream;
 import org.apache.fop.afp.RectanglePaintingInfo;
 import org.apache.fop.afp.fonts.AFPFont;
@@ -57,7 +55,6 @@
 import org.apache.fop.fonts.FontTriplet;
 import org.apache.fop.render.RenderingContext;
 import org.apache.fop.render.intermediate.AbstractIFPainter;
-import org.apache.fop.render.intermediate.BorderPainter;
 import org.apache.fop.render.intermediate.IFContext;
 import org.apache.fop.render.intermediate.IFException;
 import org.apache.fop.render.intermediate.IFState;
@@ -79,9 +76,7 @@
     private AFPDocumentHandler documentHandler;
 
     /** the border painter */
-    private AFPBorderPainterAdapter borderPainter;
-    /** the rectangle painter */
-    private AbstractAFPPainter rectanglePainter;
+    private AFPBorderPainter borderPainter;
 
     /** unit converter */
     private final AFPUnitConverter unitConv;
@@ -94,9 +89,7 @@
         super();
         this.documentHandler = documentHandler;
         this.state = IFState.create();
-        this.borderPainter = new AFPBorderPainterAdapter(
-                new AFPBorderPainter(getPaintingState(), getDataStream()));
-        this.rectanglePainter = documentHandler.createRectanglePainter();
+        this.borderPainter = new AFPBorderPainter(getPaintingState(), getDataStream());
         this.unitConv = getPaintingState().getUnitConverter();
     }
 
@@ -247,11 +240,7 @@
             }
             RectanglePaintingInfo rectanglePaintInfo = new RectanglePaintingInfo(
                     toPoint(rect.x), toPoint(rect.y), toPoint(rect.width), toPoint(rect.height));
-            try {
-                rectanglePainter.paint(rectanglePaintInfo);
-            } catch (IOException ioe) {
-                throw new IFException("IO error while painting rectangle", ioe);
-            }
+                borderPainter.paint(rectanglePaintInfo);
         }
     }
 
@@ -267,69 +256,6 @@
         }
     }
 
-    //TODO Try to resolve the name-clash between the AFPBorderPainter in the afp package
-    //and this one. Not done for now to avoid a lot of re-implementation and code duplication.
-    private static class AFPBorderPainterAdapter extends BorderPainter {
-
-        private AFPBorderPainter delegate;
-
-        public AFPBorderPainterAdapter(AFPBorderPainter borderPainter) {
-            this.delegate = borderPainter;
-        }
-
-        protected void clip() throws IOException {
-            //not supported by AFP
-        }
-
-        protected void closePath() throws IOException {
-            //used for clipping only, so not implemented
-        }
-
-        protected void moveTo(int x, int y) throws IOException {
-            //used for clipping only, so not implemented
-        }
-
-        protected void lineTo(int x, int y) throws IOException {
-            //used for clipping only, so not implemented
-        }
-
-        protected void saveGraphicsState() throws IOException {
-            //used for clipping only, so not implemented
-        }
-
-        protected void restoreGraphicsState() throws IOException {
-            //used for clipping only, so not implemented
-        }
-
-        private float toPoints(int mpt) {
-            return mpt / 1000f;
-        }
-
-        protected void drawBorderLine(                           // CSOK: ParameterNumber
-                int x1, int y1, int x2, int y2, boolean horz,
-                boolean startOrBefore, int style, Color color) throws IOException {
-            BorderPaintingInfo borderPaintInfo = new BorderPaintingInfo(
-                    toPoints(x1), toPoints(y1), toPoints(x2), toPoints(y2),
-                    horz, style, color);
-            delegate.paint(borderPaintInfo);
-        }
-
-        public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
-                throws IOException {
-            if (start.y != end.y) {
-                //TODO Support arbitrary lines if necessary
-                throw new UnsupportedOperationException(
-                        "Can only deal with horizontal lines right now");
-            }
-
-            //Simply delegates to drawBorderLine() as AFP line painting is not very sophisticated.
-            int halfWidth = width / 2;
-            drawBorderLine(start.x, start.y - halfWidth, end.x, start.y + halfWidth,
-                    true, true, style.getEnumValue(), color);
-        }
-
-    }
-
     /** {@inheritDoc} */
     public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
                 throws IFException {
Index: src/java/org/apache/fop/render/pdf/PDFBorderPainter.java
===================================================================
--- src/java/org/apache/fop/render/pdf/PDFBorderPainter.java	(revision 1026998)
+++ src/java/org/apache/fop/render/pdf/PDFBorderPainter.java	(working copy)
@@ -32,10 +32,10 @@
 import org.apache.fop.util.ColorUtil;
 
 /**
- * PDF-specific implementation of the {@link BorderPainter}.
+ * PDF-specific implementation of the {@link AdobeBorderPainter}.
  */
 public class PDFBorderPainter extends BorderPainter {
-
+    
     /** logging instance */
     private static final Log LOG = LogFactory.getLog(PDFBorderPainter.class);
 
@@ -77,25 +77,17 @@
             case Constants.EN_DASHED:
                 generator.setColor(col, false);
                 if (horz) {
-                    float unit = Math.abs(2 * h);
-                    int rep = (int)(w / unit);
-                    if (rep % 2 == 0) {
-                        rep++;
-                    }
-                    unit = w / rep;
-                    generator.add("[" + format(unit) + "] 0 d ");
+                    float dashWidth = dashWidthCalculator(w, h);
+                    generator.add("[" + format(dashWidth) + " " + 
+                            format(dashWidth * DASHED_BORDER_SPACE_RATIO)+ "] 0 d ");
                     generator.add(format(h) + " w\n");
                     float ym = y1 + (h / 2);
                     generator.add(format(x1) + " " + format(ym) + " m "
-                            + format(x2) + " " + format(ym) + " l S\n");
+                           + format(x2) + " " + format(ym) + " l S\n");
                 } else {
-                    float unit = Math.abs(2 * w);
-                    int rep = (int)(h / unit);
-                    if (rep % 2 == 0) {
-                        rep++;
-                    }
-                    unit = h / rep;
-                    generator.add("[" + format(unit) + "] 0 d ");
+                    float dashWidth = dashWidthCalculator(h, w);
+                    generator.add("[" + format(dashWidth) + " " + 
+                            format(dashWidth * DASHED_BORDER_SPACE_RATIO) + "] 0 d ");
                     generator.add(format(w) + " w\n");
                     float xm = x1 + (w / 2);
                     generator.add(format(xm) + " " + format(y1) + " m "
Index: src/java/org/apache/fop/afp/AFPBorderPainter.java
===================================================================
--- src/java/org/apache/fop/afp/AFPBorderPainter.java	(revision 1026998)
+++ src/java/org/apache/fop/afp/AFPBorderPainter.java	(working copy)
@@ -19,16 +19,30 @@
 
 package org.apache.fop.afp;
 
+import java.awt.Color;
+import java.awt.Point;
 import java.awt.geom.AffineTransform;
+import java.io.IOException;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.fop.fo.Constants;
+import org.apache.fop.render.intermediate.BorderPainter;
+import org.apache.fop.traits.RuleStyle;
 import org.apache.fop.util.ColorUtil;
 
 /**
  * Handles the drawing of borders/lines in AFP
  */
-public class AFPBorderPainter extends AbstractAFPPainter {
-
+public class AFPBorderPainter extends BorderPainter {
+    
+    /** Static logging instance */
+    private final static Log LOG = LogFactory.getLog(AFPBorderPainter.class);
+    /** data stream */
+    private final DataStream dataStream;
+    /** painting state */
+    private final AFPPaintingState paintingState;
+    
     /**
      * Main constructor
      *
@@ -36,7 +50,8 @@
      * @param dataStream the AFP datastream
      */
     public AFPBorderPainter(AFPPaintingState paintingState, DataStream dataStream) {
-        super(paintingState, dataStream);
+        this.paintingState = paintingState;
+        this.dataStream = dataStream;
     }
 
     /** {@inheritDoc} */
@@ -45,7 +60,7 @@
         float w = borderPaintInfo.getX2() - borderPaintInfo.getX1();
         float h = borderPaintInfo.getY2() - borderPaintInfo.getY1();
         if ((w < 0) || (h < 0)) {
-            log.error("Negative extent received. Border won't be painted.");
+            LOG.error("Negative extent received. Border won't be painted.");
             return;
         }
 
@@ -58,6 +73,7 @@
         float y1 = unitConv.pt2units(borderPaintInfo.getY1());
         float x2 = unitConv.pt2units(borderPaintInfo.getX2());
         float y2 = unitConv.pt2units(borderPaintInfo.getY2());
+        
 
         switch (paintingState.getRotation()) {
         default:
@@ -126,24 +142,25 @@
             }
             break;
         case Constants.EN_DASHED:
-            int thick = lineDataInfo.getThickness() * 3;
             if (borderPaintInfo.isHorizontal()) {
-                lineDataInfo.setX2 ( lineDataInfo.getX1() + thick );
+                int dashWidth = (int) (dashWidthCalculator(x2 - x1, thickness));
+                lineDataInfo.setX2 ( lineDataInfo.getX1() + dashWidth );
                 lineDataInfo.setY2 ( lineDataInfo.getY1() );
                 int ex2 = Math.round(x2);
-                while (lineDataInfo.getX1() + thick < ex2) {
+                while (lineDataInfo.getX2() < ex2) {
                     dataStream.createLine(lineDataInfo);
-                    lineDataInfo.setX1 ( lineDataInfo.getX1() + 2 * thick );
-                    lineDataInfo.setX2 ( lineDataInfo.getX1() + thick );
+                    lineDataInfo.setX1 ( lineDataInfo.getX2() + (int) (DASHED_BORDER_SPACE_RATIO * dashWidth) );
+                    lineDataInfo.setX2 ( lineDataInfo.getX1() + dashWidth );
                 }
             } else {
+                int dashWidth = (int) 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) {
+                while (lineDataInfo.getY2() < ey2) {
                     dataStream.createLine(lineDataInfo);
-                    lineDataInfo.setY1 ( lineDataInfo.getY1() + 2 * thick );
-                    lineDataInfo.setY2 ( lineDataInfo.getY1() + thick );
+                    lineDataInfo.setY1 ( lineDataInfo.getY2() + (int) (DASHED_BORDER_SPACE_RATIO * dashWidth) );
+                    lineDataInfo.setY2 ( lineDataInfo.getY1() + dashWidth );
                 }
             }
             break;
@@ -209,5 +226,60 @@
             dataStream.createLine(lineDataInfo);
         }
     }
+    
+    private float toPoints(int mpt) {
+        return mpt / 1000f;
+    }
 
+    protected void drawBorderLine(int x1, int y1, int x2, int y2, boolean horz,
+            boolean startOrBefore, int style, Color color) throws IOException {
+        BorderPaintingInfo borderPaintInfo = new BorderPaintingInfo(toPoints(x1), toPoints(y1),
+                toPoints(x2), toPoints(y2), horz, style, color);
+        paint(borderPaintInfo);
+        
+    }
+
+    public void drawLine(Point start, Point end, int width, Color color,
+            RuleStyle style) throws IOException {
+        if (start.y != end.y) {
+            //TODO Support arbitrary lines if necessary
+            throw new UnsupportedOperationException(
+                    "Can only deal with horizontal lines right now");
+        }
+        
+        //Simply delegates to drawBorderLine(...) as AFP line painting is not very sophisticated.
+        int halfWidth = width / 2;
+        drawBorderLine(start.x, start.y - halfWidth, end.x, start.y + halfWidth,
+                true, true, style.getEnumValue(), color);
+    }
+
+    protected void moveTo(int x, int y) throws IOException {
+        // used for clipping only, so not implemented
+        
+    }
+
+    protected void lineTo(int x, int y) throws IOException {
+        // used for clipping only, so not implemented
+        
+    }
+
+    protected void closePath() throws IOException {
+        // used for clipping only, so not implemented
+        
+    }
+
+    protected void clip() throws IOException {
+        // used for clipping only, so not implemented
+        
+    }
+
+    protected void saveGraphicsState() throws IOException {
+        // used for clipping only, so not implemented 
+        
+    }
+
+    protected void restoreGraphicsState() throws IOException {
+        // used for clipping only, so not implemented
+        
+    }
 }
