/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */

package org.apache.fop.render.afp;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.util.Map;

import org.w3c.dom.Document;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageProcessingHints;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;

import org.apache.fop.afp.AFPBorderPainter;
import org.apache.fop.afp.AFPEventProducer;
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPResourceInfo;
import org.apache.fop.afp.AFPUnitConverter;
import org.apache.fop.afp.AbstractAFPPainter;
import org.apache.fop.afp.BorderPaintingInfo;
import org.apache.fop.afp.DataStream;
import org.apache.fop.afp.RectanglePaintingInfo;
import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.AFPFontAttributes;
import org.apache.fop.afp.fonts.AFPPageFonts;
import org.apache.fop.afp.fonts.CharacterSet;
import org.apache.fop.afp.modca.AbstractPageObject;
import org.apache.fop.afp.modca.PresentationTextObject;
import org.apache.fop.afp.ptoca.PtocaBuilder;
import org.apache.fop.afp.ptoca.PtocaProducer;
import org.apache.fop.afp.util.AFPResourceAccessor;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontType;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.ImageHandlerUtil;
import org.apache.fop.render.RenderingContext;
import org.apache.fop.render.intermediate.AbstractIFPainter;
import org.apache.fop.render.intermediate.BorderPainter;
import org.apache.fop.render.intermediate.GraphicsPainter;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFState;
import org.apache.fop.render.intermediate.IFUtil;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.CharUtilities;

/**
 * IFPainter implementation that produces AFP (MO:DCA).
 */
public class AFPPainter extends AbstractIFPainter<AFPDocumentHandler> {

    private static final int X = 0;

    private static final int Y = 1;

    private final GraphicsPainter graphicsPainter;

    /** the border painter */
    private final AFPBorderPainterAdapter borderPainter;
    /** the rectangle painter */
    private final AbstractAFPPainter rectanglePainter;

    /** unit converter */
    private final AFPUnitConverter unitConv;

    private final AFPEventProducer eventProducer;
    private Integer bytesAvailable;

    /**
     * Default constructor.
     * @param documentHandler the parent document handler
     */
    public AFPPainter(AFPDocumentHandler documentHandler) {
        super(documentHandler);
        this.state = IFState.create();
        this.graphicsPainter = new AFPGraphicsPainter(
                new AFPBorderPainter(getPaintingState(), getDataStream()));
        this.borderPainter = new AFPBorderPainterAdapter(graphicsPainter, this, documentHandler);
        this.rectanglePainter = documentHandler.createRectanglePainter();
        this.unitConv = getPaintingState().getUnitConverter();
        this.eventProducer = AFPEventProducer.Provider.get(getUserAgent().getEventBroadcaster());
    }

    private AFPPaintingState getPaintingState() {
        return getDocumentHandler().getPaintingState();
    }

    private DataStream getDataStream() {
        return getDocumentHandler().getDataStream();
    }

    @Override
    public String getFontKey(FontTriplet triplet) throws IFException {
        try {
            return super.getFontKey(triplet);
        } catch (IFException e) {
            eventProducer.invalidConfiguration(null, e);
            return super.getFontKey(FontTriplet.DEFAULT_FONT_TRIPLET);
        }
    }

    /** {@inheritDoc} */
    public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
            throws IFException {
        //AFP doesn't support clipping, so we treat viewport like a group
        //this is the same code as for startGroup()
        try {
            saveGraphicsState();
            concatenateTransformationMatrix(transform);
        } catch (IOException ioe) {
            throw new IFException("I/O error in startViewport()", ioe);
        }
    }

    /** {@inheritDoc} */
    public void endViewport() throws IFException {
        try {
            restoreGraphicsState();
        } catch (IOException ioe) {
            throw new IFException("I/O error in endViewport()", ioe);
        }
    }

    private void concatenateTransformationMatrix(AffineTransform at) {
        if (!at.isIdentity()) {
            getPaintingState().concatenate(at);
        }
    }

    /** {@inheritDoc} */
    public void startGroup(AffineTransform transform, String layer) throws IFException {
        try {
            saveGraphicsState();
            concatenateTransformationMatrix(transform);
        } catch (IOException ioe) {
            throw new IFException("I/O error in startGroup()", ioe);
        }
    }

    /** {@inheritDoc} */
    public void endGroup() throws IFException {
        try {
            restoreGraphicsState();
        } catch (IOException ioe) {
            throw new IFException("I/O error in endGroup()", ioe);
        }
    }

    /** {@inheritDoc} */
    @Override
    protected Map createDefaultImageProcessingHints(ImageSessionContext sessionContext) {
        Map hints = super.createDefaultImageProcessingHints(sessionContext);

        //AFP doesn't support alpha channels
        hints.put(ImageProcessingHints.TRANSPARENCY_INTENT,
                ImageProcessingHints.TRANSPARENCY_INTENT_IGNORE);
        hints.put("CMYK", getDocumentHandler().getPaintingState().isCMYKImagesSupported());
        return hints;
    }

