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

// Java
import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.area.BookmarkData;
import org.apache.fop.area.CTM;
import org.apache.fop.area.DestinationData;
import org.apache.fop.area.LineArea;
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.Trait;
import org.apache.fop.area.inline.AbstractTextArea;
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.WordArea;
import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.events.ResourceEventProducer;
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.LazyFont;
import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.pdf.PDFAMode;
import org.apache.fop.pdf.PDFAction;
import org.apache.fop.pdf.PDFAnnotList;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFEncryptionParams;
import org.apache.fop.pdf.PDFFactory;
import org.apache.fop.pdf.PDFGoTo;
import org.apache.fop.pdf.PDFInfo;
import org.apache.fop.pdf.PDFLink;
import org.apache.fop.pdf.PDFNumber;
import org.apache.fop.pdf.PDFOutline;
import org.apache.fop.pdf.PDFPage;
import org.apache.fop.pdf.PDFPaintingState;
import org.apache.fop.pdf.PDFResourceContext;
import org.apache.fop.pdf.PDFResources;
import org.apache.fop.pdf.PDFTextUtil;
import org.apache.fop.pdf.PDFXMode;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.AbstractPaintingState;
import org.apache.fop.util.CharUtilities;
import org.apache.fop.util.AbstractPaintingState.AbstractData;

/**
 * Renderer that renders areas to PDF.
 */
