0001: /*
0002:
0003: Licensed to the Apache Software Foundation (ASF) under one or more
0004: contributor license agreements. See the NOTICE file distributed with
0005: this work for additional information regarding copyright ownership.
0006: The ASF licenses this file to You under the Apache License, Version 2.0
0007: (the "License"); you may not use this file except in compliance with
0008: the License. You may obtain a copy of the License at
0009:
0010: http://www.apache.org/licenses/LICENSE-2.0
0011:
0012: Unless required by applicable law or agreed to in writing, software
0013: distributed under the License is distributed on an "AS IS" BASIS,
0014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015: See the License for the specific language governing permissions and
0016: limitations under the License.
0017:
0018: */
0019: package org.apache.batik.transcoder;
0020:
0021: import java.awt.Dimension;
0022: import java.awt.geom.AffineTransform;
0023: import java.awt.geom.Dimension2D;
0024: import java.awt.geom.Rectangle2D;
0025: import java.net.URL;
0026: import java.net.MalformedURLException;
0027: import java.util.StringTokenizer;
0028: import java.util.LinkedList;
0029: import java.util.List;
0030:
0031: import org.apache.batik.bridge.BaseScriptingEnvironment;
0032: import org.apache.batik.bridge.BridgeContext;
0033: import org.apache.batik.bridge.BridgeException;
0034: import org.apache.batik.bridge.DefaultScriptSecurity;
0035: import org.apache.batik.bridge.GVTBuilder;
0036: import org.apache.batik.bridge.NoLoadScriptSecurity;
0037: import org.apache.batik.bridge.RelaxedScriptSecurity;
0038: import org.apache.batik.bridge.SVGUtilities;
0039: import org.apache.batik.bridge.ScriptSecurity;
0040: import org.apache.batik.bridge.UserAgent;
0041: import org.apache.batik.bridge.UserAgentAdapter;
0042: import org.apache.batik.bridge.ViewBox;
0043: import org.apache.batik.bridge.svg12.SVG12BridgeContext;
0044: import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
0045: import org.apache.batik.dom.svg.SVGDOMImplementation;
0046: import org.apache.batik.dom.svg.SVGOMDocument;
0047: import org.apache.batik.dom.util.DocumentFactory;
0048: import org.apache.batik.dom.util.DOMUtilities;
0049: import org.apache.batik.gvt.CanvasGraphicsNode;
0050: import org.apache.batik.gvt.CompositeGraphicsNode;
0051: import org.apache.batik.gvt.GraphicsNode;
0052: import org.apache.batik.transcoder.keys.BooleanKey;
0053: import org.apache.batik.transcoder.keys.FloatKey;
0054: import org.apache.batik.transcoder.keys.LengthKey;
0055: import org.apache.batik.transcoder.keys.Rectangle2DKey;
0056: import org.apache.batik.transcoder.keys.StringKey;
0057: import org.apache.batik.util.ParsedURL;
0058: import org.apache.batik.util.SVGConstants;
0059: import org.w3c.dom.DOMImplementation;
0060: import org.w3c.dom.Document;
0061: import org.w3c.dom.svg.SVGSVGElement;
0062:
0063: /**
0064: * This class may be the base class of all transcoders which take an
0065: * SVG document as input and which need to build a DOM tree. The
0066: * <tt>SVGAbstractTranscoder</tt> uses several different hints that
0067: * guide it's behaviour:<br/>
0068: *
0069: * <ul>
0070: * <li><tt>KEY_WIDTH, KEY_HEIGHT</tt> can be used to specify how to scale the
0071: * SVG image</li>
0072: * </ul>
0073: *
0074: * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
0075: * @version $Id: SVGAbstractTranscoder.java 513703 2007-03-02 10:59:11Z deweese $
0076: */
0077: public abstract class SVGAbstractTranscoder extends
0078: XMLAbstractTranscoder {
0079: /**
0080: * Value used as a default for the default font-family hint
0081: */
0082: public static final String DEFAULT_DEFAULT_FONT_FAMILY = "Arial, Helvetica, sans-serif";
0083:
0084: /**
0085: * Current area of interest.
0086: */
0087: protected Rectangle2D curAOI;
0088:
0089: /**
0090: * Transform needed to render the current area of interest
0091: */
0092: protected AffineTransform curTxf;
0093:
0094: /**
0095: * Current GVT Tree, i.e., the GVT tree representing the page
0096: * being printed currently.
0097: */
0098: protected GraphicsNode root;
0099:
0100: /**
0101: * Current bridge context
0102: */
0103: protected BridgeContext ctx;
0104:
0105: /**
0106: * Current gvt builder
0107: */
0108: protected GVTBuilder builder;
0109:
0110: /**
0111: * Image's width and height (init to 400x400).
0112: */
0113: protected float width = 400, height = 400;
0114:
0115: /** The user agent dedicated to an SVG Transcoder. */
0116: protected UserAgent userAgent;
0117:
0118: protected SVGAbstractTranscoder() {
0119: userAgent = createUserAgent();
0120:
0121: hints.put(KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
0122: SVGConstants.SVG_NAMESPACE_URI);
0123: hints.put(KEY_DOCUMENT_ELEMENT, SVGConstants.SVG_SVG_TAG);
0124: hints.put(KEY_DOM_IMPLEMENTATION, SVGDOMImplementation
0125: .getDOMImplementation());
0126: hints.put(KEY_MEDIA, "screen");
0127: hints.put(KEY_DEFAULT_FONT_FAMILY, DEFAULT_DEFAULT_FONT_FAMILY);
0128: hints.put(KEY_EXECUTE_ONLOAD, Boolean.FALSE);
0129: hints.put(KEY_ALLOWED_SCRIPT_TYPES,
0130: DEFAULT_ALLOWED_SCRIPT_TYPES);
0131: }
0132:
0133: protected UserAgent createUserAgent() {
0134: return new SVGAbstractTranscoderUserAgent();
0135: }
0136:
0137: /**
0138: * Creates a <tt>DocumentFactory</tt> that is used to create an SVG DOM
0139: * tree. The specified DOM Implementation is ignored and the Batik
0140: * SVG DOM Implementation is automatically used.
0141: *
0142: * @param domImpl the DOM Implementation (not used)
0143: * @param parserClassname the XML parser classname
0144: */
0145: protected DocumentFactory createDocumentFactory(
0146: DOMImplementation domImpl, String parserClassname) {
0147: return new SAXSVGDocumentFactory(parserClassname);
0148: }
0149:
0150: public void transcode(TranscoderInput input, TranscoderOutput output)
0151: throws TranscoderException {
0152:
0153: super .transcode(input, output);
0154:
0155: if (ctx != null)
0156: ctx.dispose();
0157: }
0158:
0159: /**
0160: * Transcodes the specified Document as an image in the specified output.
0161: *
0162: * @param document the document to transcode
0163: * @param uri the uri of the document or null if any
0164: * @param output the ouput where to transcode
0165: * @exception TranscoderException if an error occured while transcoding
0166: */
0167: protected void transcode(Document document, String uri,
0168: TranscoderOutput output) throws TranscoderException {
0169:
0170: if ((document != null)
0171: && !(document.getImplementation() instanceof SVGDOMImplementation)) {
0172: DOMImplementation impl;
0173: impl = (DOMImplementation) hints
0174: .get(KEY_DOM_IMPLEMENTATION);
0175: // impl = SVGDOMImplementation.getDOMImplementation();
0176: document = DOMUtilities.deepCloneDocument(document, impl);
0177: if (uri != null) {
0178: try {
0179: URL url = new URL(uri);
0180: ((SVGOMDocument) document).setURLObject(url);
0181: } catch (MalformedURLException mue) {
0182: }
0183: }
0184: }
0185:
0186: if (hints.containsKey(KEY_WIDTH))
0187: width = ((Float) hints.get(KEY_WIDTH)).floatValue();
0188: if (hints.containsKey(KEY_HEIGHT))
0189: height = ((Float) hints.get(KEY_HEIGHT)).floatValue();
0190:
0191: SVGOMDocument svgDoc = (SVGOMDocument) document;
0192: SVGSVGElement root = svgDoc.getRootElement();
0193: ctx = createBridgeContext(svgDoc);
0194:
0195: // build the GVT tree
0196: builder = new GVTBuilder();
0197: // flag that indicates if the document is dynamic
0198: boolean isDynamic = hints.containsKey(KEY_EXECUTE_ONLOAD)
0199: && ((Boolean) hints.get(KEY_EXECUTE_ONLOAD))
0200: .booleanValue();
0201:
0202: GraphicsNode gvtRoot;
0203: try {
0204: if (isDynamic)
0205: ctx.setDynamicState(BridgeContext.DYNAMIC);
0206:
0207: gvtRoot = builder.build(ctx, svgDoc);
0208:
0209: // dispatch an 'onload' event if needed
0210: if (ctx.isDynamic()) {
0211: BaseScriptingEnvironment se;
0212: se = new BaseScriptingEnvironment(ctx);
0213: se.loadScripts();
0214: se.dispatchSVGLoadEvent();
0215: if (hints.containsKey(KEY_SNAPSHOT_TIME)) {
0216: float t = ((Float) hints.get(KEY_SNAPSHOT_TIME))
0217: .floatValue();
0218: ctx.getAnimationEngine().setCurrentTime(t);
0219: } else if (ctx.isSVG12()) {
0220: float t = SVGUtilities.convertSnapshotTime(root,
0221: null);
0222: ctx.getAnimationEngine().setCurrentTime(t);
0223: }
0224: }
0225: } catch (BridgeException ex) {
0226: ex.printStackTrace();
0227: throw new TranscoderException(ex);
0228: }
0229:
0230: // get the 'width' and 'height' attributes of the SVG document
0231: float docWidth = (float) ctx.getDocumentSize().getWidth();
0232: float docHeight = (float) ctx.getDocumentSize().getHeight();
0233:
0234: setImageSize(docWidth, docHeight);
0235:
0236: // compute the preserveAspectRatio matrix
0237: AffineTransform Px;
0238:
0239: // take the AOI into account if any
0240: if (hints.containsKey(KEY_AOI)) {
0241: Rectangle2D aoi = (Rectangle2D) hints.get(KEY_AOI);
0242: // transform the AOI into the image's coordinate system
0243: Px = new AffineTransform();
0244: double sx = width / aoi.getWidth();
0245: double sy = height / aoi.getHeight();
0246: double scale = Math.min(sx, sy);
0247: Px.scale(scale, scale);
0248: double tx = -aoi.getX() + (width / scale - aoi.getWidth())
0249: / 2;
0250: double ty = -aoi.getY()
0251: + (height / scale - aoi.getHeight()) / 2;
0252: Px.translate(tx, ty);
0253: // take the AOI transformation matrix into account
0254: // we apply first the preserveAspectRatio matrix
0255: curAOI = aoi;
0256: } else {
0257: String ref = new ParsedURL(uri).getRef();
0258:
0259: String viewBox = root.getAttributeNS(null,
0260: SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
0261:
0262: if ((ref != null) && (ref.length() != 0)) {
0263: Px = ViewBox.getViewTransform(ref, root, width, height,
0264: ctx);
0265: } else if ((viewBox != null) && (viewBox.length() != 0)) {
0266: String aspectRatio = root
0267: .getAttributeNS(
0268: null,
0269: SVGConstants.SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE);
0270: Px = ViewBox.getPreserveAspectRatioTransform(root,
0271: viewBox, aspectRatio, width, height, ctx);
0272: } else {
0273: // no viewBox has been specified, create a scale transform
0274: float xscale, yscale;
0275: xscale = width / docWidth;
0276: yscale = height / docHeight;
0277: float scale = Math.min(xscale, yscale);
0278: Px = AffineTransform.getScaleInstance(scale, scale);
0279: }
0280:
0281: curAOI = new Rectangle2D.Float(0, 0, width, height);
0282: }
0283:
0284: CanvasGraphicsNode cgn = getCanvasGraphicsNode(gvtRoot);
0285: if (cgn != null) {
0286: cgn.setViewingTransform(Px);
0287: curTxf = new AffineTransform();
0288: } else {
0289: curTxf = Px;
0290: }
0291:
0292: this .root = gvtRoot;
0293: }
0294:
0295: protected CanvasGraphicsNode getCanvasGraphicsNode(GraphicsNode gn) {
0296: if (!(gn instanceof CompositeGraphicsNode))
0297: return null;
0298: CompositeGraphicsNode cgn = (CompositeGraphicsNode) gn;
0299: List children = cgn.getChildren();
0300: if (children.size() == 0)
0301: return null;
0302: gn = (GraphicsNode) children.get(0);
0303: if (!(gn instanceof CanvasGraphicsNode))
0304: return null;
0305: return (CanvasGraphicsNode) gn;
0306: }
0307:
0308: /**
0309: * Factory method for constructing an configuring a
0310: * BridgeContext so subclasses can insert new/modified
0311: * bridges in the context.
0312: */
0313: protected BridgeContext createBridgeContext(SVGOMDocument doc) {
0314: if (doc.isSVG12()) {
0315: return new SVG12BridgeContext(userAgent);
0316: }
0317: // For SVG 1.1/1.0 docs call old signature createBridgeContext
0318: // method (this allows FOP to register it's bridges).
0319: return createBridgeContext();
0320: }
0321:
0322: protected BridgeContext createBridgeContext() {
0323: return new BridgeContext(userAgent);
0324: }
0325:
0326: /**
0327: * Sets document size according to the hints.
0328: * Global variables width and height are modified.
0329: *
0330: * @param docWidth Width of the document.
0331: * @param docHeight Height of the document.
0332: */
0333: protected void setImageSize(float docWidth, float docHeight) {
0334:
0335: // Compute the image's width and height according the hints
0336: float imgWidth = -1;
0337: if (hints.containsKey(KEY_WIDTH)) {
0338: imgWidth = ((Float) hints.get(KEY_WIDTH)).floatValue();
0339: }
0340: float imgHeight = -1;
0341: if (hints.containsKey(KEY_HEIGHT)) {
0342: imgHeight = ((Float) hints.get(KEY_HEIGHT)).floatValue();
0343: }
0344:
0345: if (imgWidth > 0 && imgHeight > 0) {
0346: width = imgWidth;
0347: height = imgHeight;
0348: } else if (imgHeight > 0) {
0349: width = (docWidth * imgHeight) / docHeight;
0350: height = imgHeight;
0351: } else if (imgWidth > 0) {
0352: width = imgWidth;
0353: height = (docHeight * imgWidth) / docWidth;
0354: } else {
0355: width = docWidth;
0356: height = docHeight;
0357: }
0358:
0359: // Limit image size according to the maximuxm size hints.
0360: float imgMaxWidth = -1;
0361: if (hints.containsKey(KEY_MAX_WIDTH)) {
0362: imgMaxWidth = ((Float) hints.get(KEY_MAX_WIDTH))
0363: .floatValue();
0364: }
0365: float imgMaxHeight = -1;
0366: if (hints.containsKey(KEY_MAX_HEIGHT)) {
0367: imgMaxHeight = ((Float) hints.get(KEY_MAX_HEIGHT))
0368: .floatValue();
0369: }
0370:
0371: if ((imgMaxHeight > 0) && (height > imgMaxHeight)) {
0372: width = (docWidth * imgMaxHeight) / docHeight;
0373: height = imgMaxHeight;
0374: }
0375: if ((imgMaxWidth > 0) && (width > imgMaxWidth)) {
0376: width = imgMaxWidth;
0377: height = (docHeight * imgMaxWidth) / docWidth;
0378: }
0379: }
0380:
0381: // --------------------------------------------------------------------
0382: // Keys definition
0383: // --------------------------------------------------------------------
0384:
0385: /**
0386: * The image width key.
0387: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0388: * <TR>
0389: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0390: * <TD VALIGN="TOP">KEY_WIDTH</TD></TR>
0391: * <TR>
0392: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0393: * <TD VALIGN="TOP">Float</TD></TR>
0394: * <TR>
0395: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0396: * <TD VALIGN="TOP">The width of the top most svg element</TD></TR>
0397: * <TR>
0398: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0399: * <TD VALIGN="TOP">No</TD></TR>
0400: * <TR>
0401: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0402: * <TD VALIGN="TOP">Specify the width of the image to create.</TD></TR>
0403: * </TABLE> */
0404: public static final TranscodingHints.Key KEY_WIDTH = new LengthKey();
0405:
0406: /**
0407: * The image height key.
0408: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0409: * <TR>
0410: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0411: * <TD VALIGN="TOP">KEY_HEIGHT</TD></TR>
0412: * <TR>
0413: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0414: * <TD VALIGN="TOP">Float</TD></TR>
0415: * <TR>
0416: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0417: * <TD VALIGN="TOP">The height of the top most svg element</TD></TR>
0418: * <TR>
0419: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0420: * <TD VALIGN="TOP">No</TD></TR>
0421: * <TR>
0422: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0423: * <TD VALIGN="TOP">Specify the height of the image to create.</TD></TR>
0424: * </TABLE> */
0425: public static final TranscodingHints.Key KEY_HEIGHT = new LengthKey();
0426:
0427: /**
0428: * The maximum width of the image key.
0429: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0430: * <TR>
0431: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0432: * <TD VALIGN="TOP">KEY_MAX_WIDTH</TD></TR>
0433: * <TR>
0434: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0435: * <TD VALIGN="TOP">Float</TD></TR>
0436: * <TR>
0437: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0438: * <TD VALIGN="TOP">The width of the top most svg element</TD></TR>
0439: * <TR>
0440: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0441: * <TD VALIGN="TOP">No</TD></TR>
0442: * <TR>
0443: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0444: * <TD VALIGN="TOP">Specify the maximum width of the image to create.
0445: * The value will set the maximum width of the image even when
0446: * bigger width is specified in a document or set with KEY_WIDTH.
0447: * </TD></TR>
0448: * </TABLE>
0449: */
0450: public static final TranscodingHints.Key KEY_MAX_WIDTH = new LengthKey();
0451:
0452: /**
0453: * The maximux height of the image key.
0454: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0455: * <TR>
0456: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0457: * <TD VALIGN="TOP">KEY_MAX_HEIGHT</TD></TR>
0458: * <TR>
0459: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0460: * <TD VALIGN="TOP">Float</TD></TR>
0461: * <TR>
0462: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0463: * <TD VALIGN="TOP">The height of the top most svg element</TD></TR>
0464: * <TR>
0465: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0466: * <TD VALIGN="TOP">No</TD></TR>
0467: * <TR>
0468: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0469: * <TD VALIGN="TOP">Specify the maximum height of the image to create.
0470: * The value will set the maximum height of the image even when
0471: * bigger height is specified in a document or set with KEY_HEIGHT.
0472: * </TD></TR>
0473: * </TABLE>
0474: */
0475: public static final TranscodingHints.Key KEY_MAX_HEIGHT = new LengthKey();
0476:
0477: /**
0478: * The area of interest key.
0479: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0480: * <TR>
0481: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0482: * <TD VALIGN="TOP">KEY_AOI</TD></TR>
0483: * <TR>
0484: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0485: * <TD VALIGN="TOP">Rectangle2D</TD></TR>
0486: * <TR>
0487: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0488: * <TD VALIGN="TOP">The document's size</TD></TR>
0489: * <TR>
0490: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0491: * <TD VALIGN="TOP">No</TD></TR>
0492: * <TR>
0493: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0494: * <TD VALIGN="TOP">Specify the area of interest to render. The
0495: * rectangle coordinates must be specified in pixels and in the
0496: * document coordinates system.</TD></TR>
0497: * </TABLE>
0498: */
0499: public static final TranscodingHints.Key KEY_AOI = new Rectangle2DKey();
0500:
0501: /**
0502: * The language key.
0503: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0504: * <TR>
0505: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0506: * <TD VALIGN="TOP">KEY_LANGUAGE</TD></TR>
0507: * <TR>
0508: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0509: * <TD VALIGN="TOP">String</TD></TR>
0510: * <TR>
0511: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0512: * <TD VALIGN="TOP">"en"</TD></TR>
0513: * <TR>
0514: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0515: * <TD VALIGN="TOP">No</TD></TR>
0516: * <TR>
0517: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0518: * <TD VALIGN="TOP">Specify the preferred language of the document.
0519: * </TD></TR>
0520: * </TABLE>
0521: */
0522: public static final TranscodingHints.Key KEY_LANGUAGE = new StringKey();
0523:
0524: /**
0525: * The media key.
0526: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0527: * <TR>
0528: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0529: * <TD VALIGN="TOP">KEY_MEDIA</TD></TR>
0530: * <TR>
0531: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0532: * <TD VALIGN="TOP">String</TD></TR>
0533: * <TR>
0534: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0535: * <TD VALIGN="TOP">"screen"</TD></TR>
0536: * <TR>
0537: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0538: * <TD VALIGN="TOP">No</TD></TR>
0539: * <TR>
0540: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0541: * <TD VALIGN="TOP">Specify the media to use with CSS.
0542: * </TD></TR>
0543: * </TABLE>
0544: */
0545: public static final TranscodingHints.Key KEY_MEDIA = new StringKey();
0546:
0547: /**
0548: * The default font-family key.
0549: *
0550: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0551: * <TR>
0552: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0553: * <TD VALIGN="TOP">KEY_DEFAULT_FONT_FAMILY</TD></TR>
0554: * <TR>
0555: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0556: * <TD VALIGN="TOP">String</TD></TR>
0557: * <TR>
0558: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0559: * <TD VALIGN="TOP">"Arial, Helvetica, sans-serif"</TD></TR>
0560: * <TR>
0561: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0562: * <TD VALIGN="TOP">No</TD></TR>
0563: * <TR>
0564: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0565: * <TD VALIGN="TOP">Controls the default
0566: * value used by the CSS engine for the font-family property
0567: * when that property is unspecified.Specify the media to use with CSS.
0568: * </TD></TR>
0569: * </TABLE>
0570: */
0571: public static final TranscodingHints.Key KEY_DEFAULT_FONT_FAMILY = new StringKey();
0572:
0573: /**
0574: * The alternate stylesheet key.
0575: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0576: * <TR>
0577: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0578: * <TD VALIGN="TOP">KEY_ALTERNATE_STYLESHEET</TD></TR>
0579: * <TR>
0580: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0581: * <TD VALIGN="TOP">String</TD></TR>
0582: * <TR>
0583: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0584: * <TD VALIGN="TOP">null</TD></TR>
0585: * <TR>
0586: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0587: * <TD VALIGN="TOP">No</TD></TR>
0588: * <TR>
0589: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0590: * <TD VALIGN="TOP">Specify the alternate style sheet title.
0591: * </TD></TR>
0592: * </TABLE>
0593: */
0594: public static final TranscodingHints.Key KEY_ALTERNATE_STYLESHEET = new StringKey();
0595:
0596: /**
0597: * The user stylesheet URI key.
0598: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0599: * <TR>
0600: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0601: * <TD VALIGN="TOP">KEY_USER_STYLESHEET_URI</TD></TR>
0602: * <TR>
0603: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0604: * <TD VALIGN="TOP">String</TD></TR>
0605: * <TR>
0606: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0607: * <TD VALIGN="TOP">null</TD></TR>
0608: * <TR>
0609: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0610: * <TD VALIGN="TOP">No</TD></TR>
0611: * <TR>
0612: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0613: * <TD VALIGN="TOP">Specify the user style sheet.</TD></TR>
0614: * </TABLE>
0615: */
0616: public static final TranscodingHints.Key KEY_USER_STYLESHEET_URI = new StringKey();
0617:
0618: /**
0619: * The number of millimeters in each pixel key.
0620: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0621: * <TR>
0622: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0623: * <TD VALIGN="TOP">KEY_PIXEL_UNIT_TO_MILLIMETER</TD></TR>
0624: * <TR>
0625: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0626: * <TD VALIGN="TOP">Float</TD></TR>
0627: * <TR>
0628: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0629: * <TD VALIGN="TOP">0.264583</TD></TR>
0630: * <TR>
0631: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0632: * <TD VALIGN="TOP">No</TD></TR>
0633: * <TR>
0634: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0635: * <TD VALIGN="TOP">Specify the size of a px CSS unit in millimeters.
0636: * </TD></TR>
0637: * </TABLE>
0638: */
0639: public static final TranscodingHints.Key KEY_PIXEL_UNIT_TO_MILLIMETER = new FloatKey();
0640:
0641: /**
0642: * The pixel to millimeter conversion factor key.
0643: * @deprecated As of Batik Version 1.5b3
0644: * @see #KEY_PIXEL_UNIT_TO_MILLIMETER
0645: *
0646: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0647: * <TR>
0648: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0649: * <TD VALIGN="TOP">KEY_PIXEL_TO_MM</TD></TR>
0650: * <TR>
0651: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0652: * <TD VALIGN="TOP">Float</TD></TR>
0653: * <TR>
0654: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0655: * <TD VALIGN="TOP">0.264583</TD></TR>
0656: * <TR>
0657: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0658: * <TD VALIGN="TOP">No</TD></TR>
0659: * <TR>
0660: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0661: * <TD VALIGN="TOP">Specify the size of a px CSS unit in millimeters.
0662: * </TD></TR>
0663: * </TABLE>
0664: */
0665: public static final TranscodingHints.Key KEY_PIXEL_TO_MM = KEY_PIXEL_UNIT_TO_MILLIMETER;
0666:
0667: /**
0668: * The 'onload' execution key.
0669: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0670: * <TR>
0671: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0672: * <TD VALIGN="TOP">KEY_EXECUTE_ONLOAD</TD></TR>
0673: * <TR>
0674: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0675: * <TD VALIGN="TOP">Boolean</TD></TR>
0676: * <TR>
0677: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0678: * <TD VALIGN="TOP">false</TD></TR>
0679: * <TR>
0680: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0681: * <TD VALIGN="TOP">No</TD></TR>
0682: * <TR>
0683: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0684: * <TD VALIGN="TOP">Specify if scripts added on the 'onload' event
0685: * attribute must be invoked.</TD></TR>
0686: * </TABLE>
0687: */
0688: public static final TranscodingHints.Key KEY_EXECUTE_ONLOAD = new BooleanKey();
0689:
0690: /**
0691: * The snapshot time key.
0692: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0693: * <TR>
0694: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0695: * <TD VALIGN="TOP">KEY_SNAPSHOT_TIME</TD></TR>
0696: * <TR>
0697: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0698: * <TD VALIGN="TOP">Float</TD></TR>
0699: * <TR>
0700: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0701: * <TD VALIGN="TOP">0</TD></TR>
0702: * <TR>
0703: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0704: * <TD VALIGN="TOP">No</TD></TR>
0705: * <TR>
0706: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0707: * <TD VALIGN="TOP">Specifies the document time to seek to before
0708: * rasterization. Only applies if {@link #KEY_EXECUTE_ONLOAD} is
0709: * set to <code>true</code>.</TD></TR>
0710: * </TABLE>
0711: */
0712: public static final TranscodingHints.Key KEY_SNAPSHOT_TIME = new FloatKey();
0713:
0714: /**
0715: * The set of supported script languages (i.e., the set of possible
0716: * values for the <script> tag's type attribute).
0717: *
0718: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0719: * <TR>
0720: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0721: * <TD VALIGN="TOP">KEY_ALLOWED_SCRIPT_TYPES</TD></TR>
0722: * <TR>
0723: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0724: * <TD VALIGN="TOP">String (Comma separated values)</TD></TR>
0725: * <TR>
0726: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0727: * <TD VALIGN="TOP">text/ecmascript, application/java-archive</TD></TR>
0728: * <TR>
0729: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0730: * <TD VALIGN="TOP">No</TD></TR>
0731: * <TR>
0732: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0733: * <TD VALIGN="TOP">Specifies the allowed values for the type attribute
0734: * in the <script> element. This is a comma separated list. The
0735: * special value '*' means that all script types are allowed.
0736: * </TD></TR>
0737: * </TABLE>
0738: */
0739: public static final TranscodingHints.Key KEY_ALLOWED_SCRIPT_TYPES = new StringKey();
0740:
0741: /**
0742: * Default value for the KEY_ALLOWED_SCRIPT_TYPES key
0743: */
0744: public static final String DEFAULT_ALLOWED_SCRIPT_TYPES = SVGConstants.SVG_SCRIPT_TYPE_ECMASCRIPT
0745: + ", " + SVGConstants.SVG_SCRIPT_TYPE_JAVA;
0746:
0747: /**
0748: * Controls whether or not scripts can only be loaded from the
0749: * same location as the document which references them.
0750: *
0751: * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
0752: * <TR>
0753: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
0754: * <TD VALIGN="TOP">KEY_CONSTRAIN_SCRIPT_ORIGIN</TD></TR>
0755: * <TR>
0756: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
0757: * <TD VALIGN="TOP">boolean</TD></TR>
0758: * <TR>
0759: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
0760: * <TD VALIGN="TOP">true</TD></TR>
0761: * <TR>
0762: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
0763: * <TD VALIGN="TOP">No</TD></TR>
0764: * <TR>
0765: * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
0766: * <TD VALIGN="TOP">When set to true, script elements referencing
0767: * files from a different origin (server) than the document containing
0768: * the script element will not be loaded. When set to true, script elements
0769: * may reference script files from any origin.
0770: * </TD></TR>
0771: * </TABLE>
0772: */
0773: public static final TranscodingHints.Key KEY_CONSTRAIN_SCRIPT_ORIGIN = new BooleanKey();
0774:
0775: /**
0776: * A user agent implementation for <tt>PrintTranscoder</tt>.
0777: */
0778: protected class SVGAbstractTranscoderUserAgent extends
0779: UserAgentAdapter {
0780: /**
0781: * Vector containing the allowed script types
0782: */
0783: protected List scripts;
0784:
0785: public SVGAbstractTranscoderUserAgent() {
0786: addStdFeatures();
0787: }
0788:
0789: /**
0790: * Return the rendering transform.
0791: */
0792: public AffineTransform getTransform() {
0793: return SVGAbstractTranscoder.this .curTxf;
0794: }
0795:
0796: /**
0797: * Return the rendering transform.
0798: */
0799: public void setTransform(AffineTransform at) {
0800: SVGAbstractTranscoder.this .curTxf = at;
0801: }
0802:
0803: /**
0804: * Returns the default size of this user agent (400x400).
0805: */
0806: public Dimension2D getViewportSize() {
0807: return new Dimension(
0808: (int) SVGAbstractTranscoder.this .width,
0809: (int) SVGAbstractTranscoder.this .height);
0810: }
0811:
0812: /**
0813: * Displays the specified error message using the <tt>ErrorHandler</tt>.
0814: */
0815: public void displayError(String message) {
0816: try {
0817: SVGAbstractTranscoder.this .handler
0818: .error(new TranscoderException(message));
0819: } catch (TranscoderException ex) {
0820: throw new RuntimeException();
0821: }
0822: }
0823:
0824: /**
0825: * Displays the specified error using the <tt>ErrorHandler</tt>.
0826: */
0827: public void displayError(Exception e) {
0828: try {
0829: e.printStackTrace();
0830: SVGAbstractTranscoder.this .handler
0831: .error(new TranscoderException(e));
0832: } catch (TranscoderException ex) {
0833: throw new RuntimeException();
0834: }
0835: }
0836:
0837: /**
0838: * Displays the specified message using the <tt>ErrorHandler</tt>.
0839: */
0840: public void displayMessage(String message) {
0841: try {
0842: SVGAbstractTranscoder.this .handler
0843: .warning(new TranscoderException(message));
0844: } catch (TranscoderException ex) {
0845: throw new RuntimeException();
0846: }
0847: }
0848:
0849: /**
0850: * Returns the pixel to millimeter conversion factor specified in the
0851: * <tt>TranscodingHints</tt> or 0.26458333 if not specified.
0852: */
0853: public float getPixelUnitToMillimeter() {
0854: Object obj = SVGAbstractTranscoder.this .hints
0855: .get(KEY_PIXEL_UNIT_TO_MILLIMETER);
0856: if (obj != null) {
0857: return ((Float) obj).floatValue();
0858: }
0859:
0860: return super .getPixelUnitToMillimeter();
0861: }
0862:
0863: /**
0864: * Returns the user language specified in the
0865: * <tt>TranscodingHints</tt> or "en" (english) if any.
0866: */
0867: public String getLanguages() {
0868: if (SVGAbstractTranscoder.this .hints
0869: .containsKey(KEY_LANGUAGE)) {
0870: return (String) SVGAbstractTranscoder.this .hints
0871: .get(KEY_LANGUAGE);
0872: }
0873:
0874: return super .getLanguages();
0875: }
0876:
0877: /**
0878: * Returns this user agent's CSS media.
0879: */
0880: public String getMedia() {
0881: String s = (String) hints.get(KEY_MEDIA);
0882: if (s != null)
0883: return s;
0884:
0885: return super .getMedia();
0886: }
0887:
0888: /**
0889: * Returns the default font family.
0890: */
0891: public String getDefaultFontFamily() {
0892: String s = (String) hints.get(KEY_DEFAULT_FONT_FAMILY);
0893: if (s != null)
0894: return s;
0895:
0896: return super .getDefaultFontFamily();
0897: }
0898:
0899: /**
0900: * Returns this user agent's alternate style-sheet title.
0901: */
0902: public String getAlternateStyleSheet() {
0903: String s = (String) hints.get(KEY_ALTERNATE_STYLESHEET);
0904: if (s != null)
0905: return s;
0906:
0907: return super .getAlternateStyleSheet();
0908: }
0909:
0910: /**
0911: * Returns the user stylesheet specified in the
0912: * <tt>TranscodingHints</tt> or null if any.
0913: */
0914: public String getUserStyleSheetURI() {
0915: String s = (String) SVGAbstractTranscoder.this .hints
0916: .get(KEY_USER_STYLESHEET_URI);
0917: if (s != null)
0918: return s;
0919:
0920: return super .getUserStyleSheetURI();
0921: }
0922:
0923: /**
0924: * Returns the XML parser to use from the TranscodingHints.
0925: */
0926: public String getXMLParserClassName() {
0927: String s = (String) SVGAbstractTranscoder.this .hints
0928: .get(KEY_XML_PARSER_CLASSNAME);
0929: if (s != null)
0930: return s;
0931:
0932: return super .getXMLParserClassName();
0933: }
0934:
0935: /**
0936: * Returns true if the XML parser must be in validation mode, false
0937: * otherwise.
0938: */
0939: public boolean isXMLParserValidating() {
0940: Boolean b = (Boolean) SVGAbstractTranscoder.this .hints
0941: .get(KEY_XML_PARSER_VALIDATING);
0942: if (b != null)
0943: return b.booleanValue();
0944:
0945: return super .isXMLParserValidating();
0946: }
0947:
0948: /**
0949: * Returns the security settings for the given script
0950: * type, script url and document url
0951: *
0952: * @param scriptType type of script, as found in the
0953: * type attribute of the <script> element.
0954: * @param scriptPURL url for the script, as defined in
0955: * the script's xlink:href attribute. If that
0956: * attribute was empty, then this parameter should
0957: * be null
0958: * @param docPURL url for the document into which the
0959: * script was found.
0960: */
0961: public ScriptSecurity getScriptSecurity(String scriptType,
0962: ParsedURL scriptPURL, ParsedURL docPURL) {
0963: if (scripts == null) {
0964: computeAllowedScripts();
0965: }
0966:
0967: if (!scripts.contains(scriptType)) {
0968: return new NoLoadScriptSecurity(scriptType);
0969: }
0970:
0971: boolean constrainOrigin = true;
0972:
0973: if (SVGAbstractTranscoder.this .hints
0974: .containsKey(KEY_CONSTRAIN_SCRIPT_ORIGIN)) {
0975: constrainOrigin = ((Boolean) SVGAbstractTranscoder.this .hints
0976: .get(KEY_CONSTRAIN_SCRIPT_ORIGIN))
0977: .booleanValue();
0978: }
0979:
0980: if (constrainOrigin) {
0981: return new DefaultScriptSecurity(scriptType,
0982: scriptPURL, docPURL);
0983: } else {
0984: return new RelaxedScriptSecurity(scriptType,
0985: scriptPURL, docPURL);
0986: }
0987: }
0988:
0989: /**
0990: * Helper method. Builds a Vector containing the allowed
0991: * values for the <script> element's type attribute.
0992: */
0993: protected void computeAllowedScripts() {
0994: scripts = new LinkedList();
0995: if (!SVGAbstractTranscoder.this .hints
0996: .containsKey(KEY_ALLOWED_SCRIPT_TYPES)) {
0997: return;
0998: }
0999:
1000: String allowedScripts = (String) SVGAbstractTranscoder.this .hints
1001: .get(KEY_ALLOWED_SCRIPT_TYPES);
1002:
1003: StringTokenizer st = new StringTokenizer(allowedScripts,
1004: ",");
1005: while (st.hasMoreTokens()) {
1006: scripts.add(st.nextToken());
1007: }
1008: }
1009:
1010: }
1011: }
|