Package org.apache.fop.render

Source Code of org.apache.fop.render.AbstractRenderer

/*
* $Id: AbstractRenderer.java,v 1.4.2.10 2003/03/02 16:55:17 pietsch Exp $
* ============================================================================
*                    The Apache Software License, Version 1.1
* ============================================================================
*
* Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
*    include the following acknowledgment: "This product includes software
*    developed by the Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself, if
*    and wherever such third-party acknowledgments normally appear.
*
* 4. The names "FOP" and "Apache Software Foundation" must not be used to
*    endorse or promote products derived from this software without prior
*    written permission. For written permission, please contact
*    apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache", nor may
*    "Apache" appear in their name, without prior written permission of the
*    Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ============================================================================
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation and was originally created by
* James Tauber <jtauber@jtauber.com>. For more information on the Apache
* Software Foundation, please see <http://www.apache.org/>.
*/
package org.apache.fop.render;

// FOP
import org.apache.fop.image.ImageArea;
import org.apache.fop.image.FopImage;
import org.apache.fop.image.FopImageException;
import org.apache.fop.fo.properties.*;
import org.apache.fop.layout.*;
import org.apache.fop.layout.inline.*;
import org.apache.fop.datatypes.*;

// Avalon
import org.apache.avalon.framework.logger.Logger;

// Java
import java.util.List;

/**
* Abstract base class for all renderers.
*
*/
public abstract class AbstractRenderer implements Renderer {
    protected Logger log;

    /**
     * the current vertical position in millipoints from bottom
     */
    protected int currentYPosition = 0;

    /**
     * the current horizontal position in millipoints from left
     */
    protected int currentXPosition = 0;

    /**
     * the horizontal position of the current area container
     */
    protected int currentAreaContainerXPosition = 0;

    protected IDReferences idReferences;

    public void setLogger(Logger logger) {
        log = logger;
    }

    public void renderSpanArea(SpanArea area) {
        List children = area.getChildren();
        for (int i = 0; i < children.size(); i++) {
            Box b = (Box)children.get(i);
            b.render(this);    // column areas
        }

    }

    protected abstract void doFrame(Area area);

    /**
     * Renders an area's background.
     * @param x the x position of the left edge in millipoints
     * @param y the y position of top edge in millipoints
     * @param w the width in millipoints
     * @param h the height in millipoints
     */
    protected void doBackground(Area area, int x, int y, int w, int h) {
        if (h == 0 || w == 0)
            return;

        BackgroundProps props = area.getBackground();
        if (props == null)
            return;

        if (props.backColor.alpha() == 0) {
            this.addFilledRect(x, y, w, -h, props.backColor);
        }

        // XXX: I'm ignoring area rotation here 8(
        //      is this taken care of for me elsewhere in the codebase?
        if (props.backImage != null) {
            int imgW;
            int imgH;
            try {
            // XXX: do correct unit conversion here
            imgW = props.backImage.getWidth() * 1000;
            imgH = props.backImage.getHeight() * 1000;
            }
            catch (FopImageException fie) {
            log.error("Error obtaining bg image width and height", fie);
            return;
            }

            int dx = x;
            int dy = y;
            int endX = x + w;
            int endY = y - h;
            int clipW = w % imgW;
            int clipH = h % imgH;

            boolean repeatX = true;
            boolean repeatY = true;
            switch (props.backRepeat) {
            case BackgroundRepeat.REPEAT:
            break;

            case BackgroundRepeat.REPEAT_X:
            repeatY = false;
            break;

            case BackgroundRepeat.REPEAT_Y:
            repeatX = false;
            break;

            case BackgroundRepeat.NO_REPEAT:
            repeatX = false;
            repeatY = false;
            break;

            case BackgroundRepeat.INHERIT:
            // XXX: what to do here?
            break;

            default:
            log.error("Ignoring invalid background-repeat property");
            }

            FontState fs = area.getFontState();

            while (dy > endY) { // looping through rows
            while (dx < endX) { // looping through cols
                if (dx + imgW <= endX) {
                // no x clipping
                if (dy - imgH >= endY) {
                    // no x clipping, no y clipping
                    drawImageScaled(dx, dy, imgW, imgH,
                            props.backImage, fs);
                }
                else {
                    // no x clipping, y clipping
                    drawImageClipped(dx, dy,
                             0, 0, imgW, clipH,
                             props.backImage, fs);
                }
                }
                else {
                // x clipping
                if (dy - imgH >= endY) {
                    // x clipping, no y clipping
                    drawImageClipped(dx, dy,
                             0, 0, clipW, imgH,
                             props.backImage, fs);
                }

                else {
                    // x clipping, y clipping
                    drawImageClipped(dx, dy,
                             0, 0, clipW, clipH,
                             props.backImage, fs);
                }
                }

                if (repeatX) {
                dx += imgW;
                }
                else {
                break;
                }
            } // end looping through cols

            dx = x;

            if (repeatY) {
                dy -= imgH;
            }
            else {
                break;
            }
            } // end looping through rows
        }
    }

