Package org.apache.fop.render.ps

Source Code of org.apache.fop.render.ps.ResourceHandler

/*
* 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: ResourceHandler.java 627367 2008-02-13 12:03:30Z maxberger $ */

package org.apache.fop.render.ps;

import java.awt.geom.Dimension2D;
import java.awt.image.RenderedImage;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

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.impl.ImageGraphics2D;
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS;
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.ps.DSCConstants;
import org.apache.xmlgraphics.ps.FormGenerator;
import org.apache.xmlgraphics.ps.ImageEncoder;
import org.apache.xmlgraphics.ps.ImageFormGenerator;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSProcSets;
import org.apache.xmlgraphics.ps.dsc.DSCException;
import org.apache.xmlgraphics.ps.dsc.DSCFilter;
import org.apache.xmlgraphics.ps.dsc.DSCParser;
import org.apache.xmlgraphics.ps.dsc.DSCParserConstants;
import org.apache.xmlgraphics.ps.dsc.DefaultNestedDocumentHandler;
import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
import org.apache.xmlgraphics.ps.dsc.events.DSCComment;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentDocumentNeededResources;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentDocumentSuppliedResources;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentLanguageLevel;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPage;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPages;
import org.apache.xmlgraphics.ps.dsc.events.DSCEvent;
import org.apache.xmlgraphics.ps.dsc.events.DSCHeaderComment;
import org.apache.xmlgraphics.ps.dsc.events.PostScriptComment;
import org.apache.xmlgraphics.ps.dsc.tools.DSCTools;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.FontInfo;

/**
* This class is used when two-pass production is used to generate the PostScript file (setting
* "optimize-resources"). It uses the DSC parser from XML Graphics Commons to go over the
* temporary file generated by the PSRenderer and adds all used fonts and images as resources
* to the PostScript file.
*/
public class ResourceHandler implements DSCParserConstants, PSSupportedFlavors {

