aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/documentation/content/xdocs/trunk/output.xml17
-rw-r--r--src/java/org/apache/fop/area/PageViewport.java5
-rw-r--r--src/java/org/apache/fop/render/ps/PSDictionary.java312
-rw-r--r--src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java37
-rw-r--r--src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java110
-rw-r--r--src/java/org/apache/fop/render/ps/PSRenderer.java275
-rw-r--r--src/java/org/apache/fop/render/ps/PSRendererConfigurator.java5
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java108
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java6
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java24
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java114
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java93
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java56
13 files changed, 1052 insertions, 110 deletions
diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml
index 21743519f..798c61811 100644
--- a/src/documentation/content/xdocs/trunk/output.xml
+++ b/src/documentation/content/xdocs/trunk/output.xml
@@ -212,6 +212,8 @@ out = proc.getOutputStream();]]></source>
<auto-rotate-landscape>false</auto-rotate-landscape>
<language-level>3</language-level>
<optimize-resources>false</optimize-resources>
+ <safe-set-page-device>false</safe-set-page-device>
+ <dsc-compliant>true</dsc-compliant>
</renderer>]]></source>
<p>
The default value for the "auto-rotate-landscape" setting is "false". Setting it
@@ -230,6 +232,20 @@ out = proc.getOutputStream();]]></source>
reduce file size but can potentially increase the memory needed in the interpreter
to process.
</p>
+ <p>
+ The default value for the "safe-set-page-device" setting is "false". Setting it
+ to "true" will cause the renderer to invoke a postscript macro which guards against
+ the possibility of invalid/unsupported postscript key/values being issued to the
+ implementing postscript page device.
+ </p>
+ <p>
+ The default value for the "dsc-compliant" setting is "true". Setting it
+ to "false" will break DSC compliance by minimizing the number of setpagedevice
+ calls in the postscript document output. This feature may be useful when unwanted
+ blank pages are experienced in your postscript output. This problem is caused by
+ the particular postscript implementation issuing unwanted postscript subsystem
+ initgraphics/erasepage calls on each setpagedevice call.
+ </p>
</section>
<section id="ps-limitations">
<title>Limitations</title>
@@ -820,3 +836,4 @@ out = proc.getOutputStream();]]></source>
</body>
</document>
+
diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java
index 184eb9d32..af557ade9 100644
--- a/src/java/org/apache/fop/area/PageViewport.java
+++ b/src/java/org/apache/fop/area/PageViewport.java
@@ -666,4 +666,9 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl
public RegionReference getRegionReference(int id) {
return getPage().getRegionViewport(id).getRegionReference();
}
+
+ /** @return whether this page viewport has any extension attachments */
+ public boolean hasExtensionAttachments() {
+ return this.extensionAttachments != null && !this.extensionAttachments.isEmpty();
+ }
}
diff --git a/src/java/org/apache/fop/render/ps/PSDictionary.java b/src/java/org/apache/fop/render/ps/PSDictionary.java
new file mode 100644
index 000000000..dbf7173a5
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/PSDictionary.java
@@ -0,0 +1,312 @@
+/*
+ * 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.ps;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * This class is used to encapsulate postscript dictionary objects.
+ */
+public class PSDictionary extends java.util.HashMap {
+
+ private static final long serialVersionUID = 815367222496219197L;
+
+ /**
+ * This class is used to parse dictionary strings.
+ */
+ private static class Maker {
+
+ /**
+ * Simple token holding class
+ */
+ private class Token {
+ /**
+ * start index in string
+ */
+ private int startIndex = -1;
+
+ /**
+ * end index in string
+ */
+ private int endIndex = -1;
+
+ /**
+ * token string value
+ */
+ private String value;
+ }
+
+ private static final String[][] BRACES = {
+ {"<<", ">>"},
+ {"[", "]"},
+ {"{", "}"}
+ };
+
+ private static final int OPENING = 0;
+ private static final int CLOSING = 1;
+ private static final int DICTIONARY = 0;
+ private static final int ARRAY = 1;
+ private static final int PROCEDURE = 2;
+
+ /**
+ * Returns a Token containing the start, end index and value of the next token
+ * found in a given string
+ *
+ * @param str
+ * string to search
+ * @param fromIndex
+ * search from index
+ * @return Token containing the start, end index and value of the next token
+ */
+ protected Token nextToken(String str, int fromIndex) {
+ Token t = null;
+ for (int i = fromIndex; i < str.length(); i++) {
+ boolean isWhitespace = Character.isWhitespace(str.charAt(i));
+ // start index found
+ if (t == null && !isWhitespace) {
+ t = new Token();
+ t.startIndex = i;
+ // end index found
+ } else if (t != null && isWhitespace) {
+ t.endIndex = i;
+ break;
+ }
+ }
+ // start index found
+ if (t != null) {
+ // end index not found so take end of string
+ if (t.endIndex == -1) {
+ t.endIndex = str.length();
+ }
+ t.value = str.substring(t.startIndex, t.endIndex);
+ }
+ return t;
+ }
+
+ /**
+ * Returns the closing brace index from a given string searches from a
+ * given index
+ *
+ * @param str
+ * string to search
+ * @param braces
+ * string array of opening and closing brace
+ * @param fromIndex
+ * searches from index
+ * @return matching brace index
+ * @throws org.apache.fop.render.ps.PSDictionaryFormatException
+ * thrown in the event that a parsing error occurred
+ */
+ private int indexOfMatchingBrace(String str, String[] braces,
+ int fromIndex) throws PSDictionaryFormatException {
+ final int len = str.length();
+ if (braces.length != 2) {
+ throw new PSDictionaryFormatException("Wrong number of braces");
+ }
+ for (int openCnt = 0, closeCnt = 0; fromIndex < len; fromIndex++) {
+ if (str.startsWith(braces[OPENING], fromIndex)) {
+ openCnt++;
+ } else if (str.startsWith(braces[CLOSING], fromIndex)) {
+ closeCnt++;
+ if (openCnt > 0 && openCnt == closeCnt) {
+ return fromIndex; // found
+ }
+ }
+ }
+ return -1; // not found
+ }
+
+ /**
+ * Strips braces from complex object string
+ *
+ * @param str
+ * String to parse
+ * @param braces
+ * String array containing opening and closing braces
+ * @return String with braces stripped
+ * @throws
+ * org.apache.fop.render.ps.PSDictionaryFormatException object format exception
+ */
+ private String stripBraces(String str, String[] braces) throws PSDictionaryFormatException {
+ // find first opening brace
+ int firstIndex = str.indexOf(braces[OPENING]);
+ if (firstIndex == -1) {
+ throw new PSDictionaryFormatException(
+ "Failed to find opening parameter '" + braces[OPENING]
+ + "");
+ }
+
+ // find last matching brace
+ int lastIndex = indexOfMatchingBrace(str, braces, firstIndex);
+ if (lastIndex == -1) {
+ throw new PSDictionaryFormatException(
+ "Failed to find matching closing parameter '"
+ + braces[CLOSING] + "'");
+ }
+
+ // strip brace and trim
+ int braceLen = braces[OPENING].length();
+ str = str.substring(firstIndex + braceLen, lastIndex).trim();
+ return str;
+ }
+
+ /**
+ * Parses a dictionary string and provides a dictionary object
+ *
+ * @param str a dictionary string
+ * @return A postscript dictionary object
+ * @throws
+ * PSDictionaryFormatException thrown if a dictionary format exception occurs
+ */
+ public PSDictionary parseDictionary(String str) throws PSDictionaryFormatException {
+ PSDictionary dictionary = new PSDictionary();
+ str = stripBraces(str.trim(), BRACES[DICTIONARY]);
+ // length of dictionary string
+ final int len = str.length();
+
+ Token keyToken;
+ for (int currIndex = 0; (keyToken = nextToken(str, currIndex)) != null
+ && currIndex <= len;) {
+ if (keyToken.value == null) {
+ throw new PSDictionaryFormatException("Failed to parse object key");
+ }
+ Token valueToken = nextToken(str, keyToken.endIndex + 1);
+ String[] braces = null;
+ for (int i = 0; i < BRACES.length; i++) {
+ if (valueToken.value.startsWith(BRACES[i][OPENING])) {
+ braces = BRACES[i];
+ break;
+ }
+ }
+ Object obj = null;
+ if (braces != null) {
+ // find closing brace
+ valueToken.endIndex = indexOfMatchingBrace(str, braces,
+ valueToken.startIndex)
+ + braces[OPENING].length();
+ if (valueToken.endIndex < 0) {
+ throw new PSDictionaryFormatException("Closing value brace '"
+ + braces[CLOSING] + "' not found for key '"
+ + keyToken.value + "'");
+ }
+ valueToken.value = str.substring(valueToken.startIndex, valueToken.endIndex);
+ }
+ if (braces == null || braces == BRACES[PROCEDURE]) {
+ obj = valueToken.value;
+ } else if (BRACES[ARRAY] == braces) {
+ List objList = new java.util.ArrayList();
+ String objString = stripBraces(valueToken.value, braces);
+ StringTokenizer tokenizer = new StringTokenizer(objString, ",");
+ while (tokenizer.hasMoreTokens()) {
+ objList.add(tokenizer.nextToken());
+ }
+ obj = objList;
+ } else if (BRACES[DICTIONARY] == braces) {
+ obj = parseDictionary(valueToken.value);
+ }
+ dictionary.put(keyToken.value, obj);
+ currIndex = valueToken.endIndex + 1;
+ }
+ return dictionary;
+ }
+ }
+
+ /**
+ * Parses a given a dictionary string and returns an object
+ *
+ * @param str dictionary string
+ * @return dictionary object
+ * @throws PSDictionaryFormatException object format exception
+ */
+ public static PSDictionary valueOf(String str) throws PSDictionaryFormatException {
+ return (new Maker()).parseDictionary(str);
+ }
+
+ /**
+ * @param obj object to test equality against
+ * @return whether a given object is equal to this dictionary object
+ * @see java.lang.Object#equals(Object)
+ */
+ public boolean equals(Object obj) {
+ if (!(obj instanceof PSPageDeviceDictionary)) {
+ return false;
+ }
+ PSDictionary dictionaryObj = (PSDictionary) obj;
+ if (dictionaryObj.size() != size()) {
+ return false;
+ }
+ for (Iterator it = keySet().iterator(); it.hasNext();) {
+ String key = (String) it.next();
+ if (!dictionaryObj.containsKey(key)) {
+ return false;
+ }
+ if (!dictionaryObj.get(key).equals(get(key))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return a hash code value for this object.
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ int hashCode = 7;
+ for (Iterator it = values().iterator(); it.hasNext();) {
+ Object value = it.next();
+ hashCode += value.hashCode();
+ }
+ return hashCode;
+ }
+
+ /**
+ * @return a string representation of this dictionary
+ * @see java.lang.String#toString()
+ */
+ public String toString() {
+ if (isEmpty()) {
+ return "";
+ }
+ StringBuffer sb = new StringBuffer("<<\n");
+ for (Iterator it = super.keySet().iterator(); it.hasNext();) {
+ String key = (String) it.next();
+ sb.append(" " + key + " ");
+ Object obj = super.get(key);
+ if (obj instanceof java.util.ArrayList) {
+ List array = (List)obj;
+ String str = "[";
+ for (int i = 0; i < array.size(); i++) {
+ Object element = array.get(i);
+ str += element + " ";
+ }
+ str = str.trim();
+ str += "]";
+ sb.append(str + "\n");
+ } else {
+ sb.append(obj.toString() + "\n");
+ }
+ }
+ sb.append(">>");
+ return sb.toString();
+ }
+}
diff --git a/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java b/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java
new file mode 100644
index 000000000..2153e8116
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ps;
+
+/**
+ * Thrown to indicate that a formatting error has occured when
+ * trying to parse a postscript dictionary object
+ */
+public class PSDictionaryFormatException extends Exception {
+
+ private static final long serialVersionUID = 6492321557297860931L;
+
+ /**
+ * Default constructor
+ * @param string error message
+ */
+ public PSDictionaryFormatException(String string) {
+ super(string);
+ }
+}
diff --git a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java b/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java
new file mode 100644
index 000000000..c327423ef
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java
@@ -0,0 +1,110 @@
+/*
+ * 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.ps;
+
+/**
+ * Postscript page device dictionary object
+ *
+ * This object is used by the postscript renderer to hold postscript page device
+ * values. It can also be used to minimize the number of setpagedevice calls when
+ * DSC compliance is false.
+ */
+public class PSPageDeviceDictionary extends PSDictionary {
+
+ private static final long serialVersionUID = 845943256485806509L;
+
+ /**
+ * Whether or not the contents of the dictionary are flushed on retrieval
+ */
+ private boolean flushOnRetrieval = false;
+
+ /**
+ * Dictionary content that has not been output/written yet
+ */
+ private PSDictionary unRetrievedContentDictionary;
+
+ /**
+ * @param key key with which the specified value is to be associated.
+ * @param value value to be associated with the specified key.
+ * @return the previous value associated with the key or null
+ * @see java.util.Map#put(Object, Object)
+ */
+ public Object put(Object key, Object value) {
+ Object previousValue = super.put(key, value);
+ if (flushOnRetrieval) {
+ if (previousValue == null || !previousValue.equals(value)) {
+ unRetrievedContentDictionary.put(key, value);
+ }
+ }
+ return previousValue;
+ }
+
+ /**
+ * @see java.util.Map#clear()
+ */
+ public void clear() {
+ super.clear();
+ if (unRetrievedContentDictionary != null) {
+ unRetrievedContentDictionary.clear();
+ }
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map contains no key-value mappings.
+ *
+ * @return <tt>true</tt> if this map contains no key-value mappings.
+ */
+ public boolean isEmpty() {
+ if (flushOnRetrieval) {
+ return unRetrievedContentDictionary.isEmpty();
+ }
+ return super.isEmpty();
+ }
+
+ /**
+ * The contents of the dictionary are flushed when written
+ * @param flushOnRetrieval boolean value
+ */
+ public void setFlushOnRetrieval(boolean flushOnRetrieval) {
+ this.flushOnRetrieval = flushOnRetrieval;
+ if (flushOnRetrieval) {
+ unRetrievedContentDictionary = new PSDictionary();
+ }
+ }
+
+ /**
+ * Returns a dictionary string with containing all unwritten content note:
+ * unnecessary writes are important as there is a device specific
+ * initgraphics call by the underlying postscript interpreter on every
+ * setpagedevice call which can result in blank pages etc.
+ *
+ * @return unwritten content dictionary string
+ */
+ public String getContent() {
+ String content;
+ if (flushOnRetrieval) {
+ content = unRetrievedContentDictionary.toString();
+ unRetrievedContentDictionary.clear();
+ } else {
+ content = super.toString();
+ }
+ return content;
+ }
+}
diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java
index bb77dd55a..5d823e86e 100644
--- a/src/java/org/apache/fop/render/ps/PSRenderer.java
+++ b/src/java/org/apache/fop/render/ps/PSRenderer.java
@@ -28,6 +28,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.OutputStream;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -69,6 +70,8 @@ import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.ImageAdapter;
import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.ps.extensions.PSExtensionAttachment;
+import org.apache.fop.render.ps.extensions.PSSetPageDevice;
import org.apache.fop.render.ps.extensions.PSSetupCode;
import org.apache.fop.util.CharUtilities;
@@ -141,7 +144,16 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
private Map fontResources;
/** This is a map of PSResource instances of all forms (key: uri) */
private Map formResources;
-
+
+ /** encapsulation of dictionary used in setpagedevice instruction **/
+ private PSPageDeviceDictionary pageDeviceDictionary;
+
+ /** Whether or not the safe set page device macro will be used or not */
+ private boolean safeSetPageDevice = false;
+
+ /** Whether or not Dublin Core Standard (dsc) compliant output is enforced */
+ private boolean dscCompliant = true;
+
/**
* {@inheritDoc}
*/
@@ -713,6 +725,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
this.gen.setPSLevel(this.languageLevel);
this.currentPageNumber = 0;
+ //Initial default page device dictionary settings
+ this.pageDeviceDictionary = new PSPageDeviceDictionary();
+ pageDeviceDictionary.setFlushOnRetrieval(!this.dscCompliant);
+ pageDeviceDictionary.put("/ImagingBBox", "null");
+
//PostScript Header
writeln(DSCConstants.PS_ADOBE_30);
gen.writeDSCComment(DSCConstants.CREATOR, new String[] {userAgent.getProducer()});
@@ -755,6 +772,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
IOUtils.closeQuietly(gen.getOutputStream());
rewritePostScriptFile();
}
+ this.pageDeviceDictionary.clear();
}
/**
@@ -796,12 +814,34 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
}
if (oDI instanceof OffDocumentExtensionAttachment) {
ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment();
- if (PSSetupCode.CATEGORY.equals(attachment.getCategory())) {
- PSSetupCode setupCode = (PSSetupCode)attachment;
- if (setupCodeList == null) {
- setupCodeList = new java.util.ArrayList();
+ if (attachment != null) {
+ if (PSExtensionAttachment.CATEGORY.equals(attachment.getCategory())) {
+ if (attachment instanceof PSSetupCode) {
+ if (setupCodeList == null) {
+ setupCodeList = new java.util.ArrayList();
+ }
+ if (!setupCodeList.contains(attachment)) {
+ setupCodeList.add(attachment);
+ }
+ } else if (attachment instanceof PSSetPageDevice) {
+ /**
+ * Extract all PSSetPageDevice instances from the
+ * attachment list on the s-p-m and add all dictionary
+ * entries to our internal representation of the the
+ * page device dictionary.
+ */
+ PSSetPageDevice setPageDevice = (PSSetPageDevice)attachment;
+ String content = setPageDevice.getContent();
+ if (content != null) {
+ try {
+ this.pageDeviceDictionary.putAll(PSDictionary.valueOf(content));
+ } catch (PSDictionaryFormatException e) {
+ log.error("Failed to parse dictionary string: "
+ + e.getMessage() + ", content = '" + content + "'");
+ }
+ }
+ }
}
- setupCodeList.add(setupCode);
}
}
super.processOffDocumentItem(oDI);
@@ -872,91 +912,114 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
log.debug("renderPage(): " + page);
this.currentPageNumber++;
+
gen.getResourceTracker().notifyStartNewPage();
gen.getResourceTracker().notifyResourceUsageOnPage(PSProcSets.STD_PROCSET);
gen.writeDSCComment(DSCConstants.PAGE, new Object[]
{page.getPageNumberString(),
new Integer(this.currentPageNumber)});
- final Integer zero = new Integer(0);
- final long pagewidth = Math.round(page.getViewArea().getWidth());
- final long pageheight = Math.round(page.getViewArea().getHeight());
- final double pspagewidth = pagewidth / 1000f;
- final double pspageheight = pageheight / 1000f;
+
+ double pageWidth = Math.round(page.getViewArea().getWidth()) / 1000f;
+ double pageHeight = Math.round(page.getViewArea().getHeight()) / 1000f;
boolean rotate = false;
- if (this.autoRotateLandscape && (pageheight < pagewidth)) {
+ List pageSizes = new java.util.ArrayList();
+ if (this.autoRotateLandscape && (pageHeight < pageWidth)) {
rotate = true;
- gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[]
- {zero,
- zero,
- new Long(Math.round(pspageheight)),
- new Long(Math.round(pspagewidth))});
- gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[]
- {zero,
- zero,
- new Double(pspageheight),
- new Double(pspagewidth)});
+ pageSizes.add(new Long(Math.round(pageHeight)));
+ pageSizes.add(new Long(Math.round(pageWidth)));
+ } else {
+ pageSizes.add(new Long(Math.round(pageWidth)));
+ pageSizes.add(new Long(Math.round(pageHeight)));
+ }
+ pageDeviceDictionary.put("/PageSize", pageSizes);
+
+ if (page.hasExtensionAttachments()) {
+ for (Iterator iter = page.getExtensionAttachments().iterator();
+ iter.hasNext();) {
+ ExtensionAttachment attachment = (ExtensionAttachment) iter.next();
+ if (attachment instanceof PSSetPageDevice) {
+ /**
+ * Extract all PSSetPageDevice instances from the
+ * attachment list on the s-p-m and add all
+ * dictionary entries to our internal representation
+ * of the the page device dictionary.
+ */
+ PSSetPageDevice setPageDevice = (PSSetPageDevice)attachment;
+ String content = setPageDevice.getContent();
+ if (content != null) {
+ try {
+ pageDeviceDictionary.putAll(PSDictionary.valueOf(content));
+ } catch (PSDictionaryFormatException e) {
+ log.error("failed to parse dictionary string: "
+ + e.getMessage() + ", [" + content + "]");
+ }
+ }
+ }
+ }
+ }
+
+ try {
+ if (setupCodeList != null) {
+ writeEnclosedExtensionAttachments(setupCodeList);
+ setupCodeList.clear();
+ }
+ } catch (IOException e) {
+ log.error(e.getMessage());
+ }
+ final Integer zero = new Integer(0);
+ if (rotate) {
+ gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] {
+ zero, zero, new Long(Math.round(pageHeight)),
+ new Long(Math.round(pageWidth)) });
+ gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[] {
+ zero, zero, new Double(pageHeight),
+ new Double(pageWidth) });
gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
} else {
- gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[]
- {zero,
- zero,
- new Long(Math.round(pspagewidth)),
- new Long(Math.round(pspageheight))});
- gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[]
- {zero,
- zero,
- new Double(pspagewidth),
- new Double(pspageheight)});
- if (this.autoRotateLandscape) {
- gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Portrait");
+ gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] {
+ zero, zero, new Long(Math.round(pageWidth)),
+ new Long(Math.round(pageHeight)) });
+ gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[] {
+ zero, zero, new Double(pageWidth),
+ new Double(pageHeight) });
+ if (autoRotateLandscape) {
+ gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION,
+ "Portrait");
}
}
- gen.writeDSCComment(DSCConstants.PAGE_RESOURCES,
+ gen.writeDSCComment(DSCConstants.PAGE_RESOURCES,
new Object[] {DSCConstants.ATEND});
+
gen.commentln("%FOPSimplePageMaster: " + page.getSimplePageMasterName());
+
gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP);
-
- //Handle PSSetupCode instances on simple-page-master
- if (page.getExtensionAttachments() != null
- && page.getExtensionAttachments().size() > 0) {
- List list = new java.util.ArrayList();
- //Extract all PSSetupCode instances from the attachment list on the s-p-m
- Iterator i = page.getExtensionAttachments().iterator();
- while (i.hasNext()) {
- ExtensionAttachment attachment = (ExtensionAttachment)i.next();
- if (PSSetupCode.CATEGORY.equals(attachment.getCategory())) {
- list.add(attachment);
- }
+
+ // Write any unwritten changes to page device dictionary
+ if (!pageDeviceDictionary.isEmpty()) {
+ String content = pageDeviceDictionary.getContent();
+ if (safeSetPageDevice) {
+ content += " SSPD";
+ } else {
+ content += " setpagedevice";
}
- writeSetupCodeList(list, "PageSetupCode");
+ writeEnclosedExtensionAttachment(new PSSetPageDevice(content));
}
-
+
if (rotate) {
- gen.writeln("<<");
- gen.writeln("/PageSize ["
- + Math.round(pspageheight) + " "
- + Math.round(pspagewidth) + "]");
- gen.writeln("/ImagingBBox null");
- gen.writeln(">> setpagedevice");
- gen.writeln(Math.round(pspageheight) + " 0 translate");
+ gen.writeln(Math.round(pageHeight) + " 0 translate");
gen.writeln("90 rotate");
- } else {
- gen.writeln("<<");
- gen.writeln("/PageSize ["
- + Math.round(pspagewidth) + " "
- + Math.round(pspageheight) + "]");
- gen.writeln("/ImagingBBox null");
- gen.writeln(">> setpagedevice");
}
- concatMatrix(1, 0, 0, -1, 0, pageheight / 1000f);
-
- gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
+ concatMatrix(1, 0, 0, -1, 0, pageHeight);
+ gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
+
//Process page
super.renderPage(page);
+ //Show page
writeln("showpage");
gen.writeDSCComment(DSCConstants.PAGE_TRAILER);
+
gen.getResourceTracker().writeResources(true, gen);
}
@@ -1259,7 +1322,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
/**
* {@inheritDoc}
- * int, int, int, int, java.util.Map)
*/
protected RendererContext createRendererContext(int x, int y, int width, int height,
Map foreignAttributes) {
@@ -1275,5 +1337,84 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
return MIME_TYPE;
}
+ /**
+ * Formats and writes a PSExtensionAttachment to the output stream.
+ *
+ * @param attachment an PSExtensionAttachment instance
+ */
+ private void writeEnclosedExtensionAttachment(PSExtensionAttachment attachment)
+ throws IOException {
+ String info = "";
+ if (attachment instanceof PSSetupCode) {
+ PSSetupCode setupCodeAttach = (PSSetupCode)attachment;
+ String name = setupCodeAttach.getName();
+ if (name != null) {
+ info += ": (" + name + ")";
+ }
+ }
+ String type = attachment.getType();
+ gen.commentln("%FOPBegin" + type + info);
+ LineNumberReader reader = new LineNumberReader(
+ new java.io.StringReader(attachment.getContent()));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ line = line.trim();
+ if (line.length() > 0) {
+ gen.writeln(line);
+ }
+ }
+ gen.commentln("%FOPEnd" + type);
+ }
+
+ /**
+ * Formats and writes a Collection of PSExtensionAttachment instances to
+ * the output stream.
+ *
+ * @param attachmentCollection
+ * a Collection of PSExtensionAttachment instances
+ */
+ private void writeEnclosedExtensionAttachments(Collection attachmentCollection)
+ throws IOException {
+ Iterator iter = attachmentCollection.iterator();
+ while (iter.hasNext()) {
+ PSExtensionAttachment attachment = (PSExtensionAttachment)iter
+ .next();
+ if (attachment != null) {
+ writeEnclosedExtensionAttachment(attachment);
+ }
+ iter.remove();
+ }
+ }
+ /**
+ * Sets whether or not the safe set page device macro should be used
+ * (as opposed to directly invoking setpagedevice) when setting the
+ * postscript page device.
+ *
+ * This option is a useful option when you want to guard against the possibility
+ * of invalid/unsupported postscript key/values being placed in the page device.
+ *
+ * @param safeSetPageDevice setting to false and the renderer will make a
+ * standard "setpagedevice" call, setting to true will make a safe set page
+ * device macro call (default is false).
+ */
+ public void setSafeSetPageDevice(boolean safeSetPageDevice) {
+ this.safeSetPageDevice = safeSetPageDevice;
+ }
+
+ /**
+ * Sets whether or not Dublin Core Standard (dsc) compliance is enforced.
+ *
+ * It can cause problems (unwanted postscript subsystem initgraphics/erasepage calls)
+ * on some printers when the pagedevice is set. If this causes problems on a
+ * particular implementation then use this setting with a 'false' value to try and
+ * minimize the number of setpagedevice calls in the postscript document output.
+ *
+ * Set this value to false if you experience unwanted blank pages in your
+ * postscript output.
+ * @param dscCompliant boolean value (default is true)
+ */
+ public void setDSCCompliant(boolean dscCompliant) {
+ this.dscCompliant = dscCompliant;
+ }
}
diff --git a/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java b/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java
index c7b5a025b..6caa92c85 100644
--- a/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java
@@ -49,8 +49,13 @@ public class PSRendererConfigurator extends PrintRendererConfigurator {
super.configure(renderer);
PSRenderer psRenderer = (PSRenderer)renderer;
+
psRenderer.setAutoRotateLandscape(
cfg.getChild("auto-rotate-landscape").getValueAsBoolean(false));
+ psRenderer.setSafeSetPageDevice(
+ cfg.getChild("safe-set-page-device").getValueAsBoolean(false));
+ psRenderer.setDSCCompliant(
+ cfg.getChild("dsc-compliant").getValueAsBoolean(true));
}
}
}
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java
new file mode 100644
index 000000000..0fb623bdc
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java
@@ -0,0 +1,108 @@
+/*
+ * 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.ps.extensions;
+
+import org.apache.fop.fo.extensions.ExtensionAttachment;
+import org.apache.fop.util.XMLizable;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * This is the pass-through value object for the PostScript extension.
+ */
+public abstract class PSExtensionAttachment implements ExtensionAttachment, XMLizable {
+
+ /** extension node content */
+ protected String content;
+
+ /** The category URI for this extension attachment. */
+ public static final String CATEGORY = "apache:fop:extensions:postscript";
+
+ /**
+ * Default constructor.
+ * @param content the content of the setup code object
+ */
+ public PSExtensionAttachment(String content) {
+ this.content = content;
+ }
+
+ /**
+ * No-argument contructor.
+ */
+ public PSExtensionAttachment() {
+ }
+
+ /**
+ * @return the category URI
+ * @see org.apache.fop.fo.extensions.ExtensionAttachment#getCategory()
+ */
+ public String getCategory() {
+ return CATEGORY;
+ }
+
+ /** @return the content */
+ public String getContent() {
+ return content;
+ }
+
+ /**
+ * Sets the content for the setup code object.
+ * @param content The content to set.
+ */
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ /**
+ * Generates SAX events representing the object's state.
+ *
+ * @param handler ContentHandler instance to send the SAX events to
+ * @throws SAXException if there's a problem generating the SAX events
+ * @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler)
+ */
+ public void toSAX(ContentHandler handler) throws SAXException {
+ AttributesImpl atts = new AttributesImpl();
+ String element = getElement();
+ handler.startElement(CATEGORY, element, element, atts);
+ if (content != null && content.length() > 0) {
+ char[] chars = content.toCharArray();
+ handler.characters(chars, 0, chars.length);
+ }
+ handler.endElement(CATEGORY, element, element);
+ }
+
+ /** @return type name */
+ public String getType() {
+ String className = getClass().getName();
+ return className.substring(className.lastIndexOf('.') + 3);
+ }
+
+ /**
+ * @return a string representation of this object
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return getType() + ": content=" + content;
+ }
+
+ /** @return element */
+ protected abstract String getElement();
+}
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java
index a2aed74ff..a90af2a9c 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java
@@ -41,6 +41,7 @@ public class PSExtensionElementMapping extends ElementMapping {
foObjs = new java.util.HashMap();
foObjs.put("ps-setup-code", new PSSetupCodeMaker());
foObjs.put("ps-page-setup-code", new PSPageSetupCodeMaker());
+ foObjs.put("ps-setpagedevice", new PSSetPageDeviceMaker());
}
}
@@ -56,4 +57,9 @@ public class PSExtensionElementMapping extends ElementMapping {
}
}
+ static class PSSetPageDeviceMaker extends ElementMapping.Maker {
+ public FONode make(FONode parent) {
+ return new PSSetPageDeviceElement(parent);
+ }
+ }
}
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java
index 071ec1c25..6cc41f8cc 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-/* $Id$ */
+/* $Id: $ */
package org.apache.fop.render.ps.extensions;
@@ -39,24 +39,24 @@ public class PSExtensionHandler extends DefaultHandler
private StringBuffer content = new StringBuffer();
private Attributes lastAttributes;
- private PSSetupCode returnedObject;
+ private PSExtensionAttachment returnedObject;
private ObjectBuiltListener listener;
/** {@inheritDoc} */
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
boolean handled = false;
- if (PSSetupCode.CATEGORY.equals(uri)) {
+ if (PSExtensionAttachment.CATEGORY.equals(uri)) {
lastAttributes = attributes;
- handled = true;
- if ("ps-setup-code".equals(localName)) {
+ handled = false;
+ if (localName.equals(PSSetupCode.ELEMENT)
+ || localName.equals(PSSetPageDevice.ELEMENT)) {
//handled in endElement
- } else {
- handled = false;
+ handled = true;
}
}
if (!handled) {
- if (PSSetupCode.CATEGORY.equals(uri)) {
+ if (PSExtensionAttachment.CATEGORY.equals(uri)) {
throw new SAXException("Unhandled element " + localName
+ " in namespace: " + uri);
} else {
@@ -68,10 +68,13 @@ public class PSExtensionHandler extends DefaultHandler
/** {@inheritDoc} */
public void endElement(String uri, String localName, String qName) throws SAXException {
- if (PSSetupCode.CATEGORY.equals(uri)) {
- if ("ps-setup-code".equals(localName)) {
+ if (PSExtensionAttachment.CATEGORY.equals(uri)) {
+ if (PSSetupCode.ELEMENT.equals(localName)) {
String name = lastAttributes.getValue("name");
this.returnedObject = new PSSetupCode(name, content.toString());
+ } else if (PSSetPageDevice.ELEMENT.equals(localName)) {
+ String name = lastAttributes.getValue("name");
+ this.returnedObject = new PSSetPageDevice(name, content.toString());
}
}
content.setLength(0); //Reset text buffer (see characters())
@@ -104,5 +107,4 @@ public class PSExtensionHandler extends DefaultHandler
public void setObjectBuiltListener(ObjectBuiltListener listener) {
this.listener = listener;
}
-
}
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java
new file mode 100644
index 000000000..5684ba6a3
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java
@@ -0,0 +1,114 @@
+/*
+ * 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.ps.extensions;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Element for postscript setpagedevice instruction
+ * This is a an extension which provides a pass-through value
+ * dictionary object for the postscript setpagedevice instruction.
+ */
+public class PSSetPageDevice extends PSExtensionAttachment {
+ /** element name */
+ protected static final String ELEMENT = "ps-setpagedevice";
+
+ private static final String ATT_NAME = "name";
+
+ /**
+ * name attribute
+ */
+ protected String name = null;
+
+ /**
+ * default constructor
+ * @param content set page device dictionary
+ */
+ public PSSetPageDevice(String content) {
+ super(content);
+ }
+
+ /**
+ * constructor
+ * @param name name attribute of this setpagedevice content
+ * @param content set page device dictionary
+ */
+ public PSSetPageDevice(String name, String content) {
+ this(content);
+ this.name = name;
+ }
+
+ /**
+ * constructor
+ */
+ public PSSetPageDevice() {
+ }
+
+ /** @return the name */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name of the setup code object.
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return a string representation of this object
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return "PSSetPageDevice(name=" + getName() + ", content='" + getContent() + "')";
+ }
+
+ /**
+ * @return a string representation of this object
+ * @see org.apache.fop.render.ps.extensions.PSExtensionAttachment#getElement()
+ */
+ protected String getElement() {
+ return ELEMENT;
+ }
+
+ /**
+ * Generates SAX events representing the object's state.
+ * @param handler ContentHandler instance to send the SAX events to
+ * @throws SAXException if there's a problem generating the SAX events
+ * @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler)
+ */
+ public void toSAX(ContentHandler handler) throws SAXException {
+ AttributesImpl atts = new AttributesImpl();
+ if (name != null && name.length() > 0) {
+ atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name);
+ }
+ String element = getElement();
+ handler.startElement(CATEGORY, element, element, atts);
+ if (content != null && content.length() > 0) {
+ char[] chars = content.toCharArray();
+ handler.characters(chars, 0, chars.length);
+ }
+ handler.endElement(CATEGORY, element, element);
+ }
+}
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java
new file mode 100644
index 000000000..da51e9531
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java
@@ -0,0 +1,93 @@
+/*
+ * 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.ps.extensions;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.extensions.ExtensionAttachment;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+/**
+ * Extension element for ps:ps-setpagedevice.
+ */
+public class PSSetPageDeviceElement extends AbstractPSExtensionElement {
+
+ /**
+ * Main constructor
+ * @param parent parent FO node
+ */
+ protected PSSetPageDeviceElement(FONode parent) {
+ super(parent);
+ }
+
+ /**
+ * Called after processNode() is called. Subclasses can do additional processing.
+ * @throws FOPException if there's a problem during processing
+ * @see org.apache.fop.fo.FONode#startOfNode()
+ */
+ protected void startOfNode() throws FOPException {
+ super.startOfNode();
+ if ( !((parent.getNameId() == Constants.FO_DECLARATIONS)
+ || (parent.getNameId() == Constants.FO_SIMPLE_PAGE_MASTER)) ) {
+ throw new ValidationException( getName()
+ + " must be a child of fo:declarations or fo:simple-page-master.");
+ }
+ }
+
+ /**
+ * Initialize the node with its name, location information, and attributes
+ * The attributes must be used immediately as the sax attributes
+ * will be altered for the next element.
+ * @param elementName element name (e.g., "fo:block")
+ * @param locator Locator object (ignored by default)
+ * @param attlist Collection of attributes passed to us from the parser.
+ * @param propertyList property list
+ * @throws FOPException if there's a problem during processing
+ * @see org.apache.fop.fo.FONode#processNode
+ */
+ public void processNode(String elementName, Locator locator,
+ Attributes attlist, PropertyList propertyList)
+ throws FOPException {
+ String name = attlist.getValue("name");
+ if (name != null && name.length() > 0) {
+ ((PSSetPageDevice)getExtensionAttachment()).setName(name);
+ }
+ }
+
+ /**
+ * @return local name
+ * @see org.apache.fop.fo.FONode#getLocalName() */
+ public String getLocalName() {
+ return "ps-setpagedevice";
+ }
+
+ /**
+ * @return a new PSSetPageDevice object
+ * @see org.apache.fop.render.ps.extensions.AbstractPSExtensionElement
+ * #instantiateExtensionAttachment()
+ */
+ protected ExtensionAttachment instantiateExtensionAttachment() {
+ return new PSSetPageDevice();
+ }
+}
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java b/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java
index 7ad66427c..eb3ed0e39 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java
@@ -19,10 +19,6 @@
package org.apache.fop.render.ps.extensions;
-import java.io.Serializable;
-
-import org.apache.fop.fo.extensions.ExtensionAttachment;
-import org.apache.fop.util.XMLizable;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@@ -30,19 +26,23 @@ import org.xml.sax.helpers.AttributesImpl;
/**
* This is the pass-through value object for the PostScript extension.
*/
-public class PSSetupCode implements ExtensionAttachment, Serializable, XMLizable {
-
- /** The category URI for this extension attachment. */
- public static final String CATEGORY = "apache:fop:extensions:postscript";
+public class PSSetupCode extends PSExtensionAttachment {
+ /**
+ * element name
+ */
+ protected static final String ELEMENT = "ps-setup-code";
- private String name;
- private String content;
+ private static final String ATT_NAME = "name";
+
+ /**
+ * name attribute
+ */
+ protected String name = null;
/**
* No-argument contructor.
*/
public PSSetupCode() {
- //nop
}
/**
@@ -51,23 +51,10 @@ public class PSSetupCode implements ExtensionAttachment, Serializable, XMLizable
* @param content the content of the setup code object
*/
public PSSetupCode(String name, String content) {
+ super(content);
this.name = name;
- this.content = content;
- }
-
- /** @return the content */
- public String getContent() {
- return content;
}
-
- /**
- * Sets the content for the setup code object.
- * @param content The content to set.
- */
- public void setContent(String content) {
- this.content = content;
- }
-
+
/** @return the name */
public String getName() {
return name;
@@ -88,11 +75,16 @@ public class PSSetupCode implements ExtensionAttachment, Serializable, XMLizable
/** {@inheritDoc} */
public String toString() {
- return "PSSetupCode(name=" + getName() + ")";
+ return "PSSetupCode(name=" + getName() + ", content='" + getContent() + "')";
}
- private static final String ATT_NAME = "name";
- private static final String ELEMENT = "ps-setup-code";
+ /**
+ * @return the element name
+ * @see org.apache.fop.render.ps.extensions.PSExtensionAttachment#getElement()
+ */
+ protected String getElement() {
+ return ELEMENT;
+ }
/** {@inheritDoc} */
public void toSAX(ContentHandler handler) throws SAXException {
@@ -100,12 +92,12 @@ public class PSSetupCode implements ExtensionAttachment, Serializable, XMLizable
if (name != null && name.length() > 0) {
atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name);
}
- handler.startElement(CATEGORY, ELEMENT, ELEMENT, atts);
+ String element = getElement();
+ handler.startElement(CATEGORY, element, element, atts);
if (content != null && content.length() > 0) {
char[] chars = content.toCharArray();
handler.characters(chars, 0, chars.length);
}
- handler.endElement(CATEGORY, ELEMENT, ELEMENT);
+ handler.endElement(CATEGORY, element, element);
}
-
}