/*
 * 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.intermediate;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;

import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import org.xml.sax.SAXException;

import org.apache.batik.parser.AWTTransformProducer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.xmlgraphics.xmp.schemas.DublinCoreAdapter;
import org.apache.xmlgraphics.xmp.schemas.DublinCoreSchema;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;

import org.apache.fop.Version;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.Area;
import org.apache.fop.area.AreaTreeObject;
import org.apache.fop.area.Block;
import org.apache.fop.area.BlockViewport;
import org.apache.fop.area.BookmarkData;
import org.apache.fop.area.CTM;
import org.apache.fop.area.DestinationData;
import org.apache.fop.area.OffDocumentExtensionAttachment;
import org.apache.fop.area.OffDocumentItem;
import org.apache.fop.area.PageSequence;
import org.apache.fop.area.PageViewport;
import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Trait;
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.InlineParent;
import org.apache.fop.area.inline.Leader;
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.datatypes.URISpecification;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.intermediate.extensions.AbstractAction;
import org.apache.fop.render.intermediate.extensions.ActionSet;
import org.apache.fop.render.intermediate.extensions.Bookmark;
import org.apache.fop.render.intermediate.extensions.BookmarkTree;
import org.apache.fop.render.intermediate.extensions.GoToXYAction;
import org.apache.fop.render.intermediate.extensions.Link;
import org.apache.fop.render.intermediate.extensions.NamedDestination;
import org.apache.fop.render.intermediate.extensions.URIAction;
import org.apache.fop.render.pdf.PDFEventProducer;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;

/**
 * This renderer implementation is an adapter to the {@link IFPainter} interface. It is used
 * to generate content using FOP's intermediate format.
 */
public class IFRenderer extends AbstractPathOrientedRenderer {

    //TODO Many parts of the Renderer infrastructure are using floats (coordinates in points)
    //instead of ints (in millipoints). A lot of conversion to and from is performed.
    //When the new IF is established, the Renderer infrastructure should be revisited so check
    //if optimizations can be done to avoid int->float->int conversions.

    /** logging instance */
    protected static Log log = LogFactory.getLog(IFRenderer.class);

    /** XML MIME type */
    public static final String IF_MIME_TYPE = MimeConstants.MIME_FOP_IF;

    private IFDocumentHandler documentHandler;
    private IFPainter painter;

    /** If not null, the XMLRenderer will mimic another renderer by using its font setup. */
    protected Renderer mimic;

    private boolean inPageSequence = false;

    private Stack graphicContextStack = new Stack();
    private Stack viewportDimensionStack = new Stack();
    private IFGraphicContext graphicContext = new IFGraphicContext();
    //private Stack groupStack = new Stack();

    private Metadata documentMetadata;

    /**
     * Maps XSL-FO element IDs to their on-page XY-positions
     * Must be used in conjunction with the page reference to fully specify the details
     * of a "go-to" action.
     */
    private Map idPositions = new java.util.HashMap();

    /**
     * The "go-to" actions in idGoTos that are not complete yet
     */
    private List unfinishedGoTos = new java.util.ArrayList();
    // can't use a Set because PDFGoTo.equals returns true if the target is the same,
    // even if the object number differs

    /** Maps unique PageViewport key to page indices (for link target handling) */
    protected Map pageIndices = new java.util.HashMap();

    private BookmarkTree bookmarkTree;
    private List deferredDestinations = new java.util.ArrayList();
    private List deferredLinks = new java.util.ArrayList();
    private ActionSet actionSet = new ActionSet();

    private TextUtil textUtil = new TextUtil();

    /**
     * Main constructor
     */
    public IFRenderer() {
    }

    /** {@inheritDoc} */
    public String getMimeType() {
        return IF_MIME_TYPE;
    }

    /**
     * Sets the {@link IFDocumentHandler} to be used by the {@link IFRenderer}.
     * @param documentHandler the {@link IFDocumentHandler}
     */
    public void setDocumentHandler(IFDocumentHandler documentHandler) {
        this.documentHandler = documentHandler;
    }

    /** {@inheritDoc} */
    public void setupFontInfo(FontInfo inFontInfo) throws FOPException {
        if (this.documentHandler == null) {
            this.documentHandler = createDefaultDocumentHandler();
        }
        IFUtil.setupFonts(this.documentHandler, inFontInfo);
        this.fontInfo = inFontInfo;
    }

    private void handleIFException(IFException ife) {
        if (ife.getCause() instanceof SAXException) {
            throw new RuntimeException(ife.getCause());
        } else {
            throw new RuntimeException(ife);
        }
    }

    private void handleIFExceptionWithIOException(IFException ife) throws IOException {
        if (ife.getCause() instanceof IOException) {
            throw (IOException)ife.getCause();
        } else {
            handleIFException(ife);
        }
    }

    /** {@inheritDoc} */
    public boolean supportsOutOfOrder() {
        return (this.documentHandler != null
                ? this.documentHandler.supportsPagesOutOfOrder() : false);
    }

    /**
     * Returns the document navigation handler if available/supported.
     * @return the document navigation handler or null if not supported
     */
    protected IFDocumentNavigationHandler getDocumentNavigationHandler() {
        return this.documentHandler.getDocumentNavigationHandler();
    }