    /**
     * Add a filled rectangle to the current stream
     * This default implementation calls addRect
     * using the same color for fill and border.
     *
     * @param x the x position of left edge in millipoints
     * @param y the y position of top edge in millipoints
     * @param w the width in millipoints
     * @param h the height in millipoints
     * @param fill the fill color/gradient
     */
    protected abstract void addFilledRect(int x, int y, int w, int h,
                                 ColorType col);

    /**
     * Renders an image, rendered at the image's intrinsic size.
     * This by default calls drawImageScaled() with the image's
     * intrinsic width and height, but implementations may
     * override this method if it can provide a more efficient solution.
     *
     * @param x the x position of left edge in millipoints
     * @param y the y position of top edge in millipoints
     * @param image the image to be rendered
     * @param fs the font state to use when rendering text
     *           in non-bitmapped images.
     */
    protected void drawImage(int x, int y, FopImage image, FontState fs) {
        int w;
        int h;
        try {
            // XXX: convert these units correctly
            w = image.getWidth() * 1000;
            h = image.getHeight() * 1000;
        }
        catch (FopImageException e) {
            log.error("Failed to obtain the image width and height", e);
            return;
        }
        drawImageScaled(x, y, w, h, image, fs);
    }

    /**
     * Renders an image, scaling it to the given width and height.
     * If the scaled width and height is the same intrinsic size
     * of the image, the image is not scaled.
     *
     * @param x the x position of left edge in millipoints
     * @param y the y position of top edge in millipoints
     * @param w the width in millipoints
     * @param h the height in millipoints
     * @param image the image to be rendered
     * @param fs the font state to use when rendering text
     *           in non-bitmapped images.
     */
    protected abstract void drawImageScaled(int x, int y, int w, int h,
                        FopImage image,
                        FontState fs);

    /**
     * Renders an image, clipping it as specified.
     *
     * @param x the x position of left edge in millipoints.
     * @param y the y position of top edge in millipoints.
     * @param clipX the left edge of the clip in millipoints
     * @param clipY the top edge of the clip in millipoints
     * @param clipW the clip width in millipoints
     * @param clipH the clip height in millipoints
     * @param fill the image to be rendered
     * @param fs the font state to use when rendering text
     *           in non-bitmapped images.
     */
    protected abstract void drawImageClipped(int x, int y,
                         int clipX, int clipY,
                         int clipW, int clipH,
                         FopImage image,
                         FontState fs);

    /**
     * Render an image area.
     *
     * @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 == null) {
            log.error("Error while loading image: area.getImage() is null");
        } else {
            drawImageScaled(x, y, w, h, img, area.getFontState());
        }

        this.currentXPosition += w;
    }

    public void renderBodyAreaContainer(BodyAreaContainer area) {
        int saveY = this.currentYPosition;
        int saveX = this.currentAreaContainerXPosition;

        if (area.getPosition() == Position.ABSOLUTE) {
            // Y position is computed assuming positive Y axis, adjust for negative postscript one
            this.currentYPosition = area.getYPosition();
            this.currentAreaContainerXPosition = area.getXPosition();
        } else if (area.getPosition() == Position.RELATIVE) {
            this.currentYPosition -= area.getYPosition();
            this.currentAreaContainerXPosition += area.getXPosition();
        }

        this.currentXPosition = this.currentAreaContainerXPosition;
        int rx = this.currentAreaContainerXPosition;
        int ry = this.currentYPosition;
        // XXX: (mjg@recaldesign.com) I had to use getAllocationWidth()
        // and getMaxHeight() as the content width and height are
        // always 0. Is this supposed to be the case?
        // IMHO, the bg should cover the entire area anyway, not
        // just the parts with content, which makes this correct.
        // Probably want to check this for the other region
        // areas as well.
        int w = area.getAllocationWidth();
            int h = area.getMaxHeight();

        doBackground(area, rx, ry, w, h);

        // floats & footnotes stuff
        renderAreaContainer(area.getBeforeFloatReferenceArea());
        renderAreaContainer(area.getFootnoteReferenceArea());

        // main reference area
        List children = area.getMainReferenceArea().getChildren();
        for (int i = 0; i < children.size(); i++) {
            Box b = (Box)children.get(i);
            b.render(this);    // span areas
        }

        if (area.getPosition() != Position.STATIC) {
            this.currentYPosition = saveY;
            this.currentAreaContainerXPosition = saveX;
        } else {
            this.currentYPosition -= area.getHeight();
        }
    }

    /**
     * render region area container
     *
     * @param area the region area container to render
     */
    public void renderRegionAreaContainer(AreaContainer area) {
        int saveY = this.currentYPosition;
        int saveX = this.currentAreaContainerXPosition;

        if (area.getPosition() == Position.ABSOLUTE) {
            // Y position is computed assuming positive Y axis, adjust for negative postscript one
            this.currentYPosition = area.getYPosition();
            this.currentAreaContainerXPosition = area.getXPosition();
        } else if (area.getPosition() == Position.RELATIVE) {
            this.currentYPosition -= area.getYPosition();
            this.currentAreaContainerXPosition += area.getXPosition();
        }

        this.currentXPosition = this.currentAreaContainerXPosition;
        int rx = this.currentAreaContainerXPosition;
        int ry = this.currentYPosition;
        int w = area.getAllocationWidth();
        int h = area.getMaxHeight();

        doBackground(area, rx, ry, w, h);

        List children = area.getChildren();
        for (int i = 0; i < children.size(); i++) {
            Box b = (Box)children.get(i);
            b.render(this);    // span areas
        }

        if (area.getPosition() != Position.STATIC) {
            this.currentYPosition = saveY;
            this.currentAreaContainerXPosition = saveX;
        } else {
            this.currentYPosition -= area.getHeight();
        }
    }

