/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed 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.svg; import org.apache.batik.bridge.SVGImageElementBridge; import org.apache.fop.image.JpegImage; import org.apache.fop.image.FopImage; import org.apache.fop.image.analyser.ImageReaderFactory; import java.awt.Shape; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.io.BufferedInputStream; import java.io.InputStream; import org.w3c.dom.Element; import org.apache.commons.logging.impl.SimpleLog; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.gvt.AbstractGraphicsNode; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.util.ParsedURL; /** * Bridge class for the <image> element when jpeg images. * * @author Keiron Liddle */ public class PDFImageElementBridge extends SVGImageElementBridge { /** * Constructs a new bridge for the <image> element. */ public PDFImageElementBridge() { } /** * Create the raster image node. * THis checks if it is a jpeg file and creates a jpeg node * so the jpeg can be inserted directly into the pdf document. * @param ctx the bridge context * @param e the svg element for the image * @param purl the parsed url for the image resource * @return a new graphics node */ protected GraphicsNode createImageGraphicsNode (BridgeContext ctx, Element e, ParsedURL purl) { try { InputStream is = purl.openStream(); if (!is.markSupported()) { is = new BufferedInputStream(is, 1024); } is.mark(3); byte [] data = new byte[3]; is.read(data); is.reset(); if ((data[0] == (byte)0xFF) && (data[1] == (byte)0xD8) && (data[2] == (byte)0xFF)) { FopImage.ImageInfo ii = ImageReaderFactory.make (purl.toString(), is, null); JpegImage jpeg = new JpegImage(ii); SimpleLog logger = new SimpleLog("FOP/SVG"); logger.setLevel(SimpleLog.LOG_LEVEL_INFO); jpeg.load(FopImage.ORIGINAL_DATA); PDFJpegNode node = new PDFJpegNode(jpeg, ctx, e, purl); Rectangle2D imgBounds = getImageBounds(ctx, e); Rectangle2D bounds = node.getPrimitiveBounds(); float [] vb = new float[4]; vb[0] = 0; // x vb[1] = 0; // y vb[2] = (float) bounds.getWidth(); // width vb[3] = (float) bounds.getHeight(); // height // handles the 'preserveAspectRatio', 'overflow' and 'clip' // and sets the appropriate AffineTransform to the image node initializeViewport(ctx, e, node, vb, imgBounds); return node; } } catch (Exception ex) { } return superCreateGraphicsNode(ctx, e, purl); } protected GraphicsNode superCreateGraphicsNode (BridgeContext ctx, Element e, ParsedURL purl) { return super.createImageGraphicsNode(ctx, e, purl); } /** * A PDF jpeg node. * This holds a jpeg image so that it can be drawn into * the PDFGraphics2D. */ public class PDFJpegNode extends AbstractGraphicsNode { private JpegImage jpeg; private BridgeContext ctx; private Element e; private ParsedURL purl; private GraphicsNode origGraphicsNode=null; /** * Create a new pdf jpeg node for drawing jpeg images * into pdf graphics. * @param j the jpeg image */ public PDFJpegNode(JpegImage j, BridgeContext ctx, Element e, ParsedURL purl) { this.jpeg = j; this.ctx = ctx; this.e = e; this.purl = purl; } /** * Get the outline of this image. * @return the outline shape which is the primitive bounds */ public Shape getOutline() { return getPrimitiveBounds(); } /** * Paint this jpeg image. * As this is used for inserting jpeg into pdf * it adds the jpeg image to the PDFGraphics2D. * @param g2d the graphics to draw the image on */ public void primitivePaint(Graphics2D g2d) { if (g2d instanceof PDFGraphics2D) { PDFGraphics2D pdfg = (PDFGraphics2D) g2d; float x = 0; float y = 0; try { float width = jpeg.getWidth(); float height = jpeg.getHeight(); pdfg.addJpegImage(jpeg, x, y, width, height); } catch (Exception e) { e.printStackTrace(); } } else { // Not going directly into PDF so use // original implementation so filters etc work. if (origGraphicsNode == null) { // Haven't constructed baseclass Graphics Node, // so do so now. origGraphicsNode = PDFImageElementBridge.this.superCreateGraphicsNode (ctx, e, purl); } origGraphicsNode.primitivePaint(g2d); } } /** * Get the geometrix bounds of the image. * @return the primitive bounds */ public Rectangle2D getGeometryBounds() { return getPrimitiveBounds(); } /** * Get the primitive bounds of this bridge element. * @return the bounds of the jpeg image */ public Rectangle2D getPrimitiveBounds() { try { return new Rectangle2D.Double(0, 0, jpeg.getWidth(), jpeg.getHeight()); } catch (Exception e) { e.printStackTrace(); } return null; } /** * Returns the bounds of the sensitive area covered by this node, * This includes the stroked area but does not include the effects * of clipping, masking or filtering. * @return the bounds of the sensitive area */ public Rectangle2D getSensitiveBounds() { //No interactive features, just return primitive bounds return getPrimitiveBounds(); } } }