All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xhtmlrenderer.swt.PrinterRenderer Maven / Gradle / Ivy

Go to download

Flying Saucer is a CSS 2.1 renderer written in Java. This artifact supports SWT output.

There is a newer version: 9.11.0
Show newest version
/*
 * {{{ header & license
 * Copyright (c) 2007 Vianney le Clément
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * }}}
 */
package org.xhtmlrenderer.swt;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.List;
import java.util.logging.Level;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.printing.PrintDialog;
import org.eclipse.swt.printing.Printer;
import org.eclipse.swt.printing.PrinterData;
import org.eclipse.swt.widgets.Shell;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xhtmlrenderer.css.style.CalculatedStyle;
import org.xhtmlrenderer.extend.NamespaceHandler;
import org.xhtmlrenderer.extend.UserAgentCallback;
import org.xhtmlrenderer.extend.UserInterface;
import org.xhtmlrenderer.layout.BoxBuilder;
import org.xhtmlrenderer.layout.Layer;
import org.xhtmlrenderer.layout.LayoutContext;
import org.xhtmlrenderer.layout.SharedContext;
import org.xhtmlrenderer.render.BlockBox;
import org.xhtmlrenderer.render.PageBox;
import org.xhtmlrenderer.render.RenderingContext;
import org.xhtmlrenderer.render.ViewportBox;
import org.xhtmlrenderer.resource.XMLResource;
import org.xhtmlrenderer.util.Configuration;
import org.xhtmlrenderer.util.XRLog;

/**
 * A renderer for a SWT Printer. Instances must be disposed with
 * {@link PrinterRenderer#dispose()}.
 * 
 * @author Vianney le Clément
 */
public class PrinterRenderer implements UserInterface {

    private final Printer _printer;
    private SharedContext _sharedContext;

    public PrinterRenderer(Printer printer) {
        this(printer, new NaiveUserAgent(printer));
    }

    public PrinterRenderer(Printer printer, UserAgentCallback uac) {
        _printer = printer;
        _sharedContext = new SharedContext(uac, new SWTFontResolver(printer),
            new SWTReplacedElementFactory(), new SWTTextRenderer(), printer
                .getDPI().y);
        _sharedContext.setPrint(true);
        _sharedContext.setInteractive(false);
    }

    /**
     * Dispose resources used by this {@link PrinterRenderer}. This does NOT
     * dispose the attached {@link Printer}.
     */
    public void dispose() {
        // dispose used fonts
        _sharedContext.flushFonts();
        // clean ReplacedElementFactory
        ((SWTReplacedElementFactory) _sharedContext.getReplacedElementFactory())
            .clean();
        // dispose images when using NaiveUserAgent
        UserAgentCallback uac = _sharedContext.getUac();
        if (uac instanceof NaiveUserAgent) {
            ((NaiveUserAgent) uac).disposeCache();
        }
    }

    /**
     * @return a new {@link LayoutContext}
     */
    protected LayoutContext newLayoutcontext(GC gc) {
        LayoutContext result = _sharedContext.newLayoutContextInstance();

        result.setFontContext(new SWTFontContext(gc));
        _sharedContext.getTextRenderer().setup(result.getFontContext());

        return result;
    }

    /**
     * @param gc
     * @return a new {@link RenderingContext}
     */
    protected RenderingContext newRenderingContext(GC gc) {
        RenderingContext result = _sharedContext.newRenderingContextInstance();

        result.setFontContext(new SWTFontContext(gc));
        result.setOutputDevice(new SWTOutputDevice(gc));

        _sharedContext.getTextRenderer().setup(result.getFontContext());

        return result;
    }

