aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/render/ps
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/render/ps')
-rw-r--r--src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java22
-rw-r--r--src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java71
-rw-r--r--src/java/org/apache/fop/render/ps/ImageEncoderJPEG.java51
-rw-r--r--src/java/org/apache/fop/render/ps/NativeTextHandler.java34
-rw-r--r--src/java/org/apache/fop/render/ps/PSDictionary.java624
-rw-r--r--src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java74
-rw-r--r--src/java/org/apache/fop/render/ps/PSEventProducer.java65
-rw-r--r--src/java/org/apache/fop/render/ps/PSEventProducer.xml4
-rw-r--r--src/java/org/apache/fop/render/ps/PSFontUtils.java139
-rw-r--r--src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java198
-rw-r--r--src/java/org/apache/fop/render/ps/PSImageUtils.java163
-rw-r--r--src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java220
-rw-r--r--src/java/org/apache/fop/render/ps/PSRenderer.java427
-rw-r--r--src/java/org/apache/fop/render/ps/PSRendererConfigurator.java2
-rw-r--r--src/java/org/apache/fop/render/ps/PSRendererMaker.java108
-rw-r--r--src/java/org/apache/fop/render/ps/PSSVGHandler.java68
-rw-r--r--src/java/org/apache/fop/render/ps/PSSupportedFlavors.java67
-rw-r--r--src/java/org/apache/fop/render/ps/ResourceHandler.java170
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java5
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java266
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java13
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java1
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java1
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java218
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java22
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java5
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java228
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java191
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java5
29 files changed, 2009 insertions, 1453 deletions
diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java
index 75ed0de52..aa0fc88b9 100644
--- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java
+++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java
@@ -16,7 +16,7 @@
*/
/* $Id$ */
-
+
package org.apache.fop.render.ps;
@@ -91,28 +91,28 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder {
* @exception TranscoderException if an error occured while transcoding
*/
protected void transcode(Document document, String uri,
- TranscoderOutput output)
+ TranscoderOutput output)
throws TranscoderException {
graphics = createDocumentGraphics2D();
if (!isTextStroked()) {
- FontInfo fontInfo = new FontInfo();
- //TODO Do custom font configuration here somewhere/somehow
- FontSetup.setup(fontInfo, null, null);
+ FontInfo fontInfo = new FontInfo();
+ //TODO Do custom font configuration here somewhere/somehow
+ FontSetup.setup(fontInfo);
graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo));
}
super.transcode(document, uri, output);
getLogger().trace("document size: " + width + " x " + height);
-
+
// prepare the image to be painted
- UnitProcessor.Context uctx = UnitProcessor.createContext(ctx,
+ UnitProcessor.Context uctx = UnitProcessor.createContext(ctx,
document.getDocumentElement());
- float widthInPt = UnitProcessor.userSpaceToSVG(width, SVGLength.SVG_LENGTHTYPE_PT,
+ float widthInPt = UnitProcessor.userSpaceToSVG(width, SVGLength.SVG_LENGTHTYPE_PT,
UnitProcessor.HORIZONTAL_LENGTH, uctx);
int w = (int)(widthInPt + 0.5);
- float heightInPt = UnitProcessor.userSpaceToSVG(height, SVGLength.SVG_LENGTHTYPE_PT,
+ float heightInPt = UnitProcessor.userSpaceToSVG(height, SVGLength.SVG_LENGTHTYPE_PT,
UnitProcessor.HORIZONTAL_LENGTH, uctx);
int h = (int)(heightInPt + 0.5);
getLogger().trace("document size: " + w + "pt x " + h + "pt");
@@ -140,7 +140,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder {
throw new TranscoderException(ex);
}
}
-
+
/** {@inheritDoc} */
protected BridgeContext createBridgeContext() {
@@ -148,7 +148,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder {
if (!isTextStroked()) {
TextHandler handler = graphics.getCustomTextHandler();
if (handler instanceof NativeTextHandler) {
- NativeTextHandler nativeTextHandler = (NativeTextHandler)handler;
+ NativeTextHandler nativeTextHandler = (NativeTextHandler)handler;
PSTextPainter textPainter = new PSTextPainter(nativeTextHandler);
ctx.setTextPainter(textPainter);
ctx.putBridge(new PSTextElementBridge(textPainter));
diff --git a/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java b/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java
new file mode 100644
index 000000000..ab39966d4
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/ImageEncoderCCITTFax.java
@@ -0,0 +1,71 @@
+/*
+ * 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.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.xmlgraphics.image.codec.tiff.TIFFImage;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+import org.apache.xmlgraphics.ps.ImageEncoder;
+
+/**
+ * ImageEncoder implementation for CCITT encoded images.
+ */
+public class ImageEncoderCCITTFax implements ImageEncoder {
+
+ private final ImageRawCCITTFax ccitt;
+
+ /**
+ * Main constructor.
+ * @param ccitt the CCITT encoded image
+ */
+ public ImageEncoderCCITTFax(ImageRawCCITTFax ccitt) {
+ this.ccitt = ccitt;
+ }
+
+ /** {@inheritDoc} */
+ public void writeTo(OutputStream out) throws IOException {
+ ccitt.writeTo(out);
+ }
+
+ /** {@inheritDoc} */
+ public String getImplicitFilter() {
+ PSDictionary dict = new PSDictionary();
+ dict.put("/Columns", new Integer(ccitt.getSize().getWidthPx()));
+ int compression = ccitt.getCompression();
+ switch (compression) {
+ case TIFFImage.COMP_FAX_G3_1D :
+ dict.put("/K", new Integer(0));
+ break;
+ case TIFFImage.COMP_FAX_G3_2D :
+ dict.put("/K", new Integer(1));
+ break;
+ case TIFFImage.COMP_FAX_G4_2D :
+ dict.put("/K", new Integer(-1));
+ break;
+ default:
+ throw new IllegalStateException(
+ "Invalid compression scheme: " + compression);
+ }
+
+ return dict.toString() + " /CCITTFaxDecode";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/ps/ImageEncoderJPEG.java b/src/java/org/apache/fop/render/ps/ImageEncoderJPEG.java
new file mode 100644
index 000000000..ef4b9f16c
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/ImageEncoderJPEG.java
@@ -0,0 +1,51 @@
+/*
+ * 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.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.ps.ImageEncoder;
+
+/**
+ * ImageEncoder implementation for JPEG images.
+ */
+public class ImageEncoderJPEG implements ImageEncoder {
+ private final ImageRawJPEG jpeg;
+
+ /**
+ * Main constructor
+ * @param jpeg the JPEG image
+ */
+ public ImageEncoderJPEG(ImageRawJPEG jpeg) {
+ this.jpeg = jpeg;
+ }
+
+ /** {@inheritDoc} */
+ public void writeTo(OutputStream out) throws IOException {
+ jpeg.writeTo(out);
+ }
+
+ /** {@inheritDoc} */
+ public String getImplicitFilter() {
+ return "<< >> /DCTDecode";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java
index 5b840484d..9f62097e9 100644
--- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java
+++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java
@@ -38,16 +38,16 @@ import org.apache.xmlgraphics.ps.PSGenerator;
public class NativeTextHandler implements PSTextHandler {
private PSGraphics2D g2d;
-
+
/** FontInfo containing all available fonts */
protected FontInfo fontInfo;
/** Currently valid Font */
protected Font font;
-
+
/** Overriding FontState */
protected Font overrideFont = null;
-
+
/** the current (internal) font name */
protected String currentFontName;
@@ -67,13 +67,13 @@ public class NativeTextHandler implements PSTextHandler {
setupFontInfo();
}
}
-
+
private void setupFontInfo() {
//Sets up a FontInfo with default fonts
fontInfo = new FontInfo();
- FontSetup.setup(fontInfo, null, null);
+ FontSetup.setup(fontInfo);
}
-
+
/**
* Return the font information associated with this object
* @return the FontInfo object
@@ -85,7 +85,7 @@ public class NativeTextHandler implements PSTextHandler {
private PSGenerator getPSGenerator() {
return this.g2d.getPSGenerator();
}
-
+
/** {@inheritDoc} */
public void writeSetup() throws IOException {
if (fontInfo != null) {
@@ -99,9 +99,9 @@ public class NativeTextHandler implements PSTextHandler {
}
/**
- * Draw a string to the PostScript document. The text is painted using
+ * Draw a string to the PostScript document. The text is painted using
* text operations.
- * {@inheritDoc}
+ * {@inheritDoc}
*/
public void drawString(String s, float x, float y) throws IOException {
g2d.preparePainting();
@@ -112,7 +112,7 @@ public class NativeTextHandler implements PSTextHandler {
this.font = this.overrideFont;
this.overrideFont = null;
}
-
+
//Color and Font state
g2d.establishColor(g2d.getColor());
establishCurrentFont();
@@ -130,14 +130,14 @@ public class NativeTextHandler implements PSTextHandler {
gen.writeln(gen.formatDouble(x) + " "
+ gen.formatDouble(y) + " moveto ");
gen.writeln("1 -1 scale");
-
+
StringBuffer sb = new StringBuffer("(");
escapeText(s, sb);
sb.append(") t ");
gen.writeln(sb.toString());
-
- gen.restoreGraphicsState();
+
+ gen.restoreGraphicsState();
}
private void escapeText(final String text, StringBuffer target) {
@@ -157,7 +157,7 @@ public class NativeTextHandler implements PSTextHandler {
int fontSize = 1000 * f.getSize();
String style = f.isItalic() ? "italic" : "normal";
int weight = f.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL;
-
+
FontTriplet triplet = fontInfo.findAdjustWeight(fontFamily, style, weight);
if (triplet == null) {
triplet = fontInfo.findAdjustWeight("sans-serif", style, weight);
@@ -166,10 +166,10 @@ public class NativeTextHandler implements PSTextHandler {
}
private void establishCurrentFont() throws IOException {
- if ((currentFontName != this.font.getFontName())
+ if ((currentFontName != this.font.getFontName())
|| (currentFontSize != this.font.getFontSize())) {
PSGenerator gen = getPSGenerator();
- gen.writeln(this.font.getFontName() + " "
+ gen.writeln(this.font.getFontName() + " "
+ gen.formatDouble(font.getFontSize() / 1000f) + " F");
currentFontName = this.font.getFontName();
currentFontSize = this.font.getFontSize();
@@ -183,6 +183,6 @@ public class NativeTextHandler implements PSTextHandler {
public void setOverrideFont(Font override) {
this.overrideFont = override;
}
-
+
}
diff --git a/src/java/org/apache/fop/render/ps/PSDictionary.java b/src/java/org/apache/fop/render/ps/PSDictionary.java
index dbf7173a5..5a8f1ea14 100644
--- a/src/java/org/apache/fop/render/ps/PSDictionary.java
+++ b/src/java/org/apache/fop/render/ps/PSDictionary.java
@@ -1,312 +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();
- }
-}
+/*
+ * 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
index 2153e8116..1a0171d68 100644
--- a/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java
+++ b/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java
@@ -1,37 +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);
- }
-}
+/*
+ * 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/PSEventProducer.java b/src/java/org/apache/fop/render/ps/PSEventProducer.java
new file mode 100644
index 000000000..451ed1cea
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/PSEventProducer.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.fop.events.EventBroadcaster;
+import org.apache.fop.events.EventProducer;
+import org.apache.fop.events.model.AbstractEventModelFactory;
+import org.apache.fop.events.model.EventModel;
+
+/**
+ * Event producer interface for events generated by the PostScript renderer.
+ */
+public interface PSEventProducer extends EventProducer {
+
+ /** Provider class for the event producer. */
+ class Provider {
+
+ /**
+ * Returns an event producer.
+ * @param broadcaster the event broadcaster to use
+ * @return the event producer
+ */
+ public static PSEventProducer get(EventBroadcaster broadcaster) {
+ return (PSEventProducer)broadcaster.getEventProducerFor(
+ PSEventProducer.class);
+ }
+ }
+
+ /** Event model factory for this event producer. */
+ public static class EventModelFactory extends AbstractEventModelFactory {
+
+ /** {@inheritDoc} */
+ public EventModel createEventModel() {
+ return loadModel(getClass(), "event-model.xml");
+ }
+
+ }
+
+ /**
+ * A PostScript dictionary could not be parsed.
+ * @param source the event source
+ * @param content the PostScript content
+ * @param e the original exception
+ * @event.severity ERROR
+ */
+ void postscriptDictionaryParseError(Object source, String content, Exception e);
+
+}
diff --git a/src/java/org/apache/fop/render/ps/PSEventProducer.xml b/src/java/org/apache/fop/render/ps/PSEventProducer.xml
new file mode 100644
index 000000000..a0078223a
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/PSEventProducer.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<catalogue xml:lang="en">
+ <message key="org.apache.fop.render.ps.PSEventProducer.postscriptDictionaryParseError">Failed to parse dictionary string. Reason: {e}, content = "{content}"</message>
+</catalogue>
diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java
index 8fb29d302..63b12c5c8 100644
--- a/src/java/org/apache/fop/render/ps/PSFontUtils.java
+++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java
@@ -31,16 +31,22 @@ import javax.xml.transform.stream.StreamSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.fonts.Glyphs;
+import org.apache.xmlgraphics.ps.DSCConstants;
+import org.apache.xmlgraphics.ps.PSGenerator;
+import org.apache.xmlgraphics.ps.PSResource;
+import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
+
+import org.apache.fop.fonts.Base14Font;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontType;
import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteEncoding;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
-import org.apache.xmlgraphics.ps.DSCConstants;
-import org.apache.xmlgraphics.ps.PSGenerator;
-import org.apache.xmlgraphics.ps.PSResource;
-import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
/**
* Utility code for font handling in PostScript.
@@ -79,9 +85,21 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
while (iter.hasNext()) {
String key = (String)iter.next();
Typeface tf = getTypeFace(fontInfo, fonts, key);
- PSResource fontRes = new PSResource("font", tf.getFontName());
+ PSResource fontRes = new PSResource(PSResource.TYPE_FONT, tf.getFontName());
fontResources.put(key, fontRes);
embedFont(gen, tf, fontRes);
+
+ if (tf instanceof SingleByteFont) {
+ SingleByteFont sbf = (SingleByteFont)tf;
+ for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) {
+ SingleByteEncoding encoding = sbf.getAdditionalEncoding(i);
+ defineEncoding(gen, encoding);
+ String postFix = "_" + (i + 1);
+ PSResource derivedFontRes = defineDerivedFont(gen, tf.getFontName(),
+ tf.getFontName() + postFix, encoding.getName());
+ fontResources.put(key + postFix, derivedFontRes);
+ }
+ }
}
gen.commentln("%FOPEndFontDict");
reencodeFonts(gen, fonts);
@@ -89,27 +107,35 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
}
private static void reencodeFonts(PSGenerator gen, Map fonts) throws IOException {
+ ResourceTracker tracker = gen.getResourceTracker();
+
+ if (!tracker.isResourceSupplied(WINANSI_ENCODING_RESOURCE)) {
+ defineWinAnsiEncoding(gen);
+ }
gen.commentln("%FOPBeginFontReencode");
- defineWinAnsiEncoding(gen);
//Rewrite font encodings
Iterator iter = fonts.keySet().iterator();
while (iter.hasNext()) {
String key = (String)iter.next();
- Typeface fm = (Typeface)fonts.get(key);
- if (fm instanceof LazyFont && ((LazyFont)fm).getRealFont() == null) {
- continue;
- } else if (null == fm.getEncoding()) {
+ Typeface tf = (Typeface)fonts.get(key);
+ if (tf instanceof LazyFont) {
+ tf = ((LazyFont)tf).getRealFont();
+ if (tf == null) {
+ continue;
+ }
+ }
+ if (null == tf.getEncodingName()) {
//ignore (ZapfDingbats and Symbol used to run through here, kept for safety reasons)
- } else if ("SymbolEncoding".equals(fm.getEncoding())) {
+ } else if ("SymbolEncoding".equals(tf.getEncodingName())) {
//ignore (no encoding redefinition)
- } else if ("ZapfDingbatsEncoding".equals(fm.getEncoding())) {
+ } else if ("ZapfDingbatsEncoding".equals(tf.getEncodingName())) {
//ignore (no encoding redefinition)
- } else if ("WinAnsiEncoding".equals(fm.getEncoding())) {
- redefineFontEncoding(gen, fm.getFontName(), fm.getEncoding());
} else {
- gen.commentln("%WARNING: Only WinAnsiEncoding is supported. Font '"
- + fm.getFontName() + "' asks for: " + fm.getEncoding());
+ if (tf instanceof Base14Font) {
+ //Our Base 14 fonts don't use the default encoding
+ redefineFontEncoding(gen, tf.getFontName(), tf.getEncodingName());
+ }
}
}
gen.commentln("%FOPEndFontReencode");
@@ -165,8 +191,7 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
}
private static boolean isEmbeddable(CustomFont font) {
- return font.isEmbeddable()
- && (font.getEmbedFileName() != null || font.getEmbedResourceName() != null);
+ return font.isEmbeddable();
}
private static InputStream getInputStreamOnFont(PSGenerator gen, CustomFont font)
@@ -229,10 +254,88 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
if (isEmbeddable(cf)) {
resTracker.registerSuppliedResource(fontRes);
}
+ if (tf instanceof SingleByteFont) {
+ SingleByteFont sbf = (SingleByteFont)tf;
+ for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) {
+ SingleByteEncoding encoding = sbf.getAdditionalEncoding(i);
+ PSResource encodingRes = new PSResource(
+ PSResource.TYPE_ENCODING, encoding.getName());
+ resTracker.registerSuppliedResource(encodingRes);
+ PSResource derivedFontRes = new PSResource(
+ PSResource.TYPE_FONT, tf.getFontName() + "_" + (i + 1));
+ resTracker.registerSuppliedResource(derivedFontRes);
+ }
+ }
}
}
}
return fontResources;
}
+ /**
+ * Defines the single-byte encoding for use in PostScript files.
+ * @param gen the PostScript generator
+ * @param encoding the single-byte encoding
+ * @return the PSResource instance that represents the encoding
+ * @throws IOException In case of an I/O problem
+ */
+ public static PSResource defineEncoding(PSGenerator gen, SingleByteEncoding encoding)
+ throws IOException {
+ PSResource res = new PSResource(PSResource.TYPE_ENCODING, encoding.getName());
+ gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res);
+ gen.writeln("/" + encoding.getName() + " [");
+ String[] charNames = encoding.getCharNameMap();
+ for (int i = 0; i < 256; i++) {
+ if (i > 0) {
+ if ((i % 5) == 0) {
+ gen.newLine();
+ } else {
+ gen.write(" ");
+ }
+ }
+ String glyphname = null;
+ if (i < charNames.length) {
+ glyphname = charNames[i];
+ }
+ if (glyphname == null || "".equals(glyphname)) {
+ glyphname = Glyphs.NOTDEF;
+ }
+ gen.write("/");
+ gen.write(glyphname);
+ }
+ gen.newLine();
+ gen.writeln("] def");
+ gen.writeDSCComment(DSCConstants.END_RESOURCE);
+ gen.getResourceTracker().registerSuppliedResource(res);
+ return res;
+ }
+
+ /**
+ * Derives a new font based on an existing font with a given encoding. The encoding must
+ * have been registered before.
+ * @param gen the PostScript generator
+ * @param baseFontName the font name of the font to derive from
+ * @param fontName the font name of the new font to be define
+ * @param encoding the new encoding (must be predefined in the PS file)
+ * @return the PSResource representing the derived font
+ * @throws IOException In case of an I/O problem
+ */
+ public static PSResource defineDerivedFont(PSGenerator gen, String baseFontName, String fontName,
+ String encoding) throws IOException {
+ PSResource res = new PSResource(PSResource.TYPE_FONT, fontName);
+ gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res);
+ gen.commentln("%XGCDependencies: font " + baseFontName);
+ gen.commentln("%XGC+ encoding " + encoding);
+ gen.writeln("/" + baseFontName + " findfont");
+ gen.writeln("dup length dict begin");
+ gen.writeln(" {1 index /FID ne {def} {pop pop} ifelse} forall");
+ gen.writeln(" /Encoding " + encoding + " def");
+ gen.writeln(" currentdict");
+ gen.writeln("end");
+ gen.writeln("/" + fontName + " exch definefont pop");
+ gen.writeDSCComment(DSCConstants.END_RESOURCE);
+ gen.getResourceTracker().registerSuppliedResource(res);
+ return res;
+ }
+
}
diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java
index 286bbca80..a592b4f44 100644
--- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java
+++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java
@@ -1,93 +1,105 @@
-/*
- * 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.awt.Dimension;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
-import java.io.IOException;
-
-import org.apache.fop.render.Graphics2DAdapter;
-import org.apache.fop.render.Graphics2DImagePainter;
-import org.apache.fop.render.RendererContext;
-import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
-import org.apache.xmlgraphics.ps.PSGenerator;
-
-/**
- * Graphics2DAdapter implementation for PostScript.
- */
-public class PSGraphics2DAdapter implements Graphics2DAdapter {
-
- private PSRenderer renderer;
-
- /**
- * Main constructor
- * @param renderer the Renderer instance to which this instance belongs
- */
- public PSGraphics2DAdapter(PSRenderer renderer) {
- this.renderer = renderer;
- }
-
- /** {@inheritDoc} */
- public void paintImage(Graphics2DImagePainter painter,
- RendererContext context,
- int x, int y, int width, int height) throws IOException {
- PSGenerator gen = renderer.gen;
-
- float fwidth = width / 1000f;
- float fheight = height / 1000f;
- float fx = x / 1000f;
- float fy = y / 1000f;
-
- // get the 'width' and 'height' attributes of the SVG document
- Dimension dim = painter.getImageSize();
- float imw = (float)dim.getWidth() / 1000f;
- float imh = (float)dim.getHeight() / 1000f;
-
- float sx = fwidth / (float)imw;
- float sy = fheight / (float)imh;
-
- gen.commentln("%FOPBeginGraphics2D");
- gen.saveGraphicsState();
- // Clip to the image area.
- gen.writeln("newpath");
- gen.defineRect(fx, fy, fwidth, fheight);
- gen.writeln("clip");
-
- // transform so that the coordinates (0,0) is from the top left
- // and positive is down and to the right. (0,0) is where the
- // viewBox puts it.
- gen.concatMatrix(sx, 0, 0, sy, fx, fy);
-
- final boolean textAsShapes = false;
- PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen);
- graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
- AffineTransform transform = new AffineTransform();
- // scale to viewbox
- transform.translate(fx, fy);
- gen.getCurrentState().concatMatrix(transform);
- Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh);
- painter.paint(graphics, area);
-
- gen.restoreGraphicsState();
- gen.commentln("%FOPEndGraphics2D");
- }
-
-}
+/*
+ * 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.awt.Dimension;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
+import org.apache.xmlgraphics.ps.PSGenerator;
+
+import org.apache.fop.render.Graphics2DAdapter;
+import org.apache.fop.render.RendererContext;
+
+/**
+ * Graphics2DAdapter implementation for PostScript.
+ */
+public class PSGraphics2DAdapter implements Graphics2DAdapter {
+
+ private PSGenerator gen;
+ private boolean clip = true;
+
+ /**
+ * Main constructor
+ * @param renderer the Renderer instance to which this instance belongs
+ */
+ public PSGraphics2DAdapter(PSRenderer renderer) {
+ this(renderer.gen, true);
+ }
+
+ /**
+ * Constructor for use without a PSRenderer instance.
+ * @param gen the PostScript generator
+ * @param clip true if the image should be clipped
+ */
+ public PSGraphics2DAdapter(PSGenerator gen, boolean clip) {
+ this.gen = gen;
+ this.clip = clip;
+ }
+
+ /** {@inheritDoc} */
+ public void paintImage(Graphics2DImagePainter painter,
+ RendererContext context,
+ int x, int y, int width, int height) throws IOException {
+ float fwidth = width / 1000f;
+ float fheight = height / 1000f;
+ float fx = x / 1000f;
+ float fy = y / 1000f;
+
+ // get the 'width' and 'height' attributes of the SVG document
+ Dimension dim = painter.getImageSize();
+ float imw = (float)dim.getWidth() / 1000f;
+ float imh = (float)dim.getHeight() / 1000f;
+
+ float sx = fwidth / (float)imw;
+ float sy = fheight / (float)imh;
+
+ gen.commentln("%FOPBeginGraphics2D");
+ gen.saveGraphicsState();
+ if (clip) {
+ // Clip to the image area.
+ gen.writeln("newpath");
+ gen.defineRect(fx, fy, fwidth, fheight);
+ gen.writeln("clip");
+ }
+
+ // transform so that the coordinates (0,0) is from the top left
+ // and positive is down and to the right. (0,0) is where the
+ // viewBox puts it.
+ gen.concatMatrix(sx, 0, 0, sy, fx, fy);
+
+ final boolean textAsShapes = false;
+ PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen);
+ graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
+ AffineTransform transform = new AffineTransform();
+ // scale to viewbox
+ transform.translate(fx, fy);
+ gen.getCurrentState().concatMatrix(transform);
+ Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh);
+ painter.paint(graphics, area);
+
+ gen.restoreGraphicsState();
+ gen.commentln("%FOPEndGraphics2D");
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/ps/PSImageUtils.java b/src/java/org/apache/fop/render/ps/PSImageUtils.java
deleted file mode 100644
index 0ab329077..000000000
--- a/src/java/org/apache/fop/render/ps/PSImageUtils.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.awt.Dimension;
-import java.awt.geom.Rectangle2D;
-import java.io.IOException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.image.EPSImage;
-import org.apache.fop.image.FopImage;
-import org.apache.fop.image.JpegImage;
-import org.apache.xmlgraphics.ps.PSGenerator;
-import org.apache.xmlgraphics.ps.PSResource;
-
-/**
- * Utility code for rendering images in PostScript.
- */
-public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils {
-
- /** logging instance */
- protected static Log log = LogFactory.getLog(PSImageUtils.class);
-
- /**
- * Renders a bitmap image to PostScript.
- * @param img image to render
- * @param x x position
- * @param y y position
- * @param w width
- * @param h height
- * @param gen PS generator
- * @throws IOException In case of an I/O problem while rendering the image
- */
- public static void renderBitmapImage(FopImage img,
- float x, float y, float w, float h, PSGenerator gen)
- throws IOException {
- boolean isJPEG = (img instanceof JpegImage && (gen.getPSLevel() >= 3));
- byte[] imgmap = convertImageToRawBitmapArray(img, isJPEG);
- if (imgmap == null) {
- gen.commentln("%Image data is not available: " + img);
- return; //Image cannot be converted
- }
-
- String imgDescription = img.getMimeType() + " " + img.getOriginalURI();
- Dimension imgDim = new Dimension(img.getWidth(), img.getHeight());
- Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
- writeImage(imgmap, imgDim, imgDescription, targetRect, isJPEG,
- img.getColorSpace(), gen);
- }
-
- /**
- * Renders a bitmap image (as form) to PostScript.
- * @param img image to render
- * @param form the form resource
- * @param x x position
- * @param y y position
- * @param w width
- * @param h height
- * @param gen PS generator
- * @throws IOException In case of an I/O problem while rendering the image
- */
- public static void renderForm(FopImage img, PSResource form,
- float x, float y, float w, float h, PSGenerator gen)
- throws IOException {
- Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
- paintForm(form, targetRect, gen);
- }
-
- /**
- * Generates a form resource for a FopImage in PostScript.
- * @param img image to render
- * @param form the form resource
- * @param gen PS generator
- * @throws IOException In case of an I/O problem while rendering the image
- */
- public static void generateFormResourceForImage(FopImage img, PSResource form,
- PSGenerator gen) throws IOException {
- boolean isJPEG = (img instanceof JpegImage && (gen.getPSLevel() >= 3));
- byte[] imgmap = convertImageToRawBitmapArray(img, isJPEG);
- if (imgmap == null) {
- gen.commentln("%Image data is not available: " + img);
- return; //Image cannot be converted
- }
-
- String imgDescription = img.getMimeType() + " " + img.getOriginalURI();
- Dimension imgDim = new Dimension(img.getWidth(), img.getHeight());
- writeReusableImage(imgmap, imgDim, form.getName(), imgDescription, isJPEG,
- img.getColorSpace(), gen);
- }
-
- private static byte[] convertImageToRawBitmapArray(FopImage img, boolean allowUndecodedJPEG)
- throws IOException {
- if (img instanceof JpegImage && allowUndecodedJPEG) {
- if (!img.load(FopImage.ORIGINAL_DATA)) {
- return null;
- }
- } else {
- if (!img.load(FopImage.BITMAP)) {
- return null;
- }
- }
- byte[] imgmap;
- if (img.getBitmapsSize() > 0) {
- imgmap = img.getBitmaps();
- } else {
- imgmap = img.getRessourceBytes();
- }
- return imgmap;
- }
-
- /**
- * Renders an EPS image to PostScript.
- * @param img EPS image to render
- * @param x x position
- * @param y y position
- * @param w width
- * @param h height
- * @param gen PS generator
- */
- public static void renderEPS(EPSImage img,
- float x, float y, float w, float h,
- PSGenerator gen) {
- try {
- if (!img.load(FopImage.ORIGINAL_DATA)) {
- gen.commentln("%EPS image could not be processed: " + img);
- return;
- }
- int[] bbox = img.getBBox();
- int bboxw = bbox[2] - bbox[0];
- int bboxh = bbox[3] - bbox[1];
- String name = img.getDocName();
- if (name == null || name.length() == 0) {
- name = img.getOriginalURI();
- }
- renderEPS(img.getEPSImage(), name,
- x, y, w, h,
- bbox[0], bbox[1], bboxw, bboxh, gen);
-
- } catch (Exception e) {
- log.error("PSRenderer.renderImageArea(): Error rendering bitmap ("
- + e.getMessage() + ")", e);
- }
- }
-
-}
diff --git a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java b/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java
index c327423ef..88667c24d 100644
--- a/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java
+++ b/src/java/org/apache/fop/render/ps/PSPageDeviceDictionary.java
@@ -1,110 +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;
- }
-}
+/*
+ * 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 3befb0738..a94c8b0aa 100644
--- a/src/java/org/apache/fop/render/ps/PSRenderer.java
+++ b/src/java/org/apache/fop/render/ps/PSRenderer.java
@@ -21,9 +21,11 @@ package org.apache.fop.render.ps;
// Java
import java.awt.Color;
+import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
@@ -38,12 +40,38 @@ import javax.xml.transform.Source;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
+import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
+import org.apache.xmlgraphics.image.loader.pipeline.ImageProviderPipeline;
+import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.apache.xmlgraphics.ps.DSCConstants;
+import org.apache.xmlgraphics.ps.ImageEncoder;
+import org.apache.xmlgraphics.ps.PSGenerator;
+import org.apache.xmlgraphics.ps.PSImageUtils;
+import org.apache.xmlgraphics.ps.PSProcSets;
+import org.apache.xmlgraphics.ps.PSResource;
+import org.apache.xmlgraphics.ps.PSState;
+import org.apache.xmlgraphics.ps.dsc.DSCException;
+import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
+import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
+import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox;
+
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.area.Area;
import org.apache.fop.area.BlockViewport;
import org.apache.fop.area.CTM;
-import org.apache.fop.area.LineArea;
import org.apache.fop.area.OffDocumentExtensionAttachment;
import org.apache.fop.area.OffDocumentItem;
import org.apache.fop.area.PageViewport;
@@ -56,33 +84,25 @@ import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.inline.WordArea;
+import org.apache.fop.datatypes.URISpecification;
+import org.apache.fop.events.ResourceEventProducer;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
-import org.apache.fop.image.EPSImage;
-import org.apache.fop.image.FopImage;
-import org.apache.fop.image.ImageFactory;
-import org.apache.fop.image.XMLImage;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.ImageAdapter;
import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.RendererEventProducer;
import org.apache.fop.render.ps.extensions.PSCommentAfter;
import org.apache.fop.render.ps.extensions.PSCommentBefore;
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;
-import org.apache.xmlgraphics.ps.DSCConstants;
-import org.apache.xmlgraphics.ps.PSGenerator;
-import org.apache.xmlgraphics.ps.PSProcSets;
-import org.apache.xmlgraphics.ps.PSResource;
-import org.apache.xmlgraphics.ps.PSState;
-import org.apache.xmlgraphics.ps.dsc.DSCException;
-import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
-import org.w3c.dom.Document;
/**
* Renderer that renders to PostScript.
@@ -103,7 +123,8 @@ import org.w3c.dom.Document;
* @author <a href="mailto:fop-dev@xmlgraphics.apache.org">Apache FOP Development Team</a>
* @version $Id$
*/
-public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAdapter {
+public class PSRenderer extends AbstractPathOrientedRenderer
+ implements ImageAdapter, PSSupportedFlavors {
/** logging instance */
private static Log log = LogFactory.getLog(PSRenderer.class);
@@ -149,17 +170,22 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
/** 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 */
+ /**
+ * Whether or not PostScript Document Structuring Conventions (DSC) compliant output are
+ * enforced.
+ */
private boolean dscCompliant = true;
+ /** Is used to determine the document's bounding box */
+ private Rectangle2D documentBoundingBox;
+
/** This is a collection holding all document header comments */
private Collection headerComments;
/** This is a collection holding all document footer comments */
private Collection footerComments;
- /**
- * {@inheritDoc}
- */
+
+ /** {@inheritDoc} */
public void setUserAgent(FOUserAgent agent) {
super.setUserAgent(agent);
Object obj;
@@ -274,7 +300,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
*/
protected void handleIOTrouble(IOException ioe) {
if (!ioTrouble) {
- log.error("Error while writing to target file", ioe);
+ RendererEventProducer eventProducer = RendererEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.ioError(this, ioe);
ioTrouble = true;
}
}
@@ -305,15 +333,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
writeln("clip newpath");
}
- /**
- * Clip an area.
- * Write a clipping operation given coordinates in the current
- * transform.
- * @param x the x coordinate
- * @param y the y coordinate
- * @param width the width of the area
- * @param height the height of the area
- */
+ /** {@inheritDoc} */
protected void clipRect(float x, float y, float width, float height) {
try {
gen.defineRect(x, y, width, height);
@@ -369,58 +389,188 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
}
}
+ /**
+ * Indicates whether an image should be inlined or added as a PostScript form.
+ * @param uri the URI of the image
+ * @return true if the image should be inlined rather than added as a form
+ */
+ protected boolean isImageInlined(String uri) {
+ return !isOptimizeResources() || uri == null || "".equals(uri);
+ }
+
+ /**
+ * Indicates whether an image should be inlined or added as a PostScript form.
+ * @param info the ImageInfo object of the image
+ * @return true if the image should be inlined rather than added as a form
+ */
+ protected boolean isImageInlined(ImageInfo info) {
+ if (isImageInlined(info.getOriginalURI())) {
+ return true;
+ }
+
+ if (!isOptimizeResources()) {
+ throw new IllegalStateException("Must not get here if form support is enabled");
+ }
+
+ //Investigate choice for inline mode
+ ImageFlavor[] inlineFlavors = getInlineFlavors();
+ ImageManager manager = getUserAgent().getFactory().getImageManager();
+ ImageProviderPipeline[] inlineCandidates
+ = manager.getPipelineFactory().determineCandidatePipelines(
+ info, inlineFlavors);
+ ImageProviderPipeline inlineChoice = manager.choosePipeline(inlineCandidates);
+ ImageFlavor inlineFlavor = (inlineChoice != null ? inlineChoice.getTargetFlavor() : null);
+
+ //Investigate choice for form mode
+ ImageFlavor[] formFlavors = getFormFlavors();
+ ImageProviderPipeline[] formCandidates
+ = manager.getPipelineFactory().determineCandidatePipelines(
+ info, formFlavors);
+ ImageProviderPipeline formChoice = manager.choosePipeline(formCandidates);
+ ImageFlavor formFlavor = (formChoice != null ? formChoice.getTargetFlavor() : null);
+
+ //Inline if form is not supported or if a better choice is available with inline mode
+ return formFlavor == null || !formFlavor.equals(inlineFlavor);
+ }
+
/** {@inheritDoc} */
protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
endTextObject();
- uri = ImageFactory.getURL(uri);
- ImageFactory fact = userAgent.getFactory().getImageFactory();
- FopImage fopimage = fact.getImage(uri, userAgent);
- if (fopimage == null) {
- return;
- }
- if (!fopimage.load(FopImage.DIMENSIONS)) {
- return;
+ int x = currentIPPosition + (int)Math.round(pos.getX());
+ int y = currentBPPosition + (int)Math.round(pos.getY());
+ uri = URISpecification.getURL(uri);
+ if (log.isDebugEnabled()) {
+ log.debug("Handling image: " + uri);
}
- float x = (float)pos.getX() / 1000f;
- x += currentIPPosition / 1000f;
- float y = (float)pos.getY() / 1000f;
- y += currentBPPosition / 1000f;
- float w = (float)pos.getWidth() / 1000f;
- float h = (float)pos.getHeight() / 1000f;
+
+ ImageManager manager = getUserAgent().getFactory().getImageManager();
+ ImageInfo info = null;
try {
- String mime = fopimage.getMimeType();
- if ("text/xml".equals(mime)) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
+ ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
+ info = manager.getImageInfo(uri, sessionContext);
+ int width = (int)pos.getWidth();
+ int height = (int)pos.getHeight();
+
+ //millipoints --> points for PostScript
+ float ptx = x / 1000f;
+ float pty = y / 1000f;
+ float ptw = width / 1000f;
+ float pth = height / 1000f;
+
+ if (isImageInlined(info)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Image " + info + " is inlined");
}
- Document doc = ((XMLImage) fopimage).getDocument();
- String ns = ((XMLImage) fopimage).getNameSpace();
-
- renderDocument(doc, ns, pos, foreignAttributes);
- } else if ("image/svg+xml".equals(mime)) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
+ //Only now fully load/prepare the image
+ Map hints = ImageUtil.getDefaultHints(sessionContext);
+ org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
+ info, getInlineFlavors(), hints, sessionContext);
+
+ //...and embed as inline image
+ if (img instanceof ImageGraphics2D) {
+ ImageGraphics2D imageG2D = (ImageGraphics2D)img;
+ RendererContext context = createRendererContext(
+ x, y, width, height, foreignAttributes);
+ getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(),
+ context, x, y, width, height);
+ } else if (img instanceof ImageRendered) {
+ ImageRendered imgRend = (ImageRendered)img;
+ RenderedImage ri = imgRend.getRenderedImage();
+ PSImageUtils.renderBitmapImage(ri, ptx, pty, ptw, pth, gen);
+ } else if (img instanceof ImageXMLDOM) {
+ ImageXMLDOM imgXML = (ImageXMLDOM)img;
+ renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(),
+ pos, foreignAttributes);
+ } else if (img instanceof ImageRawStream) {
+ final ImageRawStream raw = (ImageRawStream)img;
+ if (raw instanceof ImageRawEPS) {
+ ImageRawEPS eps = (ImageRawEPS)raw;
+ Rectangle2D bbox = eps.getBoundingBox();
+ InputStream in = raw.createInputStream();
+ try {
+ PSImageUtils.renderEPS(in, uri,
+ new Rectangle2D.Float(ptx, pty, ptw, pth),
+ bbox,
+ gen);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ } else if (raw instanceof ImageRawCCITTFax) {
+ final ImageRawCCITTFax ccitt = (ImageRawCCITTFax)raw;
+ ImageEncoder encoder = new ImageEncoderCCITTFax(ccitt);
+ Rectangle2D targetRect = new Rectangle2D.Float(
+ ptx, pty, ptw, pth);
+ PSImageUtils.writeImage(encoder, info.getSize().getDimensionPx(),
+ uri, targetRect,
+ ccitt.getColorSpace(), 1, false, gen);
+ } else if (raw instanceof ImageRawJPEG) {
+ ImageRawJPEG jpeg = (ImageRawJPEG)raw;
+ ImageEncoder encoder = new ImageEncoderJPEG(jpeg);
+ Rectangle2D targetRect = new Rectangle2D.Float(
+ ptx, pty, ptw, pth);
+ PSImageUtils.writeImage(encoder, info.getSize().getDimensionPx(),
+ uri, targetRect,
+ jpeg.getColorSpace(), 8, jpeg.isInverted(), gen);
+ } else {
+ throw new UnsupportedOperationException("Unsupported raw image: " + info);
+ }
+ } else {
+ throw new UnsupportedOperationException("Unsupported image type: " + img);
}
- Document doc = ((XMLImage) fopimage).getDocument();
- String ns = ((XMLImage) fopimage).getNameSpace();
-
- renderDocument(doc, ns, pos, foreignAttributes);
- } else if (fopimage instanceof EPSImage) {
- PSImageUtils.renderEPS((EPSImage)fopimage, x, y, w, h, gen);
} else {
- if (isImageInlined(uri, fopimage)) {
- PSImageUtils.renderBitmapImage(fopimage, x, y, w, h, gen);
- } else {
- PSResource form = getFormForImage(uri, fopimage);
- PSImageUtils.renderForm(fopimage, form, x, y, w, h, gen);
+ if (log.isDebugEnabled()) {
+ log.debug("Image " + info + " is embedded as a form later");
}
+ //Don't load image at this time, just put a form placeholder in the stream
+ PSResource form = getFormForImage(uri);
+ Rectangle2D targetRect = new Rectangle2D.Double(ptx, pty, ptw, pth);
+ PSImageUtils.paintForm(form, info.getSize().getDimensionPt(), targetRect, gen);
}
+
+ } catch (ImageException ie) {
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
+ } catch (FileNotFoundException fe) {
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
} catch (IOException ioe) {
- handleIOTrouble(ioe);
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
+ }
+ }
+
+ private ImageFlavor[] getInlineFlavors() {
+ ImageFlavor[] flavors;
+ if (gen.getPSLevel() >= 3) {
+ flavors = LEVEL_3_FLAVORS_INLINE;
+ } else {
+ flavors = LEVEL_2_FLAVORS_INLINE;
+ }
+ return flavors;
+ }
+
+ private ImageFlavor[] getFormFlavors() {
+ ImageFlavor[] flavors;
+ if (gen.getPSLevel() >= 3) {
+ flavors = LEVEL_3_FLAVORS_FORM;
+ } else {
+ flavors = LEVEL_2_FLAVORS_FORM;
}
+ return flavors;
}
- protected PSResource getFormForImage(String uri, FopImage fopimage) {
+ /**
+ * Returns a PSResource instance representing a image as a PostScript form.
+ * @param uri the image URI
+ * @return a PSResource instance
+ */
+ protected PSResource getFormForImage(String uri) {
+ if (uri == null || "".equals(uri)) {
+ throw new IllegalArgumentException("uri must not be empty or null");
+ }
if (this.formResources == null) {
this.formResources = new java.util.HashMap();
}
@@ -431,11 +581,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
}
return form;
}
-
- protected boolean isImageInlined(String uri, FopImage image) {
- return !isOptimizeResources();
- }
-
+
/** {@inheritDoc} */
public void paintImage(RenderedImage image, RendererContext context,
int x, int y, int width, int height) throws IOException {
@@ -477,6 +623,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
/** Restores the last graphics state of the rendering engine. */
public void restoreGraphicsState() {
try {
+ endTextObject();
//delegate
gen.restoreGraphicsState();
} catch (IOException ioe) {
@@ -515,7 +662,22 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
}
}
+ /** {@inheritDoc} */
+ protected void concatenateTransformationMatrix(AffineTransform at) {
+ try {
+ gen.concatMatrix(at);
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
+ }
+
private String getPostScriptNameForFontKey(String key) {
+ int pos = key.indexOf('_');
+ String postFix = null;
+ if (pos > 0) {
+ postFix = key.substring(pos);
+ key = key.substring(0, pos);
+ }
Map fonts = fontInfo.getFonts();
Typeface tf = (Typeface)fonts.get(key);
if (tf instanceof LazyFont) {
@@ -524,7 +686,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
if (tf == null) {
throw new IllegalStateException("Font not available: " + key);
}
- return tf.getFontName();
+ if (postFix == null) {
+ return tf.getFontName();
+ } else {
+ return tf.getFontName() + postFix;
+ }
}
/**
@@ -554,7 +720,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
protected void useFont(String key, int size) {
try {
PSResource res = getPSResourceForFontKey(key);
- //gen.useFont(key, size / 1000f);
gen.useFont("/" + res.getName(), size / 1000f);
gen.getResourceTracker().notifyResourceUsageOnPage(res);
} catch (IOException ioe) {
@@ -776,6 +941,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
gen.writeDSCComment(DSCConstants.CREATION_DATE, new Object[] {new java.util.Date()});
gen.writeDSCComment(DSCConstants.LANGUAGE_LEVEL, new Integer(gen.getPSLevel()));
gen.writeDSCComment(DSCConstants.PAGES, new Object[] {DSCConstants.ATEND});
+ gen.writeDSCComment(DSCConstants.BBOX, DSCConstants.ATEND);
+ gen.writeDSCComment(DSCConstants.HIRES_BBOX, DSCConstants.ATEND);
+ this.documentBoundingBox = new Rectangle2D.Double();
gen.writeDSCComment(DSCConstants.DOCUMENT_SUPPLIED_RESOURCES,
new Object[] {DSCConstants.ATEND});
if (headerComments != null) {
@@ -804,7 +972,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
if (!isOptimizeResources()) {
this.fontResources = PSFontUtils.writeFontDict(gen, fontInfo);
} else {
- gen.commentln("%FOPFontSetup");
+ gen.commentln("%FOPFontSetup"); //Place-holder, will be replaced in the second pass
}
gen.writeDSCComment(DSCConstants.END_SETUP);
}
@@ -833,6 +1001,8 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
footerComments.clear();
}
gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.currentPageNumber));
+ new DSCCommentBoundingBox(this.documentBoundingBox).generate(gen);
+ new DSCCommentHiResBoundingBox(this.documentBoundingBox).generate(gen);
gen.getResourceTracker().writeResources(false, gen);
gen.writeDSCComment(DSCConstants.EOF);
gen.flush();
@@ -863,7 +1033,8 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
try {
try {
ResourceHandler.process(this.userAgent, in, this.outputStream,
- this.fontInfo, resTracker, this.formResources, this.currentPageNumber);
+ this.fontInfo, resTracker, this.formResources,
+ this.currentPageNumber, this.documentBoundingBox);
this.outputStream.flush();
} catch (DSCException e) {
throw new RuntimeException(e.getMessage());
@@ -910,8 +1081,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
try {
this.pageDeviceDictionary.putAll(PSDictionary.valueOf(content));
} catch (PSDictionaryFormatException e) {
- log.error("Failed to parse dictionary string: "
- + e.getMessage() + ", content = '" + content + "'");
+ PSEventProducer eventProducer = PSEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.postscriptDictionaryParseError(this, content, e);
}
}
} else if (attachment instanceof PSCommentBefore) {
@@ -931,11 +1103,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
super.processOffDocumentItem(oDI);
}
- /** {@inheritDoc} */
- public void startPageSequence(LineArea seqTitle) {
- super.startPageSequence(seqTitle);
- }
-
/**
* Formats and writes a List of PSSetupCode instances to the output stream.
* @param setupCodeList a List of PSSetupCode instances
@@ -1014,8 +1181,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
try {
pageDeviceDictionary.putAll(PSDictionary.valueOf(content));
} catch (PSDictionaryFormatException e) {
- log.error("failed to parse dictionary string: "
- + e.getMessage() + ", [" + content + "]");
+ PSEventProducer eventProducer = PSEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.postscriptDictionaryParseError(this, content, e);
}
}
}
@@ -1031,7 +1199,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
log.error(e.getMessage());
}
final Integer zero = new Integer(0);
+ Rectangle2D pageBoundingBox = new Rectangle2D.Double();
if (rotate) {
+ pageBoundingBox.setRect(0, 0, pageHeight, pageWidth);
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] {
zero, zero, new Long(Math.round(pageHeight)),
new Long(Math.round(pageWidth)) });
@@ -1040,6 +1210,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
new Double(pageWidth) });
gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
} else {
+ pageBoundingBox.setRect(0, 0, pageWidth, pageHeight);
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[] {
zero, zero, new Long(Math.round(pageWidth)),
new Long(Math.round(pageHeight)) });
@@ -1051,6 +1222,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
"Portrait");
}
}
+ this.documentBoundingBox.add(pageBoundingBox);
gen.writeDSCComment(DSCConstants.PAGE_RESOURCES,
new Object[] {DSCConstants.ATEND});
@@ -1132,9 +1304,9 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
/** Indicates the end of a text object. */
protected void endTextObject() {
if (inTextMode) {
+ inTextMode = false; //set before restoreGraphicsState() to avoid recursion
writeln("ET");
restoreGraphicsState();
- inTextMode = false;
}
}
@@ -1143,17 +1315,16 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
*/
public void renderText(TextArea area) {
renderInlineAreaBackAndBorders(area);
- String fontname = getInternalFontNameForArea(area);
+ String fontkey = getInternalFontNameForArea(area);
int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
// This assumes that *all* CIDFonts use a /ToUnicode mapping
- Typeface tf = (Typeface) fontInfo.getFonts().get(fontname);
+ Typeface tf = (Typeface) fontInfo.getFonts().get(fontkey);
//Determine position
int rx = currentIPPosition + area.getBorderAndPaddingWidthStart();
int bl = currentBPPosition + area.getOffset() + area.getBaselineOffset();
- useFont(fontname, fontsize);
Color ct = (Color)area.getTrait(Trait.COLOR);
if (ct != null) {
try {
@@ -1198,30 +1369,75 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
super.renderSpace(space);
}
+ private Typeface getTypeface(String fontName) {
+ Typeface tf = (Typeface)fontInfo.getFonts().get(fontName);
+ if (tf instanceof LazyFont) {
+ tf = ((LazyFont)tf).getRealFont();
+ }
+ return tf;
+ }
+
private void renderText(AbstractTextArea area, String text, int[] letterAdjust) {
+ String fontkey = getInternalFontNameForArea(area);
+ int fontSize = area.getTraitAsInteger(Trait.FONT_SIZE);
Font font = getFontFromArea(area);
- Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
+ Typeface tf = getTypeface(font.getFontName());
+ SingleByteFont singleByteFont = null;
+ if (tf instanceof SingleByteFont) {
+ singleByteFont = (SingleByteFont)tf;
+ }
+
+ int textLen = text.length();
+ if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
+ int start = 0;
+ int currentEncoding = -1;
+ for (int i = 0; i < textLen; i++) {
+ char c = text.charAt(i);
+ char mapped = tf.mapChar(c);
+ int encoding = mapped / 256;
+ if (currentEncoding != encoding) {
+ if (i > 0) {
+ writeText(area, text, start, i - start, letterAdjust, fontSize, tf);
+ }
+ if (encoding == 0) {
+ useFont(fontkey, fontSize);
+ } else {
+ useFont(fontkey + "_" + Integer.toString(encoding), fontSize);
+ }
+ currentEncoding = encoding;
+ start = i;
+ }
+ }
+ writeText(area, text, start, textLen - start, letterAdjust, fontSize, tf);
+ } else {
+ useFont(fontkey, fontSize);
+ writeText(area, text, 0, textLen, letterAdjust, fontSize, tf);
+ }
+ }
+ private void writeText(AbstractTextArea area, String text, int start, int len,
+ int[] letterAdjust, int fontsize, Typeface tf) {
+ int end = start + len;
int initialSize = text.length();
initialSize += initialSize / 2;
StringBuffer sb = new StringBuffer(initialSize);
- int textLen = text.length();
if (letterAdjust == null
&& area.getTextLetterSpaceAdjust() == 0
&& area.getTextWordSpaceAdjust() == 0) {
sb.append("(");
- for (int i = 0; i < textLen; i++) {
+ for (int i = start; i < end; i++) {
final char c = text.charAt(i);
- final char mapped = tf.mapChar(c);
+ final char mapped = (char)(tf.mapChar(c) % 256);
PSGenerator.escapeChar(mapped, sb);
}
sb.append(") t");
} else {
sb.append("(");
- int[] offsets = new int[textLen];
- for (int i = 0; i < textLen; i++) {
+ int[] offsets = new int[len];
+ for (int i = start; i < end; i++) {
final char c = text.charAt(i);
final char mapped = tf.mapChar(c);
+ char codepoint = (char)(mapped % 256);
int wordSpace;
if (CharUtilities.isAdjustableSpace(mapped)) {
@@ -1229,14 +1445,14 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
} else {
wordSpace = 0;
}
- int cw = tf.getWidth(mapped, font.getFontSize()) / 1000;
- int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0);
- int tls = (i < textLen - 1 ? area.getTextLetterSpaceAdjust() : 0);
- offsets[i] = cw + ladj + tls + wordSpace;
- PSGenerator.escapeChar(mapped, sb);
+ int cw = tf.getWidth(mapped, fontsize) / 1000;
+ int ladj = (letterAdjust != null && i < end - 1 ? letterAdjust[i + 1] : 0);
+ int tls = (i < end - 1 ? area.getTextLetterSpaceAdjust() : 0);
+ offsets[i - start] = cw + ladj + tls + wordSpace;
+ PSGenerator.escapeChar(codepoint, sb);
}
sb.append(")" + PSGenerator.LF + "[");
- for (int i = 0; i < textLen; i++) {
+ for (int i = 0; i < len; i++) {
if (i > 0) {
if (i % 8 == 0) {
sb.append(PSGenerator.LF);
@@ -1249,7 +1465,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
sb.append("]" + PSGenerator.LF + "xshow");
}
writeln(sb.toString());
-
}
/** {@inheritDoc} */
@@ -1314,7 +1529,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
* {@inheritDoc}
*/
protected void endVParea() {
- endTextObject();
restoreGraphicsState();
}
@@ -1491,13 +1705,14 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
}
/**
- * Sets whether or not Dublin Core Standard (dsc) compliance is enforced.
- *
- * It can cause problems (unwanted postscript subsystem initgraphics/erasepage calls)
+ * Sets whether or not PostScript Document Structuring Conventions (dsc) compliance are
+ * enforced.
+ * <p>
+ * 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.
- *
+ * <p>
* Set this value to false if you experience unwanted blank pages in your
* postscript output.
* @param dscCompliant boolean value (default is true)
diff --git a/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java b/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java
index e94d873cb..3ce9751b5 100644
--- a/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-/* $Id: $ */
+/* $Id$ */
package org.apache.fop.render.ps;
diff --git a/src/java/org/apache/fop/render/ps/PSRendererMaker.java b/src/java/org/apache/fop/render/ps/PSRendererMaker.java
index d879c054c..657a65f70 100644
--- a/src/java/org/apache/fop/render/ps/PSRendererMaker.java
+++ b/src/java/org/apache/fop/render/ps/PSRendererMaker.java
@@ -1,54 +1,54 @@
-/*
- * 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 org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.apps.MimeConstants;
-import org.apache.fop.render.AbstractRendererMaker;
-import org.apache.fop.render.Renderer;
-import org.apache.fop.render.RendererConfigurator;
-
-/**
- * RendererMaker for the PostScript Renderer.
- */
-public class PSRendererMaker extends AbstractRendererMaker {
-
- private static final String[] MIMES = new String[] {MimeConstants.MIME_POSTSCRIPT};
-
- /** {@inheritDoc} */
- public Renderer makeRenderer(FOUserAgent userAgent) {
- return new PSRenderer();
- }
-
- /** {@inheritDoc} */
- public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
- return new PSRendererConfigurator(userAgent);
- }
-
- /** {@inheritDoc} */
- public boolean needsOutputStream() {
- return true;
- }
-
- /** {@inheritDoc} */
- public String[] getSupportedMimeTypes() {
- return MIMES;
- }
-}
+/*
+ * 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 org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.render.AbstractRendererMaker;
+import org.apache.fop.render.Renderer;
+import org.apache.fop.render.RendererConfigurator;
+
+/**
+ * RendererMaker for the PostScript Renderer.
+ */
+public class PSRendererMaker extends AbstractRendererMaker {
+
+ private static final String[] MIMES = new String[] {MimeConstants.MIME_POSTSCRIPT};
+
+ /** {@inheritDoc} */
+ public Renderer makeRenderer(FOUserAgent userAgent) {
+ return new PSRenderer();
+ }
+
+ /** {@inheritDoc} */
+ public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
+ return new PSRendererConfigurator(userAgent);
+ }
+
+ /** {@inheritDoc} */
+ public boolean needsOutputStream() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public String[] getSupportedMimeTypes() {
+ return MIMES;
+ }
+}
diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java
index 5cfe617c8..ebe098282 100644
--- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java
+++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java
@@ -23,31 +23,24 @@ package org.apache.fop.render.ps;
import java.awt.geom.AffineTransform;
import java.io.IOException;
-// DOM
import org.w3c.dom.Document;
-import org.w3c.dom.svg.SVGDocument;
-import org.w3c.dom.svg.SVGSVGElement;
-// Batik
import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.ViewBox;
-import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.gvt.GraphicsNode;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
+import org.apache.xmlgraphics.ps.PSGenerator;
-// FOP
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.render.AbstractGenericSVGHandler;
import org.apache.fop.render.Renderer;
-import org.apache.fop.render.XMLHandler;
import org.apache.fop.render.RendererContext;
+import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
-import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
-import org.apache.xmlgraphics.ps.PSGenerator;
-
-// Commons-Logging
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
/**
* PostScript XML handler for SVG. Uses Apache Batik for SVG processing.
@@ -57,7 +50,8 @@ import org.apache.commons.logging.LogFactory;
*
* @version $Id$
*/
-public class PSSVGHandler implements XMLHandler, PSRendererContextConstants {
+public class PSSVGHandler extends AbstractGenericSVGHandler
+ implements PSRendererContextConstants {
/** logging instance */
private static Log log = LogFactory.getLog(PSSVGHandler.class);
@@ -68,16 +62,6 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants {
public PSSVGHandler() {
}
- /** {@inheritDoc} */
- public void handleXML(RendererContext context,
- Document doc, String ns) throws Exception {
- PSInfo psi = getPSInfo(context);
-
- if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) {
- renderSVGDocument(context, doc, psi);
- }
- }
-
/**
* Get the pdf information from the render context.
*
@@ -234,10 +218,10 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants {
* Render the svg document.
* @param context the renderer context
* @param doc the svg document
- * @param psInfo the pdf information of the current context
*/
protected void renderSVGDocument(RendererContext context,
- Document doc, PSInfo psInfo) {
+ Document doc) {
+ PSInfo psInfo = getPSInfo(context);
int xOffset = psInfo.currentXPosition;
int yOffset = psInfo.currentYPosition;
PSGenerator gen = psInfo.psGenerator;
@@ -250,9 +234,7 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants {
}
SVGUserAgent ua
- = new SVGUserAgent(
- context.getUserAgent().getSourcePixelUnitToMillimeter(),
- new AffineTransform());
+ = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
PSGraphics2D graphics = new PSGraphics2D(strokeText, gen);
graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
@@ -273,8 +255,9 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants {
try {
root = builder.build(ctx, doc);
} catch (Exception e) {
- log.error("SVG graphic could not be built: "
- + e.getMessage(), e);
+ SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+ context.getUserAgent().getEventBroadcaster());
+ eventProducer.svgNotBuilt(this, e, getDocumentURI(doc));
return;
}
// get the 'width' and 'height' attributes of the SVG document
@@ -305,10 +288,10 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants {
// viewBox puts it.
gen.concatMatrix(sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f);
+ /*
SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg,
- psInfo.getWidth() / 1000f, psInfo.getHeight() / 1000f);
- /*
+ psInfo.getWidth() / 1000f, psInfo.getHeight() / 1000f, ctx);
if (!at.isIdentity()) {
double[] vals = new double[6];
at.getMatrix(vals);
@@ -322,15 +305,17 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants {
try {
root.paint(graphics);
} catch (Exception e) {
- log.error("SVG graphic could not be rendered: "
- + e.getMessage(), e);
+ SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+ context.getUserAgent().getEventBroadcaster());
+ eventProducer.svgRenderingError(this, e, getDocumentURI(doc));
}
gen.restoreGraphicsState();
gen.commentln("%FOPEndSVG");
} catch (IOException ioe) {
- log.error("SVG graphic could not be rendered: "
- + ioe.getMessage(), ioe);
+ SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+ context.getUserAgent().getEventBroadcaster());
+ eventProducer.svgRenderingError(this, ioe, getDocumentURI(doc));
}
}
@@ -339,10 +324,5 @@ public class PSSVGHandler implements XMLHandler, PSRendererContextConstants {
return (renderer instanceof PSRenderer);
}
- /** {@inheritDoc} */
- public String getNamespace() {
- return SVGDOMImplementation.SVG_NAMESPACE_URI;
- }
-
}
diff --git a/src/java/org/apache/fop/render/ps/PSSupportedFlavors.java b/src/java/org/apache/fop/render/ps/PSSupportedFlavors.java
new file mode 100644
index 000000000..8ccfa8e26
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/PSSupportedFlavors.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.apache.xmlgraphics.image.loader.ImageFlavor;
+
+/**
+ * Defines the set of supported ImageFlavors for the PostScript renderer.
+ */
+public interface PSSupportedFlavors {
+
+ /** The flavors supported inline with PostScript level 2. */
+ ImageFlavor[] LEVEL_2_FLAVORS_INLINE = new ImageFlavor[]
+ {ImageFlavor.RAW_EPS,
+ ImageFlavor.RAW_CCITTFAX,
+ ImageFlavor.GRAPHICS2D,
+ ImageFlavor.BUFFERED_IMAGE,
+ ImageFlavor.RENDERED_IMAGE,
+ ImageFlavor.XML_DOM};
+
+ /** The flavors supported inline with PostScript level 3 and higher. */
+ ImageFlavor[] LEVEL_3_FLAVORS_INLINE = new ImageFlavor[]
+ {ImageFlavor.RAW_EPS,
+ ImageFlavor.RAW_JPEG,
+ ImageFlavor.RAW_CCITTFAX,
+ ImageFlavor.GRAPHICS2D,
+ ImageFlavor.BUFFERED_IMAGE,
+ ImageFlavor.RENDERED_IMAGE,
+ ImageFlavor.XML_DOM};
+
+ /** The flavors supported as forms with PostScript level 2. */
+ ImageFlavor[] LEVEL_2_FLAVORS_FORM = new ImageFlavor[]
+ {//ImageFlavor.RAW_EPS,
+ ImageFlavor.RAW_CCITTFAX,
+ ImageFlavor.GRAPHICS2D,
+ ImageFlavor.BUFFERED_IMAGE,
+ ImageFlavor.RENDERED_IMAGE/*,
+ ImageFlavor.XML_DOM*/};
+
+ /** The flavors supported as forms with PostScript level 3 or higher. */
+ ImageFlavor[] LEVEL_3_FLAVORS_FORM = new ImageFlavor[]
+ {//ImageFlavor.RAW_EPS,
+ ImageFlavor.RAW_JPEG,
+ ImageFlavor.RAW_CCITTFAX,
+ ImageFlavor.GRAPHICS2D,
+ ImageFlavor.BUFFERED_IMAGE,
+ ImageFlavor.RENDERED_IMAGE/*,
+ ImageFlavor.XML_DOM*/};
+
+}
diff --git a/src/java/org/apache/fop/render/ps/ResourceHandler.java b/src/java/org/apache/fop/render/ps/ResourceHandler.java
index f187e619a..1a363c90e 100644
--- a/src/java/org/apache/fop/render/ps/ResourceHandler.java
+++ b/src/java/org/apache/fop/render/ps/ResourceHandler.java
@@ -19,6 +19,9 @@
package org.apache.fop.render.ps;
+import java.awt.geom.Dimension2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -26,12 +29,25 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
-import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.image.FopImage;
-import org.apache.fop.image.ImageFactory;
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
+import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
+import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.ps.DSCConstants;
+import org.apache.xmlgraphics.ps.FormGenerator;
+import org.apache.xmlgraphics.ps.ImageEncoder;
+import org.apache.xmlgraphics.ps.ImageFormGenerator;
import org.apache.xmlgraphics.ps.PSGenerator;
+import org.apache.xmlgraphics.ps.PSProcSets;
import org.apache.xmlgraphics.ps.dsc.DSCException;
import org.apache.xmlgraphics.ps.dsc.DSCFilter;
import org.apache.xmlgraphics.ps.dsc.DSCParser;
@@ -39,8 +55,10 @@ import org.apache.xmlgraphics.ps.dsc.DSCParserConstants;
import org.apache.xmlgraphics.ps.dsc.DefaultNestedDocumentHandler;
import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
import org.apache.xmlgraphics.ps.dsc.events.DSCComment;
+import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentDocumentNeededResources;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentDocumentSuppliedResources;
+import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentLanguageLevel;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPage;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPages;
@@ -49,13 +67,17 @@ import org.apache.xmlgraphics.ps.dsc.events.DSCHeaderComment;
import org.apache.xmlgraphics.ps.dsc.events.PostScriptComment;
import org.apache.xmlgraphics.ps.dsc.tools.DSCTools;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.events.ResourceEventProducer;
+import org.apache.fop.fonts.FontInfo;
+
/**
* This class is used when two-pass production is used to generate the PostScript file (setting
* "optimize-resources"). It uses the DSC parser from XML Graphics Commons to go over the
* temporary file generated by the PSRenderer and adds all used fonts and images as resources
* to the PostScript file.
*/
-public class ResourceHandler implements DSCParserConstants {
+public class ResourceHandler implements DSCParserConstants, PSSupportedFlavors {
/**
* Rewrites the temporary PostScript file generated by PSRenderer adding all needed resources
@@ -67,11 +89,14 @@ public class ResourceHandler implements DSCParserConstants {
* @param resTracker the resource tracker to use
* @param formResources Contains all forms used by this document (maintained by PSRenderer)
* @param pageCount the number of pages (given here because PSRenderer writes an "(atend)")
+ * @param documentBoundingBox the document's bounding box
+ * (given here because PSRenderer writes an "(atend)")
* @throws DSCException If there's an error in the DSC structure of the PS file
* @throws IOException In case of an I/O error
*/
public static void process(FOUserAgent userAgent, InputStream in, OutputStream out,
- FontInfo fontInfo, ResourceTracker resTracker, Map formResources, int pageCount)
+ FontInfo fontInfo, ResourceTracker resTracker, Map formResources,
+ int pageCount, Rectangle2D documentBoundingBox)
throws DSCException, IOException {
DSCParser parser = new DSCParser(in);
PSGenerator gen = new PSGenerator(out);
@@ -86,6 +111,8 @@ public class ResourceHandler implements DSCParserConstants {
{
//We rewrite those as part of the processing
filtered.add(DSCConstants.PAGES);
+ filtered.add(DSCConstants.BBOX);
+ filtered.add(DSCConstants.HIRES_BBOX);
filtered.add(DSCConstants.DOCUMENT_NEEDED_RESOURCES);
filtered.add(DSCConstants.DOCUMENT_SUPPLIED_RESOURCES);
}
@@ -109,6 +136,8 @@ public class ResourceHandler implements DSCParserConstants {
//Set number of pages
DSCCommentPages pages = new DSCCommentPages(pageCount);
pages.generate(gen);
+ new DSCCommentBoundingBox(documentBoundingBox).generate(gen);
+ new DSCCommentHiResBoundingBox(documentBoundingBox).generate(gen);
PSFontUtils.determineSuppliedFonts(resTracker, fontInfo, fontInfo.getUsedFonts());
registerSuppliedForms(resTracker, formResources);
@@ -197,13 +226,132 @@ public class ResourceHandler implements DSCParserConstants {
Iterator iter = formResources.values().iterator();
while (iter.hasNext()) {
PSImageFormResource form = (PSImageFormResource)iter.next();
- ImageFactory fact = userAgent.getFactory().getImageFactory();
- FopImage image = fact.getImage(form.getImageURI(), userAgent);
- if (image == null) {
- throw new NullPointerException("Image not found: " + form.getImageURI());
+ final String uri = form.getImageURI();
+
+ ImageManager manager = userAgent.getFactory().getImageManager();
+ ImageInfo info = null;
+ try {
+ ImageSessionContext sessionContext = userAgent.getImageSessionContext();
+ info = manager.getImageInfo(uri, sessionContext);
+
+ ImageFlavor[] flavors;
+ if (gen.getPSLevel() >= 3) {
+ flavors = LEVEL_3_FLAVORS_FORM;
+ } else {
+ flavors = LEVEL_2_FLAVORS_FORM;
+ }
+ Map hints = ImageUtil.getDefaultHints(sessionContext);
+ org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
+ info, flavors, hints, sessionContext);
+
+ String imageDescription = info.getMimeType() + " " + info.getOriginalURI();
+ final Dimension2D dimensionsPt = info.getSize().getDimensionPt();
+ final Dimension2D dimensionsMpt = info.getSize().getDimensionMpt();
+
+ if (img instanceof ImageGraphics2D) {
+ final ImageGraphics2D imageG2D = (ImageGraphics2D)img;
+ FormGenerator formGen = new FormGenerator(
+ form.getName(), imageDescription, dimensionsPt) {
+
+ protected void generatePaintProc(PSGenerator gen)
+ throws IOException {
+ gen.getResourceTracker().notifyResourceUsageOnPage(
+ PSProcSets.EPS_PROCSET);
+ gen.writeln("BeginEPSF");
+ PSGraphics2DAdapter adapter = new PSGraphics2DAdapter(gen, false);
+ adapter.paintImage(imageG2D.getGraphics2DImagePainter(),
+ null,
+ 0, 0,
+ (int)Math.round(dimensionsMpt.getWidth()),
+ (int)Math.round(dimensionsMpt.getHeight()));
+ gen.writeln("EndEPSF");
+ }
+
+ };
+ formGen.generate(gen);
+ } else if (img instanceof ImageRendered) {
+ ImageRendered imgRend = (ImageRendered)img;
+ RenderedImage ri = imgRend.getRenderedImage();
+ FormGenerator formGen = new ImageFormGenerator(
+ form.getName(), imageDescription,
+ info.getSize().getDimensionPt(),
+ ri, false);
+ formGen.generate(gen);
+ } else if (img instanceof ImageXMLDOM) {
+ throw new UnsupportedOperationException(
+ "Embedding an ImageXMLDOM as a form isn't supported, yet");
+ } else if (img instanceof ImageRawStream) {
+ final ImageRawStream raw = (ImageRawStream)img;
+ if (raw instanceof ImageRawEPS) {
+ final ImageRawEPS eps = (ImageRawEPS)raw;
+ throw new UnsupportedOperationException(
+ "Embedding EPS as forms isn't supported, yet");
+ /*
+ InputStream in = eps.createInputStream();
+ try {
+ FormGenerator formGen = new EPSFormGenerator(form.getName(),
+ imageDescription, dimensions, in);
+ formGen.generate(gen);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }*/
+ } else if (raw instanceof ImageRawCCITTFax) {
+ ImageRawCCITTFax jpeg = (ImageRawCCITTFax)raw;
+ ImageEncoder encoder = new ImageEncoderCCITTFax(jpeg);
+ FormGenerator formGen = new ImageFormGenerator(
+ form.getName(), imageDescription,
+ info.getSize().getDimensionPt(),
+ info.getSize().getDimensionPx(),
+ encoder,
+ jpeg.getColorSpace(), 1, false);
+ formGen.generate(gen);
+ } else if (raw instanceof ImageRawJPEG) {
+ ImageRawJPEG jpeg = (ImageRawJPEG)raw;
+ ImageEncoder encoder = new ImageEncoderJPEG(jpeg);
+ FormGenerator formGen = new ImageFormGenerator(
+ form.getName(), imageDescription,
+ info.getSize().getDimensionPt(),
+ info.getSize().getDimensionPx(),
+ encoder,
+ jpeg.getColorSpace(), jpeg.isInverted());
+ formGen.generate(gen);
+ } else {
+ throw new UnsupportedOperationException("Unsupported raw image: " + info);
+ }
+ } else {
+ throw new UnsupportedOperationException("Unsupported image type: " + img);
+ }
+ } catch (ImageException ie) {
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+ userAgent.getEventBroadcaster());
+ eventProducer.imageError(resTracker, (info != null ? info.toString() : uri),
+ ie, null);
}
- PSImageUtils.generateFormResourceForImage(image, form, gen);
}
}
+ private static FormGenerator createMissingForm(String formName, final Dimension2D dimensions) {
+ FormGenerator formGen = new FormGenerator(formName, null, dimensions) {
+
+ protected void generatePaintProc(PSGenerator gen) throws IOException {
+ gen.writeln("0 setgray");
+ gen.writeln("0 setlinewidth");
+ String w = gen.formatDouble(dimensions.getWidth());
+ String h = gen.formatDouble(dimensions.getHeight());
+ gen.writeln(w + " " + h + " scale");
+ gen.writeln("0 0 1 1 rectstroke");
+ gen.writeln("newpath");
+ gen.writeln("0 0 moveto");
+ gen.writeln("1 1 lineto");
+ gen.writeln("stroke");
+ gen.writeln("newpath");
+ gen.writeln("0 1 moveto");
+ gen.writeln("1 0 lineto");
+ gen.writeln("stroke");
+ }
+
+ };
+ return formGen;
+ }
+
}
diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java
index a6e77fb13..1eb1d9d13 100644
--- a/src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSCommentElement.java
@@ -22,7 +22,6 @@ 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.ValidationException;
/**
* Base postscript commment element class
@@ -46,8 +45,8 @@ public abstract class AbstractPSCommentElement extends AbstractPSExtensionElemen
protected void startOfNode() throws FOPException {
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.");
+ invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(),
+ "rule.childOfSPMorDeclarations");
}
}
diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java
index f2a9c56d9..31e44d2d2 100644
--- a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionElement.java
@@ -1,133 +1,133 @@
-/*
- * 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: AbstractPSExtensionObject.java 426576 2006-07-28 15:44:37Z jeremias $ */
-
-package org.apache.fop.render.ps.extensions;
-
-// FOP
-import org.apache.fop.apps.FOPException;
-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.Locator;
-
-/**
- * Base class for the PostScript-specific extension elements.
- */
-public abstract class AbstractPSExtensionElement extends FONode {
-
- /**
- * extension attachment
- */
- protected PSExtensionAttachment attachment;
-
- /**
- * Default constructor
- *
- * @param parent parent of this node
- * @see org.apache.fop.fo.FONode#FONode(FONode)
- */
- public AbstractPSExtensionElement(FONode parent) {
- super(parent);
- }
-
- /**
- * Blocks XSL FO's from having non-FO parents.
- *
- * @param loc location in the FO source file
- * @param nsURI namespace of incoming node
- * @param localName (e.g. "table" for "fo:table")
- * @throws ValidationException if incoming node not valid for parent
- * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
- */
- protected void validateChildNode(Locator loc, String nsURI, String localName)
- throws ValidationException {
- if (FO_URI.equals(nsURI)) {
- invalidChildError(loc, nsURI, localName);
- }
- }
-
- /**
- * Adds characters (does nothing here)
- * @param data array of characters containing text to be added
- * @param start starting array element to add
- * @param length of data array to add
- * @param pList currently applicable PropertyList
- * @param locator location in fo source file.
- * @see org.apache.fop.fo.FONode#addCharacters(char[], int, int, PropertyList, Locator)
- */
- protected void addCharacters(char[] data, int start, int length,
- PropertyList pList, Locator locator) {
- PSExtensionAttachment a = (PSExtensionAttachment)getExtensionAttachment();
- if (a.getContent() != null) {
- StringBuffer sb = new StringBuffer(a.getContent());
- sb.append(data, start, length - start);
- a.setContent(sb.toString());
- } else {
- a.setContent(new String(data, start, length - start));
- }
- }
-
- /**
- * @return a String representation of this object
- * @see org.apache.fop.fo.FONode#getNamespaceURI()
- */
- public String getNamespaceURI() {
- return PSExtensionElementMapping.NAMESPACE;
- }
-
- /**
- * @return a String representation of this object
- * @see org.apache.fop.fo.FONode#getNormalNamespacePrefix()
- */
- public String getNormalNamespacePrefix() {
- return "fox";
- }
-
- /**
- * @see org.apache.fop.fo.FONode#endOfNode()
- * @throws FOPException if there's a problem during processing
- */
- protected void endOfNode() throws FOPException {
- super.endOfNode();
- String s = ((PSExtensionAttachment)getExtensionAttachment()).getContent();
- if (s == null || s.length() == 0) {
- missingChildElementError("#PCDATA");
- }
- }
-
- /**
- * @return the extension attachment if one is created by the extension element, null otherwise.
- * @see org.apache.fop.fo.FONode#getExtensionAttachment()
- */
- public ExtensionAttachment getExtensionAttachment() {
- if (attachment == null) {
- this.attachment = (PSExtensionAttachment)instantiateExtensionAttachment();
- }
- return this.attachment;
- }
-
- /**
- * Instantiates extension attachment object
- * @return extension attachment
- */
- protected abstract ExtensionAttachment instantiateExtensionAttachment();
-}
-
+/*
+ * 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;
+
+// FOP
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+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;
+
+/**
+ * Base class for the PostScript-specific extension elements.
+ */
+public abstract class AbstractPSExtensionElement extends FONode {
+
+ /**
+ * extension attachment
+ */
+ protected PSExtensionAttachment attachment;
+
+ /**
+ * Default constructor
+ *
+ * @param parent parent of this node
+ * @see org.apache.fop.fo.FONode#FONode(FONode)
+ */
+ public AbstractPSExtensionElement(FONode parent) {
+ super(parent);
+ }
+
+ /**
+ * Blocks XSL FO's from having non-FO parents.
+ *
+ * @param loc location in the FO source file
+ * @param nsURI namespace of incoming node
+ * @param localName (e.g. "table" for "fo:table")
+ * @throws ValidationException if incoming node not valid for parent
+ * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
+ */
+ protected void validateChildNode(Locator loc, String nsURI, String localName)
+ throws ValidationException {
+ if (FO_URI.equals(nsURI)) {
+ invalidChildError(loc, nsURI, localName);
+ }
+ }
+
+ /**
+ * Adds characters (does nothing here)
+ * @param data array of characters containing text to be added
+ * @param start starting array element to add
+ * @param length of data array to add
+ * @param pList currently applicable PropertyList
+ * @param locator location in fo source file.
+ * @see org.apache.fop.fo.FONode#addCharacters(char[], int, int, PropertyList, Locator)
+ */
+ protected void addCharacters(char[] data, int start, int length,
+ PropertyList pList, Locator locator) {
+ PSExtensionAttachment a = (PSExtensionAttachment)getExtensionAttachment();
+ if (a.getContent() != null) {
+ StringBuffer sb = new StringBuffer(a.getContent());
+ sb.append(data, start, length - start);
+ a.setContent(sb.toString());
+ } else {
+ a.setContent(new String(data, start, length - start));
+ }
+ }
+
+ /**
+ * @return a String representation of this object
+ * @see org.apache.fop.fo.FONode#getNamespaceURI()
+ */
+ public String getNamespaceURI() {
+ return PSExtensionElementMapping.NAMESPACE;
+ }
+
+ /**
+ * @return a String representation of this object
+ * @see org.apache.fop.fo.FONode#getNormalNamespacePrefix()
+ */
+ public String getNormalNamespacePrefix() {
+ return "ps";
+ }
+
+ /**
+ * @see org.apache.fop.fo.FONode#endOfNode()
+ * @throws FOPException if there's a problem during processing
+ */
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ String s = ((PSExtensionAttachment)getExtensionAttachment()).getContent();
+ if (s == null || s.length() == 0) {
+ missingChildElementError("#PCDATA");
+ }
+ }
+
+ /**
+ * @return the extension attachment if one is created by the extension element, null otherwise.
+ * @see org.apache.fop.fo.FONode#getExtensionAttachment()
+ */
+ public ExtensionAttachment getExtensionAttachment() {
+ if (attachment == null) {
+ this.attachment = (PSExtensionAttachment)instantiateExtensionAttachment();
+ }
+ return this.attachment;
+ }
+
+ /**
+ * Instantiates extension attachment object
+ * @return extension attachment
+ */
+ protected abstract ExtensionAttachment instantiateExtensionAttachment();
+}
+
diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java
index 6823d75d9..78b2f91eb 100644
--- a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java
+++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java
@@ -20,13 +20,14 @@
package org.apache.fop.render.ps.extensions;
// FOP
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
import org.apache.fop.apps.FOPException;
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;
/**
* Base class for the PostScript-specific extension elements.
@@ -36,15 +37,15 @@ public abstract class AbstractPSExtensionObject extends FONode {
private PSSetupCode setupCode = new PSSetupCode();
/**
+ * Main constructor.
+ * @param parent the parent node
* @see org.apache.fop.fo.FONode#FONode(FONode)
*/
public AbstractPSExtensionObject(FONode parent) {
super(parent);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException {
if (FO_URI.equals(nsURI)) {
@@ -71,7 +72,7 @@ public abstract class AbstractPSExtensionObject extends FONode {
/**{@inheritDoc} */
public String getNormalNamespacePrefix() {
- return "fox";
+ return "ps";
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java
index 306cd7bda..1dd0f4be6 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java
@@ -27,6 +27,7 @@ import org.apache.fop.fo.extensions.ExtensionAttachment;
*/
public class PSCommentAfterElement extends AbstractPSCommentElement {
+ /** the element name */
protected static final String ELEMENT = "ps-comment-after";
/**
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java
index 6058f355b..5d3c863f5 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java
@@ -27,6 +27,7 @@ import org.apache.fop.fo.extensions.ExtensionAttachment;
*/
public class PSCommentBeforeElement extends AbstractPSCommentElement {
+ /** the element name */
protected static final String ELEMENT = "ps-comment-before";
/**
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java
index 0fb623bdc..3fccf4f67 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionAttachment.java
@@ -1,108 +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.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();
-}
+/*
+ * 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;
+
+import org.apache.xmlgraphics.util.XMLizable;
+
+import org.apache.fop.fo.extensions.ExtensionAttachment;
+
+/**
+ * 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/PSExtensionHandler.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java
index 72f665a0f..e69500736 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java
@@ -15,17 +15,19 @@
* limitations under the License.
*/
-/* $Id: $ */
+/* $Id$ */
package org.apache.fop.render.ps.extensions;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
/**
* ContentHandler (parser) for restoring PSExtension objects from XML.
@@ -91,25 +93,19 @@ public class PSExtensionHandler extends DefaultHandler
content.append(ch, start, length);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void endDocument() throws SAXException {
if (listener != null) {
listener.notifyObjectBuilt(getObject());
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public Object getObject() {
return returnedObject;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void setObjectBuiltListener(ObjectBuiltListener listener) {
this.listener = listener;
}
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java
index ad46b9364..207c11e76 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java
@@ -22,13 +22,13 @@ 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.ValidationException;
/**
* Extension element for fox:ps-page-setup-code.
*/
public class PSPageSetupCodeElement extends AbstractPSExtensionObject {
+ /** The element name */
protected static final String ELEMENT = "ps-page-setup-code";
/**
@@ -43,7 +43,8 @@ public class PSPageSetupCodeElement extends AbstractPSExtensionObject {
protected void startOfNode() throws FOPException {
super.startOfNode();
if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) {
- throw new ValidationException(getName() + " must be a child of fo:simple-page-master.");
+ invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(),
+ "rule.childOfSPM");
}
}
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java
index 5684ba6a3..28ea3c24c 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDevice.java
@@ -1,114 +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);
- }
-}
+/*
+ * 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.xmlgraphics.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
index ff7e8f792..21acc8001 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSSetPageDeviceElement.java
@@ -1,95 +1,96 @@
-/*
- * 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 {
-
- protected static final String ELEMENT = "ps-setpagedevice";
-
- /**
- * 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 ELEMENT;
- }
-
- /**
- * @return a new PSSetPageDevice object
- * @see org.apache.fop.render.ps.extensions.AbstractPSExtensionElement
- * #instantiateExtensionAttachment()
- */
- protected ExtensionAttachment instantiateExtensionAttachment() {
- return new PSSetPageDevice();
- }
-}
+/*
+ * 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.Attributes;
+import org.xml.sax.Locator;
+
+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.extensions.ExtensionAttachment;
+
+/**
+ * Extension element for ps:ps-setpagedevice.
+ */
+public class PSSetPageDeviceElement extends AbstractPSExtensionElement {
+
+ /** The element name */
+ protected static final String ELEMENT = "ps-setpagedevice";
+
+ /**
+ * 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)) ) {
+ invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(),
+ "rule.childOfSPMorDeclarations");
+ }
+ }
+
+ /**
+ * 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 ELEMENT;
+ }
+
+ /**
+ * @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/PSSetupCodeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java
index ec7216c44..e76dfeb64 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java
@@ -22,13 +22,13 @@ 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.ValidationException;
/**
* Extension element for fox:ps-setup-code.
*/
public class PSSetupCodeElement extends AbstractPSExtensionObject {
+ /** The element name */
protected static final String ELEMENT = "ps-setup-code";
/**
@@ -43,7 +43,8 @@ public class PSSetupCodeElement extends AbstractPSExtensionObject {
protected void startOfNode() throws FOPException {
super.startOfNode();
if (parent.getNameId() != Constants.FO_DECLARATIONS) {
- throw new ValidationException(getName() + " must be a child of fo:declarations.");
+ invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(),
+ "rule.childOfDeclarations");
}
}