    /**
     * Rewrites the temporary PostScript file generated by PSRenderer adding all needed resources
     * (fonts and images).
     * @param userAgent the FO user agent
     * @param in the InputStream for the temporary PostScript file
     * @param out the OutputStream to write the finished file to
     * @param fontInfo the font information
     * @param resTracker the resource tracker to use
     * @param formResources Contains all forms used by this document (maintained by PSRenderer)
     * @param pageCount the number of pages (given here because PSRenderer writes an "(atend)")
     * @param documentBoundingBox the document's bounding box
     *                                  (given here because PSRenderer writes an "(atend)")
     * @throws DSCException If there's an error in the DSC structure of the PS file
     * @throws IOException In case of an I/O error
     */
    public static void process(FOUserAgent userAgent, InputStream in, OutputStream out,
            FontInfo fontInfo, ResourceTracker resTracker, Map formResources,
            int pageCount, Rectangle2D documentBoundingBox)
                    throws DSCException, IOException {
        DSCParser parser = new DSCParser(in);
        PSGenerator gen = new PSGenerator(out);
        parser.setNestedDocumentHandler(new DefaultNestedDocumentHandler(gen));
       
        //Skip DSC header
        DSCHeaderComment header = DSCTools.checkAndSkipDSC30Header(parser);
        header.generate(gen);
       
        parser.setFilter(new DSCFilter() {
            private final Set filtered = new java.util.HashSet();
            {
                //We rewrite those as part of the processing
                filtered.add(DSCConstants.PAGES);
                filtered.add(DSCConstants.BBOX);
                filtered.add(DSCConstants.HIRES_BBOX);
                filtered.add(DSCConstants.DOCUMENT_NEEDED_RESOURCES);
                filtered.add(DSCConstants.DOCUMENT_SUPPLIED_RESOURCES);
            }
            public boolean accept(DSCEvent event) {
                if (event.isDSCComment()) {
                    //Filter %%Pages which we add manually from a parameter
                    return !(filtered.contains(event.asDSCComment().getName()));
                } else {
                    return true;
                }
            }
        });

        //Get PostScript language level (may be missing)
        while (true) {
            DSCEvent event = parser.nextEvent();
            if (event == null) {
                reportInvalidDSC();
            }
            if (DSCTools.headerCommentsEndHere(event)) {
                //Set number of pages
                DSCCommentPages pages = new DSCCommentPages(pageCount);
                pages.generate(gen);
                new DSCCommentBoundingBox(documentBoundingBox).generate(gen);
                new DSCCommentHiResBoundingBox(documentBoundingBox).generate(gen);

                PSFontUtils.determineSuppliedFonts(resTracker, fontInfo, fontInfo.getUsedFonts());
                registerSuppliedForms(resTracker, formResources);
               
                //Supplied Resources
                DSCCommentDocumentSuppliedResources supplied
                    = new DSCCommentDocumentSuppliedResources(
                            resTracker.getDocumentSuppliedResources());
                supplied.generate(gen);
               
                //Needed Resources
                DSCCommentDocumentNeededResources needed
                    = new DSCCommentDocumentNeededResources(
                            resTracker.getDocumentNeededResources());
                needed.generate(gen);

                //Write original comment that ends the header comments
                event.generate(gen);
                break;
            }
            if (event.isDSCComment()) {
                DSCComment comment = event.asDSCComment();
                if (DSCConstants.LANGUAGE_LEVEL.equals(comment.getName())) {
                    DSCCommentLanguageLevel level = (DSCCommentLanguageLevel)comment;
                    gen.setPSLevel(level.getLanguageLevel());
                }
            }
            event.generate(gen);
        }
       
        //Skip to the FOPFontSetup
        PostScriptComment fontSetupPlaceholder = parser.nextPSComment("FOPFontSetup", gen);
        if (fontSetupPlaceholder == null) {
            throw new DSCException("Didn't find %FOPFontSetup comment in stream");
        }
        PSFontUtils.writeFontDict(gen, fontInfo, fontInfo.getUsedFonts());
        generateForms(resTracker, userAgent, formResources, gen);

        //Skip the prolog and to the first page
        DSCComment pageOrTrailer = parser.nextDSCComment(DSCConstants.PAGE, gen);
        if (pageOrTrailer == null) {
            throw new DSCException("Page expected, but none found");
        }
       
        //Process individual pages (and skip as necessary)
        while (true) {
            DSCCommentPage page = (DSCCommentPage)pageOrTrailer;
            page.generate(gen);
            pageOrTrailer = DSCTools.nextPageOrTrailer(parser, gen);
            if (pageOrTrailer == null) {
                reportInvalidDSC();
            } else if (!DSCConstants.PAGE.equals(pageOrTrailer.getName())) {
                pageOrTrailer.generate(gen);
                break;
            }
        }
       
        //Write the rest
        while (parser.hasNext()) {
            DSCEvent event = parser.nextEvent();
            event.generate(gen);
        }
    }

    private static void reportInvalidDSC() throws DSCException {
        throw new DSCException("File is not DSC-compliant: Unexpected end of file");
    }

    private static void registerSuppliedForms(ResourceTracker resTracker, Map formResources)
            throws IOException {
        if (formResources == null) {
            return;
        }
        Iterator iter = formResources.values().iterator();
        while (iter.hasNext()) {
            PSImageFormResource form = (PSImageFormResource)iter.next();
            resTracker.registerSuppliedResource(form);
        }
    }