    public void print(Document doc, String url, NamespaceHandler nsh,
            String jobName, int startPage, int endPage) {
        // have to do this first ?
        if (Configuration.isTrue("xr.cache.stylesheets", true)) {
            _sharedContext.getCss().flushStyleSheets();
        } else {
            _sharedContext.getCss().flushAllStyleSheets();
        }

        _sharedContext.reset();

        _sharedContext.setBaseURL(url);
        _sharedContext.setNamespaceHandler(nsh);
        _sharedContext.getCss().setDocumentContext(_sharedContext,
            _sharedContext.getNamespaceHandler(), doc, this);

        if (!_printer.startJob(jobName)) {
            return;
        }
        GC gc = new GC(_printer);
        RenderingContext c = null;
        try {
            // LAYOUT
            LayoutContext layout = newLayoutcontext(gc);
            BlockBox rootBox;

            try {
                long start = System.currentTimeMillis();

                rootBox = BoxBuilder.createRootBox(layout, doc);

                PageBox first = Layer.createPageBox(layout, "first");
                rootBox.setContainingBlock(new ViewportBox(new Rectangle(0, 0,
                    first.getContentWidth(layout), first
                        .getContentHeight(layout))));
                rootBox.layout(layout);

                long end = System.currentTimeMillis();
                XRLog.layout(Level.INFO, "Layout took " + (end - start) + "ms");
            } catch (Throwable e) {
                XRLog.exception(e.getMessage(), e);
                return;
            }

            Layer root = rootBox.getLayer();
            Dimension intrinsic_size = root.getPaintingDimension(layout);
            root.trimEmptyPages(layout, intrinsic_size.height);
            root.assignPagePaintingPositions(layout, Layer.PAGED_MODE_PRINT);

            // RENDER
            c = newRenderingContext(gc);
            List pages = root.getPages();
            c.setPageCount(pages.size());
            if (startPage < 0) {
                startPage = 0;
            } else if (startPage >= pages.size()) {
                startPage = pages.size() - 1;
            }
            if (endPage < 0 || endPage >= pages.size()) {
                endPage = pages.size() - 1;
            }

            Shape working = c.getOutputDevice().getClip();

            for (int i = startPage; i <= endPage; i++) {
                PageBox page = (PageBox) pages.get(i);
                c.setPage(i, page);

                if (!_printer.startPage()) {
                    return;
                }
                
                page.paintBackground(c, 0, Layer.PAGED_MODE_PRINT);
                page.paintMarginAreas(c, 0, Layer.PAGED_MODE_PRINT);
                page.paintBorder(c, 0, Layer.PAGED_MODE_PRINT);

                Rectangle content = page.getPrintClippingBounds(c);
                c.getOutputDevice().clip(content);

                int top = -page.getPaintingTop()
                        + page.getMarginBorderPadding(c, CalculatedStyle.TOP);
                int left = page.getMarginBorderPadding(c, CalculatedStyle.LEFT);

                c.getOutputDevice().translate(left, top);
                root.paint(c);
                c.getOutputDevice().translate(-left, -top);

                c.getOutputDevice().setClip(working);

                _printer.endPage();
            }

        } finally {
            // cleanup
            if (c != null) {
                ((SWTOutputDevice) c.getOutputDevice()).clean();
            }
            gc.dispose();
            _printer.endJob();
        }
    }

    public void print(String url, NamespaceHandler nsh, String jobName,
            int startPage, int endPage) {
        print(loadDocument(url), url, nsh, jobName, startPage, endPage);
    }

    protected Document loadDocument(final String uri) {
        XMLResource xmlResource = _sharedContext.getUac().getXMLResource(uri);
        if (xmlResource == null) {
            return null;
        }
        return xmlResource.getDocument();
    }

    public boolean isActive(Element e) {
        return false;
    }

    public boolean isFocus(Element e) {
        return false;
    }

    public boolean isHover(Element e) {
        return false;
    }

    // static helpers
    public static void print(Printer printer, Document doc, String url,
            NamespaceHandler nsh, String jobName, int startPage, int endPage) {
        PrinterRenderer render = new PrinterRenderer(printer);
        render.print(doc, url, nsh, jobName, startPage, endPage);
        render.dispose();
    }

    public static void print(Printer printer, String url, NamespaceHandler nsh,
            String jobName, int startPage, int endPage) {
        PrinterRenderer render = new PrinterRenderer(printer);
        render.print(url, nsh, jobName, startPage, endPage);
        render.dispose();
    }

    public static void print(PrinterData printerData, Document doc, String url,
            NamespaceHandler nsh, String jobName) {
        Printer printer = new Printer(printerData);
        int startPage = -1, endPage = -1;
        if (printerData.scope == PrinterData.PAGE_RANGE) {
            startPage = printerData.startPage - 1;
            endPage = printerData.endPage - 1;
        }
        print(printer, doc, url, nsh, jobName, startPage, endPage);
        printer.dispose();
    }

    public static void print(PrinterData printerData, String url,
            NamespaceHandler nsh, String jobName) {
        Printer printer = new Printer(printerData);
        int startPage = -1, endPage = -1;
        if (printerData.scope == PrinterData.PAGE_RANGE) {
            startPage = printerData.startPage - 1;
            endPage = printerData.endPage - 1;
        }
        print(printer, url, nsh, jobName, startPage, endPage);
        printer.dispose();
    }

    public static void printDialog(Shell shell, Document doc, String url,
            NamespaceHandler nsh, String jobName) {
        PrintDialog dlg = new PrintDialog(shell);
        dlg.setText(jobName);
        PrinterData data = dlg.open();
        if (data != null) {
            print(data, doc, url, nsh, jobName);
        }
    }

    public static void printDialog(Shell shell, String url,
            NamespaceHandler nsh, String jobName) {
        PrintDialog dlg = new PrintDialog(shell);
        dlg.setText(jobName);
        PrinterData data = dlg.open();
        if (data != null) {
            print(data, url, nsh, jobName);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy