You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2006/05/02 16:41:21 UTC

svn commit: r398945 [2/2] - in /xmlgraphics/fop/trunk/src: java/org/apache/fop/render/ java/org/apache/fop/render/awt/ java/org/apache/fop/render/awt/viewer/ java/org/apache/fop/render/bitmap/ java/org/apache/fop/render/java2d/ java/org/apache/fop/rend...

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java?rev=398945&r1=398944&r2=398945&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2D.java Tue May  2 07:39:32 2006
@@ -20,6 +20,7 @@
 
 import java.awt.BasicStroke;
 import java.awt.Color;
+import java.awt.Dimension;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.GraphicsConfiguration;
@@ -28,6 +29,8 @@
 import java.awt.Paint;
 import java.awt.Shape;
 import java.awt.Stroke;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.PathIterator;
 import java.awt.geom.Point2D;
@@ -50,6 +53,9 @@
     /** The PCL generator */
     protected PCLGenerator gen;
     
+    private boolean failOnUnsupportedFeature = true;
+    private boolean clippingDisabled = false;
+    
     /**
      * Create a new PCLGraphics2D.
      * @param gen the PCL Generator to paint with
@@ -70,7 +76,9 @@
 
     /** @see java.awt.Graphics#create() */
     public Graphics create() {
-        return new PCLGraphics2D(this);
+        PCLGraphics2D copy = new PCLGraphics2D(this);
+        copy.setGraphicContext((GraphicContext)getGraphicContext().clone());
+        return copy;
     }
 
     /** @see java.awt.Graphics#dispose() */
@@ -95,6 +103,18 @@
         ioe.printStackTrace();
     }
 
+    /**
+     * Raises an UnsupportedOperationException if this instance is configured to do so and an
+     * unsupported feature has been requested. Clients can make use of this to fall back to
+     * a more compatible way of painting a PCL graphic.
+     * @param msg the error message to be displayed
+     */
+    protected void handleUnsupportedFeature(String msg) {
+        if (this.failOnUnsupportedFeature) {
+            throw new UnsupportedOperationException(msg);
+        }
+    }
+    
     /** @see java.awt.Graphics2D#getDeviceConfiguration() */
     public GraphicsConfiguration getDeviceConfiguration() {
         return GraphicsEnvironment.getLocalGraphicsEnvironment().
@@ -114,18 +134,35 @@
             if (da != null) {
                 
                 gen.writeText("UL1,");
-                for (int idx = 0, len = Math.min(20, da.length); idx < len; idx++) {
-                    gen.writeText(gen.formatDouble4(da[idx]));
+                int len = Math.min(20, da.length);
+                float patternLen = 0.0f;
+                for (int idx = 0; idx < len; idx++) {
+                    patternLen += da[idx];
+                }
+                if (len == 1) {
+                    patternLen *= 2;
+                }
+                for (int idx = 0; idx < len; idx++) {
+                    float perc = da[idx] * 100 / patternLen;
+                    gen.writeText(gen.formatDouble2(perc));
                     if (idx < da.length - 1) {
                         gen.writeText(",");
                     }
                 }
+                if (len == 1) {
+                    gen.writeText("," + gen.formatDouble2(da[0] * 100 / patternLen ));
+                    
+                }
                 gen.writeText(";");
                 /* TODO Dash phase NYI
                 float offset = bs.getDashPhase();
                 gen.writeln(gen.formatDouble4(offset) + " setdash");
                 */
-                gen.writeText("LT1;");
+                Point2D ptLen = new Point2D.Double(patternLen, 0);
+                //interpret as absolute length
+                getTransform().deltaTransform(ptLen, ptLen);
+                double transLen = UnitConv.pt2mm(ptLen.distance(0, 0));
+                gen.writeText("LT1," + gen.formatDouble4(transLen) + ",1;");
             } else {
                 gen.writeText("LT;");
             }
@@ -166,13 +203,13 @@
             float lw = bs.getLineWidth();
             Point2D ptSrc = new Point2D.Double(lw, 0);
             //Pen widths are set as absolute metric values (WU0;)
-            Point2D ptDest = getTransform().transform(ptSrc, null);
+            Point2D ptDest = getTransform().deltaTransform(ptSrc, null);
             double transDist = UnitConv.pt2mm(ptDest.distance(0, 0));
             //System.out.println("--" + ptDest.distance(0, 0) + " " + transDist);
             gen.writeText(";PW" + gen.formatDouble4(transDist) + ";");
             
         } else {
-            System.err.println("Unsupported Stroke: " + stroke.getClass().getName());
+            handleUnsupportedFeature("Unsupported Stroke: " + stroke.getClass().getName());
         }
     }
 
@@ -187,7 +224,31 @@
             int shade = gen.convertToPCLShade(col);
             gen.writeText("TR0;FT10," + shade + ";");
         } else {
-            System.err.println("Unsupported Paint: " + paint.getClass().getName());
+            handleUnsupportedFeature("Unsupported Paint: " + paint.getClass().getName());
+        }
+    }
+
+    private void writeClip(Shape imclip) throws IOException {
+        if (clippingDisabled) {
+            return;
+        }
+        if (imclip == null) {
+            //gen.writeText("IW;");
+        } else {
+            handleUnsupportedFeature("Clipping is not supported. Shape: " + imclip);
+            /* This is an attempt to clip using the "InputWindow" (IW) but this only allows to 
+             * clip a rectangular area. Force falling back to bitmap mode for now.
+            Rectangle2D bounds = imclip.getBounds2D();
+            Point2D p1 = new Point2D.Double(bounds.getX(), bounds.getY());
+            Point2D p2 = new Point2D.Double(
+                    bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight());
+            getTransform().transform(p1, p1);
+            getTransform().transform(p2, p2);
+            gen.writeText("IW" + gen.formatDouble4(p1.getX())
+                    + "," + gen.formatDouble4(p2.getY())
+                    + "," + gen.formatDouble4(p2.getX())
+                    + "," + gen.formatDouble4(p1.getY()) + ";");
+            */
         }
     }
 
@@ -197,16 +258,17 @@
             AffineTransform trans = getTransform();
     
             Shape imclip = getClip();
-            //writeClip(imclip);
-            //establishColor(getColor());
+            writeClip(imclip);
     
-            applyPaint(getPaint());
+            if (!Color.black.equals(getColor())) {
+                //TODO PCL 5 doesn't support colored pens, PCL5c has a pen color (PC) command
+                handleUnsupportedFeature("Only black is supported as stroke color: " + getColor());
+            }
             applyStroke(getStroke());
     
-            //gen.writeln("newpath");
             PathIterator iter = s.getPathIterator(trans);
-            processPathIterator(iter);
-            gen.writeText("EP;");
+            processPathIteratorStroke(iter);
+            writeClip(null);
         } catch (IOException ioe) {
             handleIOException(ioe);
         }
@@ -217,16 +279,13 @@
         try {
             AffineTransform trans = getTransform();
             Shape imclip = getClip();
-            //writeClip(imclip);
+            writeClip(imclip);
             
-            //establishColor(getColor());
-
             applyPaint(getPaint());
 
             PathIterator iter = s.getPathIterator(trans);
-            processPathIterator(iter);
-            int fillMethod = (iter.getWindingRule() == PathIterator.WIND_EVEN_ODD ? 0 : 1);
-            gen.writeText("FP" + fillMethod + ";");
+            processPathIteratorFill(iter);
+            writeClip(null);
         } catch (IOException ioe) {
             handleIOException(ioe);
         }
@@ -237,97 +296,163 @@
      * @param iter PathIterator to process
      * @throws IOException In case of an I/O problem.
      */
-    public void processPathIterator(PathIterator iter) throws IOException {
+    public void processPathIteratorStroke(PathIterator iter) throws IOException {
+        gen.writeText("\n");
         double[] vals = new double[6];
         boolean penDown = false;
-        boolean hasFirst = false;
-        double x = 0, firstX = 0;
-        double y = 0, firstY = 0;
-        boolean pendingPM0 = true;
-        penUp();
+        double x = 0;
+        double y = 0;
+        StringBuffer sb = new StringBuffer(256);
+        penUp(sb);
         while (!iter.isDone()) {
             int type = iter.currentSegment(vals);
             if (type == PathIterator.SEG_CLOSE) {
-                hasFirst = false;
-                /*
-                if (firstX != x && firstY != y) {
-                    plotAbsolute(firstX, firstY);
-                }*/
-                //penUp();
-                gen.writeText("PM1;");
+                gen.writeText("PM;");
+                gen.writeText(sb.toString());
+                gen.writeText("PM2;EP;");
+                sb.setLength(0);
                 iter.next();
                 continue;
-            }
-            if (type == PathIterator.SEG_MOVETO) {
+            } else if (type == PathIterator.SEG_MOVETO) {
+                gen.writeText(sb.toString());
+                sb.setLength(0);
                 if (penDown) {
-                    penUp();
+                    penUp(sb);
                     penDown = false;
                 }
             } else {
                 if (!penDown) {
-                    penDown();
+                    penDown(sb);
                     penDown = true;
                 }
             }
             switch (type) {
+            case PathIterator.SEG_CLOSE:
+                break;
+            case PathIterator.SEG_MOVETO:
+                x = vals[0];
+                y = vals[1];
+                plotAbsolute(x, y, sb);
+                gen.writeText(sb.toString());
+                sb.setLength(0);
+                break;
+            case PathIterator.SEG_LINETO:
+                x = vals[0];
+                y = vals[1];
+                plotAbsolute(x, y, sb);
+                break;
             case PathIterator.SEG_CUBICTO:
                 x = vals[4];
                 y = vals[5];
-                bezierAbsolute(vals[0], vals[1], vals[2], vals[3], x, y);
+                bezierAbsolute(vals[0], vals[1], vals[2], vals[3], x, y, sb);
                 break;
-            case PathIterator.SEG_LINETO:
+            case PathIterator.SEG_QUADTO:
+                double originX = x;
+                double originY = y;
+                x = vals[2];
+                y = vals[3];
+                quadraticBezierAbsolute(originX, originY, vals[0], vals[1], x, y, sb);
+                break;
+            default:
+                break;
+            }
+            iter.next();
+        }
+        sb.append("\n");
+        gen.writeText(sb.toString());
+    }
+    
+    /**
+     * Processes a path iterator generating the nexessary painting operations.
+     * @param iter PathIterator to process
+     * @throws IOException In case of an I/O problem.
+     */
+    public void processPathIteratorFill(PathIterator iter) throws IOException {
+        gen.writeText("\n");
+        double[] vals = new double[6];
+        boolean penDown = false;
+        double x = 0;
+        double y = 0;
+        boolean pendingPM0 = true;
+        StringBuffer sb = new StringBuffer(256);
+        penUp(sb);
+        while (!iter.isDone()) {
+            int type = iter.currentSegment(vals);
+            if (type == PathIterator.SEG_CLOSE) {
+                sb.append("PM1;");
+                iter.next();
+                continue;
+            } else if (type == PathIterator.SEG_MOVETO) {
+                if (penDown) {
+                    penUp(sb);
+                    penDown = false;
+                }
+            } else {
+                if (!penDown) {
+                    penDown(sb);
+                    penDown = true;
+                }
+            }
+            switch (type) {
+            case PathIterator.SEG_MOVETO:
                 x = vals[0];
                 y = vals[1];
-                plotAbsolute(x, y);
+                plotAbsolute(x, y, sb);
                 break;
-            case PathIterator.SEG_MOVETO:
+            case PathIterator.SEG_LINETO:
                 x = vals[0];
                 y = vals[1];
-                plotAbsolute(x, y);
+                plotAbsolute(x, y, sb);
+                break;
+            case PathIterator.SEG_CUBICTO:
+                x = vals[4];
+                y = vals[5];
+                bezierAbsolute(vals[0], vals[1], vals[2], vals[3], x, y, sb);
                 break;
             case PathIterator.SEG_QUADTO:
                 double originX = x;
                 double originY = y;
                 x = vals[2];
                 y = vals[3];
-                quadraticBezierAbsolute(originX, originY, vals[0], vals[1], x, y);
-                break;
-            case PathIterator.SEG_CLOSE:
+                quadraticBezierAbsolute(originX, originY, vals[0], vals[1], x, y, sb);
                 break;
             default:
-                break;
+                throw new IllegalStateException("Must not get here");
             }
             if (pendingPM0) {
                 pendingPM0 = false;
-                gen.writeText("PM;");
-            }
-            if (!hasFirst) {
-                firstX = x;
-                firstY = y;
+                sb.append("PM;");
             }
             iter.next();
         }
-        gen.writeText("PM2;");
+        sb.append("PM2;");
+        fillPolygon(iter.getWindingRule(), sb);
+        sb.append("\n");
+        gen.writeText(sb.toString());
     }
-
-    private void plotAbsolute(double x, double y) throws IOException {
-        gen.writeText("PA" + gen.formatDouble4(x) + ","
-                + gen.formatDouble4(y) + ";");
-    }
-
-    private void bezierAbsolute(double x1, double y1, double x2, double y2, double x3, double y3) 
-                throws IOException {
-        gen.writeText("BZ" + gen.formatDouble4(x1) + ","
-                + gen.formatDouble4(y1) + ","
-                + gen.formatDouble4(x2) + ","
-                + gen.formatDouble4(y2) + ","
-                + gen.formatDouble4(x3) + ","
-                + gen.formatDouble4(y3) + ";");
+    
+    private void fillPolygon(int windingRule, StringBuffer sb) {
+        int fillMethod = (windingRule == PathIterator.WIND_EVEN_ODD ? 0 : 1);
+        sb.append("FP").append(fillMethod).append(";");
+    }
+
+    private void plotAbsolute(double x, double y, StringBuffer sb) {
+        sb.append("PA").append(gen.formatDouble4(x));
+        sb.append(",").append(gen.formatDouble4(y)).append(";");
+    }
+
+    private void bezierAbsolute(double x1, double y1, double x2, double y2, double x3, double y3,
+            StringBuffer sb) {
+        sb.append("BZ").append(gen.formatDouble4(x1));
+        sb.append(",").append(gen.formatDouble4(y1));
+        sb.append(",").append(gen.formatDouble4(x2));
+        sb.append(",").append(gen.formatDouble4(y2));
+        sb.append(",").append(gen.formatDouble4(x3));
+        sb.append(",").append(gen.formatDouble4(y3)).append(";");
     }
 
     private void quadraticBezierAbsolute(double originX, double originY, 
-            double x1, double y1, double x2, double y2) 
-            throws IOException {
+            double x1, double y1, double x2, double y2, StringBuffer sb) {
         //Quadratic Bezier curve can be mapped to a normal bezier curve
         //See http://pfaedit.sourceforge.net/bezier.html
         double nx1 = originX + (2.0 / 3.0) * (x1 - originX);
@@ -336,28 +461,31 @@
         double nx2 = nx1 + (1.0 / 3.0) * (x2 - originX);
         double ny2 = ny1 + (1.0 / 3.0) * (y2 - originY);
         
-        bezierAbsolute(nx1, ny1, nx2, ny2, x2, y2);
+        bezierAbsolute(nx1, ny1, nx2, ny2, x2, y2, sb);
     }
 
-    private void penDown() throws IOException {
-        gen.writeText("PD;");
+    private void penDown(StringBuffer sb) {
+        sb.append("PD;");
     }
 
-    private void penUp() throws IOException {
-        gen.writeText("PU;");
+    private void penUp(StringBuffer sb) {
+        sb.append("PU;");
     }
 
     /** @see java.awt.Graphics2D#drawString(java.lang.String, float, float) */
     public void drawString(String s, float x, float y) {
-        // TODO Auto-generated method stub
-        System.err.println("drawString NYI");
+        java.awt.Font awtFont = getFont();
+        FontRenderContext frc = getFontRenderContext();
+        GlyphVector gv = awtFont.createGlyphVector(frc, s);
+        Shape glyphOutline = gv.getOutline(x, y);
+        fill(glyphOutline);
     }
 
     /** @see java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, float, float) */
     public void drawString(AttributedCharacterIterator iterator, float x,
             float y) {
         // TODO Auto-generated method stub
-        System.err.println("drawString NYI");
+        handleUnsupportedFeature("drawString NYI");
     }
 
     /**
@@ -365,8 +493,7 @@
      *          java.awt.geom.AffineTransform)
      */
     public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
-        // TODO Auto-generated method stub
-        System.err.println("drawRenderedImage NYI");
+        handleUnsupportedFeature("Bitmap images are not supported");
     }
 
     /**
@@ -374,8 +501,7 @@
      *          java.awt.geom.AffineTransform)
      */
     public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
-        // TODO Auto-generated method stub
-        System.err.println("drawRenderedImage NYI");
+        handleUnsupportedFeature("Bitmap images are not supported");
     }
 
     /**
@@ -384,8 +510,7 @@
      */
     public boolean drawImage(Image img, int x, int y, int width, int height,
             ImageObserver observer) {
-        // TODO Auto-generated method stub
-        System.err.println("drawImage NYI");
+        handleUnsupportedFeature("Bitmap images are not supported");
         return false;
     }
 
@@ -393,21 +518,62 @@
      * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, java.awt.image.ImageObserver)
      */
     public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
-        // TODO Auto-generated method stub
-        System.err.println("drawImage NYI");
+        handleUnsupportedFeature("Bitmap images are not supported");
         return false;
+        /*
+         * First attempt disabled.
+         * Reasons: Lack of transparency control, positioning and rotation issues
+        final int width = img.getWidth(observer);
+        final int height = img.getHeight(observer);
+        if (width == -1 || height == -1) {
+            return false;
+        }
+
+        Dimension size = new Dimension(width, height);
+        BufferedImage buf = buildBufferedImage(size);
+
+        java.awt.Graphics2D g = buf.createGraphics();
+        try {
+            g.setComposite(AlphaComposite.SrcOver);
+            g.setBackground(new Color(255, 255, 255));
+            g.setPaint(new Color(255, 255, 255));
+            g.fillRect(0, 0, width, height);
+            g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight()));
+
+            if (!g.drawImage(img, 0, 0, observer)) {
+                return false;
+            }
+        } finally {
+            g.dispose();
+        }
+
+        try {
+            AffineTransform at = getTransform();
+            gen.enterPCLMode(false);
+            //Shape imclip = getClip(); Clipping is not available in PCL
+            Point2D p1 = new Point2D.Double(x, y);
+            at.transform(p1, p1);
+            pclContext.getTransform().transform(p1, p1);
+            gen.setCursorPos(p1.getX(), p1.getY());
+            gen.paintBitmap(buf, 72); 
+            gen.enterHPGL2Mode(false);
+        } catch (IOException ioe) {
+            handleIOException(ioe);
+        }
+
+        return true;*/
     }
 
     /** @see java.awt.Graphics#copyArea(int, int, int, int, int, int) */
     public void copyArea(int x, int y, int width, int height, int dx, int dy) {
         // TODO Auto-generated method stub
-        System.err.println("copyArea NYI");
+        handleUnsupportedFeature("copyArea NYI");
     }
 
     /** @see java.awt.Graphics#setXORMode(java.awt.Color) */
     public void setXORMode(Color c1) {
         // TODO Auto-generated method stub
-        System.err.println("setXORMode NYI");
+        handleUnsupportedFeature("setXORMode NYI");
     }
 
     /**
@@ -422,6 +588,16 @@
         fmg = bi.createGraphics();
     }
 
+    /**
+     * Creates a buffered image.
+     * @param size dimensions of the image to be created
+     * @return the buffered image
+     */
+    protected BufferedImage buildBufferedImage(Dimension size) {
+        return new BufferedImage(size.width, size.height,
+                                 BufferedImage.TYPE_BYTE_GRAY);
+    }
+    
     /** @see java.awt.Graphics#getFontMetrics(java.awt.Font) */
     public java.awt.FontMetrics getFontMetrics(java.awt.Font f) {
         return fmg.getFontMetrics(f);

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java?rev=398945&r1=398944&r2=398945&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java Tue May  2 07:39:32 2006
@@ -27,6 +27,9 @@
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.fop.render.Graphics2DAdapter;
 import org.apache.fop.render.Graphics2DImagePainter;
 import org.apache.fop.render.RendererContext;
@@ -38,6 +41,9 @@
  */
 public class PCLGraphics2DAdapter implements Graphics2DAdapter {
 
+    /** logging instance */
+    private static Log log = LogFactory.getLog(PCLGraphics2DAdapter.class);
+
     /**
      * Main constructor
      */
@@ -57,80 +63,84 @@
         float imw = (float)dim.getWidth();
         float imh = (float)dim.getHeight();
 
+        boolean painted = false;
         boolean paintAsBitmap = pclContext.paintAsBitmap();
-        if (paintAsBitmap) {
+        if (!paintAsBitmap) {
+            ByteArrayOutputStream baout = new ByteArrayOutputStream();
+            PCLGenerator tempGen = new PCLGenerator(baout);
+            try {
+                GraphicContext ctx = (GraphicContext)pcl.getGraphicContext().clone();
+
+                AffineTransform prepareHPGL2 = new AffineTransform();
+                prepareHPGL2.scale(0.001, 0.001);
+                ctx.setTransform(prepareHPGL2);
+
+                PCLGraphics2D graphics = new PCLGraphics2D(tempGen);
+                graphics.setGraphicContext(ctx);
+                Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh);
+                painter.paint(graphics, area);
+                
+                //If we arrive here, the graphic is natively paintable, so write the graphic
+                pcl.saveGraphicsState();
+                pcl.setCursorPos(x, y);
+                gen.writeCommand("*c" + gen.formatDouble4(width / 100f) + "x" 
+                        + gen.formatDouble4(height / 100f) + "Y");
+                gen.writeCommand("*c0T");
+                gen.enterHPGL2Mode(false);
+                gen.writeText("\nIN;");
+                gen.writeText("SP1;");
+                //One Plotter unit is 0.025mm!
+                double scale = imw / UnitConv.mm2pt(imw * 0.025);
+                gen.writeText("SC0," + gen.formatDouble4(scale) 
+                        + ",0,-" + gen.formatDouble4(scale) + ",2;");
+                gen.writeText("IR0,100,0,100;");
+                gen.writeText("PU;PA0,0;\n");
+                baout.writeTo(gen.getOutputStream()); //Buffer is written to output stream
+                gen.writeText("\n");
+
+                gen.enterPCLMode(false);
+                pcl.restoreGraphicsState();
+                painted = true;
+            } catch (UnsupportedOperationException uoe) {
+                log.debug(
+                    "Cannot paint graphic natively. Falling back to bitmap painting. Reason: " 
+                        + uoe.getMessage());
+            }
+        }
+        
+        if (!painted) {
             int resolution = 300; //TODO not hard-coded, please!
             int bmw = UnitConv.mpt2px(pclContext.getWidth(), resolution);
             int bmh = UnitConv.mpt2px(pclContext.getHeight(), resolution);
             BufferedImage bi = new BufferedImage(
                     bmw, bmh,
-                    BufferedImage.TYPE_INT_RGB);
+                    BufferedImage.TYPE_BYTE_GRAY);
             Graphics2D g2d = bi.createGraphics();
             try {
                 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
-                        RenderingHints.VALUE_ANTIALIAS_OFF);
-                    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
-                        RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
-                    g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
-                        RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
-                    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, 
-                            RenderingHints.VALUE_RENDER_QUALITY);
-                    g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, 
-                            RenderingHints.VALUE_COLOR_RENDER_QUALITY);
-                    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
-                            RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
-                    g2d.setRenderingHint(RenderingHints.KEY_DITHERING,
-                        RenderingHints.VALUE_DITHER_ENABLE);
-                    g2d.setBackground(Color.white);
-                    g2d.setColor(Color.black);
-                    g2d.clearRect(0, 0, bmw, bmh);
-                    double sx = (double)bmw / pclContext.getWidth() * 1000;
-                    double sy = (double)bmh / pclContext.getHeight() * 1000;
-                    g2d.scale(sx, sy);
-
-                    //Paint the SVG on the BufferedImage
-                    Rectangle2D area = new Rectangle2D.Double(
-                            0.0, 0.0, pclContext.getWidth(), pclContext.getHeight());
-                    painter.paint(g2d, area);
+                    RenderingHints.VALUE_ANTIALIAS_OFF);
+                g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+                g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
+                    RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+                
+                g2d.setBackground(Color.white);
+                g2d.setColor(Color.black);
+                g2d.clearRect(0, 0, bmw, bmh);
+                double sx = (double)bmw / pclContext.getWidth();
+                double sy = (double)bmh / pclContext.getHeight();
+                g2d.scale(sx, sy);
+
+                //Paint the SVG on the BufferedImage
+                Rectangle2D area = new Rectangle2D.Double(
+                        0.0, 0.0, pclContext.getWidth(), pclContext.getHeight());
+                painter.paint(g2d, area);
             } finally {
                 g2d.dispose();
             }
 
-            pcl.moveTo(x, y);
+            pcl.setCursorPos(x, y);
             gen.paintBitmap(bi, resolution);
-        } else {
-            pcl.saveGraphicsState();
-            GraphicContext ctx = (GraphicContext)pcl.getGraphicContext().clone();
-
-            // Clip to the image area.
-            //gen.writeln("newpath");
-            //gen.defineRect(fx, fy, fwidth, fheight);
-            //gen.writeln("clip");
-            
-            AffineTransform prepareHPGL2 = new AffineTransform();
-            //prepareHPGL2.scale(1, 1);
-            ctx.setTransform(prepareHPGL2);
-
-            pcl.moveTo(x, y);
-            gen.writeCommand("*c" + gen.formatDouble4(width / 100f) + "x" 
-                    + gen.formatDouble4(height / 100f) + "Y");
-            gen.writeCommand("*c0T");
-            gen.writeCommand("%0B");
-            gen.writeText("IN;");
-            gen.writeText("SP1;");
-            //One Plotter unit is 0.025mm!
-            double scale = imw / UnitConv.mm2pt(imw * 0.025);
-            gen.writeText("SC0," + gen.formatDouble4(scale) 
-                    + ",0,-" + gen.formatDouble4(scale) + ",2;");
-            gen.writeText("IR0,100,0,100;");
-            gen.writeText("PU;PA0,0;");
-            PCLGraphics2D graphics = new PCLGraphics2D(gen);
-            graphics.setGraphicContext(ctx);
-            Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh);
-            painter.paint(graphics, area);
-
-            gen.writeCommand("%0A");
-            pcl.restoreGraphicsState();
         }
     }
 

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java?rev=398945&r1=398944&r2=398945&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java Tue May  2 07:39:32 2006
@@ -18,7 +18,38 @@
  
 package org.apache.fop.render.pcl;
 
+//Java
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.PixelInterleavedSampleModel;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.w3c.dom.Document;
+
+import org.apache.xmlgraphics.java2d.GraphicContext;
+
 // FOP
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.Area;
@@ -31,44 +62,25 @@
 import org.apache.fop.area.inline.AbstractTextArea;
 import org.apache.fop.area.inline.ForeignObject;
 import org.apache.fop.area.inline.Image;
+import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.Viewport;
 import org.apache.fop.area.inline.WordArea;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontSetup;
 import org.apache.fop.image.EPSImage;
 import org.apache.fop.image.FopImage;
 import org.apache.fop.image.ImageFactory;
 import org.apache.fop.image.XMLImage;
 import org.apache.fop.render.Graphics2DAdapter;
+import org.apache.fop.render.Graphics2DImagePainter;
 import org.apache.fop.render.PrintRenderer;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.render.RendererContextConstants;
+import org.apache.fop.render.java2d.Java2DRenderer;
 import org.apache.fop.traits.BorderProps;
-import org.apache.xmlgraphics.java2d.GraphicContext;
-import org.w3c.dom.Document;
-
-// Java
-import java.awt.Rectangle;
-import java.awt.color.ColorSpace;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.ComponentColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferByte;
-import java.awt.image.PixelInterleavedSampleModel;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.awt.image.WritableRaster;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Map;
-import java.util.Stack;
+import org.apache.fop.util.QName;
 
 /**
  * Renderer for the PCL 5 printer language. It also uses HP GL/2 for certain graphic elements.
@@ -87,6 +99,15 @@
 
     private Stack graphicContextStack = new Stack();
     private GraphicContext graphicContext = new GraphicContext();
+
+    private GeneralPath currentPath = null;
+    private java.awt.Color currentFillColor = null;
+    
+    /**
+     * Controls whether appearance is more important than speed. False can cause some FO feature
+     * to be ignored (like the advanced borders). 
+     */
+    private boolean qualityBeforeSpeed = false;
     
     /**
      * Create the PCL renderer
@@ -95,6 +116,23 @@
     }
 
     /**
+     * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
+     */
+    public void configure(Configuration cfg) throws ConfigurationException {
+        super.configure(cfg);
+        String rendering = cfg.getChild("rendering").getValue(null);
+        if ("quality".equalsIgnoreCase(rendering)) {
+            this.qualityBeforeSpeed = true;
+        } else if ("speed".equalsIgnoreCase(rendering)) {
+            this.qualityBeforeSpeed = false;
+        } else if (rendering != null) {
+            throw new ConfigurationException(
+                    "Valid values for 'rendering' are 'quality' and 'speed'. Value found: " 
+                        + rendering);
+        }
+    }
+
+    /**
      * Central exception handler for I/O exceptions.
      * @param ioe IOException to handle
      */
@@ -229,6 +267,8 @@
         this.gen = new PCLGenerator(out);
 
         gen.universalEndOfLanguage();
+        gen.writeText("@PJL JOB NAME = \"" + userAgent.getTitle() + "\"\n");
+        gen.writeText("@PJL ENTER LANGUAGE = PCL\n");
         gen.resetPrinter();
     }
 
@@ -253,19 +293,6 @@
         final long pageheight = Math.round(page.getViewArea().getHeight());
         selectPageFormat(pagewidth, pageheight);
         
-        if (false) { //TODO DEBUG CODE! Remove me.
-            //gen.fillRect(0, 0, (int)pagewidth, (int)pageheight, java.awt.Color.yellow);
-            //gen.fillRect(5000, 5000, (int)pagewidth - 10000, (int)pageheight - 10000, java.awt.Color.yellow);
-            //gen.fillRect(10000, 10000, (int)pagewidth / 4 - 20000, (int)pageheight / 4 - 20000, java.awt.Color.red);
-            for (int i = 0; i < 29; i++) {
-                if (i % 2 == 0) {
-                    int w = (int)(10 * 2.835 * 1000);
-                    Point2D p = transformedPoint(i * w, 0);
-                    gen.fillRect((int)p.getX(), (int)p.getY(), w, w, java.awt.Color.yellow);
-                }
-            }
-        }
-        
         super.renderPage(page);
         gen.formFeed();
         restoreGraphicsState();
@@ -389,7 +416,7 @@
             saveGraphicsState();
             updatePrintDirection();
             graphicContext.translate(rx, bl);
-            moveTo(0, 0);
+            setCursorPos(0, 0);
         
             super.renderText(area); //Updates IPD
         
@@ -400,10 +427,83 @@
         }
     }
 
-    void moveTo(int x, int y) throws IOException {
-        Point2D transPoint = transformedPoint(x, y);
-        gen.writeCommand("&a" + gen.formatDouble2(transPoint.getX() / 100) + "h" 
-                + gen.formatDouble2(transPoint.getY() / 100) + "V");
+    /**
+     * Sets the current cursor position. The coordinates are transformed to the absolute position
+     * on the logical PCL page and then passed on to the PCLGenerator.
+     * @param x the x coordinate (in millipoints)
+     * @param y the y coordinate (in millipoints)
+     */
+    void setCursorPos(float x, float y) {
+        try {
+            Point2D transPoint = transformedPoint(x, y);
+            gen.setCursorPos(transPoint.getX(), transPoint.getY());
+        } catch (IOException ioe) {
+            handleIOTrouble(ioe);
+        }
+    }
+
+    /**
+     * @see org.apache.fop.render.AbstractPathOrientedRenderer#clip()
+     */
+    protected void clip() {
+        if (currentPath == null) {
+            throw new IllegalStateException("No current path available!");
+        }
+        //TODO Find a good way to do clipping
+        currentPath = null;
+    }
+
+    /**
+     * @see org.apache.fop.render.AbstractPathOrientedRenderer#closePath()
+     */
+    protected void closePath() {
+        currentPath.closePath();
+    }
+
+    /**
+     * @see org.apache.fop.render.AbstractPathOrientedRenderer#lineTo(float, float)
+     */
+    protected void lineTo(float x, float y) {
+        if (currentPath == null) {
+            currentPath = new GeneralPath();
+        }
+        currentPath.lineTo(x, y);
+    }
+
+    /**
+     * @see org.apache.fop.render.AbstractPathOrientedRenderer#moveTo(float, float)
+     */
+    protected void moveTo(float x, float y) {
+        if (currentPath == null) {
+            currentPath = new GeneralPath();
+        }
+        currentPath.moveTo(x, y);
+    }
+    
+    /**
+     * Fill a rectangular area.
+     * @param x the x coordinate (in pt)
+     * @param y the y coordinate (in pt)
+     * @param width the width of the rectangle
+     * @param height the height of the rectangle
+     */
+    protected void fillRect(float x, float y, float width, float height) {
+        try {
+            Point2D p = transformedPoint(x * 1000, y * 1000);
+            gen.fillRect((int)p.getX(), (int)p.getY(), 
+                    (int)width * 1000, (int)height * 1000, 
+                    this.currentFillColor);
+        } catch (IOException ioe) {
+            handleIOTrouble(ioe);
+        }
+    }
+    
+    /**
+     * Sets the new current fill color.
+     * @param color the color
+     */
+    protected void updateFillColor(java.awt.Color color) {
+        this.currentFillColor = color;
     }
 
     private void updatePrintDirection() throws IOException {
@@ -482,37 +582,6 @@
     }
 
     /**
-     * @see org.apache.fop.render.AbstractRenderer#renderViewport(org.apache.fop.area.inline.Viewport)
-     */
-    public void renderViewport(Viewport viewport) {
-
-        float x = currentIPPosition / 1000f;
-        float y = (currentBPPosition + viewport.getOffset()) / 1000f;
-        float width = viewport.getIPD() / 1000f;
-        float height = viewport.getBPD() / 1000f;
-        // TODO: Calculate the border rect correctly. 
-        float borderPaddingStart = viewport.getBorderAndPaddingWidthStart() / 1000f;
-        float borderPaddingBefore = viewport.getBorderAndPaddingWidthBefore() / 1000f;
-        float bpwidth = borderPaddingStart 
-                + (viewport.getBorderAndPaddingWidthEnd() / 1000f);
-        float bpheight = borderPaddingBefore
-                + (viewport.getBorderAndPaddingWidthAfter() / 1000f);
-
-        drawBackAndBorders(viewport, x, y, width + bpwidth, height + bpheight);
-
-        if (viewport.getClip()) {
-            saveGraphicsState();
-
-            clipRect(x + borderPaddingStart, y + borderPaddingBefore, width, height);
-        }
-        super.renderViewport(viewport);
-
-        if (viewport.getClip()) {
-            restoreGraphicsState();
-        }
-    }
-
-    /**
      * @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport, List)
      */
     protected void renderBlockViewport(BlockViewport bv, List children) {
@@ -625,7 +694,17 @@
      * @see org.apache.fop.render.AbstractRenderer#renderImage(Image, Rectangle2D)
      */
     public void renderImage(Image image, Rectangle2D pos) {
-        String url = ImageFactory.getURL(image.getURL());
+        drawImage(image.getURL(), pos, image.getForeignAttributes());
+    }
+
+    /**
+     * Draw an image at the indicated location.
+     * @param url the URI/URL of the image
+     * @param pos the position of the image
+     * @param foreignAttributes an optional Map with foreign attributes, may be null
+     */
+    protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) {
+        url = ImageFactory.getURL(url);
         ImageFactory fact = userAgent.getFactory().getImageFactory();
         FopImage fopimage = fact.getImage(url, userAgent);
         if (fopimage == null) {
@@ -642,7 +721,7 @@
             Document doc = ((XMLImage) fopimage).getDocument();
             String ns = ((XMLImage) fopimage).getNameSpace();
 
-            renderDocument(doc, ns, pos, image.getForeignAttributes());
+            renderDocument(doc, ns, pos, foreignAttributes);
         } else if ("image/svg+xml".equals(mime)) {
             if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
                 return;
@@ -650,7 +729,7 @@
             Document doc = ((XMLImage) fopimage).getDocument();
             String ns = ((XMLImage) fopimage).getNameSpace();
 
-            renderDocument(doc, ns, pos, image.getForeignAttributes());
+            renderDocument(doc, ns, pos, foreignAttributes);
         } else if (fopimage instanceof EPSImage) {
             log.warn("EPS images are not supported by this renderer");
         } else {
@@ -678,7 +757,7 @@
             RenderedImage img = new BufferedImage(cm, raster, false, null);
 
             try {
-                moveTo(this.currentIPPosition + (int)pos.getX(),
+                setCursorPos(this.currentIPPosition + (int)pos.getX(),
                         this.currentBPPosition + (int)pos.getY());
                 int resolution = (int)Math.round(Math.max(fopimage.getHorizontalResolution(), 
                                         fopimage.getVerticalResolution()));
@@ -706,27 +785,72 @@
      * @param foreignAttributes the foreign attributes containing rendering hints, or null
      */
     public void renderDocument(Document doc, String ns, Rectangle2D pos, Map foreignAttributes) {
+        int x = currentIPPosition + (int) pos.getX(); 
+        int y = currentBPPosition + (int) pos.getY();
+        int width = (int)pos.getWidth();
+        int height = (int)pos.getHeight();
+        RendererContext context = createRendererContext(x, y, width, height, foreignAttributes);
+        
+        renderXML(context, doc, ns);
+    }
+
+    /**
+     * Creates a RendererContext for an image.
+     * @param x the x coordinate (in millipoints)
+     * @param y the y coordinate (in millipoints)
+     * @param width the width of the image (in millipoints)
+     * @param height the height of the image (in millipoints)
+     * @param foreignAttributes a Map or foreign attributes, may be null
+     * @return the RendererContext
+     */
+    protected RendererContext createRendererContext(int x, int y, int width, int height, 
+            Map foreignAttributes) {
         RendererContext context;
         context = new RendererContext(this, MIME_TYPE);
         context.setUserAgent(userAgent);
 
         context.setProperty(RendererContextConstants.WIDTH,
-                            new Integer((int) pos.getWidth()));
+                            new Integer(width));
         context.setProperty(RendererContextConstants.HEIGHT,
-                            new Integer((int) pos.getHeight()));
+                            new Integer(height));
         context.setProperty(RendererContextConstants.XPOS,
-                            new Integer(currentIPPosition + (int) pos.getX()));
+                            new Integer(x));
         context.setProperty(RendererContextConstants.YPOS,
-                            new Integer(currentBPPosition + (int) pos.getY()));
+                            new Integer(y));
         context.setProperty(RendererContextConstants.PAGE_VIEWPORT, 
                             getCurrentPageViewport());
         if (foreignAttributes != null) {
             context.setProperty(RendererContextConstants.FOREIGN_ATTRIBUTES, foreignAttributes);
         }
-        
-        renderXML(context, doc, ns);
+        return context;
     }
 
+    /** 
+     * Common method to render the background and borders for any inline area.
+     * The all borders and padding are drawn outside the specified area.
+     * @param area the inline area for which the background, border and padding is to be
+     * rendered
+     * @todo Copied from AbstractPathOrientedRenderer
+     */
+    protected void renderInlineAreaBackAndBorders(InlineArea area) {
+        float x = currentIPPosition / 1000f;
+        float y = (currentBPPosition + area.getOffset()) / 1000f;
+        float width = area.getIPD() / 1000f;
+        float height = area.getBPD() / 1000f;
+        float borderPaddingStart = area.getBorderAndPaddingWidthStart() / 1000f;
+        float borderPaddingBefore = area.getBorderAndPaddingWidthBefore() / 1000f;
+        float bpwidth = borderPaddingStart 
+                + (area.getBorderAndPaddingWidthEnd() / 1000f);
+        float bpheight = borderPaddingBefore
+                + (area.getBorderAndPaddingWidthAfter() / 1000f);
+        
+        if (height != 0.0f || bpheight != 0.0f && bpwidth != 0.0f) {
+            drawBackAndBorders(area, x, y - borderPaddingBefore
+                                , width + bpwidth
+                                , height + bpheight);
+        }
+    }
+    
     /**
      * Draw the background and borders. This draws the background and border
      * traits for an area given the position.
@@ -742,127 +866,401 @@
         try {
             updatePrintDirection();
             BorderProps bpsBefore = (BorderProps) area.getTrait(Trait.BORDER_BEFORE);
-        BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER);
-        BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START);
-        BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END);
-    
-        // draw background
-        Trait.Background back;
-        back = (Trait.Background) area.getTrait(Trait.BACKGROUND);
-        if (back != null) {
-    
-            // Calculate padding rectangle
-            float sx = startx;
-            float sy = starty;
-            float paddRectWidth = width;
-            float paddRectHeight = height;
-    
-            if (bpsStart != null) {
-                sx += bpsStart.width / 1000f;
-                paddRectWidth -= bpsStart.width / 1000f;
-            }
-            if (bpsBefore != null) {
-                sy += bpsBefore.width / 1000f;
-                paddRectHeight -= bpsBefore.width / 1000f;
-            }
-            if (bpsEnd != null) {
-                paddRectWidth -= bpsEnd.width / 1000f;
-            }
-            if (bpsAfter != null) {
-                paddRectHeight -= bpsAfter.width / 1000f;
-            }
-    
-            if (back.getColor() != null) {
-                Point2D p = transformedPoint(sx * 1000, sy * 1000);
-                gen.fillRect((int)p.getX(), (int)p.getY(), 
-                        (int)paddRectWidth * 1000, (int)paddRectHeight * 1000, 
-                        back.getColor().getAWTColor());
-            }
-    
-            // background image
-            if (back.getFopImage() != null) {
-                FopImage fopimage = back.getFopImage();
-                if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
-                    saveGraphicsState();
-                    clipRect(sx, sy, paddRectWidth, paddRectHeight);
-                    int horzCount = (int) ((paddRectWidth * 1000 / fopimage
-                            .getIntrinsicWidth()) + 1.0f);
-                    int vertCount = (int) ((paddRectHeight * 1000 / fopimage
-                            .getIntrinsicHeight()) + 1.0f);
-                    if (back.getRepeat() == EN_NOREPEAT) {
-                        horzCount = 1;
-                        vertCount = 1;
-                    } else if (back.getRepeat() == EN_REPEATX) {
-                        vertCount = 1;
-                    } else if (back.getRepeat() == EN_REPEATY) {
-                        horzCount = 1;
-                    }
-                    // change from points to millipoints
-                    sx *= 1000;
-                    sy *= 1000;
-                    if (horzCount == 1) {
-                        sx += back.getHoriz();
-                    }
-                    if (vertCount == 1) {
-                        sy += back.getVertical();
-                    }
-                    for (int x = 0; x < horzCount; x++) {
-                        for (int y = 0; y < vertCount; y++) {
-                            // place once
-                            Rectangle2D pos;
-                            pos = new Rectangle2D.Float(sx
-                                    + (x * fopimage.getIntrinsicWidth()), sy
-                                    + (y * fopimage.getIntrinsicHeight()),
-                                    fopimage.getIntrinsicWidth(), fopimage
-                                            .getIntrinsicHeight());
-                            //putImage(back.getURL(), pos); // TODO test
+            BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER);
+            BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START);
+            BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END);
+        
+            // draw background
+            Trait.Background back;
+            back = (Trait.Background) area.getTrait(Trait.BACKGROUND);
+            if (back != null) {
+        
+                // Calculate padding rectangle
+                float sx = startx;
+                float sy = starty;
+                float paddRectWidth = width;
+                float paddRectHeight = height;
+        
+                if (bpsStart != null) {
+                    sx += bpsStart.width / 1000f;
+                    paddRectWidth -= bpsStart.width / 1000f;
+                }
+                if (bpsBefore != null) {
+                    sy += bpsBefore.width / 1000f;
+                    paddRectHeight -= bpsBefore.width / 1000f;
+                }
+                if (bpsEnd != null) {
+                    paddRectWidth -= bpsEnd.width / 1000f;
+                }
+                if (bpsAfter != null) {
+                    paddRectHeight -= bpsAfter.width / 1000f;
+                }
+        
+                if (back.getColor() != null) {
+                    updateFillColor(back.getColor().getAWTColor());
+                    fillRect(sx, sy, paddRectWidth, paddRectHeight);
+                }
+        
+                // background image
+                if (back.getFopImage() != null) {
+                    FopImage fopimage = back.getFopImage();
+                    if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
+                        saveGraphicsState();
+                        clipRect(sx, sy, paddRectWidth, paddRectHeight);
+                        int horzCount = (int) ((paddRectWidth * 1000 / fopimage
+                                .getIntrinsicWidth()) + 1.0f);
+                        int vertCount = (int) ((paddRectHeight * 1000 / fopimage
+                                .getIntrinsicHeight()) + 1.0f);
+                        if (back.getRepeat() == EN_NOREPEAT) {
+                            horzCount = 1;
+                            vertCount = 1;
+                        } else if (back.getRepeat() == EN_REPEATX) {
+                            vertCount = 1;
+                        } else if (back.getRepeat() == EN_REPEATY) {
+                            horzCount = 1;
+                        }
+                        // change from points to millipoints
+                        sx *= 1000;
+                        sy *= 1000;
+                        if (horzCount == 1) {
+                            sx += back.getHoriz();
                         }
+                        if (vertCount == 1) {
+                            sy += back.getVertical();
+                        }
+                        for (int x = 0; x < horzCount; x++) {
+                            for (int y = 0; y < vertCount; y++) {
+                                // place once
+                                Rectangle2D pos;
+                                // Image positions are relative to the currentIP/BP
+                                pos = new Rectangle2D.Float(
+                                        sx - currentIPPosition 
+                                            + (x * fopimage.getIntrinsicWidth()),
+                                        sy - currentBPPosition
+                                            + (y * fopimage.getIntrinsicHeight()),
+                                        fopimage.getIntrinsicWidth(),
+                                        fopimage.getIntrinsicHeight());
+                                drawImage(back.getURL(), pos, null);
+                            }
+                        }
+                        restoreGraphicsState();
+                    } else {
+                        log.warn(
+                                "Can't find background image: " + back.getURL());
                     }
-                    restoreGraphicsState();
-                } else {
-                    log.warn(
-                            "Can't find background image: " + back.getURL());
                 }
             }
+            
+            Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height);
+            drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
+            
+        } catch (IOException ioe) {
+            handleIOTrouble(ioe);
         }
-/*
-        // draw border
-        // BORDER_BEFORE
+    }
+
+    /**
+     * Draws borders.
+     * @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
+     */
+    protected void drawBorders(Rectangle2D.Float borderRect, 
+            final BorderProps bpsBefore, final BorderProps bpsAfter, 
+            final BorderProps bpsStart, final BorderProps bpsEnd) {
+        if (bpsBefore == null && bpsAfter == null && bpsStart == null && bpsEnd == null) {
+            return; //no borders to paint
+        }
+        if (qualityBeforeSpeed) {
+            drawQualityBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
+        } else {
+            drawFastBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
+        }
+    }
+    
+    /**
+     * Draws borders. Borders are drawn as shaded rectangles with no clipping.
+     * @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
+     */
+    protected void drawFastBorders(Rectangle2D.Float borderRect, 
+            final BorderProps bpsBefore, final BorderProps bpsAfter, 
+            final BorderProps bpsStart, final BorderProps bpsEnd) {
+        float startx = borderRect.x;
+        float starty = borderRect.y;
+        float width = borderRect.width;
+        float height = borderRect.height;
         if (bpsBefore != null) {
             int borderWidth = (int) Math.round((bpsBefore.width / 1000f));
-            state.updateColor(bpsBefore.color);
-            state.getGraph().fillRect((int) startx, (int) starty, (int) width,
+            updateFillColor(bpsBefore.color.getAWTColor());
+            fillRect((int) startx, (int) starty, (int) width,
                     borderWidth);
         }
-        // BORDER_AFTER
         if (bpsAfter != null) {
             int borderWidth = (int) Math.round((bpsAfter.width / 1000f));
-            float sy = starty + height;
-            state.updateColor(bpsAfter.color);
-            state.getGraph().fillRect((int) startx,
+            updateFillColor(bpsAfter.color.getAWTColor());
+            fillRect((int) startx,
                     (int) (starty + height - borderWidth), (int) width,
                     borderWidth);
         }
-        // BORDER_START
         if (bpsStart != null) {
             int borderWidth = (int) Math.round((bpsStart.width / 1000f));
-            state.updateColor(bpsStart.color);
-            state.getGraph().fillRect((int) startx, (int) starty, borderWidth,
+            updateFillColor(bpsStart.color.getAWTColor());
+            fillRect((int) startx, (int) starty, borderWidth,
                     (int) height);
         }
-        // BORDER_END
         if (bpsEnd != null) {
             int borderWidth = (int) Math.round((bpsEnd.width / 1000f));
-            float sx = startx + width;
-            state.updateColor(bpsEnd.color);
-            state.getGraph().fillRect((int) (startx + width - borderWidth),
+            updateFillColor(bpsEnd.color.getAWTColor());
+            fillRect((int) (startx + width - borderWidth),
                     (int) starty, borderWidth, (int) height);
         }
-        */
+    }
+    
+    /**
+     * Draws borders. Borders are drawn in-memory and painted as a bitmap.
+     * @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
+     */
+    protected void drawQualityBorders(Rectangle2D.Float borderRect, 
+            final BorderProps bpsBefore, final BorderProps bpsAfter, 
+            final BorderProps bpsStart, final BorderProps bpsEnd) {
+        Graphics2DAdapter g2a = getGraphics2DAdapter();
+        final Rectangle.Float effBorderRect = new Rectangle2D.Float(
+                 borderRect.x - (currentIPPosition / 1000f),
+                 borderRect.y - (currentBPPosition / 1000f),
+                 borderRect.width, borderRect.height);
+        final Rectangle paintRect = new Rectangle(
+                (int)Math.round(borderRect.x * 1000),
+                (int)Math.round(borderRect.y * 1000), 
+                (int)Math.floor(borderRect.width * 1000) + 1,
+                (int)Math.floor(borderRect.height * 1000) + 1);
+        int xoffset = (bpsStart != null ? bpsStart.width : 0);
+        paintRect.x += xoffset;
+        paintRect.width += xoffset;
+        paintRect.width += (bpsEnd != null ? bpsEnd.width : 0);
+        
+        RendererContext rc = createRendererContext(paintRect.x, paintRect.y, 
+                paintRect.width, paintRect.height, null);
+        if (false) {
+            Map atts = new java.util.HashMap();
+            atts.put(new QName(ExtensionElementMapping.URI, null, "conversion-mode"), "bitmap");
+            rc.setProperty(RendererContextConstants.FOREIGN_ATTRIBUTES, atts);
+        }
+        
+        Graphics2DImagePainter painter = new Graphics2DImagePainter() {
+
+            public void paint(Graphics2D g2d, Rectangle2D area) {
+                g2d.translate((bpsStart != null ? bpsStart.width : 0), 0);
+                g2d.scale(1000, 1000);
+                float startx = effBorderRect.x;
+                float starty = effBorderRect.y;
+                float width = effBorderRect.width;
+                float height = effBorderRect.height;
+                boolean[] b = new boolean[] {
+                    (bpsBefore != null), (bpsEnd != null), 
+                    (bpsAfter != null), (bpsStart != null)};
+                if (!b[0] && !b[1] && !b[2] && !b[3]) {
+                    return;
+                }
+                float[] bw = new float[] {
+                    (b[0] ? bpsBefore.width / 1000f : 0.0f),
+                    (b[1] ? bpsEnd.width / 1000f : 0.0f),
+                    (b[2] ? bpsAfter.width / 1000f : 0.0f),
+                    (b[3] ? bpsStart.width / 1000f : 0.0f)};
+                float[] clipw = new float[] {
+                    BorderProps.getClippedWidth(bpsBefore) / 1000f,    
+                    BorderProps.getClippedWidth(bpsEnd) / 1000f,    
+                    BorderProps.getClippedWidth(bpsAfter) / 1000f,    
+                    BorderProps.getClippedWidth(bpsStart) / 1000f};
+                starty += clipw[0];
+                height -= clipw[0];
+                height -= clipw[2];
+                startx += clipw[3];
+                width -= clipw[3];
+                width -= clipw[1];
+                
+                boolean[] slant = new boolean[] {
+                    (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])};
+                if (bpsBefore != null) {
+                    //endTextObject();
+
+                    float sx1 = startx;
+                    float sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1);
+                    float ex1 = startx + width;
+                    float ex2 = (slant[1] ? ex1 - bw[1] + clipw[1] : ex1);
+                    float outery = starty - clipw[0];
+                    float clipy = outery + clipw[0];
+                    float innery = outery + bw[0];
+
+                    //saveGraphicsState();
+                    Graphics2D g = (Graphics2D)g2d.create();
+                    moveTo(sx1, clipy);
+                    float sx1a = sx1;
+                    float ex1a = ex1;
+                    if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+                        if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+                            sx1a -= clipw[3];
+                        }
+                        if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+                            ex1a += clipw[1];
+                        }
+                        lineTo(sx1a, outery);
+                        lineTo(ex1a, outery);
+                    }
+                    lineTo(ex1, clipy);
+                    lineTo(ex2, innery);
+                    lineTo(sx2, innery);
+                    closePath();
+                    //clip();
+                    g.clip(currentPath);
+                    currentPath = null;
+                    Rectangle2D.Float lineRect = new Rectangle2D.Float(
+                            sx1a, outery, ex1a - sx1a, innery - outery);
+                    Java2DRenderer.drawBorderLine(lineRect, true, true, 
+                            bpsBefore.style, toColor(bpsBefore.color), g);
+                    //restoreGraphicsState();
+                }
+                if (bpsEnd != null) {
+                    //endTextObject();
+
+                    float sy1 = starty;
+                    float sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1);
+                    float ey1 = starty + height;
+                    float ey2 = (slant[2] ? ey1 - bw[2] + clipw[2] : ey1);
+                    float outerx = startx + width + clipw[1];
+                    float clipx = outerx - clipw[1];
+                    float innerx = outerx - bw[1];
+                    
+                    //saveGraphicsState();
+                    Graphics2D g = (Graphics2D)g2d.create();
+                    moveTo(clipx, sy1);
+                    float sy1a = sy1;
+                    float ey1a = ey1;
+                    if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+                        if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+                            sy1a -= clipw[0];
+                        }
+                        if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+                            ey1a += clipw[2];
+                        }
+                        lineTo(outerx, sy1a);
+                        lineTo(outerx, ey1a);
+                    }
+                    lineTo(clipx, ey1);
+                    lineTo(innerx, ey2);
+                    lineTo(innerx, sy2);
+                    closePath();
+                    //clip();
+                    g.setClip(currentPath);
+                    currentPath = null;
+                    Rectangle2D.Float lineRect = new Rectangle2D.Float(
+                            innerx, sy1a, outerx - innerx, ey1a - sy1a);
+                    Java2DRenderer.drawBorderLine(lineRect, false, false, 
+                            bpsEnd.style, toColor(bpsEnd.color), g);
+                    //restoreGraphicsState();
+                }
+                if (bpsAfter != null) {
+                    //endTextObject();
+
+                    float sx1 = startx;
+                    float sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1);
+                    float ex1 = startx + width;
+                    float ex2 = (slant[2] ? ex1 - bw[1] + clipw[1] : ex1);
+                    float outery = starty + height + clipw[2];
+                    float clipy = outery - clipw[2];
+                    float innery = outery - bw[2];
+
+                    //saveGraphicsState();
+                    Graphics2D g = (Graphics2D)g2d.create();
+                    moveTo(ex1, clipy);
+                    float sx1a = sx1;
+                    float ex1a = ex1;
+                    if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+                        if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+                            sx1a -= clipw[3];
+                        }
+                        if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+                            ex1a += clipw[1];
+                        }
+                        lineTo(ex1a, outery);
+                        lineTo(sx1a, outery);
+                    }
+                    lineTo(sx1, clipy);
+                    lineTo(sx2, innery);
+                    lineTo(ex2, innery);
+                    closePath();
+                    //clip();
+                    g.setClip(currentPath);
+                    currentPath = null;
+                    Rectangle2D.Float lineRect = new Rectangle2D.Float(
+                            sx1a, innery, ex1a - sx1a, outery - innery);
+                    Java2DRenderer.drawBorderLine(lineRect, true, false, 
+                            bpsAfter.style, toColor(bpsAfter.color), g);
+                    //restoreGraphicsState();
+                }
+                if (bpsStart != null) {
+                    //endTextObject();
+
+                    float sy1 = starty;
+                    float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1);
+                    float ey1 = sy1 + height;
+                    float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1);
+                    float outerx = startx - clipw[3];
+                    float clipx = outerx + clipw[3];
+                    float innerx = outerx + bw[3];
+
+                    //saveGraphicsState();
+                    Graphics2D g = (Graphics2D)g2d.create();
+                    moveTo(clipx, ey1);
+                    float sy1a = sy1;
+                    float ey1a = ey1;
+                    if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+                        if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+                            sy1a -= clipw[0];
+                        }
+                        if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+                            ey1a += clipw[2];
+                        }
+                        lineTo(outerx, ey1a);
+                        lineTo(outerx, sy1a);
+                    }
+                    lineTo(clipx, sy1);
+                    lineTo(innerx, sy2);
+                    lineTo(innerx, ey2);
+                    closePath();
+                    //clip();
+                    g.setClip(currentPath);
+                    currentPath = null;
+                    Rectangle2D.Float lineRect = new Rectangle2D.Float(
+                            outerx, sy1a, innerx - outerx, ey1a - sy1a);
+                    Java2DRenderer.drawBorderLine(lineRect, false, false, 
+                            bpsStart.style, toColor(bpsStart.color), g);
+                    //restoreGraphicsState();
+                }
+            }
+
+            public Dimension getImageSize() {
+                return paintRect.getSize();
+            }
+            
+        };
+        try {
+            g2a.paintImage(painter, rc, 
+                    paintRect.x - xoffset, paintRect.y, paintRect.width, paintRect.height);
         } catch (IOException ioe) {
             handleIOTrouble(ioe);
         }
     }
-
+    
+    
     
 }

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLSVGHandler.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLSVGHandler.java?rev=398945&r1=398944&r2=398945&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLSVGHandler.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/pcl/PCLSVGHandler.java Tue May  2 07:39:32 2006
@@ -86,33 +86,35 @@
         int x = pclContext.getCurrentXPosition();
         int y = pclContext.getCurrentYPosition();
 
+        SVGUserAgent ua = new SVGUserAgent(
+                context.getUserAgent().getSourcePixelUnitToMillimeter(),
+                new AffineTransform());
+        GVTBuilder builder = new GVTBuilder();
+        final BridgeContext ctx = new BridgeContext(ua);
+
+        final GraphicsNode root;
+        try {
+            root = builder.build(ctx, doc);
+            
+        } catch (Exception e) {
+            log.error("SVG graphic could not be built: "
+                                   + e.getMessage(), e);
+            return;
+        }
+
         Graphics2DImagePainter painter = new Graphics2DImagePainter() {
 
             public void paint(Graphics2D g2d, Rectangle2D area) {
-                SVGUserAgent ua = new SVGUserAgent(
-                        context.getUserAgent().getSourcePixelUnitToMillimeter(),
-                        new AffineTransform());
-                GVTBuilder builder = new GVTBuilder();
-                BridgeContext ctx = new BridgeContext(ua);
-
-                GraphicsNode root;
-                try {
-                    root = builder.build(ctx, doc);
-                    
-                    // If no viewbox is defined in the svg file, a viewbox of 100x100 is
-                    // assumed, as defined in SVGUserAgent.getViewportSize()
-                    float iw = (float) ctx.getDocumentSize().getWidth() * 1000f;
-                    float ih = (float) ctx.getDocumentSize().getHeight() * 1000f;
-                    float w = (float) area.getWidth();
-                    float h = (float) area.getHeight();
-                    g2d.scale(w / iw, h / ih);
+                
+                // If no viewbox is defined in the svg file, a viewbox of 100x100 is
+                // assumed, as defined in SVGUserAgent.getViewportSize()
+                float iw = (float) ctx.getDocumentSize().getWidth();
+                float ih = (float) ctx.getDocumentSize().getHeight();
+                float w = (float) area.getWidth();
+                float h = (float) area.getHeight();
+                g2d.scale(w / iw, h / ih);
 
-                    root.paint(g2d);
-                } catch (Exception e) {
-                    log.error("SVG graphic could not be built: "
-                                           + e.getMessage(), e);
-                    return;
-                }
+                root.paint(g2d);
             }
 
             public Dimension getImageSize() {

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java?rev=398945&r1=398944&r2=398945&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java Tue May  2 07:39:32 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.area.LineArea;
 import org.apache.fop.area.inline.ForeignObject;
+import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.TextArea;
 import org.apache.fop.svg.SVGUtilities;
@@ -430,6 +431,10 @@
      * @see org.apache.fop.render.AbstractRenderer#endVParea()
      */
     protected void endVParea() {
+        // TODO Auto-generated method stub
+    }
+
+    protected void renderInlineAreaBackAndBorders(InlineArea area) {
         // TODO Auto-generated method stub
     }
 



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