aboutsummaryrefslogtreecommitdiffstats
path: root/fop-core
diff options
context:
space:
mode:
authorSimon Steiner <ssteiner@apache.org>2016-08-15 14:15:27 +0000
committerSimon Steiner <ssteiner@apache.org>2016-08-15 14:15:27 +0000
commitbe0c18fc67b546056a8dc882ba760be41f690fe0 (patch)
treee23562c117d30ff5200343d18ef4403956a03c1b /fop-core
parentb40c1be43c0f464584670dddd265da19ab8d6ab0 (diff)
downloadxmlgraphics-fop-be0c18fc67b546056a8dc882ba760be41f690fe0.tar.gz
xmlgraphics-fop-be0c18fc67b546056a8dc882ba760be41f690fe0.zip
FOP-2642: Add optimize-resources for IF to PCL
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1756387 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'fop-core')
-rw-r--r--fop-core/src/main/java/org/apache/fop/fonts/CIDSubset.java3
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/Java2DRendererOption.java1
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/PCLDocumentHandler.java60
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/PCLGenerator.java24
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/PCLPainter.java21
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfig.java7
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java3
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/PCLRenderingUtil.java9
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtil.java33
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterDefinition.java19
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterWriter.java2
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReader.java5
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactory.java15
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLSoftFontManager.java147
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriter.java24
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFFontReader.java117
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/pcl/PCLPainterTestCase.java40
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/pcl/fonts/MockPCLTTFFontReader.java4
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtilTestCase.java21
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactoryTestCase.java3
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLTTFFontReaderTestCase.java9
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriterTestCase.java7
22 files changed, 362 insertions, 212 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/CIDSubset.java b/fop-core/src/main/java/org/apache/fop/fonts/CIDSubset.java
index 01b8495f8..e0fbdd6c2 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/CIDSubset.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/CIDSubset.java
@@ -22,6 +22,7 @@ package org.apache.fop.fonts;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.fop.util.CharUtilities;
@@ -40,7 +41,7 @@ public class CIDSubset implements CIDSet {
/**
* usedGlyphs contains orginal, new glyph index (glyph index -> char selector)
*/
- private Map<Integer, Integer> usedGlyphs = new HashMap<Integer, Integer>();
+ private Map<Integer, Integer> usedGlyphs = new LinkedHashMap<Integer, Integer>();
/**
* usedGlyphsIndex contains new glyph, original index (char selector -> glyph index)
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/Java2DRendererOption.java b/fop-core/src/main/java/org/apache/fop/render/pcl/Java2DRendererOption.java
index 9ec0b779b..7a0a4a77e 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/Java2DRendererOption.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/Java2DRendererOption.java
@@ -28,6 +28,7 @@ public enum Java2DRendererOption implements RendererConfigOption {
RENDERING_MODE("rendering", PCLRenderingMode.class),
TEXT_RENDERING("text-rendering", Boolean.class),
DISABLE_PJL("disable-pjl", Boolean.class),
+ OPTIMIZE_RESOURCES("optimize-resources", Boolean.class),
MODE_COLOR("color", Boolean.class);
private final String name;
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLDocumentHandler.java b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLDocumentHandler.java
index 66655a721..a4492b175 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLDocumentHandler.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLDocumentHandler.java
@@ -25,16 +25,26 @@ import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.Map;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.xmlgraphics.io.TempResourceURIGenerator;
import org.apache.xmlgraphics.util.UnitConv;
import org.apache.fop.apps.FopFactoryConfig;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
@@ -44,6 +54,7 @@ import org.apache.fop.render.java2d.Java2DPainter;
import org.apache.fop.render.java2d.Java2DUtil;
import org.apache.fop.render.pcl.PCLRendererConfig.PCLRendererConfigParser;
import org.apache.fop.render.pcl.extensions.PCLElementMapping;
+import org.apache.fop.render.pcl.fonts.PCLSoftFontManager;
/**
* {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation
@@ -55,6 +66,10 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
/** logging instance */
private static Log log = LogFactory.getLog(PCLDocumentHandler.class);
+ /** the temporary file in case of two-pass processing */
+ private URI tempURI;
+ private static final TempResourceURIGenerator TEMP_URI_GENERATOR = new TempResourceURIGenerator("pcl-optimize");
+
/** Utility class for handling all sorts of peripheral tasks around PCL generation. */
protected PCLRenderingUtil pclUtil;
@@ -127,7 +142,15 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
public void startDocument() throws IFException {
super.startDocument();
try {
- this.gen = new PCLGenerator(this.outputStream, getResolution());
+ final OutputStream out;
+ if (pclUtil.isOptimizeResources()) {
+ tempURI = TEMP_URI_GENERATOR.generate();
+ out = new BufferedOutputStream(getUserAgent().getResourceResolver().getOutputStream(tempURI));
+ } else {
+ out = this.outputStream;
+ }
+
+ this.gen = new PCLGenerator(out, getResolution());
this.gen.setDitheringQuality(pclUtil.getDitheringQuality());
if (!pclUtil.isPJLDisabled()) {
@@ -161,12 +184,47 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
if (!pclUtil.isPJLDisabled()) {
gen.universalEndOfLanguage();
}
+
+ if (pclUtil.isOptimizeResources()) {
+ IOUtils.closeQuietly(gen.getOutputStream());
+ rewritePCLFile();
+ }
} catch (IOException ioe) {
throw new IFException("I/O error in endDocument()", ioe);
}
super.endDocument();
}
+ private void rewritePCLFile() throws IOException {
+ InputStream in = new BufferedInputStream(getUserAgent().getResourceResolver().getResource(tempURI));
+ long offset = 0;
+ for (Map.Entry<PCLSoftFontManager, Map<Typeface, Long>> fontManagerMapEntry : gen.fontManagerMap.entrySet()) {
+ PCLSoftFontManager softFontManager = fontManagerMapEntry.getKey();
+ for (Map.Entry<Typeface, Long> fontEntry : fontManagerMapEntry.getValue().entrySet()) {
+ ByteArrayOutputStream fontData = softFontManager.makeSoftFont(fontEntry.getKey(), null);
+ long pos = fontEntry.getValue();
+ copy(in, pos - offset);
+ outputStream.write(fontData.toByteArray());
+ offset = pos;
+ }
+ }
+ copy(in, Long.MAX_VALUE);
+ this.outputStream.flush();
+ IOUtils.closeQuietly(in);
+ }
+
+ private void copy(InputStream is, long len) throws IOException {
+ while (len > 0) {
+ int bufsize = (int) Math.min(1024, len);
+ byte[] buf = new byte[bufsize];
+ if (is.read(buf) == -1) {
+ return;
+ }
+ outputStream.write(buf);
+ len -= bufsize;
+ }
+ }
+
/** {@inheritDoc} */
public void startPageSequence(String id) throws IFException {
//nop
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLGenerator.java b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLGenerator.java
index 589779ad9..6a4f3215e 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLGenerator.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLGenerator.java
@@ -39,13 +39,20 @@ import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Locale;
+import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.commons.io.output.CountingOutputStream;
import org.apache.xmlgraphics.util.UnitConv;
+import org.apache.fop.fonts.Typeface;
+import org.apache.fop.render.pcl.fonts.PCLFontReader;
+import org.apache.fop.render.pcl.fonts.PCLSoftFontManager;
import org.apache.fop.util.bitmap.BitmapImageUtil;
import org.apache.fop.util.bitmap.DitherUtil;
@@ -68,7 +75,10 @@ public class PCLGenerator {
private final DecimalFormat df2 = new DecimalFormat("0.##", symbols);
private final DecimalFormat df4 = new DecimalFormat("0.####", symbols);
- private final OutputStream out;
+ private final CountingOutputStream out;
+ protected Map<Typeface, PCLFontReader> fontReaderMap = new HashMap<Typeface, PCLFontReader>();
+ protected Map<PCLSoftFontManager, Map<Typeface, Long>> fontManagerMap
+ = new LinkedHashMap<PCLSoftFontManager, Map<Typeface, Long>>();
private boolean currentSourceTransparency = true;
private boolean currentPatternTransparency = true;
@@ -87,7 +97,7 @@ public class PCLGenerator {
* @param out the OutputStream to write the PCL stream to
*/
public PCLGenerator(OutputStream out) {
- this.out = out;
+ this.out = new CountingOutputStream(out);
}
/**
@@ -110,6 +120,16 @@ public class PCLGenerator {
this.maxBitmapResolution = maxResolution;
}
+ public void addFont(PCLSoftFontManager sfManager, Typeface font) {
+ if (!fontManagerMap.containsKey(sfManager)) {
+ fontManagerMap.put(sfManager, new LinkedHashMap<Typeface, Long>());
+ }
+ Map<Typeface, Long> fonts = fontManagerMap.get(sfManager);
+ if (!fonts.containsKey(font)) {
+ fonts.put(font, out.getByteCount());
+ }
+ }
+
/** @return the OutputStream that this generator writes to */
public OutputStream getOutputStream() {
return this.out;
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLPainter.java b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLPainter.java
index 65e996d08..60d6eb89f 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLPainter.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLPainter.java
@@ -85,8 +85,7 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
private Stack<GraphicContext> graphicContextStack = new Stack<GraphicContext>();
private GraphicContext graphicContext = new GraphicContext();
-
- private PCLSoftFontManager sfManager = new PCLSoftFontManager();
+ private PCLSoftFontManager sfManager;
/**
* Main constructor.
@@ -338,12 +337,20 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
} else {
// TrueType conversion to a soft font (PCL 5 Technical Reference - Chapter 11)
if (!drawAsBitmaps && isTrueType(tf)) {
- boolean madeSF = false;
- if (sfManager.getSoftFont(tf, text) == null) {
- madeSF = true;
- ByteArrayOutputStream baos = sfManager.makeSoftFont(tf);
+ if (sfManager == null) {
+ sfManager = new PCLSoftFontManager(gen.fontReaderMap);
+ }
+ if (getPCLUtil().isOptimizeResources() || sfManager.getSoftFont(tf, text) == null) {
+ for (char c : text.toCharArray()) {
+ tf.mapChar(c);
+ }
+ ByteArrayOutputStream baos = sfManager.makeSoftFont(tf, text);
if (baos != null) {
- gen.writeBytes(baos.toByteArray());
+ if (getPCLUtil().isOptimizeResources()) {
+ gen.addFont(sfManager, tf);
+ } else {
+ gen.writeBytes(baos.toByteArray());
+ }
}
}
String formattedSize = gen.formatDouble2(state.getFontSize() / 1000.0);
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfig.java b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfig.java
index 30429a7c5..06aebba71 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfig.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfig.java
@@ -34,6 +34,7 @@ import org.apache.fop.render.RendererConfig;
import static org.apache.fop.render.pcl.Java2DRendererOption.DISABLE_PJL;
import static org.apache.fop.render.pcl.Java2DRendererOption.MODE_COLOR;
+import static org.apache.fop.render.pcl.Java2DRendererOption.OPTIMIZE_RESOURCES;
import static org.apache.fop.render.pcl.Java2DRendererOption.RENDERING_MODE;
import static org.apache.fop.render.pcl.Java2DRendererOption.TEXT_RENDERING;
@@ -71,6 +72,10 @@ public final class PCLRendererConfig implements RendererConfig {
return getParam(MODE_COLOR, Boolean.class);
}
+ public Boolean isOptimizeResources() {
+ return getParam(OPTIMIZE_RESOURCES, Boolean.class);
+ }
+
private <T> T getParam(Java2DRendererOption option, Class<T> type) {
assert option.getType().equals(type);
return type.cast(params.get(option));
@@ -124,6 +129,8 @@ public final class PCLRendererConfig implements RendererConfig {
}
config.setParam(DISABLE_PJL,
cfg.getChild(DISABLE_PJL.getName()).getValueAsBoolean(false));
+ config.setParam(OPTIMIZE_RESOURCES,
+ cfg.getChild(OPTIMIZE_RESOURCES.getName()).getValueAsBoolean(false));
}
}
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java
index 7a92b7408..1641055dd 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java
@@ -70,6 +70,9 @@ public class PCLRendererConfigurator extends PrintRendererConfigurator {
if (config.isColorEnabled() != null) {
pclUtil.setColorEnabled(config.isColorEnabled());
}
+ if (config.isOptimizeResources() != null) {
+ pclUtil.setOptimizeResources(config.isOptimizeResources());
+ }
}
@Override
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRenderingUtil.java b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRenderingUtil.java
index 674605bde..0c4fb522f 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRenderingUtil.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/PCLRenderingUtil.java
@@ -51,6 +51,7 @@ public class PCLRenderingUtil {
private float ditheringQuality = 0.5f;
private boolean useColor;
+ private boolean optimizeResources;
/**
* Controls whether the generation of PJL commands gets disabled.
@@ -228,4 +229,12 @@ public class PCLRenderingUtil {
return transPoint;
}
+ public boolean isOptimizeResources() {
+ return optimizeResources;
+ }
+
+ public void setOptimizeResources(boolean b) {
+ optimizeResources = b;
+ }
+
}
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtil.java b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtil.java
index 1b9382f7b..3a5d68602 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtil.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtil.java
@@ -23,13 +23,16 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
-public class PCLByteWriterUtil {
+public final class PCLByteWriterUtil {
- public byte[] padBytes(byte[] in, int length) {
+ private PCLByteWriterUtil() {
+ }
+
+ public static byte[] padBytes(byte[] in, int length) {
return padBytes(in, length, 0);
}
- public byte[] padBytes(byte[] in, int length, int value) {
+ public static byte[] padBytes(byte[] in, int length, int value) {
byte[] out = new byte[length];
for (int i = 0; i < length; i++) {
if (i < in.length) {
@@ -41,21 +44,21 @@ public class PCLByteWriterUtil {
return out;
}
- public byte[] signedInt(int s) {
+ public static byte[] signedInt(int s) {
byte b1 = (byte) (s >> 8);
byte b2 = (byte) s;
return new byte[]{b1, b2};
}
- public byte signedByte(int s) {
+ public static byte signedByte(int s) {
return (byte) s;
}
- public byte[] unsignedLongInt(int s) {
+ public static byte[] unsignedLongInt(int s) {
return unsignedLongInt((long) s);
}
- public byte[] unsignedLongInt(long s) {
+ public static byte[] unsignedLongInt(long s) {
byte b1 = (byte) ((s >> 24) & 0xff);
byte b2 = (byte) ((s >> 16) & 0xff);
byte b3 = (byte) ((s >> 8) & 0xff);
@@ -63,17 +66,17 @@ public class PCLByteWriterUtil {
return new byte[]{b1, b2, b3, b4};
}
- public byte[] unsignedInt(int s) {
+ public static byte[] unsignedInt(int s) {
byte b1 = (byte) ((s >> 8) & 0xff);
byte b2 = (byte) (s & 0xff);
return new byte[]{b1, b2};
}
- public int unsignedByte(int b) {
+ public static int unsignedByte(int b) {
return (byte) b & 0xFF;
}
- public int maxPower2(int value) {
+ public static int maxPower2(int value) {
int test = 2;
while (test < value) {
test *= 2;
@@ -81,11 +84,11 @@ public class PCLByteWriterUtil {
return test;
}
- public int log(int x, int base) {
+ public static int log(int x, int base) {
return (int) (Math.log(x) / Math.log(base));
}
- public byte[] toByteArray(int[] s) {
+ public static byte[] toByteArray(int[] s) {
byte[] values = new byte[s.length];
for (int i = 0; i < s.length; i++) {
values[i] = (byte) s[i];
@@ -93,7 +96,7 @@ public class PCLByteWriterUtil {
return values;
}
- public byte[] insertIntoArray(int index, byte[] insertTo, byte[] data) throws IOException {
+ public static byte[] insertIntoArray(int index, byte[] insertTo, byte[] data) throws IOException {
byte[] preBytes = Arrays.copyOf(insertTo, index);
byte[] postBytes = Arrays.copyOfRange(insertTo, index, insertTo.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -103,7 +106,7 @@ public class PCLByteWriterUtil {
return baos.toByteArray();
}
- public byte[] updateDataAtLocation(byte[] data, byte[] update, int offset) {
+ public static byte[] updateDataAtLocation(byte[] data, byte[] update, int offset) {
int count = 0;
for (int i = offset; i < offset + update.length; i++) {
data[i] = update[count++];
@@ -116,7 +119,7 @@ public class PCLByteWriterUtil {
* @param cmd the command (without the ESCAPE character)
* @throws IOException In case of an I/O error
*/
- public byte[] writeCommand(String cmd) throws IOException {
+ public static byte[] writeCommand(String cmd) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(27); // ESC
baos.write(cmd.getBytes("US-ASCII"));
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterDefinition.java b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterDefinition.java
index c275084dc..3c4053c72 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterDefinition.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterDefinition.java
@@ -31,18 +31,15 @@ public class PCLCharacterDefinition {
private boolean hasContinuation;
private PCLCharacterFormat charFormat;
private PCLCharacterClass charClass;
- private PCLByteWriterUtil pclByteWriter;
private List<PCLCharacterDefinition> composites;
private boolean isComposite;
public PCLCharacterDefinition(int charCode, PCLCharacterFormat charFormat,
- PCLCharacterClass charClass, byte[] glyfData, PCLByteWriterUtil pclByteWriter,
- boolean isComposite) {
+ PCLCharacterClass charClass, byte[] glyfData, boolean isComposite) {
this.charCode = charCode;
this.charFormat = charFormat;
this.charClass = charClass;
this.glyfData = glyfData;
- this.pclByteWriter = pclByteWriter;
this.isComposite = isComposite;
// Glyph Data + (Descriptor Size) + (Character Data Size) + (Glyph ID) must
// be less than 32767 otherwise it will result in a continuation structure.
@@ -52,11 +49,11 @@ public class PCLCharacterDefinition {
}
public byte[] getCharacterCommand() throws IOException {
- return pclByteWriter.writeCommand(String.format("*c%dE", (isComposite) ? 65535 : charCode));
+ return PCLByteWriterUtil.writeCommand(String.format("*c%dE", (isComposite) ? 65535 : charCode));
}
public byte[] getCharacterDefinitionCommand() throws IOException {
- return pclByteWriter.writeCommand(String.format("(s%dW", 10 + glyfData.length));
+ return PCLByteWriterUtil.writeCommand(String.format("(s%dW", 10 + glyfData.length));
}
public byte[] getData() throws IOException {
@@ -89,12 +86,12 @@ public class PCLCharacterDefinition {
}
private void writeCharacterDescriptorHeader(int continuation, ByteArrayOutputStream baos) throws IOException {
- baos.write(pclByteWriter.unsignedByte(charFormat.getValue()));
+ baos.write(PCLByteWriterUtil.unsignedByte(charFormat.getValue()));
baos.write(continuation);
- baos.write(pclByteWriter.unsignedByte(2)); // Descriptor size (from this byte to character data)
- baos.write(pclByteWriter.unsignedByte(charClass.getValue()));
- baos.write(pclByteWriter.unsignedInt(glyfData.length + 4));
- baos.write(pclByteWriter.unsignedInt(charCode));
+ baos.write(PCLByteWriterUtil.unsignedByte(2)); // Descriptor size (from this byte to character data)
+ baos.write(PCLByteWriterUtil.unsignedByte(charClass.getValue()));
+ baos.write(PCLByteWriterUtil.unsignedInt(glyfData.length + 4));
+ baos.write(PCLByteWriterUtil.unsignedInt(charCode));
}
public void addCompositeGlyph(PCLCharacterDefinition composite) {
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterWriter.java b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterWriter.java
index df04371e0..51e067980 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterWriter.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLCharacterWriter.java
@@ -27,7 +27,6 @@ import org.apache.fop.fonts.truetype.OpenFont;
public abstract class PCLCharacterWriter {
protected PCLSoftFont font;
- protected PCLByteWriterUtil pclByteWriter;
protected OpenFont openFont;
protected FontFileReader fontReader;
@@ -35,7 +34,6 @@ public abstract class PCLCharacterWriter {
this.font = font;
openFont = font.getOpenFont();
fontReader = font.getReader();
- pclByteWriter = new PCLByteWriterUtil();
}
public abstract byte[] writeCharacterDefinitions(String text) throws IOException;
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReader.java b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReader.java
index 6bd5192ac..b0b95f34b 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReader.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReader.java
@@ -31,12 +31,10 @@ import org.apache.fop.fonts.truetype.OpenFont;
public abstract class PCLFontReader {
protected Typeface typeface;
- protected PCLByteWriterUtil pclByteWriter;
protected CustomFont font;
- public PCLFontReader(Typeface font, PCLByteWriterUtil pclByteWriter) {
+ public PCLFontReader(Typeface font) {
this.typeface = font;
- this.pclByteWriter = pclByteWriter;
}
public void setFont(CustomFont mbFont) {
@@ -81,6 +79,7 @@ public abstract class PCLFontReader {
public abstract int getMasterUnderlineThickness() throws IOException;
public abstract int getFontScalingTechnology();
public abstract int getVariety();
+ public abstract Map<Integer, Integer> scanMtxCharacters() throws IOException;
/** Segmented Font Data **/
public abstract List<PCLFontSegment> getFontSegments(Map<Character, Integer> mappedGlyphs)
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactory.java b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactory.java
index 15c4e8d54..aced97a99 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactory.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactory.java
@@ -31,19 +31,12 @@ import org.apache.fop.render.pcl.fonts.truetype.PCLTTFFontReader;
public final class PCLFontReaderFactory {
- private PCLByteWriterUtil pclByteWriter;
-
- private PCLFontReaderFactory(PCLByteWriterUtil pclByteWriter) {
- this.pclByteWriter = pclByteWriter;
- }
-
- public static PCLFontReaderFactory getInstance(PCLByteWriterUtil pclByteWriter) {
- return new PCLFontReaderFactory(pclByteWriter);
+ private PCLFontReaderFactory() {
}
- public PCLFontReader createInstance(Typeface font) throws IOException {
+ public static PCLFontReader createInstance(Typeface font) throws IOException {
if (font.getFontType() == FontType.TRUETYPE || isCIDType2(font)) {
- return new PCLTTFFontReader(font, pclByteWriter);
+ return new PCLTTFFontReader(font);
}
// else if (font instanceof MultiByteFont && ((MultiByteFont) font).isOTFFile()) {
// Placeholder for future Type 1 / OTF Soft font implementations e.g.
@@ -52,7 +45,7 @@ public final class PCLFontReaderFactory {
return null;
}
- private boolean isCIDType2(Typeface font) {
+ private static boolean isCIDType2(Typeface font) {
CustomFontMetricsMapper fontMetrics = (CustomFontMetricsMapper) font;
CustomFont customFont = (CustomFont) fontMetrics.getRealFont();
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLSoftFontManager.java b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLSoftFontManager.java
index 621ea4f18..42616581e 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLSoftFontManager.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLSoftFontManager.java
@@ -21,8 +21,10 @@ package org.apache.fop.render.pcl.fonts;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -32,35 +34,37 @@ import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.java2d.CustomFontMetricsMapper;
public class PCLSoftFontManager {
- private ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ private Map<Typeface, PCLFontReader> fontReaderMap;
private PCLFontReader fontReader;
- private PCLByteWriterUtil pclByteWriter = new PCLByteWriterUtil();
private List<PCLSoftFont> fonts = new ArrayList<PCLSoftFont>();
- private PCLFontReaderFactory fontReaderFactory;
private static final int SOFT_FONT_SIZE = 255;
- public ByteArrayOutputStream makeSoftFont(Typeface font) throws IOException {
+ public PCLSoftFontManager(Map<Typeface, PCLFontReader> fontReaderMap) {
+ this.fontReaderMap = fontReaderMap;
+ }
+
+ public ByteArrayOutputStream makeSoftFont(Typeface font, String text) throws IOException {
List<Map<Character, Integer>> mappedGlyphs = mapFontGlyphs(font);
- if (fontReaderFactory == null) {
- fontReaderFactory = PCLFontReaderFactory.getInstance(pclByteWriter);
+ if (!fontReaderMap.containsKey(font)) {
+ fontReaderMap.put(font, PCLFontReaderFactory.createInstance(font));
}
- fontReader = fontReaderFactory.createInstance(font);
- initialize();
+ fontReader = fontReaderMap.get(font);
if (mappedGlyphs.isEmpty()) {
mappedGlyphs.add(new HashMap<Character, Integer>());
}
if (fontReader != null) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PCLSoftFont softFont = null;
for (Map<Character, Integer> glyphSet : mappedGlyphs) {
- PCLSoftFont softFont = new PCLSoftFont(fonts.size() + 1, font,
- mappedGlyphs.get(0).size() != 0);
+ softFont = getSoftFont(font, text, mappedGlyphs, softFont);
softFont.setMappedChars(glyphSet);
- assignFontID();
- writeFontHeader(softFont.getMappedChars());
+ writeFontID(softFont.getFontID(), baos);
+ writeFontHeader(softFont.getMappedChars(), baos);
softFont.setCharacterOffsets(fontReader.getCharacterOffsets());
softFont.setOpenFont(fontReader.getFontFile());
softFont.setReader(fontReader.getFontFileReader());
- fonts.add(softFont);
+ softFont.setMtxCharIndexes(fontReader.scanMtxCharacters());
}
return baos;
} else {
@@ -68,6 +72,29 @@ public class PCLSoftFontManager {
}
}
+ private PCLSoftFont getSoftFont(Typeface font, String text, List<Map<Character, Integer>> mappedGlyphs,
+ PCLSoftFont last) {
+ if (text == null) {
+ Iterator<PCLSoftFont> fontIterator = fonts.iterator();
+ while (fontIterator.hasNext()) {
+ PCLSoftFont sftFont = fontIterator.next();
+ if (sftFont.getTypeface().equals(font)) {
+ fontIterator.remove();
+ return sftFont;
+ }
+ }
+ }
+ for (PCLSoftFont sftFont : fonts) {
+ if (sftFont.getTypeface().equals(font) && sftFont != last
+ && (sftFont.getCharCount() + countNonMatches(sftFont, text)) < SOFT_FONT_SIZE) {
+ return sftFont;
+ }
+ }
+ PCLSoftFont f = new PCLSoftFont(fonts.size() + 1, font, mappedGlyphs.get(0).size() != 0);
+ fonts.add(f);
+ return f;
+ }
+
private List<Map<Character, Integer>> mapFontGlyphs(Typeface tf) {
List<Map<Character, Integer>> mappedGlyphs = new ArrayList<Map<Character, Integer>>();
if (tf instanceof CustomFontMetricsMapper) {
@@ -101,63 +128,59 @@ public class PCLSoftFontManager {
return mappedGlyphs;
}
- private void initialize() {
- baos.reset();
- }
-
- private void assignFontID() throws IOException {
- baos.write(assignFontID(fonts.size() + 1));
+ private void writeFontID(int fontID, OutputStream os) throws IOException {
+ os.write(assignFontID(fontID));
}
public byte[] assignFontID(int fontID) throws IOException {
- return pclByteWriter.writeCommand(String.format("*c%dD", fontID));
+ return PCLByteWriterUtil.writeCommand(String.format("*c%dD", fontID));
}
- private void writeFontHeader(Map<Character, Integer> mappedGlyphs) throws IOException {
+ private void writeFontHeader(Map<Character, Integer> mappedGlyphs, OutputStream os) throws IOException {
ByteArrayOutputStream header = new ByteArrayOutputStream();
- header.write(pclByteWriter.unsignedInt(fontReader.getDescriptorSize()));
- header.write(pclByteWriter.unsignedByte(fontReader.getHeaderFormat()));
- header.write(pclByteWriter.unsignedByte(fontReader.getFontType()));
- header.write(pclByteWriter.unsignedByte(fontReader.getStyleMSB()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getDescriptorSize()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getHeaderFormat()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getFontType()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getStyleMSB()));
header.write(0); // Reserved
- header.write(pclByteWriter.unsignedInt(fontReader.getBaselinePosition()));
- header.write(pclByteWriter.unsignedInt(fontReader.getCellWidth()));
- header.write(pclByteWriter.unsignedInt(fontReader.getCellHeight()));
- header.write(pclByteWriter.unsignedByte(fontReader.getOrientation()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getBaselinePosition()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getCellWidth()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getCellHeight()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getOrientation()));
header.write(fontReader.getSpacing());
- header.write(pclByteWriter.unsignedInt(fontReader.getSymbolSet()));
- header.write(pclByteWriter.unsignedInt(fontReader.getPitch()));
- header.write(pclByteWriter.unsignedInt(fontReader.getHeight()));
- header.write(pclByteWriter.unsignedInt(fontReader.getXHeight()));
- header.write(pclByteWriter.signedByte(fontReader.getWidthType()));
- header.write(pclByteWriter.unsignedByte(fontReader.getStyleLSB()));
- header.write(pclByteWriter.signedByte(fontReader.getStrokeWeight()));
- header.write(pclByteWriter.unsignedByte(fontReader.getTypefaceLSB()));
- header.write(pclByteWriter.unsignedByte(fontReader.getTypefaceMSB()));
- header.write(pclByteWriter.unsignedByte(fontReader.getSerifStyle()));
- header.write(pclByteWriter.unsignedByte(fontReader.getQuality()));
- header.write(pclByteWriter.signedByte(fontReader.getPlacement()));
- header.write(pclByteWriter.signedByte(fontReader.getUnderlinePosition()));
- header.write(pclByteWriter.unsignedByte(fontReader.getUnderlineThickness()));
- header.write(pclByteWriter.unsignedInt(fontReader.getTextHeight()));
- header.write(pclByteWriter.unsignedInt(fontReader.getTextWidth()));
- header.write(pclByteWriter.unsignedInt(fontReader.getFirstCode()));
- header.write(pclByteWriter.unsignedInt(fontReader.getLastCode()));
- header.write(pclByteWriter.unsignedByte(fontReader.getPitchExtended()));
- header.write(pclByteWriter.unsignedByte(fontReader.getHeightExtended()));
- header.write(pclByteWriter.unsignedInt(fontReader.getCapHeight()));
- header.write(pclByteWriter.unsignedLongInt(fontReader.getFontNumber()));
- header.write(pclByteWriter.padBytes(fontReader.getFontName().getBytes("US-ASCII"), 16, 32));
- header.write(pclByteWriter.unsignedInt(fontReader.getScaleFactor()));
- header.write(pclByteWriter.signedInt(fontReader.getMasterUnderlinePosition()));
- header.write(pclByteWriter.unsignedInt(fontReader.getMasterUnderlineThickness()));
- header.write(pclByteWriter.unsignedByte(fontReader.getFontScalingTechnology()));
- header.write(pclByteWriter.unsignedByte(fontReader.getVariety()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getSymbolSet()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getPitch()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getHeight()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getXHeight()));
+ header.write(PCLByteWriterUtil.signedByte(fontReader.getWidthType()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getStyleLSB()));
+ header.write(PCLByteWriterUtil.signedByte(fontReader.getStrokeWeight()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getTypefaceLSB()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getTypefaceMSB()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getSerifStyle()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getQuality()));
+ header.write(PCLByteWriterUtil.signedByte(fontReader.getPlacement()));
+ header.write(PCLByteWriterUtil.signedByte(fontReader.getUnderlinePosition()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getUnderlineThickness()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getTextHeight()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getTextWidth()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getFirstCode()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getLastCode()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getPitchExtended()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getHeightExtended()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getCapHeight()));
+ header.write(PCLByteWriterUtil.unsignedLongInt(fontReader.getFontNumber()));
+ header.write(PCLByteWriterUtil.padBytes(fontReader.getFontName().getBytes("US-ASCII"), 16, 32));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getScaleFactor()));
+ header.write(PCLByteWriterUtil.signedInt(fontReader.getMasterUnderlinePosition()));
+ header.write(PCLByteWriterUtil.unsignedInt(fontReader.getMasterUnderlineThickness()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getFontScalingTechnology()));
+ header.write(PCLByteWriterUtil.unsignedByte(fontReader.getVariety()));
writeSegmentedFontData(header, mappedGlyphs);
- baos.write(getFontHeaderCommand(header.size()));
- baos.write(header.toByteArray());
+ os.write(getFontHeaderCommand(header.size()));
+ os.write(header.toByteArray());
}
private void writeSegmentedFontData(ByteArrayOutputStream header,
@@ -178,12 +201,12 @@ public class PCLSoftFontManager {
}
private byte[] getFontHeaderCommand(int headerSize) throws IOException {
- return pclByteWriter.writeCommand(String.format(")s%dW", headerSize));
+ return PCLByteWriterUtil.writeCommand(String.format(")s%dW", headerSize));
}
private void writeFontSegment(ByteArrayOutputStream header, PCLFontSegment segment) throws IOException {
- header.write(pclByteWriter.unsignedInt(segment.getIdentifier().getValue()));
- header.write(pclByteWriter.unsignedInt(segment.getData().length));
+ header.write(PCLByteWriterUtil.unsignedInt(segment.getIdentifier().getValue()));
+ header.write(PCLByteWriterUtil.unsignedInt(segment.getData().length));
header.write(segment.getData());
}
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriter.java b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriter.java
index 41fefaaf0..d09048bc0 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriter.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriter.java
@@ -44,7 +44,6 @@ public class PCLTTFCharacterWriter extends PCLCharacterWriter {
public PCLTTFCharacterWriter(PCLSoftFont softFont) throws IOException {
super(softFont);
- softFont.setMtxCharIndexes(scanMtxCharacters());
}
@Override
@@ -70,25 +69,6 @@ public class PCLTTFCharacterWriter extends PCLCharacterWriter {
baos.write(pclChar.getData());
}
- private Map<Integer, Integer> scanMtxCharacters() throws IOException {
- Map<Integer, Integer> charMtxOffsets = new HashMap<Integer, Integer>();
- List<OFMtxEntry> mtx = openFont.getMtx();
- OFTableName glyfTag = OFTableName.GLYF;
- if (openFont.seekTab(fontReader, glyfTag, 0)) {
- for (int i = 1; i < mtx.size(); i++) {
- OFMtxEntry entry = mtx.get(i);
- int charCode = 0;
- if (entry.getUnicodeIndex().size() > 0) {
- charCode = (Integer) entry.getUnicodeIndex().get(0);
- } else {
- charCode = entry.getIndex();
- }
- charMtxOffsets.put(charCode, i);
- }
- }
- return charMtxOffsets;
- }
-
private PCLCharacterDefinition getCharacterDefinition(int unicode) throws IOException {
if (mtx == null) {
mtx = openFont.getMtx();
@@ -112,7 +92,7 @@ public class PCLTTFCharacterWriter extends PCLCharacterWriter {
PCLCharacterDefinition newChar = new PCLCharacterDefinition(
font.getCharCode((char) unicode),
PCLCharacterFormat.TrueType,
- PCLCharacterClass.TrueType, glyphData, pclByteWriter, false);
+ PCLCharacterClass.TrueType, glyphData, false);
// Handle composite character definitions
GlyfTable glyfTable = new GlyfTable(fontReader, mtx.toArray(new OFMtxEntry[mtx.size()]),
@@ -123,7 +103,7 @@ public class PCLTTFCharacterWriter extends PCLCharacterWriter {
byte[] compositeData = getGlyphData(compositeIndex);
newChar.addCompositeGlyph(new PCLCharacterDefinition(compositeIndex,
PCLCharacterFormat.TrueType,
- PCLCharacterClass.TrueType, compositeData, pclByteWriter, true));
+ PCLCharacterClass.TrueType, compositeData, true));
}
}
diff --git a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFFontReader.java b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFFontReader.java
index 35e37f23f..6839bf948 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFFontReader.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFFontReader.java
@@ -55,6 +55,8 @@ public class PCLTTFFontReader extends PCLFontReader {
private PCLTTFOS2FontTable os2Table;
private PCLTTFPOSTFontTable postTable;
private PCLTTFTableFactory ttfTableFactory;
+ private Map<Integer, int[]> charOffsets;
+ private Map<Integer, Integer> charMtxOffsets;
private static final int HMTX_RESTRICT_SIZE = 50000;
@@ -115,8 +117,8 @@ public class PCLTTFFontReader extends PCLFontReader {
private int scaleFactor = -1;
private PCLSymbolSet symbolSet = PCLSymbolSet.Bound_Generic;
- public PCLTTFFontReader(Typeface font, PCLByteWriterUtil pclByteWriter) throws IOException {
- super(font, pclByteWriter);
+ public PCLTTFFontReader(Typeface font) throws IOException {
+ super(font);
loadFont();
}
@@ -461,7 +463,7 @@ public class PCLTTFFontReader extends PCLFontReader {
throws IOException {
List<PCLFontSegment> fontSegments = new ArrayList<PCLFontSegment>();
fontSegments.add(new PCLFontSegment(SegmentID.CC, getCharacterComplement()));
- fontSegments.add(new PCLFontSegment(SegmentID.PA, pclByteWriter.toByteArray(os2Table.getPanose())));
+ fontSegments.add(new PCLFontSegment(SegmentID.PA, PCLByteWriterUtil.toByteArray(os2Table.getPanose())));
fontSegments.add(new PCLFontSegment(SegmentID.GT, getGlobalTrueTypeData(mappedGlyphs)));
fontSegments.add(new PCLFontSegment(SegmentID.CP, ttfFont.getCopyrightNotice().getBytes("US-ASCII")));
fontSegments.add(new PCLFontSegment(SegmentID.NULL, new byte[0]));
@@ -484,8 +486,8 @@ public class PCLTTFFontReader extends PCLFontReader {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
List<TableOffset> tableOffsets = new ArrayList<TableOffset>();
// Version
- baos.write(pclByteWriter.unsignedInt(1)); // Major
- baos.write(pclByteWriter.unsignedInt(0)); // Minor
+ baos.write(PCLByteWriterUtil.unsignedInt(1)); // Major
+ baos.write(PCLByteWriterUtil.unsignedInt(0)); // Minor
int numTables = 5; // head, hhea, hmtx, maxp and gdir
// Optional Hint Tables
OFDirTabEntry headTable = ttfFont.getDirectoryEntry(OFTableName.CVT);
@@ -500,12 +502,12 @@ public class PCLTTFFontReader extends PCLFontReader {
if (prepTable != null) {
numTables++;
}
- baos.write(pclByteWriter.unsignedInt(numTables)); // numTables
- int maxPowerNumTables = pclByteWriter.maxPower2(numTables);
+ baos.write(PCLByteWriterUtil.unsignedInt(numTables)); // numTables
+ int maxPowerNumTables = PCLByteWriterUtil.maxPower2(numTables);
int searchRange = maxPowerNumTables * 16;
- baos.write(pclByteWriter.unsignedInt(searchRange));
- baos.write(pclByteWriter.unsignedInt(pclByteWriter.log(maxPowerNumTables, 2))); // Entry Selector
- baos.write(pclByteWriter.unsignedInt(numTables * 16 - searchRange)); // Range shift
+ baos.write(PCLByteWriterUtil.unsignedInt(searchRange));
+ baos.write(PCLByteWriterUtil.unsignedInt(PCLByteWriterUtil.log(maxPowerNumTables, 2))); // Entry Selector
+ baos.write(PCLByteWriterUtil.unsignedInt(numTables * 16 - searchRange)); // Range shift
// Add default data tables
writeTrueTypeTable(baos, OFTableName.HEAD, tableOffsets);
@@ -555,20 +557,20 @@ public class PCLTTFFontReader extends PCLFontReader {
OFDirTabEntry tabEntry = ttfFont.getDirectoryEntry(table);
if (tabEntry != null) {
baos.write(tabEntry.getTag());
- baos.write(pclByteWriter.unsignedLongInt(tabEntry.getChecksum()));
+ baos.write(PCLByteWriterUtil.unsignedLongInt(tabEntry.getChecksum()));
TableOffset newTableOffset = new TableOffset(tabEntry.getOffset(),
tabEntry.getLength(), baos.size());
tableOffsets.add(newTableOffset);
- baos.write(pclByteWriter.unsignedLongInt(0)); // Offset to be set later
- baos.write(pclByteWriter.unsignedLongInt(tabEntry.getLength()));
+ baos.write(PCLByteWriterUtil.unsignedLongInt(0)); // Offset to be set later
+ baos.write(PCLByteWriterUtil.unsignedLongInt(tabEntry.getLength()));
}
}
private void writeGDIR(ByteArrayOutputStream baos) throws UnsupportedEncodingException, IOException {
baos.write("gdir".getBytes("ISO-8859-1"));
- baos.write(pclByteWriter.unsignedLongInt(0)); // Checksum
- baos.write(pclByteWriter.unsignedLongInt(0)); // Offset
- baos.write(pclByteWriter.unsignedLongInt(0)); // Length
+ baos.write(PCLByteWriterUtil.unsignedLongInt(0)); // Checksum
+ baos.write(PCLByteWriterUtil.unsignedLongInt(0)); // Offset
+ baos.write(PCLByteWriterUtil.unsignedLongInt(0)); // Length
}
private ByteArrayOutputStream copyTables(List<TableOffset> tableOffsets,
@@ -576,7 +578,7 @@ public class PCLTTFFontReader extends PCLFontReader {
throws IOException {
Map<Integer, byte[]> offsetValues = new HashMap<Integer, byte[]>();
for (TableOffset tableOffset : tableOffsets) {
- offsetValues.put(tableOffset.getNewOffset(), pclByteWriter.unsignedLongInt(baos.size()));
+ offsetValues.put(tableOffset.getNewOffset(), PCLByteWriterUtil.unsignedLongInt(baos.size()));
if (tableOffset.getOriginOffset() == -1) { // Update the offset in the table directory
baos.write(hmtxTable);
} else {
@@ -604,7 +606,7 @@ public class PCLTTFFontReader extends PCLFontReader {
throws IOException {
byte[] softFont = baos.toByteArray();
for (int offset : offsets.keySet()) {
- pclByteWriter.updateDataAtLocation(softFont, offsets.get(offset), offset);
+ PCLByteWriterUtil.updateDataAtLocation(softFont, offsets.get(offset), offset);
}
baos = new ByteArrayOutputStream();
baos.write(softFont);
@@ -613,32 +615,34 @@ public class PCLTTFFontReader extends PCLFontReader {
@Override
public Map<Integer, int[]> getCharacterOffsets() throws IOException {
- List<OFMtxEntry> mtx = ttfFont.getMtx();
- OFTableName glyfTag = OFTableName.GLYF;
- Map<Integer, int[]> charOffsets = new HashMap<Integer, int[]>();
- OFDirTabEntry tabEntry = ttfFont.getDirectoryEntry(glyfTag);
- if (ttfFont.seekTab(reader, glyfTag, 0)) {
- for (int i = 1; i < mtx.size(); i++) {
- OFMtxEntry entry = mtx.get(i);
- OFMtxEntry nextEntry;
- int nextOffset = 0;
- int charCode = 0;
- if (entry.getUnicodeIndex().size() > 0) {
- charCode = (Integer) entry.getUnicodeIndex().get(0);
- } else {
- charCode = entry.getIndex();
+ if (charOffsets == null) {
+ List<OFMtxEntry> mtx = ttfFont.getMtx();
+ OFTableName glyfTag = OFTableName.GLYF;
+ charOffsets = new HashMap<Integer, int[]>();
+ OFDirTabEntry tabEntry = ttfFont.getDirectoryEntry(glyfTag);
+ if (ttfFont.seekTab(reader, glyfTag, 0)) {
+ for (int i = 1; i < mtx.size(); i++) {
+ OFMtxEntry entry = mtx.get(i);
+ OFMtxEntry nextEntry;
+ int nextOffset = 0;
+ int charCode = 0;
+ if (entry.getUnicodeIndex().size() > 0) {
+ charCode = (Integer) entry.getUnicodeIndex().get(0);
+ } else {
+ charCode = entry.getIndex();
+ }
+
+ if (i < mtx.size() - 1) {
+ nextEntry = mtx.get(i + 1);
+ nextOffset = (int) nextEntry.getOffset();
+ } else {
+ nextOffset = (int) ttfFont.getLastGlyfLocation();
+ }
+ int glyphOffset = (int) entry.getOffset();
+ int glyphLength = nextOffset - glyphOffset;
+
+ charOffsets.put(charCode, new int[]{(int) tabEntry.getOffset() + glyphOffset, glyphLength});
}
-
- if (i < mtx.size() - 1) {
- nextEntry = mtx.get(i + 1);
- nextOffset = (int) nextEntry.getOffset();
- } else {
- nextOffset = (int) ttfFont.getLastGlyfLocation();
- }
- int glyphOffset = (int) entry.getOffset();
- int glyphLength = nextOffset - glyphOffset;
-
- charOffsets.put(charCode, new int[]{(int) tabEntry.getOffset() + glyphOffset, glyphLength});
}
}
return charOffsets;
@@ -660,11 +664,11 @@ public class PCLTTFFontReader extends PCLFontReader {
if (tabEntry != null) {
baos.write(tabEntry.getTag());
// Override the original checksum for the subset version
- baos.write(pclByteWriter.unsignedLongInt(getCheckSum(hmtxTable, 0, hmtxTable.length)));
+ baos.write(PCLByteWriterUtil.unsignedLongInt(getCheckSum(hmtxTable, 0, hmtxTable.length)));
TableOffset newTableOffset = new TableOffset(-1, hmtxTable.length, baos.size());
tableOffsets.add(newTableOffset);
- baos.write(pclByteWriter.unsignedLongInt(0)); // Offset to be set later
- baos.write(pclByteWriter.unsignedLongInt(hmtxTable.length));
+ baos.write(PCLByteWriterUtil.unsignedLongInt(0)); // Offset to be set later
+ baos.write(PCLByteWriterUtil.unsignedLongInt(hmtxTable.length));
}
}
@@ -728,5 +732,26 @@ public class PCLTTFFontReader extends PCLFontReader {
out[offset] = b1;
out[offset + 1] = b2;
}
+
+ public Map<Integer, Integer> scanMtxCharacters() throws IOException {
+ if (charMtxOffsets == null) {
+ charMtxOffsets = new HashMap<Integer, Integer>();
+ List<OFMtxEntry> mtx = ttfFont.getMtx();
+ OFTableName glyfTag = OFTableName.GLYF;
+ if (ttfFont.seekTab(reader, glyfTag, 0)) {
+ for (int i = 1; i < mtx.size(); i++) {
+ OFMtxEntry entry = mtx.get(i);
+ int charCode = 0;
+ if (entry.getUnicodeIndex().size() > 0) {
+ charCode = (Integer) entry.getUnicodeIndex().get(0);
+ } else {
+ charCode = entry.getIndex();
+ }
+ charMtxOffsets.put(charCode, i);
+ }
+ }
+ }
+ return charMtxOffsets;
+ }
}
diff --git a/fop-core/src/test/java/org/apache/fop/render/pcl/PCLPainterTestCase.java b/fop-core/src/test/java/org/apache/fop/render/pcl/PCLPainterTestCase.java
index 65ac6ef0b..fe637589d 100644
--- a/fop-core/src/test/java/org/apache/fop/render/pcl/PCLPainterTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/pcl/PCLPainterTestCase.java
@@ -20,9 +20,13 @@ package org.apache.fop.render.pcl;
import java.awt.Color;
import java.awt.Dimension;
+import java.awt.FontFormatException;
import java.awt.Rectangle;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import javax.xml.transform.stream.StreamResult;
@@ -30,8 +34,13 @@ import org.junit.Test;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FopFactory;
+import org.apache.fop.fonts.EmbeddingMode;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontType;
+import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.java2d.CustomFontMetricsMapper;
import junit.framework.Assert;
@@ -57,4 +66,35 @@ public class PCLPainterTestCase {
Assert.assertTrue(output.toString().contains("*v255a0b0c0I\u001B*v0S\u001B*c0.01h0.01V\u001B*c0P"));
}
+ @Test
+ public void testTruetype() throws IFException, IOException, FontFormatException, URISyntaxException {
+ String optimizeResources = getPCL(true).toString();
+ String notOptimizeResources = getPCL(false).toString();
+ Assert.assertTrue(notOptimizeResources.contains("DejaVu"));
+ Assert.assertFalse(optimizeResources.contains("DejaVu"));
+ Assert.assertEquals(optimizeResources.length(), 935);
+ }
+
+ private ByteArrayOutputStream getPCL(boolean optimizeResources)
+ throws IFException, URISyntaxException, IOException, FontFormatException {
+ Rectangle size = new Rectangle(1, 1);
+ PCLPageDefinition pclPageDef = new PCLPageDefinition("", 0, new Dimension(), size, true);
+ PCLDocumentHandler documentHandler = new PCLDocumentHandler(new IFContext(ua));
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ documentHandler.setResult(new StreamResult(output));
+ documentHandler.startDocument();
+ PCLPainter pclPainter = new PCLPainter(documentHandler, pclPageDef);
+ pclPainter.getPCLUtil().setOptimizeResources(optimizeResources);
+ FontInfo fi = new FontInfo();
+ fi.addFontProperties("", "", "", 0);
+ MultiByteFont mbf = new MultiByteFont(ua.getResourceResolver(), EmbeddingMode.AUTO);
+ mbf.setEmbedURI(new URI("test/resources/fonts/ttf/DejaVuLGCSerif.ttf"));
+ mbf.setFontType(FontType.TRUETYPE);
+ fi.addMetrics("", new CustomFontMetricsMapper(mbf));
+ documentHandler.setFontInfo(fi);
+ pclPainter.setFont("", "", 0, "", 0, Color.BLACK);
+ pclPainter.drawText(0, 0, 0, 0, null, "test");
+ return output;
+ }
+
}
diff --git a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/MockPCLTTFFontReader.java b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/MockPCLTTFFontReader.java
index a155dd43d..85e15b0a0 100644
--- a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/MockPCLTTFFontReader.java
+++ b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/MockPCLTTFFontReader.java
@@ -29,8 +29,8 @@ import org.apache.fop.render.pcl.fonts.truetype.PCLTTFFontReader;
public class MockPCLTTFFontReader extends PCLTTFFontReader {
- public MockPCLTTFFontReader(Typeface font, PCLByteWriterUtil pclByteWriter) throws IOException {
- super(font, pclByteWriter);
+ public MockPCLTTFFontReader(Typeface font) throws IOException {
+ super(font);
}
@Override
diff --git a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtilTestCase.java b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtilTestCase.java
index a21f204bf..a558a23d9 100644
--- a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtilTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLByteWriterUtilTestCase.java
@@ -20,31 +20,24 @@ package org.apache.fop.render.pcl.fonts;
import java.io.IOException;
-import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
public class PCLByteWriterUtilTestCase {
- private PCLByteWriterUtil byteWriter;
-
- @Before
- public void setUp() {
- byteWriter = new PCLByteWriterUtil();
- }
@Test
public void testWriteMethods() throws IOException {
- byte[] output = byteWriter.writeCommand("(s4X");
+ byte[] output = PCLByteWriterUtil.writeCommand("(s4X");
// 27 = PCL escape character with rest in ASCII format
byte[] command = {27, 40, 115, 52, 88};
assertArrayEquals(command, output);
- byte[] resultB = byteWriter.unsignedLongInt(102494);
+ byte[] resultB = PCLByteWriterUtil.unsignedLongInt(102494);
byte[] compareB = {0, 1, -112, 94};
assertArrayEquals(compareB, resultB);
- byte[] resultC = byteWriter.unsignedInt(1024);
+ byte[] resultC = PCLByteWriterUtil.unsignedInt(1024);
byte[] compareC = {4, 0};
assertArrayEquals(compareC, resultC);
}
@@ -53,21 +46,21 @@ public class PCLByteWriterUtilTestCase {
public void testUtilMethods() throws IOException {
byte[] anArray = {1, 2, 3, 4, 5, 9, 10};
byte[] insertArray = {6, 7, 8};
- byte[] result = byteWriter.insertIntoArray(5, anArray, insertArray);
+ byte[] result = PCLByteWriterUtil.insertIntoArray(5, anArray, insertArray);
byte[] compareA = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
assertArrayEquals(compareA, result);
byte[] reverse = {10, 9, 8, 7, 6};
- byteWriter.updateDataAtLocation(compareA, reverse, 5);
+ PCLByteWriterUtil.updateDataAtLocation(compareA, reverse, 5);
byte[] compareB = {1, 2, 3, 4, 5, 10, 9, 8, 7, 6};
assertArrayEquals(compareB, compareA);
byte[] anArrayC = {1, 2, 3, 4, 5};
- byte[] resultC = byteWriter.padBytes(anArrayC, 10);
+ byte[] resultC = PCLByteWriterUtil.padBytes(anArrayC, 10);
byte[] compareC = {1, 2, 3, 4, 5, 0, 0, 0, 0, 0};
assertArrayEquals(compareC, resultC);
- byte[] resultD = byteWriter.padBytes(anArrayC, 10, 1);
+ byte[] resultD = PCLByteWriterUtil.padBytes(anArrayC, 10, 1);
byte[] compareD = {1, 2, 3, 4, 5, 1, 1, 1, 1, 1};
assertArrayEquals(compareD, resultD);
}
diff --git a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactoryTestCase.java b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactoryTestCase.java
index 2860afbdf..cf05a0ca5 100644
--- a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactoryTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLFontReaderFactoryTestCase.java
@@ -46,7 +46,6 @@ public class PCLFontReaderFactoryTestCase {
// Have to mock the input stream twice otherwise get a Stream is closed exception
when(((CustomFont) customFont.getRealFont()).getInputStream()).thenReturn(
new FileInputStream(new File(TEST_FONT_TTF)));
- PCLFontReaderFactory fontReaderFactory = PCLFontReaderFactory.getInstance(null);
- assertTrue(fontReaderFactory.createInstance(customFont) instanceof PCLTTFFontReader);
+ assertTrue(PCLFontReaderFactory.createInstance(customFont) instanceof PCLTTFFontReader);
}
}
diff --git a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLTTFFontReaderTestCase.java b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLTTFFontReaderTestCase.java
index 5673efbb4..08323e0cf 100644
--- a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLTTFFontReaderTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLTTFFontReaderTestCase.java
@@ -27,7 +27,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
@@ -44,14 +43,8 @@ import org.apache.fop.render.pcl.fonts.truetype.PCLTTFFontReader;
public class PCLTTFFontReaderTestCase {
private CustomFontMetricsMapper customFont = mock(CustomFontMetricsMapper.class);
- private PCLByteWriterUtil byteWriter;
private static final String TEST_FONT_A = "./test/resources/fonts/ttf/DejaVuLGCSerif.ttf";
- @Before
- public void setUp() {
- byteWriter = new PCLByteWriterUtil();
- }
-
@Test
public void verifyFontAData() throws Exception {
CustomFont sbFont = mock(CustomFont.class);
@@ -62,7 +55,7 @@ public class PCLTTFFontReaderTestCase {
when(font.getGIDFromChar('e')).thenReturn(101);
when(font.getGIDFromChar('l')).thenReturn(108);
when(font.getGIDFromChar('o')).thenReturn(111);
- PCLTTFFontReader reader = new MockPCLTTFFontReader(customFont, byteWriter);
+ PCLTTFFontReader reader = new MockPCLTTFFontReader(customFont);
reader.setFont(font);
verifyFontData(reader);
validateOffsets(reader);
diff --git a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriterTestCase.java b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriterTestCase.java
index 04849db87..4a8edb401 100644
--- a/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriterTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriterTestCase.java
@@ -46,6 +46,7 @@ public class PCLTTFCharacterWriterTestCase {
public void verifyCharacterDefinition() throws Exception {
CustomFont sbFont = mock(CustomFont.class);
when(customFont.getRealFont()).thenReturn(sbFont);
+ when(sbFont.getInputStream()).thenReturn(new FileInputStream(TEST_FONT_A));
softFont = new PCLSoftFont(1, customFont, false);
TTFFile openFont = new TTFFile();
FontFileReader reader = new FontFileReader(new FileInputStream(new File(TEST_FONT_A)));
@@ -53,15 +54,15 @@ public class PCLTTFCharacterWriterTestCase {
openFont.readFont(reader, header);
softFont.setOpenFont(openFont);
softFont.setReader(reader);
+ softFont.setMtxCharIndexes(new PCLTTFFontReader(customFont).scanMtxCharacters());
characterWriter = new PCLTTFCharacterWriter(softFont);
byte[] charDefinition = characterWriter.writeCharacterDefinitions("f");
- PCLByteWriterUtil pclByteWriter = new PCLByteWriterUtil();
// Character command
- byte[] command = pclByteWriter.writeCommand(String.format("*c%dE", 32));
+ byte[] command = PCLByteWriterUtil.writeCommand(String.format("*c%dE", 32));
assertArrayEquals(getBytes(charDefinition, 0, 6), command);
// Character definition command
- byte[] charDefCommand = pclByteWriter.writeCommand(String.format("(s%dW", 210));
+ byte[] charDefCommand = PCLByteWriterUtil.writeCommand(String.format("(s%dW", 210));
assertArrayEquals(getBytes(charDefinition, 6, 7), charDefCommand);
}