You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-dev@xmlgraphics.apache.org by Paul Reavis <pr...@partnersoft.com> on 2002/04/25 16:36:39 UTC

stuck on OnTheFlyFopImage implementation

OK, I've gotten in over my head at last I think. This is what I have
so far - it's clearly calling the code, but I get tiny (1.1k) pdf with
nothing in it to speak of. I don't even pretend to understand PDF; I'm
just trying to make do with gum and duct tape here.

Warning: ugly code.

I added a class, OnTheFlyFopImage, did various bad things to
FopImageFactory so that I can plug them in and use them, and am stuck
trying to get good output from PDFRenderer - I think I might be having
coordinate space/AffineTransform or just plain PDF formatting
problems. I dunno, you tell me.

I could probably cobble this together as a patch to 0.20.3 and put up
a test case if anyone wanted to actually compile it; I was hoping that
someone would just spot the mistake though.

It's certainly fast :-)

****************************************

First, my OnTheFlyFopImage. As you can see, it does almost nothing
other than store the width and height and provide an abstract
paint(Graphics2D g) method for subclasses.

package org.apache.fop.image;

import org.apache.fop.datatypes.ColorSpace;
import org.apache.fop.pdf.PDFColor;
import org.apache.fop.pdf.PDFFilter;
import java.awt.Graphics2D;

public abstract class OnTheFlyFopImage implements FopImage {

    private String url;
    private ColorSpace colorSpace;
    private int height;
    private int width;

    public OnTheFlyFopImage(String url, int width, int height) throws
FopImageException {
        this.url = url;
        this.width = width;
        this.height = height;

        colorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
        }

    public boolean invertImage() {
        return false;
        }

    public String getURL() {
        return url;
        }

    // image size
    public int getWidth() throws FopImageException {
        return width;
        }

    public int getHeight() throws FopImageException {
        return height;
        }

    public ColorSpace getColorSpace() throws FopImageException {
        return colorSpace;
        }

    public int getBitsPerPixel() throws FopImageException {
        return 24;
        }

    public boolean isTransparent() throws FopImageException {
        return false;
        }

    public PDFColor getTransparentColor() throws FopImageException {
        return new PDFColor(0.0, 0.0, 0.0);
        }

    // get the image bytes, and bytes properties

    // get uncompressed image bytes
    public byte[] getBitmaps() throws FopImageException {
        return null;
        }

    // width * (bitsPerPixel / 8) * height, no ?
    public int getBitmapsSize() throws FopImageException {
        return 0;
        }

    // get compressed image bytes
    // I don't know if we really need it, nor if it
    // should be changed...
    public byte[] getRessourceBytes() throws FopImageException {
        return null;
        }

    public int getRessourceBytesSize() throws FopImageException {
        return 0;
        }

    // return null if no corresponding PDFFilter
    public PDFFilter getPDFFilter() throws FopImageException {
        return null;
        }

    // release memory
    public void close() {
        }

    // ******** subclass homework
    public abstract void paint(Graphics2D graphics);

}

****************************************

Here are the relevant parts of PDFRenderer that I modified. I changed
renderImageArea to pass through OnTheFlyFopImages to my new
renderOnTheFlyFopImage subroutine. The latter does the actual
production, or rather lack thereof.


    /**
     * render image area to PDF
     *
     * @param area the image area to render
     */
    public void renderImageArea(ImageArea area) {
        // adapted from contribution by BoBoGi
        int x = this.currentXPosition + area.getXOffset();
        int y = this.currentYPosition;
        int w = area.getContentWidth();
        int h = area.getHeight();

        this.currentYPosition -= h;

        FopImage img = area.getImage();
        if (img instanceof SVGImage) {
            try {
                closeText();

                SVGDocument svg = ((SVGImage)img).getSVGDocument();
                currentStream.add("ET\nq\n");
                renderSVGDocument(svg, (int)x, (int)y,
area.getFontState());
                currentStream.add("Q\nBT\n");
                } catch (FopImageException e) {}

            } 
        else if (img instanceof OnTheFlyFopImage) {
            //             try {
            closeText();
            //                  currentStream.add("ET\nq\n");
            renderOnTheFlyFopImage((OnTheFlyFopImage)img, x, y,
area.getFontState());
            //                  currentStream.add("Q\nBT\n");
            //                 } catch (FopImageException e) {}
            }

        else {
            int xObjectNum = this.pdfDoc.addImage(img);
            closeText();

            currentStream.add("ET\nq\n" + (((float)w) / 1000f) + " 0 0
"
                              + (((float)h) / 1000f) + " "
                              + (((float)x) / 1000f) + " "
                              + (((float)(y - h)) / 1000f) + " cm\n" +
"/Im"
                              + xObjectNum + " Do\nQ\nBT\n");
            }
        this.currentXPosition += area.getContentWidth();
        }


   /**
    * I copied and butchered this from renderSVGDocument. I took out
    * everything that seemed SVG-specific. It runs, and does indeed
    * use the graphics object, but nothing comes out in the final.
    */
    protected void renderOnTheFlyFopImage(OnTheFlyFopImage image, int
x, int y, FontState fs) {
        System.out.println("Rendering on-the-fly graphic to pdf.");

        try {

            // ******** mysterious stuff here
            float sx = 1, sy = -1;
            int xOffset = x, yOffset = y;

            // get the 'width' and 'height' attributes of the image
            float w = (float)image.getWidth() * 1000f;
            float h = (float)image.getHeight() * 1000f;

            currentStream.add("q\n");
            if (w != 0 && h != 0) {
                currentStream.add(x / 1000f + " " + y / 1000f + "
m\n");
                currentStream.add((x + w) / 1000f + " " + y / 1000f +
" l\n");
                currentStream.add((x + w) / 1000f + " " + (y - h) /
1000f
                                  + " l\n");
                currentStream.add(x / 1000f + " " + (y - h) / 1000f +
" l\n");
                currentStream.add("h\n");
                currentStream.add("W\n");
                currentStream.add("n\n");
                }
            // transform so that the coordinates (0,0) is from the top
left
            // and positive is down and to the right. (0,0) is where
the
            // viewBox puts it.
            currentStream.add(sx + " 0 0 " + sy + " " + xOffset /
1000f + " "
                              + yOffset / 1000f + " cm\n");


            // do the actual paint
            PDFGraphics2D graphics = new PDFGraphics2D(true, fs,
pdfDoc,
                                                       currentFontName,
                                                       currentFontSize,
                                                       currentXPosition,
                                                       currentYPosition);
            graphics.setGraphicContext(new
org.apache.batik.ext.awt.g2d.GraphicContext());
            image.paint(graphics);

            // more mystery
            currentStream.add(graphics.getString());
            currentAnnotList = graphics.getAnnotList();

            currentStream.add("Q\n");
            }
        catch (Exception oopsie) {
            oopsie.printStackTrace(System.err);
            }
        }

-- 

Paul Reavis                                      preavis@partnersoft.com
Design Lead
Partner Software, Inc.                        http://www.partnersoft.com

---------------------------------------------------------------------
To unsubscribe, e-mail: fop-dev-unsubscribe@xml.apache.org
For additional commands, email: fop-dev-help@xml.apache.org