You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by jg...@apache.org on 2026/01/12 22:17:07 UTC

(xmlgraphics-fop) branch main updated: FOP-3286 Fix rounded borders

This is an automated email from the ASF dual-hosted git repository.

jgoncalves pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/xmlgraphics-fop.git


The following commit(s) were added to refs/heads/main by this push:
     new c5f55eb20 FOP-3286 Fix rounded borders
c5f55eb20 is described below

commit c5f55eb205d88aaa1c6bfc5ef64f1769ee5c98c3
Author: Joao Goncalves <an...@gmail.com>
AuthorDate: Thu Jan 8 11:09:50 2026 -0600

    FOP-3286 Fix rounded borders
---
 .../fop/render/intermediate/BorderPainter.java     | 24 +++++--
 .../render/intermediate/BorderPainterTestCase.java | 73 ++++++++++++++++++++++
 2 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/BorderPainter.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/BorderPainter.java
index d6d2a10c9..d29783be9 100644
--- a/fop-core/src/main/java/org/apache/fop/render/intermediate/BorderPainter.java
+++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/BorderPainter.java
@@ -317,11 +317,25 @@ public class BorderPainter {
         //Determine scale factor if any adjacent elliptic corners overlap
         double cornerCorrectionFactor = calculateCornerScaleCorrection(width, height, before, after, start,
                 end);
-        drawBorderSegment(start, before, end, 0, width, startx, starty, cornerCorrectionFactor);
-        drawBorderSegment(before, end, after, 1, height, startx + width, starty, cornerCorrectionFactor);
-        drawBorderSegment(end, after, start, 2, width, startx + width, starty + height,
-                cornerCorrectionFactor);
-        drawBorderSegment(after, start, before, 3, height, startx, starty + height, cornerCorrectionFactor);
+
+        if (hasRadius(before) || hasRadius(after) || hasRadius(start) || hasRadius(end)) {
+            drawBorderSegment(before, end, after, 1, height, startx + width, starty, cornerCorrectionFactor);
+            drawBorderSegment(after, start, before, 3, height, startx, starty + height, cornerCorrectionFactor);
+
+            drawBorderSegment(start, before, end, 0, width, startx, starty, cornerCorrectionFactor);
+            drawBorderSegment(end, after, start, 2, width, startx + width, starty + height,
+                    cornerCorrectionFactor);
+        } else {
+            drawBorderSegment(start, before, end, 0, width, startx, starty, cornerCorrectionFactor);
+            drawBorderSegment(before, end, after, 1, height, startx + width, starty, cornerCorrectionFactor);
+            drawBorderSegment(end, after, start, 2, width, startx + width, starty + height,
+                    cornerCorrectionFactor);
+            drawBorderSegment(after, start, before, 3, height, startx, starty + height, cornerCorrectionFactor);
+        }
+    }
+
+    private boolean hasRadius(BorderSegment segment) {
+        return segment.getRadiusStart() != 0 || segment.getRadiusEnd() != 0;
     }
 
     private void drawBorderSegment(BorderSegment start, BorderSegment before, BorderSegment end,
diff --git a/fop-core/src/test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java b/fop-core/src/test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java
index 509a6c09d..a5a193a1e 100644
--- a/fop-core/src/test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/intermediate/BorderPainterTestCase.java
@@ -22,9 +22,11 @@ import java.awt.Rectangle;
 import java.io.IOException;
 
 import org.junit.Test;
+import org.mockito.InOrder;
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -35,6 +37,7 @@ 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,
@@ -73,6 +76,10 @@ public class BorderPainterTestCase {
         tester.test();
     }
 
+    private void testOrientation(BorderPainterTester<?> tester) throws IOException {
+        tester.testOrientation();
+    }
+
     @Test (expected = IFException.class)
     public void drawBordersThrowsIFException() throws Exception {
         GraphicsPainter graphicsPainter = mock(GraphicsPainter.class);
@@ -89,6 +96,12 @@ public class BorderPainterTestCase {
                 .beforeBorder().setWidth(0).tester());
     }
 
+    @Test
+    public void testDrawRectangularBordersOrientation() throws IOException {
+        testOrientation(new DrawRectangularBordersTester(0, 0, 1000, 1000)
+                .setBorderWidth(10).beforeBorder().setWidth(10).tester());
+    }
+
     @Test
     public void testDrawRectangularBordersWithNullBorders() throws IOException, IFException {
         GraphicsPainter graphicsPainter = mock(GraphicsPainter.class);
@@ -112,6 +125,12 @@ public class BorderPainterTestCase {
         test(new DrawRoundedBordersTester(0, 0, 60, 60).setBorderWidth(4).setCornerRadii(30));
     }
 
+    @Test
+    public void drawRoundedBordersOrientation() throws Exception {
+        testOrientation(new DrawRoundedBordersTester(0, 0, 100, 100).setBorderWidth(15)
+                .setCornerRadii(10).beforeBorder().setWidth(5).tester());
+    }
+
     @Test
     public void testDrawRoundedBordersWithNullBorders() throws IOException, IFException {
         GraphicsPainter graphicsPainter = mock(GraphicsPainter.class);
@@ -244,8 +263,18 @@ public class BorderPainterTestCase {
             testMethod();
         }
 
+        public void testOrientation() throws IOException {
+            before = beforeBuilder.build();
+            after = afterBuilder.build();
+            end = endBuilder.build();
+            start = startBuilder.build();
+            testMethodOrientation();
+        }
+
         protected abstract void testMethod() throws IOException;
 
+        protected abstract void testMethodOrientation() throws IOException;
+
         protected static int numberOfNonZeroBorders(BorderProps first, BorderProps... borders) {
             int i = first.width == 0 ? 0 : 1;
             for (BorderProps borderProp : borders) {
@@ -339,6 +368,26 @@ public class BorderPainterTestCase {
             verifyDrawing();
         }
 
+        @Override
+        protected void testMethodOrientation() throws IOException {
+            sut.drawRoundedBorders(borderExtent, before, after, start, end);
+
+            InOrder inOrder = inOrder(graphicsPainter);
+
+            // orientation 0
+            inOrder.verify(graphicsPainter, times(0)).rotateCoordinates(0);
+            inOrder.verify(graphicsPainter).closePath();
+            // orientation 1
+            inOrder.verify(graphicsPainter).rotateCoordinates(Math.PI / 2d);
+            inOrder.verify(graphicsPainter).closePath();
+            // orientation 2
+            inOrder.verify(graphicsPainter).rotateCoordinates(Math.PI * 2 / 2d);
+            inOrder.verify(graphicsPainter).closePath();
+            // orientation 3
+            inOrder.verify(graphicsPainter).rotateCoordinates(Math.PI * 3 / 2d);
+            inOrder.verify(graphicsPainter).closePath();
+        }
+
         private void verifyDrawing() throws IOException {
             final int rectX = borderExtent.x;
             final int rectY = borderExtent.y;
@@ -400,6 +449,25 @@ public class BorderPainterTestCase {
             verifyDrawing();
         }
 
+        public void testMethodOrientation() throws IOException {
+            sut.drawRoundedBorders(borderExtent, before, after, start, end);
+
+            InOrder inOrder = inOrder(graphicsPainter);
+
+            // orientation 1
+            inOrder.verify(graphicsPainter).rotateCoordinates(Math.PI / 2d);
+            inOrder.verify(graphicsPainter).closePath();
+            // orientation 3
+            inOrder.verify(graphicsPainter).rotateCoordinates(Math.PI * 3 / 2d);
+            inOrder.verify(graphicsPainter).closePath();
+            // orientation 0
+            inOrder.verify(graphicsPainter, times(0)).rotateCoordinates(0);
+            inOrder.verify(graphicsPainter).closePath();
+            // orientation 2
+            inOrder.verify(graphicsPainter).rotateCoordinates(Math.PI * 2 / 2d);
+            inOrder.verify(graphicsPainter).closePath();
+        }
+
         private void verifyDrawing() throws IOException {
             int numBorders = numberOfNonZeroBorders();
             final int rectWidth = borderExtent.width;
@@ -482,6 +550,11 @@ public class BorderPainterTestCase {
             verifyClipping();
         }
 
+        @Override
+        protected void testMethodOrientation() throws IOException {
+            //not needed
+        }
+
         private void verifyClipping() throws IOException {
             int xOrigin = borderExtent.x;
             int yOrigin = borderExtent.y;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: commits-help@xmlgraphics.apache.org