    private static void generateForms(ResourceTracker resTracker, FOUserAgent userAgent,
            Map formResources, PSGenerator gen) throws IOException {
        if (formResources == null) {
            return;
        }
        Iterator iter = formResources.values().iterator();
        while (iter.hasNext()) {
            PSImageFormResource form = (PSImageFormResource)iter.next();
            final String uri = form.getImageURI();
           
            ImageManager manager = userAgent.getFactory().getImageManager();
            ImageInfo info = null;
            try {
                ImageSessionContext sessionContext = userAgent.getImageSessionContext();
                info = manager.getImageInfo(uri, sessionContext);
               
                ImageFlavor[] flavors;
                if (gen.getPSLevel() >= 3) {
                    flavors = LEVEL_3_FLAVORS_FORM;
                } else {
                    flavors = LEVEL_2_FLAVORS_FORM;
                }
                Map hints = ImageUtil.getDefaultHints(sessionContext);
                org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
                        info, flavors, hints, sessionContext);
               
                String imageDescription = info.getMimeType() + " " + info.getOriginalURI();
                final Dimension2D dimensionsPt = info.getSize().getDimensionPt();
                final Dimension2D dimensionsMpt = info.getSize().getDimensionMpt();

                if (img instanceof ImageGraphics2D) {
                    final ImageGraphics2D imageG2D = (ImageGraphics2D)img;
                    FormGenerator formGen = new FormGenerator(
                            form.getName(), imageDescription, dimensionsPt) {

                        protected void generatePaintProc(PSGenerator gen)
                                throws IOException {
                            gen.getResourceTracker().notifyResourceUsageOnPage(
                                    PSProcSets.EPS_PROCSET);
                            gen.writeln("BeginEPSF");
                            PSGraphics2DAdapter adapter = new PSGraphics2DAdapter(gen, false);
                            adapter.paintImage(imageG2D.getGraphics2DImagePainter(),
                                    null,
                                    0, 0,
                                    (int)Math.round(dimensionsMpt.getWidth()),
                                    (int)Math.round(dimensionsMpt.getHeight()));
                            gen.writeln("EndEPSF");
                        }
                       
                    };
                    formGen.generate(gen);
                } else if (img instanceof ImageRendered) {
                    ImageRendered imgRend = (ImageRendered)img;
                    RenderedImage ri = imgRend.getRenderedImage();
                    FormGenerator formGen = new ImageFormGenerator(
                            form.getName(), imageDescription,
                            info.getSize().getDimensionPt(),
                            ri, false);
                    formGen.generate(gen);
                } else if (img instanceof ImageXMLDOM) {
                    throw new UnsupportedOperationException(
                            "Embedding an ImageXMLDOM as a form isn't supported, yet");
                } else if (img instanceof ImageRawStream) {
                    final ImageRawStream raw = (ImageRawStream)img;
                    if (raw instanceof ImageRawEPS) {
                        final ImageRawEPS eps = (ImageRawEPS)raw;
                        throw new UnsupportedOperationException(
                                "Embedding EPS as forms isn't supported, yet");
                        /*
                        InputStream in = eps.createInputStream();
                        try {
                            FormGenerator formGen = new EPSFormGenerator(form.getName(),
                                    imageDescription, dimensions, in);
                            formGen.generate(gen);
                        } finally {
                            IOUtils.closeQuietly(in);
                        }*/
                    } else if (raw instanceof ImageRawCCITTFax) {
                        ImageRawCCITTFax jpeg = (ImageRawCCITTFax)raw;
                        ImageEncoder encoder = new ImageEncoderCCITTFax(jpeg);
                        FormGenerator formGen = new ImageFormGenerator(
                                form.getName(), imageDescription,
                                info.getSize().getDimensionPt(),
                                info.getSize().getDimensionPx(),
                                encoder,
                                jpeg.getColorSpace(), 1, false);
                        formGen.generate(gen);
                    } else if (raw instanceof ImageRawJPEG) {
                        ImageRawJPEG jpeg = (ImageRawJPEG)raw;
                        ImageEncoder encoder = new ImageEncoderJPEG(jpeg);
                        FormGenerator formGen = new ImageFormGenerator(
                                form.getName(), imageDescription,
                                info.getSize().getDimensionPt(),
                                info.getSize().getDimensionPx(),
                                encoder,
                                jpeg.getColorSpace(), jpeg.isInverted());
                        formGen.generate(gen);
                    } else {
                        throw new UnsupportedOperationException("Unsupported raw image: " + info);
                    }
                } else {
                    throw new UnsupportedOperationException("Unsupported image type: " + img);
                }
            } catch (ImageException ie) {
                throw new IOException("Error while generating form for image: " + ie.getMessage());
            }
        }
    }

    private static FormGenerator createMissingForm(String formName, final Dimension2D dimensions) {
        FormGenerator formGen = new FormGenerator(formName, null, dimensions) {

            protected void generatePaintProc(PSGenerator gen) throws IOException {
                gen.writeln("0 setgray");
                gen.writeln("0 setlinewidth");
                String w = gen.formatDouble(dimensions.getWidth());
                String h = gen.formatDouble(dimensions.getHeight());
                gen.writeln(w + " " + h  + " scale");
                gen.writeln("0 0 1 1 rectstroke");
                gen.writeln("newpath");
                gen.writeln("0 0 moveto");
                gen.writeln("1 1 lineto");
                gen.writeln("stroke");
                gen.writeln("newpath");
                gen.writeln("0 1 moveto");
                gen.writeln("1 0 lineto");
                gen.writeln("stroke");
            }
           
        };
        return formGen;
    }
   
}
TOP

Related Classes of org.apache.fop.render.ps.ResourceHandler

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