    /** {@inheritDoc} */
    @Override
    protected RenderingContext createRenderingContext() {
        AFPRenderingContext renderingContext = new AFPRenderingContext(
                getUserAgent(),
                getDocumentHandler().getResourceManager(),
                getPaintingState(),
                getFontInfo(),
                getContext().getForeignAttributes());
        return renderingContext;
    }

    /** {@inheritDoc} */
    public void drawImage(String uri, Rectangle rect) throws IFException {
        PageSegmentDescriptor pageSegment = getDocumentHandler().getPageSegmentNameFor(uri);

        if (pageSegment != null) {
            float[] srcPts = {rect.x, rect.y};
            int[] coords = unitConv.mpts2units(srcPts);
            int width = Math.round(unitConv.mpt2units(rect.width));
            int height = Math.round(unitConv.mpt2units(rect.height));

            getDataStream().createIncludePageSegment(pageSegment.getName(),
                    coords[X], coords[Y], width, height);

            //Do we need to embed an external page segment?
            if (pageSegment.getURI() != null) {
                AFPResourceAccessor accessor = new AFPResourceAccessor(
                        getDocumentHandler().getUserAgent().getResourceResolver());
                try {
                    URI resourceUri = new URI(pageSegment.getURI());
                    getDocumentHandler().getResourceManager().createIncludedResourceFromExternal(
                            pageSegment.getName(), resourceUri, accessor);

                } catch (URISyntaxException urie) {
                    throw new IFException("Could not handle resource url"
                            + pageSegment.getURI(), urie);
                } catch (IOException ioe) {
                    throw new IFException("Could not handle resource" + pageSegment.getURI(), ioe);
                }
            }

        } else {
            drawImageUsingURI(uri, rect);
        }
    }

    /** {@inheritDoc} */
    protected void drawImage(Image image, Rectangle rect,
            RenderingContext context, boolean convert, Map additionalHints)
                    throws IOException, ImageException {


        AFPRenderingContext afpContext = (AFPRenderingContext) context;

        AFPResourceInfo resourceInfo = AFPImageHandler.createResourceInformation(
                image.getInfo().getOriginalURI(),
                afpContext.getForeignAttributes());

        //Check if the image is cached before processing it again
        if (afpContext.getResourceManager().isObjectCached(resourceInfo)) {

            AFPObjectAreaInfo areaInfo = AFPImageHandler.createObjectAreaInfo(
                    afpContext.getPaintingState(), rect);

            afpContext.getResourceManager().includeCachedObject(resourceInfo, areaInfo);

        } else {
            super.drawImage(image, rect, context, convert, additionalHints);
        }

    }

    /** {@inheritDoc} */
    public void drawImage(Document doc, Rectangle rect) throws IFException {
        drawImageUsingDocument(doc, rect);
    }

    /** {@inheritDoc} */
    public void clipRect(Rectangle rect) throws IFException {
        //Not supported!
    }

    private float toPoint(int mpt) {
        return mpt / 1000f;
    }

    /** {@inheritDoc} */
    public void fillRect(Rectangle rect, Paint fill) throws IFException {
        if (fill == null) {
            return;
        }
        if (rect.width != 0 && rect.height != 0) {
            if (fill instanceof Color) {
                getPaintingState().setColor((Color) fill);
            } else {
                throw new UnsupportedOperationException("Non-Color paints NYI");
            }
            RectanglePaintingInfo rectanglePaintInfo = new RectanglePaintingInfo(
                    toPoint(rect.x), toPoint(rect.y), toPoint(rect.width), toPoint(rect.height));
            try {
                rectanglePainter.paint(rectanglePaintInfo);
            } catch (IOException ioe) {
                throw new IFException("IO error while painting rectangle", ioe);
            }
        }
    }