    /**
     * render area container
     *
     * @param area the area container to render
     */
    public void renderAreaContainer(AreaContainer area) {

        int saveY = this.currentYPosition;
        int saveX = this.currentAreaContainerXPosition;

        if (area.getPosition() == Position.ABSOLUTE) {
            // XPosition and YPosition give the content rectangle position
            this.currentYPosition = area.getYPosition();
            this.currentAreaContainerXPosition = area.getXPosition();
        } else if (area.getPosition() == Position.RELATIVE) {
            this.currentYPosition -= area.getYPosition();
            this.currentAreaContainerXPosition += area.getXPosition();
        } else if (area.getPosition() == Position.STATIC) {
            this.currentYPosition -= area.getPaddingTop()
                                     + area.getBorderTopWidth();
            /*
             * this.currentAreaContainerXPosition +=
             * area.getPaddingLeft() + area.getBorderLeftWidth();
             */
        }

        this.currentXPosition = this.currentAreaContainerXPosition;
        doFrame(area);

        List children = area.getChildren();
        for (int i = 0; i < children.size(); i++) {
            Box b = (Box)children.get(i);
            b.render(this);
        }
        // Restore previous origin
        this.currentYPosition = saveY;
        this.currentAreaContainerXPosition = saveX;
        if (area.getPosition() == Position.STATIC) {
            this.currentYPosition -= area.getHeight();
        }

        /**
         * **
         * if (area.getPosition() != Position.STATIC) {
         * this.currentYPosition = saveY;
         * this.currentAreaContainerXPosition = saveX;
         * } else
         * this.currentYPosition -= area.getHeight();
         * **
         */
    }

    /**
     * render block area
     *
     * @param area the block area to render
     */
    public void renderBlockArea(BlockArea area) {
        // KLease: Temporary test to fix block positioning
        // Offset ypos by padding and border widths
        this.currentYPosition -= (area.getPaddingTop()
                                  + area.getBorderTopWidth());
        doFrame(area);
        List children = area.getChildren();
        for (int i = 0; i < children.size(); i++) {
            Box b = (Box)children.get(i);
            b.render(this);
        }
        this.currentYPosition -= (area.getPaddingBottom()
                                  + area.getBorderBottomWidth());
    }

    /**
     * render line area
     *
     * @param area area to render
     */
    public void renderLineArea(LineArea area) {
        int rx = this.currentAreaContainerXPosition + area.getStartIndent();
        int ry = this.currentYPosition;
        int w = area.getContentWidth();
        int h = area.getHeight();

        this.currentYPosition -= area.getPlacementOffset();
        this.currentXPosition = rx;

        int bl = this.currentYPosition;

        List children = area.getChildren();
        for (int i = 0; i < children.size(); i++) {
            Box b = (Box)children.get(i);
            if (b instanceof InlineArea) {
                InlineArea ia = (InlineArea)b;
                this.currentYPosition = ry - ia.getYOffset();
            } else {
                this.currentYPosition = ry - area.getPlacementOffset();
            }
            b.render(this);
        }

        this.currentYPosition = ry - h;
        this.currentXPosition = rx;
    }

    /**
     * render region areas
     *
     * @param page the page whose regions to render
     */
    public void renderRegions(Page page) {
        page.getBody().render(this);
        if (page.getBefore() != null)
            page.getBefore().render(this);
        if (page.getAfter() != null)
            page.getAfter().render(this);
        if (page.getStart() != null)
            page.getStart().render(this);
        if (page.getEnd() != null)
            page.getEnd().render(this);
    }

    public IDReferences getIDReferences() {
        return idReferences;
    }
}
TOP

Related Classes of org.apache.fop.render.AbstractRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.