]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
FOP-2486 - Enhancements and fixes to existing patch Temp_PCLSoftFonts Temp_PCLSoftFonts
authorRobert Meyer <rmeyer@apache.org>
Tue, 4 Aug 2015 15:05:19 +0000 (15:05 +0000)
committerRobert Meyer <rmeyer@apache.org>
Tue, 4 Aug 2015 15:05:19 +0000 (15:05 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_PCLSoftFonts@1694075 13f79535-47bb-0310-9956-ffa450edef68

15 files changed:
src/java/org/apache/fop/fonts/CIDFull.java
src/java/org/apache/fop/fonts/CIDSet.java
src/java/org/apache/fop/fonts/CIDSubset.java
src/java/org/apache/fop/fonts/CustomFont.java
src/java/org/apache/fop/fonts/MultiByteFont.java
src/java/org/apache/fop/fonts/SingleByteFont.java
src/java/org/apache/fop/render/pcl/PCLPainter.java
src/java/org/apache/fop/render/pcl/fonts/PCLCharacterDefinition.java
src/java/org/apache/fop/render/pcl/fonts/PCLFontReader.java
src/java/org/apache/fop/render/pcl/fonts/PCLSoftFont.java
src/java/org/apache/fop/render/pcl/fonts/PCLSoftFontManager.java
src/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriter.java
src/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFFontReader.java
test/java/org/apache/fop/render/pcl/fonts/PCLTTFFontReaderTestCase.java
test/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFCharacterWriterTestCase.java

index ee062a2bbfbe4930d86902398b77d610b7ba998b..1130459b725dc3603e33737d878a1565ca00220d 100644 (file)
@@ -56,6 +56,18 @@ public class CIDFull implements CIDSet {
         return index;
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public char getUnicodeFromGID(int glyphIndex) {
+        return ' ';
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int getGIDFromChar(char ch) {
+        return ch;
+    }
+
     /** {@inheritDoc} */
     public char getUnicode(int index) {
         initGlyphIndices();
@@ -109,5 +121,4 @@ public class CIDFull implements CIDSet {
     public int[] getWidths() {
         return font.getWidths();
     }
-
 }
index 7530ea6e760854c19b04589df7aee71ad14962fc..acfc705c84b92ce374afec790fbab5b08050b952 100644 (file)
@@ -43,6 +43,20 @@ public interface CIDSet {
      */
     char getUnicode(int index);
 
+    /**
+     * Gets the unicode character from the original font glyph index
+     * @param glyphIndex The original glyph index of the character in the font
+     * @return The character represented by the passed GID
+     */
+    char getUnicodeFromGID(int glyphIndex);
+
+    /**
+     * Returns the glyph index from the original font from a character
+     * @param ch The character
+     * @return The glyph index in the original font.
+     */
+    int getGIDFromChar(char ch);
+
     /**
      * Maps a character to a character selector for a font subset. If the character isn't in the
      * subset, yet, it is added and a new character selector returned. Otherwise, the already
index f442c13ed56e675e182ec6b245c001c6195ff12a..01b8495f8037994a54eea9eef2c6d4768a27fc61 100644 (file)
@@ -53,6 +53,12 @@ public class CIDSubset implements CIDSet {
      */
     private Map<Integer, Character> usedCharsIndex = new HashMap<Integer, Character>();
 
+    /**
+     * A map between the original character and it's GID in the original font.
+     */
+    private Map<Character, Integer> charToGIDs = new HashMap<Character, Integer>();
+
+
     private final MultiByteFont font;
 
     public CIDSubset(MultiByteFont mbf) {
@@ -93,6 +99,7 @@ public class CIDSubset implements CIDSet {
             usedGlyphs.put(glyphIndex, selector);
             usedGlyphsIndex.put(selector, glyphIndex);
             usedCharsIndex.put(selector, unicode);
+            charToGIDs.put(unicode, glyphIndex);
             usedGlyphsCount++;
             return selector;
         } else {
@@ -105,6 +112,17 @@ public class CIDSubset implements CIDSet {
         return Collections.unmodifiableMap(this.usedGlyphs);
     }
 
+    /** {@inheritDoc} */
+    public char getUnicodeFromGID(int glyphIndex) {
+        int selector = usedGlyphs.get(glyphIndex);
+        return usedCharsIndex.get(selector);
+    }
+
+    /** {@inheritDoc} */
+    public int getGIDFromChar(char ch) {
+        return charToGIDs.get(ch);
+    }
+
     /** {@inheritDoc} */
     public char[] getChars() {
         char[] charArray = new char[usedGlyphsCount];
index fffb429ed2a4db5cf198d290f9b683d2f107457b..6f325d96dda5326668643f21bdf3051123491865 100644 (file)
@@ -568,4 +568,16 @@ public abstract class CustomFont extends Typeface
         this.strikeoutThickness = strikeoutThickness;
     }
 
+    /**
+     * Returns a Map of used Glyphs.
+     * @return Map Map of used Glyphs
+     */
+    public abstract Map<Integer, Integer> getUsedGlyphs();
+
+    /**
+     * Returns the character from it's original glyph index in the font
+     * @param glyphIndex The original index of the character
+     * @return The character
+     */
+    public abstract char getUnicodeFromGID(int glyphIndex);
 }
index 296c86de220566a045dc6526e6817ff96ab1e3c7..22b5116bbf12440cdb63393cc01e9ceb68f7052f 100644 (file)
@@ -425,6 +425,24 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
         return cidSet.getGlyphs();
     }
 
+    /**
+     * Returns the character from it's original glyph index in the font
+     * @param glyphIndex The original index of the character
+     * @return The character
+     */
+    public char getUnicodeFromGID(int glyphIndex) {
+        return cidSet.getUnicodeFromGID(glyphIndex);
+    }
+
+    /**
+     * Gets the original glyph index in the font from a character.
+     * @param ch The character
+     * @return The glyph index in the font
+     */
+    public int getGIDFromChar(char ch) {
+        return cidSet.getGIDFromChar(ch);
+    }
+
     /**
      * Establishes the glyph definition table.
      * @param gdef the glyph definition table to be used by this font
index e12da81cc6af44606db2389b490b58a7eb8ee6d1..e3037a524cb4d5fe32cebb816b175facf379822c 100644 (file)
@@ -63,6 +63,7 @@ public class SingleByteFont extends CustomFont {
     private LinkedHashMap<Integer, String> usedGlyphNames;
     private Map<Integer, Integer> usedGlyphs;
     private Map<Integer, Character> usedCharsIndex;
+    private Map<Character, Integer> charGIDMappings;
 
     public SingleByteFont(InternalResourceResolver resourceResolver) {
         super(resourceResolver);
@@ -76,6 +77,7 @@ public class SingleByteFont extends CustomFont {
             usedGlyphNames = new LinkedHashMap<Integer, String>();
             usedGlyphs = new HashMap<Integer, Integer>();
             usedCharsIndex = new HashMap<Integer, Character>();
+            charGIDMappings = new HashMap<Character, Integer>();
 
             // The zeroth value is reserved for .notdef
             usedGlyphs.put(0, 0);
@@ -234,6 +236,7 @@ public class SingleByteFont extends CustomFont {
             int selector = usedGlyphsCount;
             usedGlyphs.put(glyphIndex, selector);
             usedCharsIndex.put(selector, unicode);
+            charGIDMappings.put(unicode, glyphIndex);
             usedGlyphsCount++;
             return selector;
         } else {
@@ -519,6 +522,15 @@ public class SingleByteFont extends CustomFont {
         return getUnicode(selector);
     }
 
+    public int getGIDFromChar(char ch) {
+        return charGIDMappings.get(ch);
+    }
+
+    public char getUnicodeFromGID(int glyphIndex) {
+        int selector = usedGlyphs.get(glyphIndex);
+        return usedCharsIndex.get(selector);
+    }
+
     public void mapUsedGlyphName(int gid, String value) {
         usedGlyphNames.put(gid, value);
     }
index 26a6da66b5fe4c8a8df08a60c8557fd42ce18708..69465a7fdd2e4cdab4bcc4776c1830eefc34d603 100644 (file)
@@ -30,6 +30,7 @@ import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.util.List;
 import java.util.Map;
 import java.util.Stack;
 
@@ -62,6 +63,7 @@ import org.apache.fop.render.java2d.Java2DPainter;
 import org.apache.fop.render.pcl.fonts.PCLCharacterWriter;
 import org.apache.fop.render.pcl.fonts.PCLSoftFont;
 import org.apache.fop.render.pcl.fonts.PCLSoftFontManager;
+import org.apache.fop.render.pcl.fonts.PCLSoftFontManager.PCLTextSegment;
 import org.apache.fop.render.pcl.fonts.truetype.PCLTTFCharacterWriter;
 import org.apache.fop.traits.BorderProps;
 import org.apache.fop.traits.RuleStyle;
@@ -337,24 +339,35 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
                 // TrueType conversion to a soft font (PCL 5 Technical Reference - Chapter 11)
                 if (!drawAsBitmaps && isTrueType(tf)) {
                     boolean madeSF = false;
-                    if (sfManager.getSoftFont(tf) == null) {
+                    if (sfManager.getSoftFont(tf, text) == null) {
                         madeSF = true;
                         ByteArrayOutputStream baos = sfManager.makeSoftFont(tf);
                         if (baos != null) {
                             gen.writeBytes(baos.toByteArray());
                         }
                     }
-                    int fontID = sfManager.getSoftFontID(tf);
                     String formattedSize = gen.formatDouble2(state.getFontSize() / 1000.0);
                     gen.writeCommand(String.format("(s%sV", formattedSize));
-                    gen.writeCommand(String.format("(%dX", fontID));
-                    PCLSoftFont softFont = sfManager.getSoftFont(tf);
-                    PCLCharacterWriter charWriter = new PCLTTFCharacterWriter(softFont);
-                    if (!madeSF) {
-                        gen.writeBytes(sfManager.writeFontIDCommand(fontID));
+                    List<PCLTextSegment> textSegments = sfManager.getTextSegments(text, tf);
+                    if (textSegments.isEmpty()) {
+                        textSegments.add(new PCLTextSegment(sfManager.getSoftFontID(tf), text));
+                    }
+                    boolean first = true;
+                    for (PCLTextSegment textSegment : textSegments) {
+                        gen.writeCommand(String.format("(%dX", textSegment.getFontID()));
+                        PCLSoftFont softFont = sfManager.getSoftFontFromID(textSegment.getFontID());
+                        PCLCharacterWriter charWriter = new PCLTTFCharacterWriter(softFont);
+                        gen.writeBytes(sfManager.assignFontID(textSegment.getFontID()));
+                        gen.writeBytes(charWriter.writeCharacterDefinitions(textSegment.getText()));
+                        if (first) {
+                            drawTextUsingSoftFont(x, y, letterSpacing, wordSpacing, dp,
+                                    textSegment.getText(), triplet, softFont);
+                            first = false;
+                        } else {
+                            drawTextUsingSoftFont(-1, -1, letterSpacing, wordSpacing, dp,
+                                    textSegment.getText(), triplet, softFont);
+                        }
                     }
-                    gen.writeBytes(charWriter.writeCharacterDefinitions(text));
-                    drawTextUsingSoftFont(x, y, letterSpacing, wordSpacing, dp, text, triplet, softFont);
                 } else {
                     drawTextAsBitmap(x, y, letterSpacing, wordSpacing, dp, text, triplet);
                     if (DEBUG) {
@@ -482,7 +495,9 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
             gen.selectGrayscale(textColor);
         }
 
-        setCursorPos(x, y);
+        if (x != -1 && y != -1) {
+            setCursorPos(x, y);
+        }
 
         float fontSize = state.getFontSize() / 1000f;
         Font font = getFontInfo().getFontInstance(triplet, state.getFontSize());
@@ -519,8 +534,7 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
             if (glyphAdjust != 0) {
                 gen.getOutputStream().write(sb.toString().getBytes(gen.getTextEncoding()));
                 for (int j = 0; j < current.length(); j++) {
-                    gen.getOutputStream().write(
-                            softFont.getUnicodeCodePoint((int) current.charAt(j)));
+                    gen.getOutputStream().write(softFont.getCharCode(current.charAt(j)));
                 }
                 sb = new StringBuffer();
 
@@ -533,7 +547,7 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
         if (!current.equals("")) {
             gen.getOutputStream().write(sb.toString().getBytes(gen.getTextEncoding()));
             for (int i = 0; i < current.length(); i++) {
-                gen.getOutputStream().write(softFont.getUnicodeCodePoint((int) current.charAt(i)));
+                gen.getOutputStream().write(softFont.getCharCode(current.charAt(i)));
             }
         }
     }
index be1ba7adccb6ec9c94ebdc2e5ded82bd1b69cceb..c275084dcab31cd3df950277987e608bfc40102e 100644 (file)
@@ -25,7 +25,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 public class PCLCharacterDefinition {
-    private int glyphID;
     private int charCode;
     private int charDefinitionSize;
     private byte[] glyfData;
@@ -34,15 +33,17 @@ public class PCLCharacterDefinition {
     private PCLCharacterClass charClass;
     private PCLByteWriterUtil pclByteWriter;
     private List<PCLCharacterDefinition> composites;
+    private boolean isComposite;
 
-    public PCLCharacterDefinition(int glyphID, int charCode, PCLCharacterFormat charFormat,
-            PCLCharacterClass charClass, byte[] glyfData, PCLByteWriterUtil pclByteWriter) {
-        this.glyphID = glyphID;
+    public PCLCharacterDefinition(int charCode, PCLCharacterFormat charFormat,
+            PCLCharacterClass charClass, byte[] glyfData, PCLByteWriterUtil pclByteWriter,
+            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.
         charDefinitionSize = glyfData.length + 4 + 2 + 2;
@@ -51,7 +52,7 @@ public class PCLCharacterDefinition {
     }
 
     public byte[] getCharacterCommand() throws IOException {
-        return pclByteWriter.writeCommand(String.format("*c%dE", charCode));
+        return pclByteWriter.writeCommand(String.format("*c%dE", (isComposite) ? 65535 : charCode));
     }
 
     public byte[] getCharacterDefinitionCommand() throws IOException {
@@ -93,7 +94,7 @@ public class PCLCharacterDefinition {
         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(glyphID));
+        baos.write(pclByteWriter.unsignedInt(charCode));
     }
 
     public void addCompositeGlyph(PCLCharacterDefinition composite) {
index 22e97605bcf3216ddf9b35e2a055a97fc708f364..6bd5192acc87a74ac5cc12b4f59cef9e87bbf6c4 100644 (file)
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.Typeface;
 import org.apache.fop.fonts.truetype.FontFileReader;
 import org.apache.fop.fonts.truetype.OpenFont;
@@ -31,12 +32,17 @@ public abstract class PCLFontReader {
 
     protected Typeface typeface;
     protected PCLByteWriterUtil pclByteWriter;
+    protected CustomFont font;
 
     public PCLFontReader(Typeface font, PCLByteWriterUtil pclByteWriter) {
         this.typeface = font;
         this.pclByteWriter = pclByteWriter;
     }
 
+    public void setFont(CustomFont mbFont) {
+        this.font = mbFont;
+    }
+
     /** Header Data **/
     public abstract int getDescriptorSize();
     public abstract int getHeaderFormat();
@@ -77,7 +83,8 @@ public abstract class PCLFontReader {
     public abstract int getVariety();
 
     /** Segmented Font Data **/
-    public abstract List<PCLFontSegment> getFontSegments() throws IOException;
+    public abstract List<PCLFontSegment> getFontSegments(Map<Character, Integer> mappedGlyphs)
+            throws IOException;
 
     /** Character Definitions **/
     public abstract Map<Integer, int[]> getCharacterOffsets() throws IOException;
index 87f399839eb552b402dd878025e2df01ff32d5c6..8412534eba8cee2d1612d2e37c76e8e072e813b5 100644 (file)
@@ -38,13 +38,17 @@ public class PCLSoftFont {
     private FontFileReader reader;
     /** Map containing unicode character and it's soft font codepoint **/
     private Map<Integer, Integer> charsWritten;
+    private Map<Character, Integer> mappedChars;
     private Map<Integer, Integer> charMtxPositions;
+    private boolean multiByteFont;
     private int charCount = 32;
 
-    public PCLSoftFont(int fontID, Typeface font) {
+    public PCLSoftFont(int fontID, Typeface font, boolean multiByteFont) {
         this.fontID = fontID;
         this.font = font;
         charsWritten = new HashMap<Integer, Integer>();
+        mappedChars = new HashMap<Character, Integer>();
+        this.multiByteFont = multiByteFont;
     }
 
     public Typeface getTypeface() {
@@ -92,7 +96,11 @@ public class PCLSoftFont {
     }
 
     public int getUnicodeCodePoint(int unicode) {
-        return charsWritten.get(unicode);
+        if (charsWritten.containsKey(unicode)) {
+            return charsWritten.get(unicode);
+        } else {
+            return -1;
+        }
     }
 
     public boolean hasPreviouslyWritten(int unicode) {
@@ -125,4 +133,28 @@ public class PCLSoftFont {
     public int getCharCount() {
         return charCount;
     }
+
+    public void setMappedChars(Map<Character, Integer> mappedChars) {
+        this.mappedChars = mappedChars;
+    }
+
+    public Map<Character, Integer> getMappedChars() {
+        return mappedChars;
+    }
+
+    public int getCharIndex(char ch) {
+        if (mappedChars.containsKey(ch)) {
+            return mappedChars.get(ch);
+        } else {
+            return -1;
+        }
+    }
+
+    public int getCharCode(char ch) {
+        if (multiByteFont) {
+            return getCharIndex(ch);
+        } else {
+            return getUnicodeCodePoint(ch);
+        }
+    }
 }
index 77da40a262375c6c11f55bf2325e39ff26e4f73a..621ea4f18ead54053ce240e57c220c99efd1d347 100644 (file)
@@ -22,45 +22,98 @@ package org.apache.fop.render.pcl.fonts;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
+import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.Typeface;
+import org.apache.fop.render.java2d.CustomFontMetricsMapper;
 
 public class PCLSoftFontManager {
     private ByteArrayOutputStream baos = new ByteArrayOutputStream();
     private PCLFontReader fontReader;
     private PCLByteWriterUtil pclByteWriter = new PCLByteWriterUtil();
-    private int byte64Offset;
     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 {
-        PCLSoftFont softFont = new PCLSoftFont(fonts.size() + 1, font);
-        fontReaderFactory = PCLFontReaderFactory.getInstance(pclByteWriter);
+        List<Map<Character, Integer>> mappedGlyphs = mapFontGlyphs(font);
+        if (fontReaderFactory == null) {
+            fontReaderFactory = PCLFontReaderFactory.getInstance(pclByteWriter);
+        }
         fontReader = fontReaderFactory.createInstance(font);
+        initialize();
+        if (mappedGlyphs.isEmpty()) {
+            mappedGlyphs.add(new HashMap<Character, Integer>());
+        }
         if (fontReader != null) {
-            initialize();
-            assignFontID();
-            writeFontHeader();
-            softFont.setCharacterOffsets(fontReader.getCharacterOffsets());
-            softFont.setOpenFont(fontReader.getFontFile());
-            softFont.setReader(fontReader.getFontFileReader());
-            fonts.add(softFont);
+            for (Map<Character, Integer> glyphSet : mappedGlyphs) {
+                PCLSoftFont softFont = new PCLSoftFont(fonts.size() + 1, font,
+                        mappedGlyphs.get(0).size() != 0);
+                softFont.setMappedChars(glyphSet);
+                assignFontID();
+                writeFontHeader(softFont.getMappedChars());
+                softFont.setCharacterOffsets(fontReader.getCharacterOffsets());
+                softFont.setOpenFont(fontReader.getFontFile());
+                softFont.setReader(fontReader.getFontFileReader());
+                fonts.add(softFont);
+            }
             return baos;
         } else {
             return null;
         }
     }
 
+    private List<Map<Character, Integer>> mapFontGlyphs(Typeface tf) {
+        List<Map<Character, Integer>> mappedGlyphs = new ArrayList<Map<Character, Integer>>();
+        if (tf instanceof CustomFontMetricsMapper) {
+            CustomFontMetricsMapper fontMetrics = (CustomFontMetricsMapper) tf;
+            CustomFont customFont = (CustomFont) fontMetrics.getRealFont();
+            mappedGlyphs = mapGlyphs(customFont.getUsedGlyphs(), customFont);
+        }
+        return mappedGlyphs;
+    }
+
+    private List<Map<Character, Integer>> mapGlyphs(Map<Integer, Integer> usedGlyphs, CustomFont font) {
+        int charCount = 32;
+        List<Map<Character, Integer>> mappedGlyphs = new ArrayList<Map<Character, Integer>>();
+        Map<Character, Integer> fontGlyphs = new HashMap<Character, Integer>();
+        for (Entry<Integer, Integer> entry : usedGlyphs.entrySet()) {
+            int glyphID = entry.getKey();
+            if (glyphID == 0) {
+                continue;
+            }
+            char unicode = font.getUnicodeFromGID(glyphID);
+            if (charCount > SOFT_FONT_SIZE) {
+                mappedGlyphs.add(fontGlyphs);
+                charCount = 32;
+                fontGlyphs = new HashMap<Character, Integer>();
+            }
+            fontGlyphs.put(unicode, charCount++);
+        }
+        if (fontGlyphs.size() > 0) {
+            mappedGlyphs.add(fontGlyphs);
+        }
+        return mappedGlyphs;
+    }
+
     private void initialize() {
         baos.reset();
     }
 
     private void assignFontID() throws IOException {
-        baos.write(pclByteWriter.writeCommand(String.format("*c%dD", fonts.size() + 1)));
+        baos.write(assignFontID(fonts.size() + 1));
     }
 
-    private void writeFontHeader() throws IOException {
+    public byte[] assignFontID(int fontID) throws IOException {
+        return pclByteWriter.writeCommand(String.format("*c%dD", fontID));
+    }
+
+    private void writeFontHeader(Map<Character, Integer> mappedGlyphs) throws IOException {
         ByteArrayOutputStream header = new ByteArrayOutputStream();
         header.write(pclByteWriter.unsignedInt(fontReader.getDescriptorSize()));
         header.write(pclByteWriter.unsignedByte(fontReader.getHeaderFormat()));
@@ -95,22 +148,21 @@ public class PCLSoftFontManager {
         header.write(pclByteWriter.unsignedInt(fontReader.getCapHeight()));
         header.write(pclByteWriter.unsignedLongInt(fontReader.getFontNumber()));
         header.write(pclByteWriter.padBytes(fontReader.getFontName().getBytes("US-ASCII"), 16, 32));
-        // Byte 64 starting point stored for checksum
-        byte64Offset = header.size();
         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()));
 
-        writeSegmentedFontData(header, byte64Offset);
+        writeSegmentedFontData(header, mappedGlyphs);
 
         baos.write(getFontHeaderCommand(header.size()));
         baos.write(header.toByteArray());
     }
 
-    private void writeSegmentedFontData(ByteArrayOutputStream header, int byte64Offset) throws IOException {
-        List<PCLFontSegment> fontSegments = fontReader.getFontSegments();
+    private void writeSegmentedFontData(ByteArrayOutputStream header,
+            Map<Character, Integer> mappedGlyphs) throws IOException {
+        List<PCLFontSegment> fontSegments = fontReader.getFontSegments(mappedGlyphs);
         for (PCLFontSegment segment : fontSegments) {
             writeFontSegment(header, segment);
         }
@@ -135,27 +187,39 @@ public class PCLSoftFontManager {
         header.write(segment.getData());
     }
 
-    public List<PCLSoftFont> getSoftFonts() {
-        return fonts;
-    }
-
     /**
      * Finds a soft font associated with the given typeface. If more than one instance of the font exists (as each font
      * is bound and restricted to 255 characters) it will find the last font with available capacity.
      * @param font The typeface associated with the soft font
      * @return Returns the PCLSoftFont with available capacity
      */
-    public PCLSoftFont getSoftFont(Typeface font) {
+    public PCLSoftFont getSoftFont(Typeface font, String text) {
         for (PCLSoftFont sftFont : fonts) {
-            if (sftFont.getTypeface().equals(font) && sftFont.getCharCount() < 255) {
+            if (sftFont.getTypeface().equals(font)
+                    && sftFont.getCharCount() + countNonMatches(sftFont, text) < SOFT_FONT_SIZE) {
                 return sftFont;
             }
         }
         return null;
     }
 
+    public PCLSoftFont getSoftFontFromID(int index) {
+        return fonts.get(index - 1);
+    }
+
+    private int countNonMatches(PCLSoftFont font, String text) {
+        int result = 0;
+        for (char ch : text.toCharArray()) {
+            int value = font.getUnicodeCodePoint(ch);
+            if (value == -1) {
+                result++;
+            }
+        }
+        return result;
+    }
+
     public int getSoftFontID(Typeface tf) throws IOException {
-        PCLSoftFont font = getSoftFont(tf);
+        PCLSoftFont font = getSoftFont(tf, "");
         for (int i = 0; i < fonts.size(); i++) {
             if (fonts.get(i).equals(font)) {
                 return i + 1;
@@ -164,7 +228,51 @@ public class PCLSoftFontManager {
         return -1;
     }
 
-    public byte[] writeFontIDCommand(int fontID) throws IOException {
-        return pclByteWriter.writeCommand(String.format("*c%dD", fontID));
+    public List<PCLTextSegment> getTextSegments(String text, Typeface font) {
+        List<PCLTextSegment> textSegments = new ArrayList<PCLTextSegment>();
+        int curFontID = -1;
+        String current = "";
+        for (char ch : text.toCharArray()) {
+            for (PCLSoftFont softFont : fonts) {
+                if (curFontID == -1) {
+                    curFontID = softFont.getFontID();
+                }
+                if (softFont.getCharIndex(ch) == -1 || !softFont.getTypeface().equals(font)) {
+                    continue;
+                }
+                if (current.length() > 0 && curFontID != softFont.getFontID()) {
+                    textSegments.add(new PCLTextSegment(curFontID, current));
+                    current = "";
+                    curFontID = softFont.getFontID();
+                }
+                if (curFontID != softFont.getFontID()) {
+                    curFontID = softFont.getFontID();
+                }
+                current += ch;
+                break;
+            }
+        }
+        if (current.length() > 0) {
+            textSegments.add(new PCLTextSegment(curFontID, current));
+        }
+        return textSegments;
+    }
+
+    public static class PCLTextSegment {
+        private String text;
+        private int fontID;
+
+        public PCLTextSegment(int fontID, String text) {
+            this.text = text;
+            this.fontID = fontID;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public int getFontID() {
+            return fontID;
+        }
     }
 }
index 0d2eaf41eec89d58b9b93b80ee0bd8e7128448aa..41fefaaf00a73f7cc22fd5483d2e8d9db9f0e0f3 100644 (file)
@@ -109,19 +109,21 @@ public class PCLTTFCharacterWriter extends PCLCharacterWriter {
 
             font.writeCharacter(unicode);
 
-            PCLCharacterDefinition newChar = new PCLCharacterDefinition(charIndex, font.getUnicodeCodePoint(unicode),
+            PCLCharacterDefinition newChar = new PCLCharacterDefinition(
+                    font.getCharCode((char) unicode),
                     PCLCharacterFormat.TrueType,
-                    PCLCharacterClass.TrueType, glyphData, pclByteWriter);
+                    PCLCharacterClass.TrueType, glyphData, pclByteWriter, false);
 
             // Handle composite character definitions
             GlyfTable glyfTable = new GlyfTable(fontReader, mtx.toArray(new OFMtxEntry[mtx.size()]),
                     tabEntry, subsetGlyphs);
             if (glyfTable.isComposite(charIndex)) {
-                Set<Integer> composite = glyfTable.retrieveComposedGlyphs(charIndex);
-                for (Integer compositeIndex : composite) {
+                Set<Integer> composites = glyfTable.retrieveComposedGlyphs(charIndex);
+                for (Integer compositeIndex : composites) {
                     byte[] compositeData = getGlyphData(compositeIndex);
-                    newChar.addCompositeGlyph(new PCLCharacterDefinition(compositeIndex, 65535,
-                            PCLCharacterFormat.TrueType, PCLCharacterClass.TrueType, compositeData, pclByteWriter));
+                    newChar.addCompositeGlyph(new PCLCharacterDefinition(compositeIndex,
+                            PCLCharacterFormat.TrueType,
+                            PCLCharacterClass.TrueType, compositeData, pclByteWriter, true));
                 }
             }
 
index c52d2d5ab3e05308710a2872619d709b906f5c44..1a054953ca4728556a210b3df6009c9734832df3 100644 (file)
@@ -30,6 +30,8 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import org.apache.fop.fonts.CustomFont;
+import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.SingleByteFont;
 import org.apache.fop.fonts.Typeface;
 import org.apache.fop.fonts.truetype.FontFileReader;
 import org.apache.fop.fonts.truetype.OFDirTabEntry;
@@ -121,13 +123,15 @@ public class PCLTTFFontReader extends PCLFontReader {
     protected void loadFont() throws IOException {
         if (typeface instanceof CustomFontMetricsMapper) {
             CustomFontMetricsMapper fontMetrics = (CustomFontMetricsMapper) typeface;
-            CustomFont customFont = (CustomFont) fontMetrics.getRealFont();
-            fontStream = customFont.getInputStream();
+            CustomFont font = (CustomFont) fontMetrics.getRealFont();
+            setFont((CustomFont) fontMetrics.getRealFont());
+            String fontName = font.getFullName();
+            fontStream = font.getInputStream();
             reader = new FontFileReader(fontStream);
 
             ttfFont = new TTFFile();
             String header = OFFontLoader.readHeader(reader);
-            ttfFont.readFont(reader, header, customFont.getFullName());
+            ttfFont.readFont(reader, header, fontName);
             readFontTables();
         } else {
             // TODO - Handle when typeface is not in the expected format for a PCL TrueType object
@@ -453,11 +457,12 @@ public class PCLTTFFontReader extends PCLFontReader {
         return 0; // TrueType fonts must be set to zero
     }
 
-    public List<PCLFontSegment> getFontSegments() throws IOException {
+    public List<PCLFontSegment> getFontSegments(Map<Character, Integer> mappedGlyphs)
+            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.GT, getGlobalTrueTypeData()));
+        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]));
         return fontSegments;
@@ -475,9 +480,9 @@ public class PCLTTFFontReader extends PCLFontReader {
         return ccUnicode;
     }
 
-    private byte[] getGlobalTrueTypeData() throws IOException {
+    private byte[] getGlobalTrueTypeData(Map<Character, Integer> mappedGlyphs) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Map<OFDirTabEntry, Integer> tableOffsets = new HashMap<OFDirTabEntry, Integer>();
+        List<TableOffset> tableOffsets = new ArrayList<TableOffset>();
         // Version
         baos.write(pclByteWriter.unsignedInt(1)); // Major
         baos.write(pclByteWriter.unsignedInt(0)); // Minor
@@ -505,9 +510,9 @@ public class PCLTTFFontReader extends PCLFontReader {
         // Add default data tables
         writeTrueTypeTable(baos, OFTableName.HEAD, tableOffsets);
         writeTrueTypeTable(baos, OFTableName.HHEA, tableOffsets);
-        writeTrueTypeTable(baos, OFTableName.HMTX, tableOffsets);
+        byte[] hmtxTable = createHmtx(mappedGlyphs);
+        writeSubsetHMTX(baos, OFTableName.HMTX, tableOffsets, hmtxTable);
         writeTrueTypeTable(baos, OFTableName.MAXP, tableOffsets);
-
         // Write the blank GDIR directory which is built in memory on the printer
         writeGDIR(baos);
 
@@ -516,23 +521,46 @@ public class PCLTTFFontReader extends PCLFontReader {
         writeTrueTypeTable(baos, OFTableName.FPGM, tableOffsets);
         writeTrueTypeTable(baos, OFTableName.PREP, tableOffsets);
 
-        baos = copyTables(tableOffsets, baos);
+        baos = copyTables(tableOffsets, baos, hmtxTable, mappedGlyphs.size());
 
         return baos.toByteArray();
     }
 
+    private static class TableOffset {
+        private long originOffset;
+        private long originLength;
+        private int newOffset;
+
+        public TableOffset(long originOffset, long originLength, int newOffset) {
+            this.originOffset = originOffset;
+            this.originLength = originLength;
+            this.newOffset = newOffset;
+        }
+
+        public long getOriginOffset() {
+            return originOffset;
+        }
+
+        public long getOriginLength() {
+            return originLength;
+        }
+
+        public int getNewOffset() {
+            return newOffset;
+        }
+    }
+
     private void writeTrueTypeTable(ByteArrayOutputStream baos, OFTableName table,
-            Map<OFDirTabEntry, Integer> tableOffsets) throws IOException, UnsupportedEncodingException {
+            List<TableOffset> tableOffsets) throws IOException, UnsupportedEncodingException {
         OFDirTabEntry tabEntry = ttfFont.getDirectoryEntry(table);
         if (tabEntry != null) {
             baos.write(tabEntry.getTag());
             baos.write(pclByteWriter.unsignedLongInt(tabEntry.getChecksum()));
-            tableOffsets.put(tabEntry, baos.size());
+            TableOffset newTableOffset = new TableOffset(tabEntry.getOffset(),
+                    tabEntry.getLength(), baos.size());
+            tableOffsets.add(newTableOffset);
             baos.write(pclByteWriter.unsignedLongInt(0)); // Offset to be set later
-            long length = (tabEntry.getLength() > HMTX_RESTRICT_SIZE)
-                    ? HMTX_RESTRICT_SIZE
-                    : tabEntry.getLength();
-            baos.write(pclByteWriter.unsignedLongInt(length));
+            baos.write(pclByteWriter.unsignedLongInt(tabEntry.getLength()));
         }
     }
 
@@ -543,26 +571,35 @@ public class PCLTTFFontReader extends PCLFontReader {
         baos.write(pclByteWriter.unsignedLongInt(0)); // Length
     }
 
-    private ByteArrayOutputStream copyTables(Map<OFDirTabEntry, Integer> tableOffsets, ByteArrayOutputStream baos)
+    private ByteArrayOutputStream copyTables(List<TableOffset> tableOffsets,
+            ByteArrayOutputStream baos, byte[] hmtxTable, int hmtxSize)
             throws IOException {
         Map<Integer, byte[]> offsetValues = new HashMap<Integer, byte[]>();
-        //for (OFDirTabEntry table : tableOffsets.keySet()) {
-        for (Entry<OFDirTabEntry, Integer> table : tableOffsets.entrySet()) {
-            byte[] tableData = reader.getBytes((int) table.getKey().getOffset(), (int) table.getKey().getLength());
-            if (tableData.length > HMTX_RESTRICT_SIZE) {
-                byte[] truncated = new byte[HMTX_RESTRICT_SIZE];
-                System.arraycopy(tableData, 0, truncated, 0, HMTX_RESTRICT_SIZE);
-                tableData = truncated;
+        for (TableOffset tableOffset : tableOffsets) {
+            offsetValues.put(tableOffset.getNewOffset(), pclByteWriter.unsignedLongInt(baos.size()));
+            if (tableOffset.getOriginOffset() == -1) { // Update the offset in the table directory
+                baos.write(hmtxTable);
+            } else {
+                byte[] tableData = reader.getBytes((int) tableOffset.getOriginOffset(),
+                        (int) tableOffset.getOriginLength());
+                int index = tableOffsets.indexOf(tableOffset);
+                if (index == 1) {
+                    tableData = updateHHEA(tableData, hmtxSize + 33);
+                }
+
+                // Write the table data to the end of the TrueType segment output
+                baos.write(tableData);
             }
-            // Update the offset in the table directory
-            offsetValues.put(table.getValue(), pclByteWriter.unsignedLongInt(baos.size()));
-            // Write the table data to the end of the TrueType segment output
-            baos.write(tableData);
         }
         baos = updateOffsets(baos, offsetValues);
         return baos;
     }
 
+    private byte[] updateHHEA(byte[] tableData, int hmtxSize) {
+        writeUShort(tableData, tableData.length - 2, hmtxSize);
+        return tableData;
+    }
+
     private ByteArrayOutputStream updateOffsets(ByteArrayOutputStream baos, Map<Integer, byte[]> offsets)
             throws IOException {
         byte[] softFont = baos.toByteArray();
@@ -616,4 +653,79 @@ public class PCLTTFFontReader extends PCLFontReader {
     public FontFileReader getFontFileReader() {
         return reader;
     }
-}
+
+    private void writeSubsetHMTX(ByteArrayOutputStream baos, OFTableName table,
+            List<TableOffset> tableOffsets, byte[] hmtxTable) throws IOException {
+        OFDirTabEntry tabEntry = ttfFont.getDirectoryEntry(table);
+        if (tabEntry != null) {
+            baos.write(tabEntry.getTag());
+            // Override the original checksum for the subset version
+            baos.write(pclByteWriter.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));
+        }
+    }
+
+    protected static int getCheckSum(byte[] data, int start, int size) {
+        // All the tables here are aligned on four byte boundaries
+        // Add remainder to size if it's not a multiple of 4
+        int remainder = size % 4;
+        if (remainder != 0) {
+            size += remainder;
+        }
+
+        long sum = 0;
+
+        for (int i = 0; i < size; i += 4) {
+            long l = 0;
+            for (int j = 0; j < 4; j++) {
+                l <<= 8;
+                if (data.length > (start + i + j)) {
+                    l |= data[start + i + j] & 0xff;
+                }
+            }
+            sum += l;
+        }
+        return (int) sum;
+    }
+
+    protected byte[] createHmtx(Map<Character, Integer> mappedGlyphs) throws IOException {
+        byte[] hmtxTable = new byte[((mappedGlyphs.size() + 32) * 4)];
+        OFDirTabEntry entry = ttfFont.getDirectoryEntry(OFTableName.HMTX);
+
+        if (entry != null) {
+            for (Entry<Character, Integer> glyphSubset : mappedGlyphs.entrySet()) {
+                char unicode = glyphSubset.getKey();
+                int originalIndex = 0;
+                int softFontGlyphIndex = glyphSubset.getValue();
+                if (font instanceof MultiByteFont) {
+                    originalIndex = ((MultiByteFont) font).getGIDFromChar(unicode);
+
+                    writeUShort(hmtxTable, (softFontGlyphIndex) * 4,
+                            ttfFont.getMtx().get(originalIndex).getWx());
+                    writeUShort(hmtxTable, (softFontGlyphIndex) * 4 + 2,
+                            ttfFont.getMtx().get(originalIndex).getLsb());
+                } else {
+                    originalIndex = ((SingleByteFont) font).getGIDFromChar(unicode);
+
+                    writeUShort(hmtxTable, (softFontGlyphIndex) * 4,
+                            ((SingleByteFont) font).getWidth(originalIndex, 1));
+                    writeUShort(hmtxTable, (softFontGlyphIndex) * 4 + 2, 0);
+                }
+            }
+        }
+        return hmtxTable;
+    }
+
+    /**
+     * Appends a USHORT to the output array, updates currentPost but not realSize
+     */
+    private void writeUShort(byte[] out, int offset, int s) {
+        byte b1 = (byte) ((s >> 8) & 0xff);
+        byte b2 = (byte) (s & 0xff);
+        out[offset] = b1;
+        out[offset + 1] = b2;
+    }
+}
\ No newline at end of file
index 88c613e7dadd307e9f6fc9d403f475b801cc4267..5673efbb47111e95a4a8eb11493d2f9cf7f2ae89 100644 (file)
 /* $Id$ */
 package org.apache.fop.render.pcl.fonts;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -33,6 +36,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import org.apache.fop.fonts.CustomFont;
+import org.apache.fop.fonts.SingleByteFont;
 import org.apache.fop.render.java2d.CustomFontMetricsMapper;
 import org.apache.fop.render.pcl.fonts.PCLFontSegment.SegmentID;
 import org.apache.fop.render.pcl.fonts.truetype.PCLTTFFontReader;
@@ -53,7 +57,13 @@ public class PCLTTFFontReaderTestCase {
         CustomFont sbFont = mock(CustomFont.class);
         when(sbFont.getInputStream()).thenReturn(new FileInputStream(new File(TEST_FONT_A)));
         when(customFont.getRealFont()).thenReturn(sbFont);
+        SingleByteFont font = mock(SingleByteFont.class);
+        when(font.getGIDFromChar('h')).thenReturn(104);
+        when(font.getGIDFromChar('e')).thenReturn(101);
+        when(font.getGIDFromChar('l')).thenReturn(108);
+        when(font.getGIDFromChar('o')).thenReturn(111);
         PCLTTFFontReader reader = new MockPCLTTFFontReader(customFont, byteWriter);
+        reader.setFont(font);
         verifyFontData(reader);
         validateOffsets(reader);
         validateFontSegments(reader);
@@ -103,7 +113,13 @@ public class PCLTTFFontReaderTestCase {
      * @throws IOException
      */
     private void validateFontSegments(PCLTTFFontReader reader) throws IOException {
-        List<PCLFontSegment> segments = reader.getFontSegments();
+        HashMap<Character, Integer> mappedChars = new HashMap<Character, Integer>();
+        mappedChars.put('H', 1);
+        mappedChars.put('e', 1);
+        mappedChars.put('l', 1);
+        mappedChars.put('o', 1);
+
+        List<PCLFontSegment> segments = reader.getFontSegments(mappedChars);
         assertEquals(segments.size(), 5);
         for (PCLFontSegment segment : segments) {
             if (segment.getIdentifier() == SegmentID.PA) {
@@ -111,10 +127,72 @@ public class PCLTTFFontReaderTestCase {
                 assertEquals(segment.getData().length, 10);
                 byte[] panose = {2, 6, 6, 3, 5, 6, 5, 2, 2, 4};
                 assertArrayEquals(segment.getData(), panose);
+            } else if (segment.getIdentifier() == SegmentID.GT) {
+                verifyGlobalTrueTypeData(segment, mappedChars.size());
             } else if (segment.getIdentifier() == SegmentID.NULL) {
                 // Terminating segment
                 assertEquals(segment.getData().length, 0);
             }
         }
     }
+
+    private void verifyGlobalTrueTypeData(PCLFontSegment segment, int mappedCharsSize)
+            throws IOException {
+        byte[] ttfData = segment.getData();
+        int currentPos = 0;
+        //Version
+        assertEquals(readInt(new byte[]{ttfData[currentPos++], ttfData[currentPos++]}), 1);
+        assertEquals(readInt(new byte[]{ttfData[currentPos++], ttfData[currentPos++]}), 0);
+        //Number of tables
+        int numTables = readInt(new byte[]{ttfData[currentPos++], ttfData[currentPos++]});
+        assertEquals(numTables, 8);
+        //Search range
+        assertEquals(readInt(new byte[]{ttfData[currentPos++], ttfData[currentPos++]}), 128);
+        //Entry Selector
+        assertEquals(readInt(new byte[]{ttfData[currentPos++], ttfData[currentPos++]}), 3);
+        //Range shift
+        assertEquals(readInt(new byte[]{ttfData[currentPos++], ttfData[currentPos++]}), 0);
+        String[] validTags = {"head", "hhea", "hmtx", "maxp", "gdir"};
+        int matches = 0;
+        for (int i = 0; i < numTables; i++) {
+            String tag = readTag(new byte[]{ttfData[currentPos++], ttfData[currentPos++],
+                    ttfData[currentPos++], ttfData[currentPos++]});
+            if (Arrays.asList(validTags).contains(tag)) {
+                matches++;
+            }
+            if (tag.equals("hmtx")) {
+                currentPos += 4;
+                int offset = readLong(new byte[]{ttfData[currentPos++], ttfData[currentPos++],
+                        ttfData[currentPos++], ttfData[currentPos++]});
+                int length = readLong(new byte[]{ttfData[currentPos++], ttfData[currentPos++],
+                        ttfData[currentPos++], ttfData[currentPos++]});
+                verifyHmtx(ttfData, offset, length, mappedCharsSize);
+            } else {
+                currentPos += 12;
+            }
+        }
+        assertEquals(matches, 5);
+    }
+
+    private void verifyHmtx(byte[] ttfData, int offset, int length, int mappedCharsSize)
+            throws IOException {
+        ByteArrayInputStream bais = new ByteArrayInputStream(ttfData);
+        byte[] subsetHmtx = new byte[length];
+        bais.skip(offset);
+        bais.read(subsetHmtx);
+        assertEquals(subsetHmtx.length, (mappedCharsSize + 32) * 4);
+    }
+
+    private int readInt(byte[] bytes) {
+        return ((0xFF & bytes[0]) << 8) | (0xFF & bytes[1]);
+    }
+
+    private int readLong(byte[] bytes) {
+        return ((0xFF & bytes[0]) << 24) | ((0xFF & bytes[1]) << 16) | ((0xFF & bytes[2]) << 8)
+                | (0xFF & bytes[3]);
+    }
+
+    private String readTag(byte[] tag) {
+        return new String(tag);
+    }
 }
index 10263d067993b916de47ea6afcdf66c1f4a8447d..04849db873ef4316320eb711b2f713d35b4eac28 100644 (file)
@@ -46,7 +46,7 @@ public class PCLTTFCharacterWriterTestCase {
     public void verifyCharacterDefinition() throws Exception {
         CustomFont sbFont = mock(CustomFont.class);
         when(customFont.getRealFont()).thenReturn(sbFont);
-        softFont = new PCLSoftFont(1, customFont);
+        softFont = new PCLSoftFont(1, customFont, false);
         TTFFile openFont = new TTFFile();
         FontFileReader reader = new FontFileReader(new FileInputStream(new File(TEST_FONT_A)));
         String header = OFFontLoader.readHeader(reader);