    /**
     * Indicates whether document navigation features are supported by the document handler.
     * @return true if document navigation features are available
     */
    protected boolean hasDocumentNavigation() {
        return getDocumentNavigationHandler() != null;
    }

    /**
     * Creates a default {@link IFDocumentHandler} when none has been set.
     * @return the default IFDocumentHandler
     */
    protected IFDocumentHandler createDefaultDocumentHandler() {
        IFSerializer serializer = new IFSerializer();
        serializer.setContext(new IFContext(getUserAgent()));
        return serializer;
    }

    /** {@inheritDoc} */
    public void startRenderer(OutputStream outputStream)
                throws IOException {
        try {
            if (outputStream != null) {
                StreamResult result = new StreamResult(outputStream);
                if (getUserAgent().getOutputFile() != null) {
                    result.setSystemId(
                            getUserAgent().getOutputFile().toURI().toURL().toExternalForm());
                }
                if (this.documentHandler == null) {
                    this.documentHandler = createDefaultDocumentHandler();
                }
                this.documentHandler.setResult(result);
            }
            super.startRenderer(null);
            if (log.isDebugEnabled()) {
                log.debug("Rendering areas via IF document handler ("
                        + this.documentHandler.getClass().getName() + ")...");
            }
            documentHandler.startDocument();
            documentHandler.startDocumentHeader();
        } catch (IFException e) {
            handleIFExceptionWithIOException(e);
        }
    }

    /** {@inheritDoc} */
    public void stopRenderer() throws IOException {
        try {
            if (this.inPageSequence) {
                documentHandler.endPageSequence();
                this.inPageSequence = false;
            }
            documentHandler.startDocumentTrailer();

            //Wrap up document navigation
            if (hasDocumentNavigation()) {
                finishOpenGoTos();
                Iterator iter = this.deferredDestinations.iterator();
                while (iter.hasNext()) {
                    NamedDestination dest = (NamedDestination)iter.next();
                    iter.remove();
                    getDocumentNavigationHandler().renderNamedDestination(dest);
                }

                if (this.bookmarkTree != null) {
                    getDocumentNavigationHandler().renderBookmarkTree(this.bookmarkTree);
                }
            }

            documentHandler.endDocumentTrailer();
            documentHandler.endDocument();
        } catch (IFException e) {
            handleIFExceptionWithIOException(e);
        }
        pageIndices.clear();
        idPositions.clear();
        actionSet.clear();
        super.stopRenderer();
        log.debug("Rendering finished.");
    }

