aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/org/apache/fop/pdf/PDFNumber.java18
-rw-r--r--src/java/org/apache/fop/pdf/PDFStream.java29
-rw-r--r--src/java/org/apache/fop/pdf/PDFText.java12
-rw-r--r--src/java/org/apache/fop/pdf/PDFTextUtil.java73
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFContentGenerator.java3
-rw-r--r--src/java/org/apache/fop/svg/PDFTextPainter.java4
-rw-r--r--status.xml3
7 files changed, 113 insertions, 29 deletions
diff --git a/src/java/org/apache/fop/pdf/PDFNumber.java b/src/java/org/apache/fop/pdf/PDFNumber.java
index e638a51b1..1c31f8e9d 100644
--- a/src/java/org/apache/fop/pdf/PDFNumber.java
+++ b/src/java/org/apache/fop/pdf/PDFNumber.java
@@ -83,6 +83,24 @@ public class PDFNumber extends PDFObject {
return buf.toString();
}
+ /**
+ * Append a double value to a string buffer suitable for PDF.
+ * In this method it is possible to set the maximum
+ * number of decimal places to output.
+ *
+ * @param doubleDown the Double value
+ * @param dec the number of decimal places to output
+ * @param buf the string buffer to which double is formatted (appended)
+ * @return the string buffer
+ */
+ public static StringBuffer doubleOut(double doubleDown, int dec, StringBuffer buf) {
+ if (dec < 0 || dec > 16) {
+ throw new IllegalArgumentException("Parameter dec must be between 1 and 16");
+ }
+ DoubleFormatUtil.formatDouble(doubleDown, dec, dec, buf);
+ return buf;
+ }
+
/** {@inheritDoc} */
protected String toPDFString() {
if (getNumber() == null) {
diff --git a/src/java/org/apache/fop/pdf/PDFStream.java b/src/java/org/apache/fop/pdf/PDFStream.java
index a0b990ec5..2801d4d1f 100644
--- a/src/java/org/apache/fop/pdf/PDFStream.java
+++ b/src/java/org/apache/fop/pdf/PDFStream.java
@@ -40,6 +40,7 @@ public class PDFStream extends AbstractPDFStream {
protected StreamCache data;
private transient Writer streamWriter;
+ private transient char[] charBuffer;
/**
* Create an empty stream object
@@ -89,6 +90,34 @@ public class PDFStream extends AbstractPDFStream {
}
}
+ /**
+ * Append data to the stream
+ *
+ * @param sb the string buffer of PDF to add
+ */
+ public void add(StringBuffer sb) {
+ try {
+ int nHave = sb.length();
+ if (charBuffer == null) {
+ charBuffer = new char [ nHave * 2 ];
+ } else {
+ int nAvail = charBuffer.length;
+ if (nAvail < nHave) {
+ int nAlloc = nAvail;
+ while (nAlloc < nHave) {
+ nAlloc *= 2;
+ }
+ charBuffer = new char [ nAlloc ];
+ }
+ }
+ sb.getChars(0, nHave, charBuffer, 0);
+ this.streamWriter.write(charBuffer, 0, nHave);
+ } catch (IOException ex) {
+ //TODO throw the exception and catch it elsewhere
+ ex.printStackTrace();
+ }
+ }
+
private void flush() throws IOException {
this.streamWriter.flush();
}
diff --git a/src/java/org/apache/fop/pdf/PDFText.java b/src/java/org/apache/fop/pdf/PDFText.java
index 3cddfe426..e581800e0 100644
--- a/src/java/org/apache/fop/pdf/PDFText.java
+++ b/src/java/org/apache/fop/pdf/PDFText.java
@@ -206,6 +206,18 @@ public class PDFText extends PDFObject {
}
/**
+ * Convert a char to a multibyte hex representation appending to string buffer.
+ * Since Java always stores strings in UTF-16, we don't have to do any conversion.
+ * @param c character to encode
+ * @param sb the string buffer to append output
+ */
+ public static final void toUnicodeHex(char c, StringBuffer sb) {
+ for (int i = 0; i < 4; ++i) {
+ sb.append(DIGITS[(c >> (12-4*i)) & 0x0F]);
+ }
+ }
+
+ /**
* Escaped a String as described in section 4.4 in the PDF 1.3 specs.
* @param s String to escape
* @return String the escaped String
diff --git a/src/java/org/apache/fop/pdf/PDFTextUtil.java b/src/java/org/apache/fop/pdf/PDFTextUtil.java
index ed475fcb8..1b960ebb5 100644
--- a/src/java/org/apache/fop/pdf/PDFTextUtil.java
+++ b/src/java/org/apache/fop/pdf/PDFTextUtil.java
@@ -70,15 +70,26 @@ public abstract class PDFTextUtil {
*/
protected abstract void write(String code);
+ /**
+ * Writes PDF code.
+ * @param code the PDF code to write
+ */
+ protected abstract void write(StringBuffer code);
+
private void writeAffineTransform(AffineTransform at, StringBuffer sb) {
double[] lt = new double[6];
at.getMatrix(lt);
- sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[5], DEC));
+ PDFNumber.doubleOut(lt[0], DEC, sb);
+ sb.append(' ');
+ PDFNumber.doubleOut(lt[1], DEC, sb);
+ sb.append(' ');
+ PDFNumber.doubleOut(lt[2], DEC, sb);
+ sb.append(' ');
+ PDFNumber.doubleOut(lt[3], DEC, sb);
+ sb.append(' ');
+ PDFNumber.doubleOut(lt[4], DEC, sb);
+ sb.append(' ');
+ PDFNumber.doubleOut(lt[5], DEC, sb);
}
private static void writeChar(char ch, StringBuffer sb, boolean multibyte) {
@@ -90,14 +101,14 @@ public abstract class PDFTextUtil {
case '(':
case ')':
case '\\':
- sb.append("\\");
+ sb.append('\\');
break;
default:
}
sb.append(ch);
}
} else {
- sb.append(PDFText.toUnicodeHex(ch));
+ PDFText.toUnicodeHex(ch, sb);
}
}
@@ -160,7 +171,7 @@ public abstract class PDFTextUtil {
StringBuffer sb = new StringBuffer();
writeAffineTransform(at, sb);
sb.append(" cm\n");
- write(sb.toString());
+ write(sb);
}
}
@@ -171,8 +182,13 @@ public abstract class PDFTextUtil {
*/
public void writeTf(String fontName, double fontSize) {
checkInTextObject();
- write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
-
+ StringBuffer sb = new StringBuffer();
+ sb.append('/');
+ sb.append(fontName);
+ sb.append(' ');
+ PDFNumber.doubleOut(fontSize,6,sb);
+ sb.append(" Tf\n");
+ write(sb);
this.startText = useMultiByte ? "<" : "(";
this.endText = useMultiByte ? ">" : ")";
}
@@ -237,7 +253,7 @@ public abstract class PDFTextUtil {
StringBuffer sb = new StringBuffer();
writeAffineTransform(localTransform, sb);
sb.append(" Tm ");
- write(sb.toString());
+ write(sb);
}
/**
@@ -249,7 +265,7 @@ public abstract class PDFTextUtil {
bufTJ = new StringBuffer();
}
if (bufTJ.length() == 0) {
- bufTJ.append("[");
+ bufTJ.append('[');
bufTJ.append(startText);
}
writeChar(codepoint, bufTJ);
@@ -277,13 +293,13 @@ public abstract class PDFTextUtil {
bufTJ = new StringBuffer();
}
if (bufTJ.length() == 0) {
- bufTJ.append("[");
+ bufTJ.append('[');
} else {
bufTJ.append(endText);
- bufTJ.append(" ");
+ bufTJ.append(' ');
}
- bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4));
- bufTJ.append(" ");
+ PDFNumber.doubleOut(adjust, DEC - 4, bufTJ);
+ bufTJ.append(' ');
bufTJ.append(startText);
}
@@ -293,8 +309,9 @@ public abstract class PDFTextUtil {
*/
public void writeTJ() {
if (isInString()) {
- bufTJ.append(endText).append("] TJ\n");
- write(bufTJ.toString());
+ bufTJ.append(endText);
+ bufTJ.append("] TJ\n");
+ write(bufTJ);
bufTJ.setLength(0);
}
}
@@ -310,11 +327,11 @@ public abstract class PDFTextUtil {
*/
public void writeTd ( double x, double y ) {
StringBuffer sb = new StringBuffer();
- sb.append(PDFNumber.doubleOut(x, DEC));
+ PDFNumber.doubleOut(x, DEC, sb);
sb.append(' ');
- sb.append(PDFNumber.doubleOut(y, DEC));
- sb.append ( " Td\n" );
- write ( sb.toString() );
+ PDFNumber.doubleOut(y, DEC, sb);
+ sb.append(" Td\n");
+ write(sb);
}
/**
@@ -323,11 +340,11 @@ public abstract class PDFTextUtil {
*/
public void writeTj ( char ch ) {
StringBuffer sb = new StringBuffer();
- sb.append ( '<' );
- writeChar ( ch, sb, true );
- sb.append ( '>' );
- sb.append ( " Tj\n" );
- write ( sb.toString() );
+ sb.append('<');
+ writeChar(ch, sb, true);
+ sb.append('>');
+ sb.append(" Tj\n");
+ write(sb);
}
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
index f20339078..6235ceda9 100644
--- a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
+++ b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
@@ -80,6 +80,9 @@ public class PDFContentGenerator {
protected void write(String code) {
currentStream.add(code);
}
+ protected void write(StringBuffer code) {
+ currentStream.add(code);
+ }
};
this.currentState = new PDFPaintingState();
diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java
index 299bdc22f..ef376663f 100644
--- a/src/java/org/apache/fop/svg/PDFTextPainter.java
+++ b/src/java/org/apache/fop/svg/PDFTextPainter.java
@@ -90,10 +90,12 @@ class PDFTextPainter extends NativeTextPainter {
final PDFGraphics2D pdf = (PDFGraphics2D)g2d;
PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) {
- @Override
protected void write(String code) {
pdf.currentStream.write(code);
}
+ protected void write(StringBuffer code) {
+ pdf.currentStream.append(code);
+ }
};
if (DEBUG) {
diff --git a/status.xml b/status.xml
index 9df7abdbc..a566da0c3 100644
--- a/status.xml
+++ b/status.xml
@@ -59,6 +59,9 @@
documents. Example: the fix of marks layering will be such a case when it's done.
-->
<release version="FOP Trunk" date="TBD">
+ <action context="Renderers" dev="GA" type="fix" fixes-bug="FOP-2188">
+ Optimize string allocation in PDF output processing.
+ </action>
<action context="Renderers" dev="GA" type="fix" fixes-bug="FOP-2186">
Optimize inefficient glyph processing state update operations in CS path.
</action>