From ae8a5035235e1262e412e1eacd0eb3adfaef83ef Mon Sep 17 00:00:00 2001 From: Peter Hancock Date: Wed, 8 Jun 2011 12:33:47 +0000 Subject: Bugzilla #49913 Minor bug fixes and some cleanup git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_RoundedCorners@1133370 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/render/intermediate/BorderPainter.java | 81 ++++++++++++++++------ .../apache/fop/render/intermediate/IFPainter.java | 18 ++--- .../apache/fop/render/intermediate/IFParser.java | 34 ++++++++- .../fop/render/intermediate/IFSerializer.java | 54 ++++++++++++++- 4 files changed, 155 insertions(+), 32 deletions(-) (limited to 'src/java/org/apache/fop/render/intermediate') diff --git a/src/java/org/apache/fop/render/intermediate/BorderPainter.java b/src/java/org/apache/fop/render/intermediate/BorderPainter.java index 31218af6b..5cf50ecbb 100644 --- a/src/java/org/apache/fop/render/intermediate/BorderPainter.java +++ b/src/java/org/apache/fop/render/intermediate/BorderPainter.java @@ -32,9 +32,14 @@ import org.apache.fop.traits.RuleStyle; */ public abstract class BorderPainter { + /** TODO remove before integration*/ public static final String ROUNDED_CORNERS = "fop.round-corners"; + /** TODO Use a class to model border instead of an array + * convention index of before, end, after and start borders */ protected static final int BEFORE = 0, END = 1, AFTER = 2, START = 3; + /** TODO Use a class to model border corners instead of an array + convention index of before_start, before_end, after_end and after_start border corners*/ protected static final int BEFORE_START = 0, BEFORE_END = 1, AFTER_END = 2, AFTER_START = 3; @@ -45,6 +50,7 @@ public abstract class BorderPainter { * @param bpsAfter the border specification on the after side * @param bpsStart the border specification on the start side * @param bpsEnd the border specification on the end side + * @param innerBackgroundColor the inner background color * @throws IFException if an error occurs while drawing the borders */ public void drawBorders(Rectangle borderRect, // CSOK: MethodLength @@ -71,6 +77,15 @@ public abstract class BorderPainter { return bps == null ? bps : bps.width == 0 ? (BorderProps)null : bps; } + /** + * TODO merge with drawRoundedBorders()? + * @param borderRect the border rectangle + * @param bpsBefore the border specification on the before side + * @param bpsAfter the border specification on the after side + * @param bpsStart the border specification on the start side + * @param bpsEnd the border specification on the end side + * @throws IOException + */ protected void drawRectangularBorders(Rectangle borderRect, BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) throws IOException { @@ -243,6 +258,14 @@ public abstract class BorderPainter { } } + /** TODO merge with drawRectangularBorders? + * @param borderRect the border rectangle + * @param bpsBefore the border specification on the before side + * @param bpsAfter the border specification on the after side + * @param bpsStart the border specification on the start side + * @param bpsEnd the border specification on the end side + * @throws IOException on io exception + * */ protected void drawRoundedBorders(Rectangle borderRect, BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) throws IOException { @@ -400,6 +423,7 @@ public abstract class BorderPainter { } } + /** TODO collect parameters into useful data structures*/ private void drawBorderSegment(final int sx2, final int ex1, final int ex2, final int outery, final int innery, final int clipWidthStart, final int clipWidthEnd, @@ -444,7 +468,7 @@ public abstract class BorderPainter { } } - if (ellipseBERadiusX != 0) { + if (ellipseBERadiusX != 0 && ellipseBERadiusY != 0) { final double[] outerJoinMetrics = getCornerBorderJoinMetrics( ellipseBERadiusX, ellipseBERadiusY, (double)innery / (ex1 - ex2)); @@ -553,11 +577,11 @@ public abstract class BorderPainter { /** * Clip the background to the inner border - * @param rect - * @param bpsBefore - * @param bpsAfter - * @param bpsStart - * @param bpsEnd + * @param rect clipping rectangle + * @param bpsBefore before border + * @param bpsAfter after border + * @param bpsStart start border + * @param bpsEnd end border * @throws IOException if an I/O error occurs */ public void clipBackground(Rectangle rect, @@ -629,7 +653,7 @@ public abstract class BorderPainter { lineTo(startx + ellipseSE, starty + height); - if (ellipseSE > 0 && ellipseSE > 0) { + if (ellipseSE > 0 && ellipseAS > 0) { arcTo( Math.PI / 2, Math.PI, startx + ellipseSE, starty + height - ellipseAS, ellipseSE, ellipseAS); } @@ -645,8 +669,9 @@ public abstract class BorderPainter { } - /* - * If the ellipse radii exceed the border edge length, the ellipses are rescaled. + /** + * TODO javadocs + * If an ellipse radii exceed the border edge length then all ellipses must be rescaled. */ protected double cornerScaleFactor(int width, int height, BorderProps bpsBefore, BorderProps bpsAfter, @@ -655,29 +680,35 @@ public abstract class BorderPainter { double esf = 1d; if (bpsBefore != null) { - if (bpsStart != null && bpsEnd != null - && bpsStart.getRadiusStart() + bpsEnd.getRadiusStart() > 0) { + double ellipseExtent = (bpsStart == null ? 0 : bpsStart.getRadiusStart()) + + (bpsEnd == null ? 0 : bpsEnd.getRadiusStart()); - double f = (double)width / (bpsStart.getRadiusStart() + bpsEnd.getRadiusStart()); + if (ellipseExtent > 0) { + double f = width / ellipseExtent; if (f < esf) { esf = f; } } } + if (bpsStart != null) { - if (bpsAfter != null && bpsBefore != null - && bpsAfter.getRadiusStart() + bpsBefore.getRadiusStart() > 0) { - double f = (double)height / (bpsAfter.getRadiusStart() - + bpsBefore.getRadiusStart()); + double ellipseExtent = (bpsAfter == null ? 0 : bpsAfter.getRadiusStart()) + + (bpsBefore == null ? 0 : bpsBefore.getRadiusStart()); + + if (ellipseExtent > 0) { + double f = height / ellipseExtent; if ( f < esf) { esf = f; } } } + if (bpsAfter != null) { - if (bpsStart != null && bpsEnd != null - && bpsStart.getRadiusEnd() + bpsEnd.getRadiusEnd() > 0) { - double f = (double)width / (bpsStart.getRadiusEnd() + bpsEnd.getRadiusEnd()); + double ellipseExtent = (bpsStart == null ? 0 : bpsStart.getRadiusEnd()) + + (bpsEnd == null ? 0 : bpsEnd.getRadiusEnd()); + + if (ellipseExtent > 0) { + double f = width / ellipseExtent; if (f < esf) { esf = f; } @@ -685,9 +716,11 @@ public abstract class BorderPainter { } if (bpsEnd != null) { - if (bpsAfter != null && bpsBefore != null - && bpsAfter.getRadiusEnd() + bpsBefore.getRadiusEnd() > 0) { - double f = (double)height / (bpsAfter.getRadiusEnd() + bpsBefore.getRadiusEnd()); + double ellipseExtent = (bpsAfter == null ? 0 : bpsAfter.getRadiusEnd()) + + (bpsBefore == null ? 0 : bpsBefore.getRadiusEnd()); + + if (ellipseExtent > 0) { + double f = height / ellipseExtent; if (f < esf) { esf = f; } @@ -881,6 +914,10 @@ public abstract class BorderPainter { */ protected abstract void restoreGraphicsState() throws IOException; + /** + * TODO remove the System.props when rounded corners code is stable + * @return true iff in rounded corners mode + */ public static boolean isRoundedCornersSupported() { return "true".equalsIgnoreCase(System.getProperty(ROUNDED_CORNERS, "true")); } diff --git a/src/java/org/apache/fop/render/intermediate/IFPainter.java b/src/java/org/apache/fop/render/intermediate/IFPainter.java index b0ddf462d..8d92d1ca9 100644 --- a/src/java/org/apache/fop/render/intermediate/IFPainter.java +++ b/src/java/org/apache/fop/render/intermediate/IFPainter.java @@ -182,14 +182,16 @@ public interface IFPainter { /** - * - * @param bpsBefore - * @param bpsAfter - * @param bpsStart - * @param bpsEnd - * @return true if the background needs to be painted - */ - boolean isBackgroundRequired( BorderProps bpsBefore, BorderProps bpsAfter, + * TODO Painter-specific rounded borders logic required background drawing to be + * made optional. A future refactoring of the rounded borders code should aim to make + * the need for this abstraction obsolete + * @param bpsBefore the before border + * @param bpsAfter the after border + * @param bpsStart the start border + * @param bpsEnd the end border + * @return true if and only if background drawing is required + */ + boolean isBackgroundRequired(BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd); /** diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java index 0abf3839a..0f143018d 100644 --- a/src/java/org/apache/fop/render/intermediate/IFParser.java +++ b/src/java/org/apache/fop/render/intermediate/IFParser.java @@ -583,6 +583,19 @@ public class IFParser implements IFConstants { int y = Integer.parseInt(attributes.getValue("y")); int width = Integer.parseInt(attributes.getValue("width")); int height = Integer.parseInt(attributes.getValue("height")); + BorderProps[] borders = new BorderProps[4]; + for (int i = 0; i < 4; i++) { + String b = attributes.getValue(SIDES[i]); + if (b != null) { + borders[i] = BorderProps.valueOf(userAgent, b); + } + } + + if (!(borders[0] == null && borders[1] == null + && borders[2] == null && borders[3] == null)) { + painter.clipBackground(new Rectangle(x, y, width, height), + borders[0], borders[1], borders[2], borders[3]); + } painter.clipRect(new Rectangle(x, y, width, height)); } @@ -601,7 +614,26 @@ public class IFParser implements IFConstants { } catch (PropertyException pe) { throw new IFException("Error parsing the fill attribute", pe); } - painter.fillRect(new Rectangle(x, y, width, height), fillColor); + + Rectangle rectangularArea = new Rectangle(x, y, width, height); + + //TODO should rect be overloaded to include rounded corners + // or should we introduce a new IF element? + BorderProps[] borders = new BorderProps[4]; + for (int i = 0; i < 4; i++) { + String b = attributes.getValue(SIDES[i]); + if (b != null) { + borders[i] = BorderProps.valueOf(userAgent, b); + } + } + + if (!(borders[0] == null && borders[1] == null + && borders[2] == null && borders[3] == null)) { + painter.clipBackground(rectangularArea, + borders[0], borders[1], borders[2], borders[3]); + } + + painter.fillRect(rectangularArea , fillColor); } } diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java index 0b3b24110..4af90faed 100644 --- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java +++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java @@ -474,8 +474,31 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler /** {@inheritDoc} */ public void clipBackground(Rectangle rect, BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) throws IFException { - // TODO Auto-generated method stub + try { + AttributesImpl atts = new AttributesImpl(); + addAttribute(atts, "x", Integer.toString(rect.x)); + addAttribute(atts, "y", Integer.toString(rect.y)); + addAttribute(atts, "width", Integer.toString(rect.width)); + addAttribute(atts, "height", Integer.toString(rect.height)); + if (hasRoundedCorners(bpsBefore, bpsAfter, bpsStart, bpsEnd)) { + if (bpsBefore != null) { + addAttribute(atts, "before", bpsBefore.toString()); + } + if (bpsAfter != null) { + addAttribute(atts, "after", bpsAfter.toString()); + } + if (bpsStart != null) { + addAttribute(atts, "start", bpsStart.toString()); + } + if (bpsEnd != null) { + addAttribute(atts, "end", bpsEnd.toString()); + } + } + handler.element(EL_CLIP_RECT, atts); + } catch (SAXException e) { + throw new IFException("SAX error in clipRect()", e); + } } @@ -497,6 +520,35 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler } } + //TODO create a class representing all borders should exist + //with query methods like this + private boolean hasRoundedCorners(BorderProps bpsBefore, BorderProps bpsAfter, + BorderProps bpsStart, BorderProps bpsEnd) { + boolean rtn = false; + + if (bpsBefore != null && bpsBefore.getRadiusStart() > 0 + && bpsStart != null && bpsStart.getRadiusStart() > 0) { + rtn = true; + } + + if (bpsBefore != null && bpsBefore.getRadiusEnd() > 0 + && bpsEnd != null && bpsEnd.getRadiusStart() > 0) { + rtn = true; + } + + if (bpsEnd != null && bpsEnd.getRadiusEnd() > 0 + && bpsAfter != null && bpsAfter.getRadiusEnd() > 0) { + rtn = true; + } + + if (bpsAfter != null && bpsAfter.getRadiusStart() > 0 + && bpsStart != null && bpsStart.getRadiusEnd() > 0) { + rtn = true; + } + + return rtn; + } + /** {@inheritDoc} */ public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, BorderProps start, BorderProps end, Color innerBackgroundColor) throws IFException { -- cgit v1.2.3