    /** {@inheritDoc} */
    public void processOffDocumentItem(OffDocumentItem odi) {
        if (odi instanceof DestinationData) {
            // render Destinations
            renderDestination((DestinationData) odi);
        } else if (odi instanceof BookmarkData) {
            // render Bookmark-Tree
            renderBookmarkTree((BookmarkData) odi);
        } else if (odi instanceof OffDocumentExtensionAttachment) {
            ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)odi).getAttachment();
            if (XMPMetadata.CATEGORY.equals(attachment.getCategory())) {
                renderXMPMetadata((XMPMetadata)attachment);
            } else {
                try {
                    this.documentHandler.handleExtensionObject(attachment);
                } catch (IFException ife) {
                    handleIFException(ife);
                }
            }
        }
    }

    private void renderDestination(DestinationData dd) {
        if (!hasDocumentNavigation()) {
            return;
        }
        String targetID = dd.getIDRef();
        if (targetID == null || targetID.length() == 0) {
            throw new IllegalArgumentException("DestinationData must contain a ID reference");
        }
        PageViewport pv = dd.getPageViewport();
        if (pv != null) {
            GoToXYAction action = getGoToActionForID(targetID, pv.getPageIndex());
            NamedDestination namedDestination = new NamedDestination(targetID, action);
            this.deferredDestinations.add(namedDestination);
        } else {
            //Warning already issued by AreaTreeHandler (debug level is sufficient)
            log.debug("Unresolved destination item received: " + dd.getIDRef());
        }
    }

    /**
     * Renders a Bookmark-Tree object
     * @param bookmarks the BookmarkData object containing all the Bookmark-Items
     */
    protected void renderBookmarkTree(BookmarkData bookmarks) {
        assert this.bookmarkTree == null;
        if (!hasDocumentNavigation()) {
            return;
        }
        this.bookmarkTree = new BookmarkTree();
        for (int i = 0; i < bookmarks.getCount(); i++) {
            BookmarkData ext = bookmarks.getSubData(i);
            Bookmark b = renderBookmarkItem(ext);
            bookmarkTree.addBookmark(b);
        }
    }

    private Bookmark renderBookmarkItem(BookmarkData bookmarkItem) {

        String targetID = bookmarkItem.getIDRef();
        if (targetID == null || targetID.length() == 0) {
            throw new IllegalArgumentException("DestinationData must contain a ID reference");
        }
        GoToXYAction action = null;
        PageViewport pv = bookmarkItem.getPageViewport();

        if (pv != null) {
            action = getGoToActionForID(targetID, pv.getPageIndex());
        } else {
            //Warning already issued by AreaTreeHandler (debug level is sufficient)
            log.debug("Bookmark with IDRef \"" + targetID + "\" has a null PageViewport.");
        }

        Bookmark b = new Bookmark(
                bookmarkItem.getBookmarkTitle(),
                bookmarkItem.showChildItems(),
                action);
        for (int i = 0; i < bookmarkItem.getCount(); i++) {
            b.addChildBookmark(renderBookmarkItem(bookmarkItem.getSubData(i)));
        }
        return b;
    }

    private void renderXMPMetadata(XMPMetadata metadata) {
        this.documentMetadata = metadata.getMetadata();
    }

    private GoToXYAction getGoToActionForID(String targetID, int pageIndex) {
        // Already a GoToXY present for this target? If not, create.
        GoToXYAction action = (GoToXYAction)actionSet.get(targetID);
        //GoToXYAction action = (GoToXYAction)idGoTos.get(targetID);
        if (action == null) {
            if (pageIndex < 0) {
                //pageIndex = page
            }
            Point position = (Point)idPositions.get(targetID);
            // can the GoTo already be fully filled in?
            if (pageIndex >= 0 && position != null) {
                action = new GoToXYAction(targetID, pageIndex, position);
            } else {
                // Not complete yet, can't use getPDFGoTo:
                action = new GoToXYAction(targetID, pageIndex, null);
                unfinishedGoTos.add(action);
            }
            action = (GoToXYAction)actionSet.put(action);
            //idGoTos.put(targetID, action);
        }
        return action;
    }

    private void finishOpenGoTos() {
        int count = unfinishedGoTos.size();
        if (count > 0) {
            Point defaultPos = new Point(0, 0);  // top-o-page
            while (!unfinishedGoTos.isEmpty()) {
                GoToXYAction action = (GoToXYAction)unfinishedGoTos.get(0);
                noteGoToPosition(action, defaultPos);
            }
            PDFEventProducer eventProducer = PDFEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.nonFullyResolvedLinkTargets(this, count);
            // dysfunctional if pageref is null
        }
    }

    private void noteGoToPosition(GoToXYAction action, Point position) {
        action.setTargetLocation(position);
        try {
            getDocumentNavigationHandler().addResolvedAction(action);
        } catch (IFException ife) {
            handleIFException(ife);
        }
        unfinishedGoTos.remove(action);
    }

    private void noteGoToPosition(GoToXYAction action, PageViewport pv, Point position) {
        action.setPageIndex(pv.getPageIndex());
        noteGoToPosition(action, position);
    }

    private void saveAbsolutePosition(String id, PageViewport pv,
            int relativeIPP, int relativeBPP, AffineTransform tf) {
        Point position = new Point(relativeIPP, relativeBPP);
        tf.transform(position, position);
        idPositions.put(id, position);
        // is there already a GoTo action waiting to be completed?
        GoToXYAction action = (GoToXYAction)actionSet.get(id);
        if (action != null) {
            noteGoToPosition(action, pv, position);
        }
    }

    private void saveAbsolutePosition(String id, int relativeIPP, int relativeBPP) {
        saveAbsolutePosition(id, this.currentPageViewport,
                             relativeIPP, relativeBPP, graphicContext.getTransform());
    }

    private void saveBlockPosIfTargetable(Block block) {
        String id = getTargetableID(block);
        if (hasDocumentNavigation() && id != null) {
            // FIXME: Like elsewhere in the renderer code, absolute and relative
            //        directions are happily mixed here. This makes sure that the
            //        links point to the right location, but it is not correct.
            int ipp = block.getXOffset();
            int bpp = block.getYOffset() + block.getSpaceBefore();
            int positioning = block.getPositioning();
            if (!(positioning == Block.FIXED || positioning == Block.ABSOLUTE)) {
                ipp += currentIPPosition;
                bpp += currentBPPosition;
            }
            saveAbsolutePosition(id, currentPageViewport, ipp, bpp, graphicContext.getTransform());
        }
    }

    private void saveInlinePosIfTargetable(InlineArea inlineArea) {
        String id = getTargetableID(inlineArea);
        if (hasDocumentNavigation() && id != null) {
            int extraMarginBefore = 5000; // millipoints
            int ipp = currentIPPosition;
            int bpp = currentBPPosition + inlineArea.getOffset() - extraMarginBefore;
            saveAbsolutePosition(id, ipp, bpp);
        }
    }

    private String getTargetableID(Area area) {
        String id = (String) area.getTrait(Trait.PROD_ID);
        if (id == null || id.length() == 0
            || !currentPageViewport.isFirstWithID(id)
            || idPositions.containsKey(id)) {
            return null;
        } else {
            return id;
        }
    }

    /** {@inheritDoc} */
    public void startPageSequence(PageSequence pageSequence) {
        try {
            if (this.inPageSequence) {
                documentHandler.endPageSequence();
                documentHandler.getContext().setLanguage(null);
            } else {
                if (this.documentMetadata == null) {
                    this.documentMetadata = createDefaultDocumentMetadata();
                }
                documentHandler.handleExtensionObject(this.documentMetadata);
                documentHandler.endDocumentHeader();
                this.inPageSequence = true;
            }
            establishForeignAttributes(pageSequence.getForeignAttributes());
            documentHandler.getContext().setLanguage(toLocale(pageSequence));
            documentHandler.startPageSequence(null);
            resetForeignAttributes();
            processExtensionAttachments(pageSequence);
        } catch (IFException e) {
            handleIFException(e);
        }
    }

    private Locale toLocale(PageSequence pageSequence) {
        if (pageSequence.getLanguage() != null) {
            if (pageSequence.getCountry() != null) {
                return new Locale(pageSequence.getLanguage(), pageSequence.getCountry());
            } else {
                return new Locale(pageSequence.getLanguage());
            }
        }
        return null;
    }

    private Metadata createDefaultDocumentMetadata() {
        Metadata xmp = new Metadata();
        DublinCoreAdapter dc = DublinCoreSchema.getAdapter(xmp);
        if (getUserAgent().getTitle() != null) {
            dc.setTitle(getUserAgent().getTitle());
        }
        if (getUserAgent().getAuthor() != null) {
            dc.addCreator(getUserAgent().getAuthor());
        }
        if (getUserAgent().getKeywords() != null) {
            dc.addSubject(getUserAgent().getKeywords());
        }
        XMPBasicAdapter xmpBasic = XMPBasicSchema.getAdapter(xmp);
        if (getUserAgent().getProducer() != null) {
            xmpBasic.setCreatorTool(getUserAgent().getProducer());
        } else {
            xmpBasic.setCreatorTool(Version.getVersion());
        }
        xmpBasic.setMetadataDate(new java.util.Date());
        if (getUserAgent().getCreationDate() != null) {
            xmpBasic.setCreateDate(getUserAgent().getCreationDate());
        } else {
            xmpBasic.setCreateDate(xmpBasic.getMetadataDate());
        }
        return xmp;
    }

    /** {@inheritDoc} */
    public void preparePage(PageViewport page) {
        super.preparePage(page);
    }

    /** {@inheritDoc} */
    public void renderPage(PageViewport page) throws IOException, FOPException {
        if (log.isTraceEnabled()) {
            log.trace("renderPage() " + page);
        }
        try {
            pageIndices.put(page.getKey(), new Integer(page.getPageIndex()));
            Rectangle viewArea = page.getViewArea();
            Dimension dim = new Dimension(viewArea.width, viewArea.height);

            establishForeignAttributes(page.getForeignAttributes());
            documentHandler.startPage(page.getPageIndex(), page.getPageNumberString(),
                    page.getSimplePageMasterName(), dim);
            resetForeignAttributes();
            documentHandler.startPageHeader();

            //Add page attachments to page header
            processExtensionAttachments(page);

            documentHandler.endPageHeader();
            this.painter = documentHandler.startPageContent();
            super.renderPage(page);
            this.painter = null;
            documentHandler.endPageContent();

            documentHandler.startPageTrailer();
            if (hasDocumentNavigation()) {
                Iterator iter = this.deferredLinks.iterator();
                while (iter.hasNext()) {
                    Link link = (Link)iter.next();
                    iter.remove();
                    getDocumentNavigationHandler().renderLink(link);
                }
            }
            documentHandler.endPageTrailer();

            establishForeignAttributes(page.getForeignAttributes());
            documentHandler.endPage();
            resetForeignAttributes();
        } catch (IFException e) {
            handleIFException(e);
        }
    }

    private void processExtensionAttachments(AreaTreeObject area) throws IFException {
        if (area.hasExtensionAttachments()) {
            for (Iterator iter = area.getExtensionAttachments().iterator();
                iter.hasNext();) {
                ExtensionAttachment attachment = (ExtensionAttachment) iter.next();
                this.documentHandler.handleExtensionObject(attachment);
            }
        }
    }

    private void establishForeignAttributes(Map foreignAttributes) {
        documentHandler.getContext().setForeignAttributes(foreignAttributes);
    }

    private void resetForeignAttributes() {
        documentHandler.getContext().resetForeignAttributes();
    }

    private void establishStructurePointer(String ptr) {
        documentHandler.getContext().setStructurePointer(ptr);
    }

    private void resetStructurePointer() {
        documentHandler.getContext().resetStructurePointer();
    }

    /** {@inheritDoc} */
    protected void saveGraphicsState() {
        graphicContextStack.push(graphicContext);
        graphicContext = (IFGraphicContext)graphicContext.clone();
    }

    /** {@inheritDoc} */
    protected void restoreGraphicsState() {
        while (graphicContext.getGroupStackSize() > 0) {
            IFGraphicContext.Group[] groups = graphicContext.dropGroups();
            for (int i = groups.length - 1; i >= 0; i--) {
                try {
                    groups[i].end(painter);
                } catch (IFException ife) {
                    handleIFException(ife);
                }
            }
        }
        graphicContext = (IFGraphicContext)graphicContextStack.pop();
    }

    private void pushGroup(IFGraphicContext.Group group) {
        graphicContext.pushGroup(group);
        try {
            group.start(painter);
        } catch (IFException ife) {
            handleIFException(ife);
        }
    }

    /** {@inheritDoc} */
    protected List breakOutOfStateStack() {
        log.debug("Block.FIXED --> break out");
        List breakOutList = new java.util.ArrayList();
        while (!this.graphicContextStack.empty()) {
            //Handle groups
            IFGraphicContext.Group[] groups = graphicContext.getGroups();
            for (int j = groups.length - 1; j >= 0; j--) {
                try {
                    groups[j].end(painter);
                } catch (IFException ife) {
                    handleIFException(ife);
                }
            }

            breakOutList.add(0, this.graphicContext);
            graphicContext = (IFGraphicContext)graphicContextStack.pop();
        }
        return breakOutList;
    }

    /** {@inheritDoc} */
    protected void restoreStateStackAfterBreakOut(List breakOutList) {
        log.debug("Block.FIXED --> restoring context after break-out");
        for (int i = 0, c = breakOutList.size(); i < c; i++) {
            graphicContextStack.push(graphicContext);
            this.graphicContext = (IFGraphicContext)breakOutList.get(i);

            //Handle groups
            IFGraphicContext.Group[] groups = graphicContext.getGroups();
            for (int j = 0, jc = groups.length; j < jc; j++) {
                try {
                    groups[j].start(painter);
                } catch (IFException ife) {
                    handleIFException(ife);
                }
            }
        }
        log.debug("restored.");
    }

    /** {@inheritDoc} */
    protected void concatenateTransformationMatrix(AffineTransform at) {
        if (!at.isIdentity()) {
            concatenateTransformationMatrixMpt(ptToMpt(at), false);
        }
    }

    private void concatenateTransformationMatrixMpt(AffineTransform at, boolean force) {
        if (force || !at.isIdentity()) {
            if (log.isTraceEnabled()) {
                log.trace("-----concatenateTransformationMatrix: " + at);
            }
            IFGraphicContext.Group group = new IFGraphicContext.Group(at);
            pushGroup(group);
        }
    }

    /** {@inheritDoc} */
    protected void beginTextObject() {
        //nop - Ignore, handled by painter internally
    }

    /** {@inheritDoc} */
    protected void endTextObject() {
        //nop - Ignore, handled by painter internally
    }

    /** {@inheritDoc} */
    protected void renderRegionViewport(RegionViewport viewport) {
        Dimension dim = new Dimension(viewport.getIPD(), viewport.getBPD());
        viewportDimensionStack.push(dim);
        super.renderRegionViewport(viewport);
        viewportDimensionStack.pop();
    }

    /** {@inheritDoc} */
    protected void renderBlockViewport(BlockViewport bv, List children) {
        //Essentially the same code as in the super class but optimized for the IF

        //This is the content-rect
        Dimension dim = new Dimension(bv.getIPD(), bv.getBPD());
        viewportDimensionStack.push(dim);

        // save positions
        int saveIP = currentIPPosition;
        int saveBP = currentBPPosition;

        CTM ctm = bv.getCTM();
        int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
        int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();

        if (bv.getPositioning() == Block.ABSOLUTE
                || bv.getPositioning() == Block.FIXED) {

            //For FIXED, we need to break out of the current viewports to the
            //one established by the page. We save the state stack for restoration
            //after the block-container has been painted. See below.
            List breakOutList = null;
            if (bv.getPositioning() == Block.FIXED) {
                breakOutList = breakOutOfStateStack();
            }

            AffineTransform positionTransform = new AffineTransform();
            positionTransform.translate(bv.getXOffset(), bv.getYOffset());

            //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle
            positionTransform.translate(-borderPaddingStart, -borderPaddingBefore);

            //Free transformation for the block-container viewport
            String transf;
            transf = bv.getForeignAttributeValue(FOX_TRANSFORM);
            if (transf != null) {
                AffineTransform freeTransform = AWTTransformProducer.createAffineTransform(transf);
                positionTransform.concatenate(freeTransform);
            }

            saveGraphicsState();
            //Viewport position
            concatenateTransformationMatrixMpt(positionTransform, false);

            //Background and borders
            float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd());
            float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter());
            drawBackAndBorders(bv, 0, 0,
                    (dim.width + bpwidth) / 1000f, (dim.height + bpheight) / 1000f);

            //Shift to content rectangle after border painting
            AffineTransform contentRectTransform = new AffineTransform();
            contentRectTransform.translate(borderPaddingStart, borderPaddingBefore);
            concatenateTransformationMatrixMpt(contentRectTransform, false);

            //Clipping
            Rectangle clipRect = null;
            if (bv.getClip()) {
                clipRect = new Rectangle(0, 0, dim.width, dim.height);
                //clipRect(0f, 0f, width, height);
            }

            //saveGraphicsState();
            //Set up coordinate system for content rectangle
            AffineTransform contentTransform = ctm.toAffineTransform();
            //concatenateTransformationMatrixMpt(contentTransform);
            startViewport(contentTransform, clipRect);

            currentIPPosition = 0;
            currentBPPosition = 0;
            renderBlocks(bv, children);

            endViewport();
            //restoreGraphicsState();
            restoreGraphicsState();

            if (breakOutList != null) {
                restoreStateStackAfterBreakOut(breakOutList);
            }

            currentIPPosition = saveIP;
            currentBPPosition = saveBP;
        } else {

            currentBPPosition += bv.getSpaceBefore();

            //borders and background in the old coordinate system
            handleBlockTraits(bv);

            //Advance to start of content area
            currentIPPosition += bv.getStartIndent();

            CTM tempctm = new CTM(containingIPPosition, currentBPPosition);
            ctm = tempctm.multiply(ctm);

            //Now adjust for border/padding
            currentBPPosition += borderPaddingBefore;

            Rectangle2D clippingRect = null;
            if (bv.getClip()) {
                clippingRect = new Rectangle(currentIPPosition, currentBPPosition,
                        bv.getIPD(), bv.getBPD());
            }

            startVParea(ctm, clippingRect);
            currentIPPosition = 0;
            currentBPPosition = 0;
            renderBlocks(bv, children);
            endVParea();

            currentIPPosition = saveIP;
            currentBPPosition = saveBP;

            currentBPPosition += bv.getAllocBPD();
        }
        viewportDimensionStack.pop();
    }

    /** {@inheritDoc} */
    public void renderViewport(Viewport viewport) {
        String ptr = (String) viewport.getTrait(Trait.PTR);
        establishStructurePointer(ptr);
        Dimension dim = new Dimension(viewport.getIPD(), viewport.getBPD());
        viewportDimensionStack.push(dim);
        super.renderViewport(viewport);
        viewportDimensionStack.pop();
        resetStructurePointer();
    }

    /** {@inheritDoc} */
    protected void startVParea(CTM ctm, Rectangle2D clippingRect) {
        if (log.isTraceEnabled()) {
            log.trace("startVParea() ctm=" + ctm + ", clippingRect=" + clippingRect);
        }
        AffineTransform at = new AffineTransform(ctm.toArray());
        Rectangle clipRect = null;
        if (clippingRect != null) {
            clipRect = new Rectangle(
                    (int)clippingRect.getMinX() - currentIPPosition,
                    (int)clippingRect.getMinY() - currentBPPosition,
                    (int)clippingRect.getWidth(), (int)clippingRect.getHeight());
        }
        startViewport(at, clipRect);
        if (log.isTraceEnabled()) {
            log.trace("startVPArea: " + at + " --> " + graphicContext.getTransform());
        }
    }

    private void startViewport(AffineTransform at, Rectangle clipRect) {
        saveGraphicsState();
        try {
            IFGraphicContext.Viewport viewport = new IFGraphicContext.Viewport(
                    at, (Dimension)viewportDimensionStack.peek(), clipRect);
            graphicContext.pushGroup(viewport);
            viewport.start(painter);
        } catch (IFException e) {
            handleIFException(e);
        }
    }

    /** {@inheritDoc} */
    protected void endVParea() {
        log.trace("endVParea()");
        endViewport();
        if (log.isTraceEnabled()) {
            log.trace("endVPArea() --> " + graphicContext.getTransform());
        }
    }

    private void endViewport() {
        restoreGraphicsState();
    }

    /** {@inheritDoc} */
    protected void renderInlineArea(InlineArea inlineArea) {
        saveInlinePosIfTargetable(inlineArea);
        super.renderInlineArea(inlineArea);
    }

    /** {@inheritDoc} */
    public void renderInlineParent(InlineParent ip) {
        // stuff we only need if a link must be created:
        Rectangle ipRect = null;
        AbstractAction action = null;
        String ptr = (String) ip.getTrait(Trait.PTR); // used for accessibility
        // make sure the rect is determined *before* calling super!
        int ipp = currentIPPosition;
        int bpp = currentBPPosition + ip.getOffset();
        ipRect = new Rectangle(ipp, bpp, ip.getIPD(), ip.getBPD());
        AffineTransform transform = graphicContext.getTransform();
        ipRect = transform.createTransformedShape(ipRect).getBounds();

        // render contents
        super.renderInlineParent(ip);

        boolean linkTraitFound = false;

        // try INTERNAL_LINK first
        Trait.InternalLink intLink = (Trait.InternalLink) ip.getTrait(Trait.INTERNAL_LINK);
        if (intLink != null) {
            linkTraitFound = true;
            String pvKey = intLink.getPVKey();
            String idRef = intLink.getIDRef();
            boolean pvKeyOK = pvKey != null && pvKey.length() > 0;
            boolean idRefOK = idRef != null && idRef.length() > 0;
            if (pvKeyOK && idRefOK) {
                Integer pageIndex = (Integer)pageIndices.get(pvKey);
                action = getGoToActionForID(idRef, (pageIndex != null ? pageIndex.intValue() : -1));
            } else {
                //Warnings already issued by AreaTreeHandler
            }
        }

        // no INTERNAL_LINK, look for EXTERNAL_LINK
        if (!linkTraitFound) {
            Trait.ExternalLink extLink = (Trait.ExternalLink) ip.getTrait(Trait.EXTERNAL_LINK);
            if (extLink != null) {
                String extDest = extLink.getDestination();
                if (extDest != null && extDest.length() > 0) {
                    linkTraitFound = true;
                    action = new URIAction(extDest, extLink.newWindow());
                    action = actionSet.put(action);
                }
            }
        }

        // warn if link trait found but not allowed, else create link
        if (linkTraitFound) {
            action.setStructurePointer(ptr);  // used for accessibility
            Link link = new Link(action, ipRect);
            this.deferredLinks.add(link);
        }
    }

    /** {@inheritDoc} */
    protected void renderBlock(Block block) {
        if (log.isTraceEnabled()) {
            log.trace("renderBlock() " + block);
        }
        saveBlockPosIfTargetable(block);
        super.renderBlock(block);
    }

    private Typeface getTypeface(String fontName) {
        Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
        if (tf instanceof LazyFont) {
            tf = ((LazyFont)tf).getRealFont();
        }
        return tf;
    }

    /** {@inheritDoc} */
    protected void renderText(TextArea text) {
        if (log.isTraceEnabled()) {
            log.trace("renderText() " + text);
        }
        renderInlineAreaBackAndBorders(text);
        Color ct = (Color) text.getTrait(Trait.COLOR);

        beginTextObject();

        String fontName = getInternalFontNameForArea(text);
        int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
        String ptr = (String)text.getTrait(Trait.PTR); // used for accessibility
        establishStructurePointer(ptr);

        // This assumes that *all* CIDFonts use a /ToUnicode mapping
        Typeface tf = getTypeface(fontName);

        FontTriplet triplet = (FontTriplet)text.getTrait(Trait.FONT);
        try {
            painter.setFont(triplet.getName(), triplet.getStyle(), new Integer(triplet.getWeight()),
                    "normal", new Integer(size), ct);
        } catch (IFException e) {
            handleIFException(e);
        }

        int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
        int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
        textUtil.flush();
        textUtil.setStartPosition(rx, bl);
        textUtil.setSpacing(text.getTextLetterSpaceAdjust(), text.getTextWordSpaceAdjust());
        super.renderText(text);

        textUtil.flush();
        renderTextDecoration(tf, size, text, bl, rx);
        resetStructurePointer();
    }

    /** {@inheritDoc} */
    protected void renderWord(WordArea word) {
        Font font = getFontFromArea(word.getParentArea());
        String s = word.getWord();

        renderText(s, word.getLetterAdjustArray(),
                font, (AbstractTextArea)word.getParentArea());

        super.renderWord(word);
    }

    /** {@inheritDoc} */
    protected void renderSpace(SpaceArea space) {
        Font font = getFontFromArea(space.getParentArea());
        String s = space.getSpace();

        AbstractTextArea textArea = (AbstractTextArea)space.getParentArea();
        renderText(s, null, font, textArea);

        if (textUtil.combined && space.isAdjustable()) {
            //Used for justified text, for example
            int tws = textArea.getTextWordSpaceAdjust()
                         + 2 * textArea.getTextLetterSpaceAdjust();
            if (tws != 0) {
                textUtil.adjust(tws);
            }
        }
        super.renderSpace(space);
    }

    /**
     * Does low-level rendering of text.
     * @param s text to render
     * @param letterAdjust an array of widths for letter adjustment (may be null)
     * @param font to font in use
     * @param parentArea the parent text area to retrieve certain traits from
     */
    protected void renderText(String s,
                           int[] letterAdjust,
                           Font font, AbstractTextArea parentArea) {
        int l = s.length();
        if (l == 0) {
            return;
        }

        if (letterAdjust != null) {
            textUtil.adjust(letterAdjust[0]);
        }
        for (int i = 0; i < l; i++) {
            char ch = s.charAt(i);
            textUtil.addChar(ch);
            int glyphAdjust = 0;
            if (textUtil.combined && font.hasChar(ch)) {
                int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0);
                glyphAdjust += tls;
            }
            if (letterAdjust != null && i < l - 1) {
                glyphAdjust += letterAdjust[i + 1];
            }

            textUtil.adjust(glyphAdjust);
        }
    }

    private class TextUtil {
        private static final int INITIAL_BUFFER_SIZE = 16;
        private int[] dx = new int[INITIAL_BUFFER_SIZE];
        private int lastDXPos = 0;
        private final StringBuffer text = new StringBuffer();
        private int startx, starty;
        private int tls, tws;
        private final boolean combined = false;

        void addChar(char ch) {
            text.append(ch);
        }

        void adjust(int adjust) {
            if (adjust != 0) {
                int idx = text.length();
                if (idx > dx.length - 1) {
                    int newSize = Math.max(dx.length, idx + 1) + INITIAL_BUFFER_SIZE;
                    int[] newDX = new int[newSize];
                    System.arraycopy(dx, 0, newDX, 0, dx.length);
                    dx = newDX;
                }
                dx[idx] += adjust;
                lastDXPos = idx;
            }
        }

        void reset() {
            if (text.length() > 0) {
                text.setLength(0);
                Arrays.fill(dx, 0);
                lastDXPos = 0;
            }
        }

        void setStartPosition(int x, int y) {
            this.startx = x;
            this.starty = y;
        }

        void setSpacing(int tls, int tws) {
            this.tls = tls;
            this.tws = tws;
        }

        void flush() {
            if (text.length() > 0) {
                try {
                    int[] effDX = null;
                    if (lastDXPos > 0) {
                        int size = lastDXPos + 1;
                        effDX = new int[size];
                        System.arraycopy(dx, 0, effDX, 0, size);
                    }
                    if (combined) {
                        painter.drawText(startx, starty, 0, 0, effDX, text.toString());
                    } else {
                        painter.drawText(startx, starty, tls, tws, effDX, text.toString());
                    }
                } catch (IFException e) {
                    handleIFException(e);
                }
                reset();
            }
        }
    }

    /** {@inheritDoc} */
    public void renderImage(Image image, Rectangle2D pos) {
        drawImage(image.getURL(), pos, image.getForeignAttributes());
    }

    /** {@inheritDoc} */
    protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
        Rectangle posInt = new Rectangle(
                currentIPPosition + (int)pos.getX(),
                currentBPPosition + (int)pos.getY(),
                (int)pos.getWidth(),
                (int)pos.getHeight());
        uri = URISpecification.getURL(uri);
        try {
            establishForeignAttributes(foreignAttributes);
            painter.drawImage(uri, posInt);
            resetForeignAttributes();
        } catch (IFException ife) {
            handleIFException(ife);
        }
    }

    /** {@inheritDoc} */
    public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
        endTextObject();
        Rectangle posInt = new Rectangle(
                currentIPPosition + (int)pos.getX(),
                currentBPPosition + (int)pos.getY(),
                (int)pos.getWidth(),
                (int)pos.getHeight());
        Document doc = fo.getDocument();
        try {
            establishForeignAttributes(fo.getForeignAttributes());
            painter.drawImage(doc, posInt);
            resetForeignAttributes();
        } catch (IFException ife) {
            handleIFException(ife);
        }
    }

    /** {@inheritDoc} */
    public void renderLeader(Leader area) {
        renderInlineAreaBackAndBorders(area);

        int style = area.getRuleStyle();
        int ruleThickness = area.getRuleThickness();
        int startx = currentIPPosition + area.getBorderAndPaddingWidthStart();
        int starty = currentBPPosition + area.getOffset() + (ruleThickness / 2);
        int endx = currentIPPosition
                        + area.getBorderAndPaddingWidthStart()
                        + area.getIPD();
        Color col = (Color)area.getTrait(Trait.COLOR);

        Point start = new Point(startx, starty);
        Point end = new Point(endx, starty);
        try {
            painter.drawLine(start, end, ruleThickness, col, RuleStyle.valueOf(style));
        } catch (IFException ife) {
            handleIFException(ife);
        }

        super.renderLeader(area);
    }

    /** {@inheritDoc} */
    protected void clip() {
        throw new IllegalStateException("Not used");
    }

    /** {@inheritDoc} */
    protected void clipRect(float x, float y, float width, float height) {
        pushGroup(new IFGraphicContext.Group());
        try {
            painter.clipRect(toMillipointRectangle(x, y, width, height));
        } catch (IFException ife) {
            handleIFException(ife);
        }
    }

    /** {@inheritDoc} */
    protected void closePath() {
        throw new IllegalStateException("Not used");
    }

    /** {@inheritDoc} */
    protected void drawBorders(float startx, float starty,
            float width, float height,
            BorderProps bpsBefore, BorderProps bpsAfter,
            BorderProps bpsStart, BorderProps bpsEnd) {
        Rectangle rect = toMillipointRectangle(startx, starty, width, height);
        try {
            painter.drawBorderRect(rect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
        } catch (IFException ife) {
            handleIFException(ife);
        }
    }

    /** {@inheritDoc} */
    protected void drawBorderLine(float x1, float y1, float x2, float y2, boolean horz,
            boolean startOrBefore, int style, Color col) {
        //Simplified implementation that is only used by renderTextDecoration()
        //drawBorders() is overridden and uses the Painter's high-level method drawBorderRect()
        updateColor(col, true);
        fillRect(x1, y1, x2 - x1, y2 - y1);
    }

    private int toMillipoints(float coordinate) {
        return Math.round(coordinate * 1000);
    }

    private Rectangle toMillipointRectangle(float x, float y, float width, float height) {
        return new Rectangle(
                toMillipoints(x),
                toMillipoints(y),
                toMillipoints(width),
                toMillipoints(height));
    }

    /** {@inheritDoc} */
    protected void fillRect(float x, float y, float width, float height) {
        try {
            painter.fillRect(
                    toMillipointRectangle(x, y, width, height),
                    this.graphicContext.getPaint());
        } catch (IFException e) {
            handleIFException(e);
        }
    }

    /** {@inheritDoc} */
    protected void moveTo(float x, float y) {
        throw new IllegalStateException("Not used");
    }

    /** {@inheritDoc} */
    protected void lineTo(float x, float y) {
        throw new IllegalStateException("Not used");
    }

    /** {@inheritDoc} */
    protected void updateColor(Color col, boolean fill) {
        if (fill) {
            this.graphicContext.setPaint(col);
        } else {
            this.graphicContext.setColor(col);
        }

    }

}