public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConfigurationConstants {

    /** The MIME type for PDF */
    public static final String MIME_TYPE = MimeConstants.MIME_PDF;

    /** Normal PDF resolution (72dpi) */
    public static final int NORMAL_PDF_RESOLUTION = 72;


    /** Controls whether comments are written to the PDF stream. */
    protected static final boolean WRITE_COMMENTS = true;

    /**
     * the PDF Document being created
     */
    protected PDFDocument pdfDoc;

    /**
     * Utility class which enables all sorts of features that are not directly connected to the
     * normal rendering process.
     */
    protected PDFRenderingUtil pdfUtil;

    /**
     * Map of pages using the PageViewport as the key
     * this is used for prepared pages that cannot be immediately
     * rendered
     */
    protected Map pages = null;

    /**
     * Maps unique PageViewport key to PDF page reference
     */
    protected Map pageReferences = new java.util.HashMap();

    /**
     *  Maps unique PageViewport key back to PageViewport itself
     */
    //protected Map pvReferences = new java.util.HashMap();

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

    /**
     * Maps XSL-FO element IDs to PDFGoTo objects targeting the corresponding areas
     * These objects may not all be fully filled in yet
     */
    protected Map idGoTos = new java.util.HashMap();

    /**
     * The PDFGoTos in idGoTos that are not complete yet
     */
    protected 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

    /**
     * The output stream to write the document to
     */
    protected OutputStream ostream;

    /**
     * the /Resources object of the PDF document being created
     */
    protected PDFResources pdfResources;

    /** The current content generator to produce PDF commands with */
    protected PDFContentGenerator generator;
    private PDFBorderPainter borderPainter;

    /**
     * the current annotation list to add annotations to
     */
    protected PDFResourceContext currentContext = null;

    /**
     * the current page to add annotations to
     */
    protected PDFPage currentPage;

    /**
     * the current page's PDF reference string (to avoid numerous function calls)
     */
    protected String currentPageRef;

    /** page height */
    protected int pageHeight;

    /** Image handler registry */
    private final PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();


    /**
     * create the PDF renderer
     */
    public PDFRenderer() {
    }

    /** {@inheritDoc} */
    public void setUserAgent(FOUserAgent agent) {
        super.setUserAgent(agent);
        this.pdfUtil = new PDFRenderingUtil(getUserAgent());
    }

    PDFRenderingUtil getPDFUtil() {
        return this.pdfUtil;
    }

    PDFContentGenerator getGenerator() {
        return this.generator;
    }

    PDFPaintingState getState() {
        return getGenerator().getState();
    }

    /** {@inheritDoc} */
    public void startRenderer(OutputStream stream) throws IOException {
        if (userAgent == null) {
            throw new IllegalStateException("UserAgent must be set before starting the renderer");
        }
        ostream = stream;
        this.pdfDoc = pdfUtil.setupPDFDocument(stream);
    }

    /**
     * Checks if there are any unfinished PDFGoTos left in the list and resolves them
     * to a default position on the page. Logs a warning, as this should not happen.
     */
    protected void finishOpenGoTos() {
        int count = unfinishedGoTos.size();
        if (count > 0) {
            // TODO : page height may not be the same for all targeted pages
            Point2D.Float defaultPos = new Point2D.Float(0f, pageHeight / 1000f);  // top-o-page
            while (!unfinishedGoTos.isEmpty()) {
                PDFGoTo gt = (PDFGoTo) unfinishedGoTos.get(0);
                finishIDGoTo(gt, defaultPos);
            }
            PDFEventProducer eventProducer = PDFEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.nonFullyResolvedLinkTargets(this, count);
            // dysfunctional if pageref is null
        }
    }

    /** {@inheritDoc} */
    public void stopRenderer() throws IOException {
        finishOpenGoTos();

        pdfDoc.getResources().addFonts(pdfDoc, fontInfo);
        pdfDoc.outputTrailer(ostream);

        this.pdfDoc = null;
        ostream = null;

        pages = null;

        pageReferences.clear();
        //pvReferences.clear();
        pdfResources = null;
        this.generator = null;
        currentContext = null;
        currentPage = null;

        idPositions.clear();
        idGoTos.clear();
    }

    /**
     * {@inheritDoc}
     */
    public boolean supportsOutOfOrder() {
        //return false;
        return true;
    }

    /**
     * {@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())) {
                pdfUtil.renderXMPMetadata((XMPMetadata)attachment);
            }
        }
    }

    private void renderDestination(DestinationData dd) {
        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) {
            PDFGoTo gt = getPDFGoToForID(targetID, pv.getKey());
            pdfDoc.getFactory().makeDestination(
                    dd.getIDRef(), gt.makeReference());
        } 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) {
        for (int i = 0; i < bookmarks.getCount(); i++) {
            BookmarkData ext = bookmarks.getSubData(i);
            renderBookmarkItem(ext, null);
        }
    }

    private void renderBookmarkItem(BookmarkData bookmarkItem,
                                    PDFOutline parentBookmarkItem) {
        PDFOutline pdfOutline = null;

        String targetID = bookmarkItem.getIDRef();
        if (targetID == null || targetID.length() == 0) {
            throw new IllegalArgumentException("DestinationData must contain a ID reference");
        }
        PageViewport pv = bookmarkItem.getPageViewport();
        if (pv != null) {
            String pvKey = pv.getKey();
            PDFGoTo gt = getPDFGoToForID(targetID, pvKey);
            // create outline object:
            PDFOutline parent = parentBookmarkItem != null
                ? parentBookmarkItem
                : pdfDoc.getOutlineRoot();
            pdfOutline = pdfDoc.getFactory().makeOutline(parent,
                    bookmarkItem.getBookmarkTitle(), gt, bookmarkItem.showChildItems());
        } else {
            //Warning already issued by AreaTreeHandler (debug level is sufficient)
            log.debug("Bookmark with IDRef \"" + targetID + "\" has a null PageViewport.");
        }

        for (int i = 0; i < bookmarkItem.getCount(); i++) {
            renderBookmarkItem(bookmarkItem.getSubData(i), pdfOutline);
        }
    }

    /** {@inheritDoc} */
    public Graphics2DAdapter getGraphics2DAdapter() {
        return new PDFGraphics2DAdapter(this);
    }

    /** {@inheritDoc} */
    protected void saveGraphicsState() {
        generator.saveGraphicsState();
    }

    /** {@inheritDoc} */
    protected void restoreGraphicsState() {
        generator.restoreGraphicsState();
    }

    /** Indicates the beginning of a text object. */
    protected void beginTextObject() {
        generator.beginTextObject();
    }

    /** Indicates the end of a text object. */
    protected void endTextObject() {
        generator.endTextObject();
    }

    /**
     * Start the next page sequence.
     * For the PDF renderer there is no concept of page sequences
     * but it uses the first available page sequence title to set
     * as the title of the PDF document, and the language of the
     * document.
     * @param pageSequence the page sequence
     */
    public void startPageSequence(PageSequence pageSequence) {
        super.startPageSequence(pageSequence);
        LineArea seqTitle = pageSequence.getTitle();
        if (seqTitle != null) {
            String str = convertTitleToString(seqTitle);
            PDFInfo info = this.pdfDoc.getInfo();
            if (info.getTitle() == null) {
                info.setTitle(str);
            }
        }
        if (pageSequence.getLanguage() != null) {
            String lang = pageSequence.getLanguage();
            String country = pageSequence.getCountry();
            String langCode = lang + (country != null ? "-" + country : "");
            if (pdfDoc.getRoot().getLanguage() == null) {
                //Only set if not set already (first non-null is used)
                //Note: No checking is performed whether the values are valid!
                pdfDoc.getRoot().setLanguage(langCode);
            }
        }
        pdfUtil.generateDefaultXMPMetadata();
    }

    /**
     * The pdf page is prepared by making the page.
     * The page is made in the pdf document without any contents
     * and then stored to add the contents later.
     * The page objects is stored using the area tree PageViewport
     * as a key.
     *
     * @param page the page to prepare
     */
    public void preparePage(PageViewport page) {
        setupPage(page);
        if (pages == null) {
            pages = new java.util.HashMap();
        }
        pages.put(page, currentPage);
    }

    private void setupPage(PageViewport page) {
        this.pdfResources = this.pdfDoc.getResources();

        Rectangle2D bounds = page.getViewArea();
        double w = bounds.getWidth();
        double h = bounds.getHeight();
        this.currentPage = this.pdfDoc.getFactory().makePage(
            this.pdfResources,
            (int) Math.round(w / 1000), (int) Math.round(h / 1000),
            page.getPageIndex());
        pageReferences.put(page.getKey(), currentPage.referencePDF());
        //pvReferences.put(page.getKey(), page);

        pdfUtil.generatePageLabel(page.getPageIndex(), page.getPageNumberString());
    }

    /**
     * This method creates a PDF stream for the current page
     * uses it as the contents of a new page. The page is written
     * immediately to the output stream.
     * {@inheritDoc}
     */
    public void renderPage(PageViewport page)
                throws IOException, FOPException {
        if (pages != null
                && (currentPage = (PDFPage) pages.get(page)) != null) {
            //Retrieve previously prepared page (out-of-line rendering)
            pages.remove(page);
        } else {
            setupPage(page);
        }
        currentPageRef = currentPage.referencePDF();

        Rectangle bounds = page.getViewArea();
        pageHeight = bounds.height;

        this.generator = new PDFContentGenerator(this.pdfDoc, this.ostream, this.currentPage);
        this.borderPainter = new PDFBorderPainter(this.generator);

        // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's
        AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0,
                pageHeight / 1000f);
        generator.concatenate(basicPageTransform);
        /*
        currentState.concatenate(basicPageTransform);
        currentStream.add(CTMHelper.toPDFString(basicPageTransform, false) + " cm\n");
        */

        super.renderPage(page);

        this.pdfDoc.registerObject(generator.getStream());
        currentPage.setContents(generator.getStream());
        PDFAnnotList annots = currentPage.getAnnotations();
        if (annots != null) {
            this.pdfDoc.addObject(annots);
        }
        this.pdfDoc.addObject(currentPage);
        this.borderPainter = null;
        this.generator.flushPDFDoc();
        this.generator = null;
    }

    /** {@inheritDoc} */
    protected void startVParea(CTM ctm, Rectangle2D clippingRect) {
        saveGraphicsState();
        // Set the given CTM in the graphics state
        /*
        currentState.concatenate(
                new AffineTransform(CTMHelper.toPDFArray(ctm)));
                */

        if (clippingRect != null) {
            clipRect((float)clippingRect.getX() / 1000f,
                    (float)clippingRect.getY() / 1000f,
                    (float)clippingRect.getWidth() / 1000f,
                    (float)clippingRect.getHeight() / 1000f);
        }
        // multiply with current CTM
        generator.concatenate(new AffineTransform(CTMHelper.toPDFArray(ctm)));
    }

    /** {@inheritDoc} */
    protected void endVParea() {
        restoreGraphicsState();
    }

    /** {@inheritDoc} */
    protected void concatenateTransformationMatrix(AffineTransform at) {
        generator.concatenate(at);
    }

    /**
     * Formats a float value (normally coordinates) as Strings.
     * @param value the value
     * @return the formatted value
     */
    protected static String format(float value) {
        return PDFNumber.doubleOut(value);
    }

    /** {@inheritDoc} */
    protected void drawBorderLine(float x1, float y1, float x2, float y2,
            boolean horz, boolean startOrBefore, int style, Color col) {
        PDFBorderPainter.drawBorderLine(generator, x1, y1, x2, y2, horz, startOrBefore, style, col);
    }

    /** {@inheritDoc} */
    protected void clipRect(float x, float y, float width, float height) {
        generator.add(format(x) + " " + format(y) + " "
                + format(width) + " " + format(height) + " re ");
        clip();
    }

    /**
     * Clip an area.
     */
    protected void clip() {
        generator.add("W\n" + "n\n");
    }

    /**
     * Moves the current point to (x, y), omitting any connecting line segment.
     * @param x x coordinate
     * @param y y coordinate
     */
    protected void moveTo(float x, float y) {
        generator.add(format(x) + " " + format(y) + " m ");
    }

    /**
     * Appends a straight line segment from the current point to (x, y). The
     * new current point is (x, y).
     * @param x x coordinate
     * @param y y coordinate
     */
    protected void lineTo(float x, float y) {
        generator.add(format(x) + " " + format(y) + " l ");
    }

    /**
     * Closes the current subpath by appending a straight line segment from
     * the current point to the starting point of the subpath.
     */
    protected void closePath() {
        generator.add("h ");
    }

    /**
     * {@inheritDoc}
     */
    protected void fillRect(float x, float y, float width, float height) {
        if (width > 0 && height > 0) {
            generator.add(format(x) + " " + format(y) + " "
                    + format(width) + " " + format(height) + " re f\n");
        }
    }

    /**
     * Draw a line.
     *
     * @param startx the start x position
     * @param starty the start y position
     * @param endx the x end position
     * @param endy the y end position
     */
    private void drawLine(float startx, float starty, float endx, float endy) {
        generator.add(format(startx) + " " + format(starty) + " m ");
        generator.add(format(endx) + " " + format(endy) + " l S\n");
    }

    /**
     * Breaks out of the state stack to handle fixed block-containers.
     * @return the saved state stack to recreate later
     */
    protected List breakOutOfStateStack() {
        PDFPaintingState paintingState = getState();
        List breakOutList = new java.util.ArrayList();
        AbstractPaintingState.AbstractData data;
        while (true) {
            data = paintingState.getData();
            if (paintingState.restore() == null) {
                break;
            }
            if (breakOutList.size() == 0) {
                generator.comment("------ break out!");
            }
            breakOutList.add(0, data); //Insert because of stack-popping
            generator.restoreGraphicsState(false);
        }
        return breakOutList;
    }

    /**
     * Restores the state stack after a break out.
     * @param breakOutList the state stack to restore.
     */
    protected void restoreStateStackAfterBreakOut(List breakOutList) {
        generator.comment("------ restoring context after break-out...");
//        currentState.pushAll(breakOutList);
        AbstractData data;
        Iterator i = breakOutList.iterator();
        while (i.hasNext()) {
            data = (AbstractData)i.next();
            saveGraphicsState();
            AffineTransform at = data.getTransform();
            concatenateTransformationMatrix(at);
            //TODO Break-out: Also restore items such as line width and color
            //Left out for now because all this painting stuff is very
            //inconsistent. Some values go over PDFState, some don't.
        }
        generator.comment("------ done.");
    }

    /**
     * Returns area's id if it is the first area in the document with that id
     * (i.e. if the area qualifies as a link target).
     * Otherwise, or if the area has no id, null is returned.
     *
     * <i>NOTE</i>: area must be on currentPageViewport, otherwise result may be wrong!
     *
     * @param area the area for which to return the id
     * @return the area's id (null if the area has no id or
     *              other preceding areas have the same id)
     */
    protected 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;
        }
    }

    /**
     * Set XY position in the PDFGoTo and add it to the PDF trailer.
     *
     * @param gt the PDFGoTo object
     * @param position the X,Y position to set
     */
    protected void finishIDGoTo(PDFGoTo gt, Point2D.Float position) {
        gt.setPosition(position);
        pdfDoc.addTrailerObject(gt);
        unfinishedGoTos.remove(gt);
    }

    /**
     * Set page reference and XY position in the PDFGoTo and add it to the PDF trailer.
     *
     * @param gt the PDFGoTo object
     * @param pdfPageRef the PDF reference string of the target page object
     * @param position the X,Y position to set
     */
    protected void finishIDGoTo(PDFGoTo gt, String pdfPageRef, Point2D.Float position) {
        gt.setPageReference(pdfPageRef);
        finishIDGoTo(gt, position);
    }

    /**
     * Get a PDFGoTo pointing to the given id. Create one if necessary.
     * It is possible that the PDFGoTo is not fully resolved yet. In that case
     * it must be completed (and added to the PDF trailer) later.
     *
     * @param targetID the target id of the PDFGoTo
     * @param pvKey the unique key of the target PageViewport
     *
     * @return the PDFGoTo that was found or created
     */
    protected PDFGoTo getPDFGoToForID(String targetID, String pvKey) {
        // Already a PDFGoTo present for this target? If not, create.
        PDFGoTo gt = (PDFGoTo) idGoTos.get(targetID);
        if (gt == null) {
            String pdfPageRef = (String) pageReferences.get(pvKey);
            Point2D.Float position = (Point2D.Float) idPositions.get(targetID);
            // can the GoTo already be fully filled in?
            if (pdfPageRef != null && position != null) {
                // getPDFGoTo shares PDFGoTo objects as much as possible.
                // It also takes care of assignObjectNumber and addTrailerObject.
                gt = pdfDoc.getFactory().getPDFGoTo(pdfPageRef, position);
            } else {
                // Not complete yet, can't use getPDFGoTo:
                gt = new PDFGoTo(pdfPageRef);
                pdfDoc.assignObjectNumber(gt);
                // pdfDoc.addTrailerObject() will be called later, from finishIDGoTo()
                unfinishedGoTos.add(gt);
            }
            idGoTos.put(targetID, gt);
        }
        return gt;
    }

    /**
     * Saves id's absolute position on page for later retrieval by PDFGoTos
     *
     * @param id the id of the area whose position must be saved
     * @param pdfPageRef the PDF page reference string
     * @param relativeIPP the *relative* IP position in millipoints
     * @param relativeBPP the *relative* BP position in millipoints
     * @param tf the transformation to apply once the relative positions have been
     *           converted to points
     */
    protected void saveAbsolutePosition(String id, String pdfPageRef,
                                        int relativeIPP, int relativeBPP, AffineTransform tf) {
        Point2D.Float position = new Point2D.Float(relativeIPP / 1000f, relativeBPP / 1000f);
        tf.transform(position, position);
        idPositions.put(id, position);
        // is there already a PDFGoTo waiting to be completed?
        PDFGoTo gt = (PDFGoTo) idGoTos.get(id);
        if (gt != null) {
            finishIDGoTo(gt, pdfPageRef, position);
        }
/*
        // The code below auto-creates a named destination for every id in the document.
        // This should probably be controlled by a user-configurable setting, as it may
        // make the PDF file grow noticeably.
        // *** NOT YET WELL-TESTED ! ***
        if (true) {
            PDFFactory factory = pdfDoc.getFactory();
            if (gt == null) {
                gt = factory.getPDFGoTo(pdfPageRef, position);
                idGoTos.put(id, gt);  // so others can pick it up too
            }
            factory.makeDestination(id, gt.referencePDF(), currentPageViewport);
            // Note: using currentPageViewport is only correct if the id is indeed on
            // the current PageViewport. But even if incorrect, it won't interfere with
            // what gets created in the PDF.
            // For speedup, we should also create a lookup map id -> PDFDestination
        }
*/
    }

    /**
     * Saves id's absolute position on page for later retrieval by PDFGoTos,
     * using the currently valid transformation and the currently valid PDF page reference
     *
     * @param id the id of the area whose position must be saved
     * @param relativeIPP the *relative* IP position in millipoints
     * @param relativeBPP the *relative* BP position in millipoints
     */
    protected void saveAbsolutePosition(String id, int relativeIPP, int relativeBPP) {
        saveAbsolutePosition(id, currentPageRef,
                             relativeIPP, relativeBPP, getState().getTransform());
    }

    /**
     * If the given block area is a possible link target, its id + absolute position will
     * be saved. The saved position is only correct if this function is called at the very
     * start of renderBlock!
     *
     * @param block the block area in question
     */
    protected void saveBlockPosIfTargetable(Block block) {
        String id = getTargetableID(block);
        if (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;
            }
            AffineTransform tf = positioning == Block.FIXED
                ? getState().getBaseTransform()
                : getState().getTransform();
            saveAbsolutePosition(id, currentPageRef, ipp, bpp, tf);
        }
    }

    /**
     * If the given inline area is a possible link target, its id + absolute position will
     * be saved. The saved position is only correct if this function is called at the very
     * start of renderInlineArea!
     *
     * @param inlineArea the inline area in question
     */
    protected void saveInlinePosIfTargetable(InlineArea inlineArea) {
        String id = getTargetableID(inlineArea);
        if (id != null) {
            int extraMarginBefore = 5000; // millipoints
            int ipp = currentIPPosition;
            int bpp = currentBPPosition + inlineArea.getOffset() - extraMarginBefore;
            saveAbsolutePosition(id, ipp, bpp);
        }
    }

    /**
     * {@inheritDoc}
     */
    protected void renderBlock(Block block) {
        saveBlockPosIfTargetable(block);
        super.renderBlock(block);
    }

    /** {@inheritDoc} */
    protected void renderLineArea(LineArea line) {
        super.renderLineArea(line);
    }

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

    /**
     * Render inline parent area.
     * For pdf this handles the inline parent area traits such as
     * links, border, background.
     * @param ip the inline parent area
     */
    public void renderInlineParent(InlineParent ip) {

        boolean annotsAllowed = pdfDoc.getProfile().isAnnotationAllowed();

        // stuff we only need if a link must be created:
        Rectangle2D ipRect = null;
        PDFFactory factory = null;
        PDFAction action   = null;
        if (annotsAllowed) {
            // make sure the rect is determined *before* calling super!
            int ipp = currentIPPosition;
            int bpp = currentBPPosition + ip.getOffset();
            ipRect = new Rectangle2D.Float(ipp / 1000f, bpp / 1000f,
                                           ip.getIPD() / 1000f, ip.getBPD() / 1000f);
            AffineTransform transform = getState().getTransform();
            ipRect = transform.createTransformedShape(ipRect).getBounds2D();

            factory = pdfDoc.getFactory();
        }

        // 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) {
                if (annotsAllowed) {
                    action = getPDFGoToForID(idRef, pvKey);
                }
            } 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;
                    if (annotsAllowed) {
                        action = factory.getExternalAction(extDest, extLink.newWindow());
                    }
                }
            }
        }

        // warn if link trait found but not allowed, else create link
        if (linkTraitFound) {
            if (!annotsAllowed) {
                log.warn("Skipping annotation for a link due to PDF profile: "
                         + pdfDoc.getProfile());
            } else if (action != null) {
                PDFLink pdfLink = factory.makeLink(ipRect, action);
                currentPage.addAnnotation(pdfLink);
            }
        }
    }

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

    /** {@inheritDoc} */
    public void renderText(TextArea text) {
        renderInlineAreaBackAndBorders(text);
        Color ct = (Color) text.getTrait(Trait.COLOR);
        updateColor(ct, true);

        beginTextObject();

        String fontName = getInternalFontNameForArea(text);
        int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();

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

        PDFTextUtil textutil = generator.getTextUtil();
        textutil.updateTf(fontName, size / 1000f, tf.isMultiByte());


        // word.getOffset() = only height of text itself
        // currentBlockIPPosition: 0 for beginning of line; nonzero
        //  where previous line area failed to take up entire allocated space
        int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
        int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();

        textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, rx / 1000f, bl / 1000f));

        super.renderText(text);

        textutil.writeTJ();

        renderTextDecoration(tf, size, text, bl, rx);
    }

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

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

        super.renderWord(word);
    }

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

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

        if (space.isAdjustable()) {
            int tws = -((TextArea) space.getParentArea()).getTextWordSpaceAdjust()
                         - 2 * textArea.getTextLetterSpaceAdjust();

            if (tws != 0) {
                float adjust = tws / (font.getFontSize() / 1000f);
                generator.getTextUtil().adjustGlyphTJ(adjust);
            }
        }

        super.renderSpace(space);
    }

    /**
     * Escapes text according to PDF rules.
     * @param s Text to escape
     * @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 escapeText(String s,
                           int[] letterAdjust,
                           Font font, AbstractTextArea parentArea) {
        escapeText(s, 0, s.length(), letterAdjust, font, parentArea);
    }

    /**
     * Escapes text according to PDF rules.
     * @param s Text to escape
     * @param start the start position in the text
     * @param end the end position in the text
     * @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 escapeText(String s, int start, int end,
                           int[] letterAdjust,
                           Font font, AbstractTextArea parentArea) {
        String fontName = font.getFontName();
        float fontSize = font.getFontSize() / 1000f;
        Typeface tf = getTypeface(fontName);
        SingleByteFont singleByteFont = null;
        if (tf instanceof SingleByteFont) {
            singleByteFont = (SingleByteFont)tf;
        }
        PDFTextUtil textutil = generator.getTextUtil();

        int l = s.length();

        for (int i = start; i < end; i++) {
            char orgChar = s.charAt(i);
            char ch;
            float glyphAdjust = 0;
            if (font.hasChar(orgChar)) {
                ch = font.mapChar(orgChar);
                if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
                    int encoding = ch / 256;
                    if (encoding == 0) {
                        textutil.updateTf(fontName, fontSize, tf.isMultiByte());
                    } else {
                        textutil.updateTf(fontName + "_" + Integer.toString(encoding),
                                fontSize, tf.isMultiByte());
                        ch = (char)(ch % 256);
                    }
                }
                int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0);
                glyphAdjust -= tls;
            } else {
                if (CharUtilities.isFixedWidthSpace(orgChar)) {
                    //Fixed width space are rendered as spaces so copy/paste works in a reader
                    ch = font.mapChar(CharUtilities.SPACE);
                    glyphAdjust = font.getCharWidth(ch) - font.getCharWidth(orgChar);
                } else {
                    ch = font.mapChar(orgChar);
                }
            }
            if (letterAdjust != null && i < l - 1) {
                glyphAdjust -= letterAdjust[i + 1];
            }

            textutil.writeTJMappedChar(ch);

            float adjust = glyphAdjust / fontSize;

            if (adjust != 0) {
                textutil.adjustGlyphTJ(adjust);
            }

        }
    }

    /** {@inheritDoc} */
    protected void updateColor(Color col, boolean fill) {
        generator.updateColor(col, fill, null);
    }

    /** {@inheritDoc} */
    public void renderImage(Image image, Rectangle2D pos) {
        endTextObject();
        String url = image.getURL();
        putImage(url, pos, image.getForeignAttributes());
    }

    /** {@inheritDoc} */
    protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) {
        endTextObject();
        putImage(url, pos, foreignAttributes);
    }

    /**
     * Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced.
     * @param uri URL of the bitmap
     * @param pos Position of the bitmap
     * @deprecated Use {@link #putImage(String, Rectangle2D, Map)} instead.
     */
    protected void putImage(String uri, Rectangle2D pos) {
        putImage(uri, pos, null);
    }

    /**
     * Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced.
     * @param uri URL of the bitmap
     * @param pos Position of the bitmap
     * @param foreignAttributes foreign attributes associated with the image
     */
    protected void putImage(String uri, Rectangle2D pos, Map foreignAttributes) {
        Rectangle posInt = new Rectangle(
                (int)pos.getX(),
                (int)pos.getY(),
                (int)pos.getWidth(),
                (int)pos.getHeight());

        uri = URISpecification.getURL(uri);
        PDFXObject xobject = pdfDoc.getXObject(uri);
        if (xobject != null) {
            float w = (float) pos.getWidth() / 1000f;
            float h = (float) pos.getHeight() / 1000f;
            placeImage((float)pos.getX() / 1000f,
                       (float)pos.getY() / 1000f, w, h, xobject);
            return;
        }
        Point origin = new Point(currentIPPosition, currentBPPosition);
        int x = origin.x + posInt.x;
        int y = origin.y + posInt.y;

        ImageManager manager = getUserAgent().getFactory().getImageManager();
        ImageInfo info = null;
        try {
            ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
            info = manager.getImageInfo(uri, sessionContext);

            Map hints = ImageUtil.getDefaultHints(sessionContext);
            ImageFlavor[] supportedFlavors = imageHandlerRegistry.getSupportedFlavors();
            org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
                        info, supportedFlavors, hints, sessionContext);

            //First check for a dynamically registered handler
            PDFImageHandler handler
                = (PDFImageHandler)imageHandlerRegistry.getHandler(img.getClass());
            if (handler != null) {
                if (log.isDebugEnabled()) {
                    log.debug("Using PDFImageHandler: " + handler.getClass().getName());
                }
                try {
                    RendererContext context = createRendererContext(
                            x, y, posInt.width, posInt.height, foreignAttributes);
                    handler.generateImage(context, img, origin, posInt);
                } catch (IOException ioe) {
                    ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                            getUserAgent().getEventBroadcaster());
                    eventProducer.imageWritingError(this, ioe);
                    return;
                }
            } else {
                throw new UnsupportedOperationException(
                        "No PDFImageHandler available for image: "
                            + info + " (" + img.getClass().getName() + ")");
            }
        } catch (ImageException ie) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
        } catch (FileNotFoundException fe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
        } catch (IOException ioe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
        }

        // output new data
        try {
            this.generator.flushPDFDoc();
        } catch (IOException ioe) {
            // ioexception will be caught later
            log.error(ioe.getMessage());
        }
    }

    /**
     * Places a previously registered image at a certain place on the page.
     * @param x X coordinate
     * @param y Y coordinate
     * @param w width for image
     * @param h height for image
     * @param xobj the image XObject
     */
    public void placeImage(float x, float y, float w, float h, PDFXObject xobj) {
        saveGraphicsState();
        generator.add(format(w) + " 0 0 "
                          + format(-h) + " "
                          + format(currentIPPosition / 1000f + x) + " "
                          + format(currentBPPosition / 1000f + h + y)
                          + " cm\n" + xobj.getName() + " Do\n");
        restoreGraphicsState();
    }

    /** {@inheritDoc} */
    protected RendererContext createRendererContext(int x, int y, int width, int height,
            Map foreignAttributes) {
        RendererContext context = super.createRendererContext(
                x, y, width, height, foreignAttributes);
        context.setProperty(PDFRendererContextConstants.PDF_DOCUMENT, pdfDoc);
        context.setProperty(PDFRendererContextConstants.OUTPUT_STREAM, ostream);
        context.setProperty(PDFRendererContextConstants.PDF_PAGE, currentPage);
        context.setProperty(PDFRendererContextConstants.PDF_CONTEXT,
                    currentContext == null ? currentPage : currentContext);
        context.setProperty(PDFRendererContextConstants.PDF_CONTEXT, currentContext);
        context.setProperty(PDFRendererContextConstants.PDF_STREAM, generator.getStream());
        context.setProperty(PDFRendererContextConstants.PDF_FONT_INFO, fontInfo);
        context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, "");
        context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE, new Integer(0));
        return context;
    }

    /**
     * Render leader area.
     * This renders a leader area which is an area with a rule.
     * @param area the leader area to render
     */
    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);

        endTextObject();
        borderPainter.drawLine(new Point(startx, starty), new Point(endx, starty),
                ruleThickness, col, RuleStyle.valueOf(style));
        super.renderLeader(area);
    }

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

    /**
     * Sets the PDF/A mode for the PDF renderer.
     * @param mode the PDF/A mode
     */
    public void setAMode(PDFAMode mode) {
        this.pdfUtil.setAMode(mode);
    }

    /**
     * Sets the PDF/X mode for the PDF renderer.
     * @param mode the PDF/X mode
     */
    public void setXMode(PDFXMode mode) {
        this.pdfUtil.setXMode(mode);
    }

    /**
     * Sets the output color profile for the PDF renderer.
     * @param outputProfileURI the URI to the output color profile
     */
    public void setOutputProfileURI(String outputProfileURI) {
        this.pdfUtil.setOutputProfileURI(outputProfileURI);
    }

    /**
     * Sets the filter map to be used by the PDF renderer.
     * @param filterMap the filter map
     */
    public void setFilterMap(Map filterMap) {
        this.pdfUtil.setFilterMap(filterMap);
    }

    /**
     * Sets the encryption parameters used by the PDF renderer.
     * @param encryptionParams the encryption parameters
     */
    public void setEncryptionParams(PDFEncryptionParams encryptionParams) {
        this.pdfUtil.setEncryptionParams(encryptionParams);
    }
}