    @Override
    public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom,
            BorderProps left, BorderProps right, Color innerBackgroundColor) throws IFException {
        if (top != null || bottom != null || left != null || right != null) {
            this.borderPainter.drawBorders(rect, top, bottom, left, right, innerBackgroundColor);
        }
    }


    private static final class AFPGraphicsPainter implements GraphicsPainter {

        private final AFPBorderPainter graphicsPainter;

        private AFPGraphicsPainter(AFPBorderPainter delegate) {
            this.graphicsPainter = delegate;
        }

        public void drawBorderLine(int x1, int y1, int x2, int y2,
                boolean horz, boolean startOrBefore, int style, Color color)
                        throws IOException {
            BorderPaintingInfo borderPaintInfo = new BorderPaintingInfo(
                    toPoints(x1), toPoints(y1), toPoints(x2), toPoints(y2),
                    horz, style, color);
            graphicsPainter.paint(borderPaintInfo);
        }

        private float toPoints(int mpt) {
            return mpt / 1000f;
        }

        public void drawLine(Point start, Point end, int width,
                Color color, RuleStyle style) throws IOException {
            if (start.y != end.y) {
                //TODO Support arbitrary lines if necessary
                throw new UnsupportedOperationException("Can only deal with horizontal lines right now");
            }
            //Simply delegates to drawBorderLine() as AFP line painting is not very sophisticated.
            int halfWidth = width / 2;
            drawBorderLine(start.x, start.y - halfWidth, end.x, start.y + halfWidth,
                    true, true, style.getEnumValue(), color);
        }

        public void moveTo(int x, int y) throws IOException {
        }

        public void lineTo(int x, int y) throws IOException {
        }

        public void arcTo(double startAngle, double endAngle, int cx, int cy,
                int width, int height) throws IOException {
        }

        public void rotateCoordinates(double angle) throws IOException {
            throw new UnsupportedOperationException("Cannot handle coordinate rotation");
        }

        public void translateCoordinates(int xTranslate, int yTranslate) throws IOException {
            throw new UnsupportedOperationException("Cannot handle coordinate translation");
        }

        public void scaleCoordinates(float xScale, float yScale) throws IOException {
            throw new UnsupportedOperationException("Cannot handle coordinate scaling");
        }

        public void closePath() throws IOException {
        }

        public void clip() throws IOException {
        }

        public void saveGraphicsState() throws IOException {
        }

        public void restoreGraphicsState() throws IOException {
        }


    }

    //TODO Try to resolve the name-clash between the AFPBorderPainter in the afp package
    //and this one. Not done for now to avoid a lot of re-implementation and code duplication.
    private static class AFPBorderPainterAdapter extends BorderPainter {

        private final class BorderImagePainter implements Graphics2DImagePainter {
            private final double cornerCorrectionFactor;
            private final Rectangle borderRect;
            private final BorderProps bpsStart;
            private final BorderProps bpsEnd;
            private final BorderProps bpsBefore;
            private final BorderProps bpsAfter;
            private final boolean[] roundCorner;
            private final Color innerBackgroundColor;

            /* TODO represent border related parameters in a class */
            private BorderImagePainter(double cornerCorrectionFactor, Rectangle borderRect,
                    BorderProps bpsStart, BorderProps bpsEnd,
                    BorderProps bpsBefore, BorderProps bpsAfter,
                    boolean[] roundCorner, Color innerBackgroundColor) {
                this.cornerCorrectionFactor = cornerCorrectionFactor;
                this.borderRect = borderRect;
                this.bpsStart = bpsStart;
                this.bpsBefore = bpsBefore;
                this.roundCorner = roundCorner;
                this.bpsEnd = bpsEnd;
                this.bpsAfter = bpsAfter;
                this.innerBackgroundColor = innerBackgroundColor;
            }

            public void paint(Graphics2D g2d, Rectangle2D area) {

                //background
                Area background = new Area(area);
                Area cornerRegion = new Area();
                Area[] cornerBorder = new Area[]{new Area(), new Area(), new Area(), new Area()};
                Area[] clip = new Area[4];
                if (roundCorner[TOP_LEFT]) {
                    AffineTransform transform =  new AffineTransform();
                    int beforeRadius = (int)(cornerCorrectionFactor * bpsBefore.getRadiusStart());
                    int startRadius = (int)(cornerCorrectionFactor * bpsStart.getRadiusStart());

                    int beforeWidth = bpsBefore.width;
                    int startWidth = bpsStart.width;
                    int corner = TOP_LEFT;

                    background.subtract(makeCornerClip(beforeRadius, startRadius,
                            transform));

                    clip[TOP_LEFT] = new Area(new Rectangle(0, 0, startRadius, beforeRadius));
                    clip[TOP_LEFT].transform(transform);
                    cornerRegion.add(clip[TOP_LEFT]);

                    cornerBorder[TOP].add(makeCornerBorderBPD(beforeRadius,
                                    startRadius, beforeWidth, startWidth, transform));

                    cornerBorder[LEFT].add(makeCornerBorderIPD(beforeRadius,
                            startRadius, beforeWidth, startWidth, transform));
                }

                if (roundCorner[TOP_RIGHT]) {
                    AffineTransform transform
                            = new AffineTransform(-1, 0, 0, 1, borderRect.width, 0);

                    int beforeRadius = (int)(cornerCorrectionFactor * bpsBefore.getRadiusEnd());
                    int startRadius = (int)(cornerCorrectionFactor * bpsEnd.getRadiusStart());

                    int beforeWidth = bpsBefore.width;
                    int startWidth = bpsEnd.width;
                    int corner = TOP_RIGHT;

                    background.subtract(makeCornerClip(beforeRadius, startRadius,
                            transform));

                    clip[TOP_RIGHT] = new Area(new Rectangle(0, 0, startRadius, beforeRadius));
                    clip[TOP_RIGHT].transform(transform);
                    cornerRegion.add(clip[TOP_RIGHT]);

                    cornerBorder[TOP].add(makeCornerBorderBPD(beforeRadius,
                                    startRadius, beforeWidth, startWidth, transform));

                    cornerBorder[RIGHT].add(makeCornerBorderIPD(beforeRadius,
                            startRadius, beforeWidth, startWidth, transform));
                }

                if (roundCorner[BOTTOM_RIGHT]) {
                    AffineTransform transform = new AffineTransform(-1, 0, 0, -1,
                            borderRect.width, borderRect.height);

                    int beforeRadius = (int)(cornerCorrectionFactor * bpsAfter.getRadiusEnd());
                    int startRadius = (int)(cornerCorrectionFactor * bpsEnd.getRadiusEnd());

                    int beforeWidth = bpsAfter.width;
                    int startWidth = bpsEnd.width;
                    int corner = BOTTOM_RIGHT;

                    background.subtract(makeCornerClip(beforeRadius, startRadius,
                            transform));

                    clip[BOTTOM_RIGHT] = new Area(new Rectangle(0, 0, startRadius, beforeRadius));
                    clip[BOTTOM_RIGHT].transform(transform);
                    cornerRegion.add(clip[BOTTOM_RIGHT]);

                    cornerBorder[BOTTOM].add(makeCornerBorderBPD(beforeRadius,
                            startRadius, beforeWidth, startWidth, transform));
                    cornerBorder[RIGHT].add(makeCornerBorderIPD(beforeRadius,
                            startRadius, beforeWidth, startWidth, transform));
                }

                if (roundCorner[BOTTOM_LEFT]) {
                    AffineTransform transform
                            = new AffineTransform(1, 0, 0, -1, 0, borderRect.height);

                    int beforeRadius = (int)(cornerCorrectionFactor * bpsAfter.getRadiusStart());
                    int startRadius = (int)(cornerCorrectionFactor * bpsStart.getRadiusEnd());

                    int beforeWidth = bpsAfter.width;
                    int startWidth = bpsStart.width;
                    int corner = BOTTOM_LEFT;

                    background.subtract(makeCornerClip(beforeRadius, startRadius,
                            transform));

                    clip[BOTTOM_LEFT] = new Area(new Rectangle(0, 0, startRadius, beforeRadius));
                    clip[BOTTOM_LEFT].transform(transform);
                    cornerRegion.add(clip[BOTTOM_LEFT]);

                    cornerBorder[BOTTOM].add(makeCornerBorderBPD(beforeRadius,
                                    startRadius, beforeWidth, startWidth, transform));
                    cornerBorder[LEFT].add(makeCornerBorderIPD(beforeRadius,
                            startRadius, beforeWidth, startWidth, transform));
                }

                g2d.setColor(innerBackgroundColor);
                g2d.fill(background);

                //paint the borders
                //TODO refactor to repeating code into method
                if (bpsBefore != null && bpsBefore.width > 0) {
                    GeneralPath borderPath = new GeneralPath();
                    borderPath.moveTo(0, 0);
                    borderPath.lineTo(borderRect.width, 0);
                    borderPath.lineTo(
                            borderRect.width - (bpsEnd == null ? 0 : bpsEnd.width),
                            bpsBefore.width);
                    borderPath.lineTo(bpsStart == null ? 0 : bpsStart.width, bpsBefore.width);

                    Area border = new Area(borderPath);

                    if (clip[TOP_LEFT] != null) {
                        border.subtract(clip[TOP_LEFT]);
                    }
                    if (clip[TOP_RIGHT] != null) {
                        border.subtract(clip[TOP_RIGHT]);
                    }

                    g2d.setColor(bpsBefore.color);
                    g2d.fill(border);
                    g2d.fill(cornerBorder[TOP]);
                }

                if (bpsEnd != null && bpsEnd.width > 0) {
                    GeneralPath borderPath = new GeneralPath();
                    borderPath.moveTo(borderRect.width, 0);
                    borderPath.lineTo(borderRect.width, borderRect.height);
                    borderPath.lineTo(
                            borderRect.width - bpsEnd.width,
                            borderRect.height - (bpsAfter == null ? 0 : bpsAfter.width));
                    borderPath.lineTo(
                            borderRect.width - bpsEnd.width,
                            bpsBefore == null ? 0 : bpsBefore.width);

                    Area border = new Area(borderPath);

                    if (clip[BOTTOM_RIGHT] != null) {
                        border.subtract(clip[BOTTOM_RIGHT]);
                    }
                    if (clip[TOP_RIGHT] != null) {
                        border.subtract(clip[TOP_RIGHT]);
                    }

                    g2d.setColor(bpsEnd.color);
                    g2d.fill(border);
                    g2d.fill(cornerBorder[RIGHT]);
                }

                if (bpsAfter != null && bpsAfter.width > 0) {
                    GeneralPath borderPath = new GeneralPath();
                    borderPath.moveTo(0, borderRect.height);
                    borderPath.lineTo(borderRect.width, borderRect.height);
                    borderPath.lineTo(
                            borderRect.width - (bpsEnd == null ? 0 : bpsEnd.width),
                            borderRect.height - bpsAfter.width);
                    borderPath.lineTo(bpsStart == null ? 0 : bpsStart.width,
                            borderRect.height - bpsAfter.width);
                    Area border = new Area(borderPath);
                    if (clip[BOTTOM_LEFT] != null) {
                        border.subtract(clip[BOTTOM_LEFT]);
                    }
                    if (clip[BOTTOM_RIGHT] != null) {
                        border.subtract(clip[BOTTOM_RIGHT]);
                    }
                    g2d.setColor(bpsAfter.color);
                    g2d.fill(border);
                    g2d.fill(cornerBorder[BOTTOM]);
                }

                if (bpsStart != null && bpsStart.width > 0) {

                    GeneralPath borderPath = new GeneralPath();
                    borderPath.moveTo(bpsStart.width,
                            bpsBefore == null ? 0 : bpsBefore.width);
                    borderPath.lineTo(bpsStart.width,
                            borderRect.height - (bpsAfter == null ? 0 : bpsAfter.width));
                    borderPath.lineTo(0, borderRect.height);
                    borderPath.lineTo(0, 0);

                    Area border = new Area(borderPath);

                    if (clip[BOTTOM_LEFT] != null) {
                        border.subtract(clip[BOTTOM_LEFT]);
                    }
                    if (clip[TOP_LEFT] != null) {
                        border.subtract(clip[TOP_LEFT]);
                    }
                    g2d.setColor(bpsStart.color);
                    g2d.fill(border);
                    g2d.fill(cornerBorder[LEFT]);
                }
            }

            public Dimension getImageSize() {
                return borderRect.getSize();
            }
        }

        private final AFPPainter painter;
        private final AFPDocumentHandler documentHandler;

        public AFPBorderPainterAdapter(GraphicsPainter graphicsPainter, AFPPainter painter,
                AFPDocumentHandler documentHandler) {
            super(graphicsPainter);
            this.painter = painter;
            this.documentHandler = documentHandler;
        }

        public void drawBorders(final Rectangle borderRect,
                final BorderProps bpsBefore, final BorderProps bpsAfter,
                final BorderProps bpsStart, final BorderProps bpsEnd, Color innerBackgroundColor)
                        throws IFException {
            drawRoundedCorners(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd, innerBackgroundColor);
        }

        private boolean isBackgroundRequired(BorderProps bpsBefore, BorderProps bpsAfter,
                BorderProps bpsStart, BorderProps bpsEnd) {
            return !hasRoundedCorners(bpsBefore,  bpsAfter, bpsStart,  bpsEnd);
        }

        private boolean hasRoundedCorners(final BorderProps bpsBefore, final BorderProps bpsAfter,
                final BorderProps bpsStart, final BorderProps bpsEnd) {
            return ((bpsStart == null ? false : bpsStart.getRadiusStart() > 0)
                    && (bpsBefore == null ? false : bpsBefore.getRadiusStart() > 0))
                    || ((bpsBefore == null ? false : bpsBefore.getRadiusEnd() > 0)
                            && (bpsEnd == null ? false : bpsEnd.getRadiusStart() > 0))
                            || ((bpsEnd == null ? false : bpsEnd.getRadiusEnd() > 0)
                                    && (bpsAfter == null ? false : bpsAfter.getRadiusEnd() > 0))
                                    || ((bpsAfter == null ? false : bpsAfter.getRadiusStart() > 0)
                                            && (bpsStart == null ? false : bpsStart.getRadiusEnd() > 0));
        }

        private void drawRoundedCorners(final Rectangle borderRect,
                final BorderProps bpsBefore, final BorderProps bpsAfter,
                final BorderProps bpsStart, final BorderProps bpsEnd,
                final Color innerBackgroundColor) throws IFException {
            final double cornerCorrectionFactor = calculateCornerCorrectionFactor(borderRect.width,
                    borderRect.height, bpsBefore,  bpsAfter, bpsStart,  bpsEnd);
            final boolean[] roundCorner = new boolean[]{
                    bpsBefore != null  && bpsStart != null
                            && bpsBefore.getRadiusStart() > 0
                            && bpsStart.getRadiusStart() > 0
                            && isNotCollapseOuter(bpsBefore)
                            && isNotCollapseOuter(bpsStart),
                            bpsEnd != null && bpsBefore != null
                            && bpsEnd.getRadiusStart() > 0
                            && bpsBefore.getRadiusEnd() > 0
                            && isNotCollapseOuter(bpsEnd)
                            && isNotCollapseOuter(bpsBefore),
                            bpsEnd != null && bpsAfter != null
                            && bpsEnd.getRadiusEnd() > 0
                            && bpsAfter.getRadiusEnd() > 0
                            && isNotCollapseOuter(bpsEnd)
                            && isNotCollapseOuter(bpsAfter),
                            bpsStart != null && bpsAfter != null
                            && bpsStart.getRadiusEnd() > 0
                            && bpsAfter.getRadiusStart() > 0
                            && isNotCollapseOuter(bpsStart)
                            && isNotCollapseOuter(bpsAfter)
            };

            if (!roundCorner[TOP_LEFT] && !roundCorner[TOP_RIGHT]
                    && !roundCorner[BOTTOM_RIGHT] && !roundCorner[BOTTOM_LEFT]) {
                try {
                    drawRectangularBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
                } catch (IOException ioe) {
                    throw new IFException("IO error drawing borders", ioe);
                }
                return;
            }

            String areaKey = makeKey(borderRect,
                    bpsBefore, bpsEnd, bpsAfter,
                    bpsStart, innerBackgroundColor);

            Graphics2DImagePainter painter = null;
            String name = documentHandler.getCachedRoundedCorner(areaKey);

            if (name == null) {

                name = documentHandler.cacheRoundedCorner(areaKey);

                painter = new BorderImagePainter(cornerCorrectionFactor, borderRect,
                        bpsStart, bpsEnd, bpsBefore, bpsAfter,
                        roundCorner, innerBackgroundColor);
            }
            paintCornersAsBitmap(painter, borderRect, name);
        }

        private boolean isNotCollapseOuter(BorderProps bp) {
            return !bp.isCollapseOuter();
        }

        private Area makeCornerClip(final int beforeRadius, final int startRadius,
                final AffineTransform transform) {

            Rectangle clipR = new Rectangle(0, 0, startRadius, beforeRadius);

            Area clip = new Area(clipR);

            Ellipse2D.Double e = new  Ellipse2D.Double();
            e.x = 0;
            e.y = 0;
            e.width = 2 * startRadius;
            e.height = 2 * beforeRadius;

            clip.subtract(new Area(e));

            clip.transform(transform);
            return clip;
        }


        private Area makeCornerBorderBPD(final int beforeRadius, final int startRadius,
                final int beforeWidth, final int startWidth, final AffineTransform transform) {

            Rectangle clipR = new Rectangle(0, 0, startRadius, beforeRadius);

            Ellipse2D.Double e = new  Ellipse2D.Double();
            e.x = 0;
            e.y = 0;
            e.width = 2 * startRadius;
            e.height = 2 * beforeRadius;

            Ellipse2D.Double i = new  Ellipse2D.Double();
            i.x = startWidth;
            i.y = beforeWidth;
            i.width = 2 * (startRadius - startWidth);
            i.height = 2 * (beforeRadius - beforeWidth);

            Area clip = new Area(e);
            clip.subtract(new Area(i));
            clip.intersect(new Area(clipR));

            GeneralPath cut = new GeneralPath();
            cut.moveTo(0, 0);
            cut.lineTo(startRadius, ((float) startRadius * beforeWidth) / startWidth);
            cut.lineTo(startRadius, 0);
            clip.intersect(new Area(cut));
            clip.transform(transform);
            return clip;
        }


        private Area makeCornerBorderIPD(final int beforeRadius, final int startRadius,
                final int beforeWidth, final int startWidth, final AffineTransform transform) {

            Rectangle clipR = new Rectangle(0, 0, startRadius, beforeRadius);


            Ellipse2D.Double e = new  Ellipse2D.Double();
            e.x = 0;
            e.y = 0;
            e.width = 2 * startRadius;
            e.height = 2 * beforeRadius;

            Ellipse2D.Double i = new  Ellipse2D.Double();
            i.x = startWidth;
            i.y = beforeWidth;
            i.width = 2 * (startRadius - startWidth);
            i.height = 2 * (beforeRadius - beforeWidth);

            Area clip = new Area(e);
            clip.subtract(new Area(i));
            clip.intersect(new Area(clipR));

            GeneralPath cut = new GeneralPath();
            cut.moveTo(0, 0);
            cut.lineTo(startRadius, ((float) startRadius * beforeWidth) / startWidth);
            cut.lineTo(startRadius, 0);
            clip.subtract(new Area(cut));
            clip.transform(transform);
            return clip;
        }

        private String makeKey(Rectangle area, BorderProps beforeProps,
                BorderProps endProps, BorderProps afterProps, BorderProps startProps,
                Color innerBackgroundColor) {

            return hash(new StringBuffer()
                    .append(area.width)
                    .append(":")
                    .append(area.height)
                    .append(":")
                    .append(beforeProps)
                    .append(":")
                    .append(endProps)
                    .append(":")
                    .append(afterProps)
                    .append(":")
                    .append(startProps)
                    .append(":")
                    .append(innerBackgroundColor)
                    .toString());
        }


        private String hash(String text) {

            MessageDigest md;
            try {
                md = MessageDigest.getInstance("MD5");
            } catch (Exception e) {
                throw new RuntimeException("Internal error", e);
            }

            byte[] result = md.digest(text.getBytes());

            StringBuffer sb = new StringBuffer();
            char[] digits = {'0', '1', '2', '3', '4', '5', '6',
                    '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
            for (int idx = 0; idx < 6; ++idx) {
                byte b = result[idx];
                sb.append(digits[(b & 0xf0) >> 4]);
                sb.append(digits[b & 0x0f]);
            }
            return sb.toString();
        }

        private void paintCornersAsBitmap(Graphics2DImagePainter painter,
                Rectangle boundingBox, String name) throws IFException {
            //TODO parameters ok?
            ImageInfo info = new ImageInfo(name, null);

            ImageSize size = new ImageSize();
            size.setSizeInMillipoints(boundingBox.width, boundingBox.height);

            //Use the foreign attributes map to set image handling hints
            Map map = new java.util.HashMap(2);
            map.put(AFPForeignAttributeReader.RESOURCE_NAME, name);
            map.put(AFPForeignAttributeReader.RESOURCE_LEVEL, "print-file");

            AFPRenderingContext context = (AFPRenderingContext)
                    this.painter.createRenderingContext(/*map*/);

            size.setResolution(context.getPaintingState().getResolution());
            size.calcPixelsFromSize();
            info.setSize(size);
            ImageGraphics2D img = new ImageGraphics2D(info, painter);

            Map hints = new java.util.HashMap();

            hints.put(ImageHandlerUtil.CONVERSION_MODE, ImageHandlerUtil.CONVERSION_MODE_BITMAP);
            hints.put("TARGET_RESOLUTION",
                    context.getPaintingState().getResolution());


            try {
                this.painter.drawImage(img, boundingBox, context, true, hints);
            } catch (IOException ioe) {
                throw new IFException(
                        "I/O error while painting corner using a bitmap", ioe);
            } catch (ImageException ie) {
                throw new IFException(
                        "Image error while painting corner using a bitmap", ie);
            }
        }

        protected void arcTo(double startAngle, double endAngle, int cx, int cy, int width,
                int height) throws IOException {
            throw new UnsupportedOperationException("Can only deal with horizontal lines right now");

        }
    }

    /** {@inheritDoc} */
    @Override
    public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
            throws IFException {
        try {
            this.graphicsPainter.drawLine(start, end, width, color, style);
        } catch (IOException ioe) {
            throw new IFException("I/O error in drawLine()", ioe);
        }
    }

    /** {@inheritDoc} */
    public void drawText(int x, int y,
            final int letterSpacing, final int wordSpacing, final int[][] dp,
            final String text) throws IFException {
        new DefaultPtocaProducer(x, y, letterSpacing, wordSpacing, dp, text);
    }

    private final class DefaultPtocaProducer implements PtocaProducer {
        final int[] coords;
        final int fontReference;
        final String text;
        final int[][] dp;
        final int letterSpacing;
        final int wordSpacing;
        final Font font;
        final AFPFont afpFont;
        final CharacterSet charSet;
        PresentationTextObject pto;

        private DefaultPtocaProducer(int x, int y,
                                      final int letterSpacing, final int wordSpacing, final int[][] dp,
                                      final String text) throws IFException {
            this.letterSpacing = letterSpacing;
            this.wordSpacing = wordSpacing;
            this.text = text;
            this.dp = dp;
            final int fontSize = state.getFontSize();
            getPaintingState().setFontSize(fontSize);

            FontTriplet triplet = new FontTriplet(
                    state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
            //TODO Ignored: state.getFontVariant()
            String fontKey = getFontKey(triplet);

            // register font as necessary
            Map<String, Typeface> fontMetricMap = getFontInfo().getFonts();
            afpFont = (AFPFont) fontMetricMap.get(fontKey);
            font = getFontInfo().getFontInstance(triplet, fontSize);
            AFPPageFonts pageFonts = getPaintingState().getPageFonts();
            AFPFontAttributes fontAttributes = pageFonts.registerFont(fontKey, afpFont, fontSize);

            fontReference = fontAttributes.getFontReference();

            coords = unitConv.mpts2units(new float[] {x, y});

            charSet = afpFont.getCharacterSet(fontSize);

            if (afpFont.isEmbeddable()) {
                try {
                    getDocumentHandler().getResourceManager().embedFont(afpFont, charSet);
                } catch (IOException ioe) {
                    throw new IFException("Error while embedding font resources", ioe);
                }
            }

            AbstractPageObject page = getDataStream().getCurrentPage();

            try {
                if (bytesAvailable != null && bytesAvailable < getSize()) {
                    page.endPresentationObject();
                }
                pto = page.getPresentationTextObject();
                boolean success = pto.createControlSequences(this);
                if (!success) {
                    page.endPresentationObject();
                    pto = page.getPresentationTextObject();
                    pto.createControlSequences(this);
                }
            } catch (IOException ioe) {
                throw new IFException("I/O error in drawText()", ioe);
            }
        }

        private int getSize() throws IOException {
            final ByteArrayOutputStream bos = new ByteArrayOutputStream();
            PtocaBuilder pb = new PtocaBuilder() {
                protected OutputStream getOutputStreamForControlSequence(int length) {
                    return bos;
                }
            };
            produce(pb);
            return bos.size();
        }

        public void produce(PtocaBuilder builder) throws IOException {
            Point p = getPaintingState().getPoint(coords[X], coords[Y]);
            builder.setTextOrientation(getPaintingState().getRotation());
            builder.absoluteMoveBaseline(p.y);
            builder.absoluteMoveInline(p.x);

            builder.setExtendedTextColor(state.getTextColor());
            builder.setCodedFont((byte) fontReference);

            int l = text.length();
            int[] dx = IFUtil.convertDPToDX(dp);
            int dxl = (dx != null ? dx.length : 0);
            StringBuffer sb = new StringBuffer();

            if (dxl > 0 && dx[0] != 0) {
                int dxu = Math.round(unitConv.mpt2units(dx[0]));
                builder.relativeMoveInline(-dxu);
            }

            //Following are two variants for glyph placement.
            //SVI does not seem to be implemented in the same way everywhere, so
            //a fallback alternative is preserved here.
            final boolean usePTOCAWordSpacing = true;
            if (usePTOCAWordSpacing) {

                int interCharacterAdjustment = 0;
                if (letterSpacing != 0) {
                    interCharacterAdjustment = Math.round(unitConv.mpt2units(
                            letterSpacing));
                }
                builder.setInterCharacterAdjustment(interCharacterAdjustment);

                int spaceWidth = font.getCharWidth(CharUtilities.SPACE);
                int fixedSpaceCharacterIncrement = Math.round(unitConv.mpt2units(
                        spaceWidth + letterSpacing));
                int varSpaceCharacterIncrement = fixedSpaceCharacterIncrement;
                if (wordSpacing != 0) {
                    varSpaceCharacterIncrement = Math.round(unitConv.mpt2units(
                            spaceWidth + wordSpacing + letterSpacing));
                }
                builder.setVariableSpaceCharacterIncrement(varSpaceCharacterIncrement);

                boolean fixedSpaceMode = false;
                double ttPos = p.x;

                for (int i = 0; i < l; i++) {
                    char orgChar = text.charAt(i);
                    float glyphAdjust = 0;
                    if (afpFont.getFontType() == FontType.TRUETYPE) {
                        flushText(builder, sb, charSet);
                        fixedSpaceMode = true;
                        int charWidth = font.getCharWidth(orgChar);
                        sb.append(orgChar);
                        glyphAdjust += charWidth;
                    } else if (CharUtilities.isFixedWidthSpace(orgChar)) {
                        flushText(builder, sb, charSet);
                        builder.setVariableSpaceCharacterIncrement(
                                fixedSpaceCharacterIncrement);
                        fixedSpaceMode = true;
                        sb.append(CharUtilities.SPACE);
                        int charWidth = font.getCharWidth(orgChar);
                        glyphAdjust += (charWidth - spaceWidth);
                    } else {
                        if (fixedSpaceMode) {
                            flushText(builder, sb, charSet);
                            builder.setVariableSpaceCharacterIncrement(
                                    varSpaceCharacterIncrement);
                            fixedSpaceMode = false;
                        }
                        char ch;
                        if (orgChar == CharUtilities.NBSPACE) {
                            ch = ' '; //converted to normal space to allow word spacing
                        } else {
                            ch = orgChar;
                        }
                        sb.append(ch);
                    }

                    if (i < dxl - 1) {
                        glyphAdjust += dx[i + 1];
                    }

                    if (afpFont.getFontType() == FontType.TRUETYPE) {
                        flushText(builder, sb, charSet);
                        ttPos += unitConv.mpt2units(glyphAdjust);
                        builder.absoluteMoveInline((int) Math.round(ttPos));
                    } else if (glyphAdjust != 0) {
                        flushText(builder, sb, charSet);
                        int increment = Math.round(unitConv.mpt2units(glyphAdjust));
                        builder.relativeMoveInline(increment);
                    }
                }
            } else {
                for (int i = 0; i < l; i++) {
                    char orgChar = text.charAt(i);
                    float glyphAdjust = 0;
                    if (CharUtilities.isFixedWidthSpace(orgChar)) {
                        sb.append(CharUtilities.SPACE);
                        int spaceWidth = font.getCharWidth(CharUtilities.SPACE);
                        int charWidth = font.getCharWidth(orgChar);
                        glyphAdjust += (charWidth - spaceWidth);
                    } else {
                        sb.append(orgChar);
                    }

                    if ((wordSpacing != 0) && CharUtilities.isAdjustableSpace(orgChar)) {
                        glyphAdjust += wordSpacing;
                    }
                    glyphAdjust += letterSpacing;
                    if (i < dxl - 1) {
                        glyphAdjust += dx[i + 1];
                    }

                    if (glyphAdjust != 0) {
                        flushText(builder, sb, charSet);
                        int increment = Math.round(unitConv.mpt2units(glyphAdjust));
                        builder.relativeMoveInline(increment);
                    }
                }
            }
            flushText(builder, sb, charSet);
            if (pto != null) {
                bytesAvailable = pto.getBytesAvailable();
            }
        }

        private void flushText(PtocaBuilder builder, StringBuffer sb,
                               final CharacterSet charSet) throws IOException {
            if (sb.length() > 0) {
                builder.addTransparentData(charSet.encodeChars(sb));
                sb.setLength(0);
            }
        }

    }

    /**
     * Saves the graphics state of the rendering engine.
     * @throws IOException if an I/O error occurs
     */
    protected void saveGraphicsState() throws IOException {
        getPaintingState().save();
    }

    /**
     * Restores the last graphics state of the rendering engine.
     * @throws IOException if an I/O error occurs
     */
    protected void restoreGraphicsState() throws IOException {
        getPaintingState().restore();
    }


    /** {@inheritDoc} */
    public void clipBackground(Rectangle rect, BorderProps bpsBefore, BorderProps bpsAfter,
            BorderProps bpsStart, BorderProps bpsEnd) throws IFException {
    }

    /** {@inheritDoc} */
    public boolean isBackgroundRequired(BorderProps bpsBefore, BorderProps bpsAfter,
            BorderProps bpsStart, BorderProps bpsEnd) {
        return borderPainter.isBackgroundRequired(bpsBefore,  bpsAfter, bpsStart,  bpsEnd);
    }

    /** {@inheritDoc} */
    public void fillBackground(Rectangle rect, Paint fill, BorderProps bpsBefore,
            BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) throws IFException {
        // not supported in AFP
    }
}
