You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2008/02/14 09:12:38 UTC

svn commit: r627679 [2/2] - in /xmlgraphics/fop/trunk: ./ lib/ src/codegen/fonts/ src/java/org/apache/fop/fonts/ src/java/org/apache/fop/fonts/truetype/ src/java/org/apache/fop/fonts/type1/ src/java/org/apache/fop/pdf/ src/java/org/apache/fop/render/pd...

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCIDFontDescriptor.java Thu Feb 14 00:12:34 2008
@@ -22,24 +22,14 @@
 // based on work by Takayuki Takeuchi
 
 /**
- * class representing a font descriptor for CID fonts.
+ * Class representing a font descriptor for CID fonts.
  *
  * Font descriptors for CID fonts are specified on page 227 and onwards of the PDF 1.3 spec.
  */
 public class PDFCIDFontDescriptor extends PDFFontDescriptor {
 
     /**
-     * The language for the font
-     */
-    protected String lang;
-
-    /**
-     * The cid set stream
-     */
-    protected PDFStream cidSet;
-
-    /**
-     * create the /FontDescriptor object
+     * Create a /FontDescriptor object.
      *
      * @param basefont the base font name
      * @param fontBBox the bounding box for the described font
@@ -56,31 +46,19 @@
         super(basefont, fontBBox[3], fontBBox[1], capHeight, flags,
               new PDFRectangle(fontBBox), italicAngle, stemV);
 
-        this.lang = lang;
+        put("MissingWidth", new Integer(500));
+        if (lang != null) {
+            put("Lang", lang);
+        }
     }
 
     /**
      * Set the CID set stream.
-     * @param cidSet the pdf stream cotnaining the CID set
+     * @param cidSet the PDF stream containing the CID set
      */
     public void setCIDSet(PDFStream cidSet) {
-        this.cidSet = cidSet;
-    }
-
-    /**
-     * Fill in the pdf data for this font descriptor.
-     * The charset specific dictionary entries are output.
-     * @param p the string buffer to append the data
-     */
-    protected void fillInPDF(StringBuffer p) {
-        p.append("\n/MissingWidth 500\n");
-        if (lang != null) {
-            p.append("\n/Lang /");
-            p.append(lang);
-        }
         if (cidSet != null) {
-            p.append("\n/CIDSet /");
-            p.append(this.cidSet.referencePDF());
+            put("CIDSet", cidSet);
         }
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCMap.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCMap.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCMap.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCMap.java Thu Feb 14 00:12:34 2008
@@ -21,6 +21,8 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.Writer;
 
 /**
  * Class representing the CMap encodings.
@@ -395,15 +397,6 @@
     }
 
     /**
-     * Add the contents of this pdf object to the PDF stream.
-     */
-    public void addContents() {
-        StringBuffer p = new StringBuffer();
-        fillInPDF(p);
-        add(p.toString());
-    }
-
-    /**
      * set the base CMap
      *
      * @param base the name of the base CMap
@@ -422,107 +415,20 @@
     }
 
     /**
-     * Fill in the pdf string for this CMap.
-     *
-     * @param p the string buffer to add the pdf data to
+     * Creates the CMapBuilder that will build the CMap's content.
+     * @param writer a Writer to write the CMap's contents to
+     * @return the newly created CMapBuilder
      */
-    public void fillInPDF(StringBuffer p) {
-        writePreStream(p);
-        writeStreamComments(p);
-        writeCIDInit(p);
-        writeCIDSystemInfo(p);
-        writeVersionTypeName(p);
-        writeCodeSpaceRange(p);
-        writeCIDRange(p);
-        writeBFEntries(p);
-        writeWrapUp(p);
-        writeStreamAfterComments(p);
-        writeUseCMap(p);
-        add(p.toString());
-    }
-
-    protected void writePreStream(StringBuffer p) {
-        // p.append("/Type /CMap\n");
-        // p.append(sysInfo.toPDFString());
-        // p.append("/CMapName /" + name + EOL);
-    }
-
-    protected void writeStreamComments(StringBuffer p) {
-        p.append("%!PS-Adobe-3.0 Resource-CMap\n");
-        p.append("%%DocumentNeededResources: ProcSet (CIDInit)\n");
-        p.append("%%IncludeResource: ProcSet (CIDInit)\n");
-        p.append("%%BeginResource: CMap (" + name + ")\n");
-        p.append("%%EndComments\n");
-    }
-
-    protected void writeCIDInit(StringBuffer p) {
-        p.append("/CIDInit /ProcSet findresource begin\n");
-        p.append("12 dict begin\n");
-        p.append("begincmap\n");
-    }
-
-    protected void writeCIDSystemInfo(StringBuffer p) {
-        p.append("/CIDSystemInfo 3 dict dup begin\n");
-        p.append("  /Registry (Adobe) def\n");
-        p.append("  /Ordering (Identity) def\n");
-        p.append("  /Supplement 0 def\n");
-        p.append("end def\n");
-    }
-
-    protected void writeVersionTypeName(StringBuffer p) {
-        p.append("/CMapVersion 1 def\n");
-        p.append("/CMapType 1 def\n");
-        p.append("/CMapName /" + name + " def\n");
-    }
-
-    protected void writeCodeSpaceRange(StringBuffer p) {
-        p.append("1 begincodespacerange\n");
-        p.append("<0000> <FFFF>\n");
-        p.append("endcodespacerange\n");
-    }
-
-    protected void writeCIDRange(StringBuffer p) {
-        p.append("1 begincidrange\n");
-        p.append("<0000> <FFFF> 0\n");
-        p.append("endcidrange\n");
-    }
-
-    protected void writeBFEntries(StringBuffer p) {
-        // p.append("1 beginbfrange\n");
-        // p.append("<0020> <0100> <0000>\n");
-        // p.append("endbfrange\n");
+    protected CMapBuilder createCMapBuilder(Writer writer) {
+        return new CMapBuilder(writer, this.name);
     }
-
-    protected void writeWrapUp(StringBuffer p) {
-        p.append("endcmap\n");
-        p.append("CMapName currentdict /CMap defineresource pop\n");
-        p.append("end\n");
-        p.append("end\n");
-    }
-
-    protected void writeStreamAfterComments(StringBuffer p) {
-        p.append("%%EndResource\n");
-        p.append("%%EOF\n");
-    }
-
-    protected void writeUseCMap(StringBuffer p) {
-        /*
-         * p.append(" /Type /CMap");
-         * p.append("/CMapName /" + name + EOL);
-         * p.append("/WMode " + wMode + EOL);
-         * if (base != null) {
-         *     p.append("/UseCMap ");
-         * if (base instanceof String) {
-         * p.append("/"+base);
-         * } else {// base instanceof PDFStream
-         * p.append(((PDFStream)base).referencePDF());
-         * }
-         * }
-         */
-    }
-
+    
+    /** {@inheritDoc} */
     protected int output(OutputStream stream) throws IOException {
-        fillInPDF(new StringBuffer());
+        StringWriter writer = new StringWriter();
+        CMapBuilder builder = createCMapBuilder(writer);
+        builder.writeCMap();
+        add(writer.getBuffer().toString()); //TODO Could be optimized by not buffering
         return super.output(stream);
     }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java Thu Feb 14 00:12:34 2008
@@ -65,6 +65,12 @@
      * @param value the value
      */
     public void put(String name, Object value) {
+        if (value instanceof PDFObject) {
+            PDFObject pdfObj = (PDFObject)value;
+            if (!pdfObj.hasObjectNumber()) {
+                pdfObj.setParent(this);
+            }
+        }
         if (!entries.containsKey(name)) {
             this.order.add(name);
         }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEncoding.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEncoding.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEncoding.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEncoding.java Thu Feb 14 00:12:34 2008
@@ -20,12 +20,11 @@
 package org.apache.fop.pdf;
 
 // Java
-import java.util.List;
-import java.util.Map;
-import java.util.Iterator;
+import java.util.Collections;
+import java.util.Set;
 
 /**
- * class representing an /Encoding object.
+ * Class representing an /Encoding object.
  *
  * A small object expressing the base encoding name and
  * the differences from the base encoding.
@@ -34,90 +33,113 @@
  *
  * Encodings are specified in section 5.5.5 of the PDF 1.4 spec.
  */
-public class PDFEncoding extends PDFObject {
+public class PDFEncoding extends PDFDictionary {
 
-    /**
-     * the name for the standard encoding scheme
-     */
+    /** the name for the standard encoding scheme */
+    public static final String STANDARD_ENCODING = "StandardEncoding";
+    /** the name for the Mac Roman encoding scheme */
     public static final String MAC_ROMAN_ENCODING = "MacRomanEncoding";
-
-    /**
-     * the name for the standard encoding scheme
-     */
+    /** the name for the Mac Export encoding scheme */
     public static final String MAC_EXPERT_ENCODING = "MacExpertEncoding";
-
-    /**
-     * the name for the standard encoding scheme
-     */
+    /** the name for the WinAnsi encoding scheme */
     public static final String WIN_ANSI_ENCODING = "WinAnsiEncoding";
+    /** the name for the PDF document encoding scheme */
+    public static final String PDF_DOC_ENCODING = "PDFDocEncoding";
 
-    /**
-     * the name for the base encoding.
-     * One of the three base encoding scheme names or
-     * the default font's base encoding if null.
-     */
-    protected String basename;
-
-    /**
-     * the differences from the base encoding
-     */
-    protected Map differences;
+    /** the set of predefined encodings that can be assumed present in a PDF viewer */
+    private static final Set PREDEFINED_ENCODINGS;
+    
+    static {
+        Set encodings = new java.util.HashSet();
+        encodings.add(STANDARD_ENCODING);
+        encodings.add(MAC_ROMAN_ENCODING);
+        encodings.add(MAC_EXPERT_ENCODING);
+        encodings.add(WIN_ANSI_ENCODING);
+        encodings.add(PDF_DOC_ENCODING);
+        PREDEFINED_ENCODINGS = Collections.unmodifiableSet(encodings);
+    }
 
     /**
-     * create the /Encoding object
+     * Create a new /Encoding object.
      *
      * @param basename the name of the character encoding schema
      */
     public PDFEncoding(String basename) {
-
-        /* generic creation of PDF object */
         super();
 
-        /* set fields using paramaters */
-        this.basename = basename;
-        this.differences = new java.util.HashMap();
+        put("Type", new PDFName("Encoding"));
+        if (basename != null) {
+            put("BaseEncoding", new PDFName(basename));
+        }
     }
 
     /**
-     * add differences to the encoding
-     *
-     * @param code the first index of the sequence to be changed
-     * @param sequence the sequence of glyph names (as String)
+     * Indicates whether a given encoding is one of the predefined encodings.
+     * @param name the encoding name (ex. "StandardEncoding")
+     * @return true if it is a predefined encoding
+     */
+    public static boolean isPredefinedEncoding(String name) {
+        return PREDEFINED_ENCODINGS.contains(name);
+    }
+    
+    /**
+     * Creates and returns a new DifferencesBuilder instance for constructing the Differences
+     * array.
+     * @return the DifferencesBuilder
      */
-    public void addDifferences(int code, List sequence) {
-        differences.put(new Integer(code), sequence);
+    public DifferencesBuilder createDifferencesBuilder() {
+        return new DifferencesBuilder();
     }
 
     /**
-     * {@inheritDoc}
+     * Sets the Differences value.
+     * @param differences the differences.
+     */
+    public void setDifferences(PDFArray differences) {
+        put("Differences", differences);
+    }
+    
+    /**
+     * Builder class for constructing the Differences array.
      */
-    public String toPDFString() {
-        StringBuffer p = new StringBuffer(128);
-        p.append(getObjectID() 
-            + "<< /Type /Encoding");
-        if ((basename != null) && (!basename.equals(""))) {
-            p.append("\n/BaseEncoding /" + this.basename);
+    public class DifferencesBuilder {
+        
+        private PDFArray differences = new PDFArray();
+        private int currentCode = -1;
+        
+        /**
+         * Start a new difference.
+         * @param code the starting code index inside the encoding
+         * @return this builder instance
+         */
+        public DifferencesBuilder addDifference(int code) {
+            this.currentCode = code;
+            this.differences.add(new Integer(code));
+            return this;
         }
-        if (!differences.isEmpty()) {
-            p.append("\n/Differences [ ");
-            Object code;
-            Iterator codes = differences.keySet().iterator();
-            while (codes.hasNext()) {
-                code = codes.next();
-                p.append(" ");
-                p.append(code);
-                List sequence = (List)differences.get(code);
-                for (int i = 0; i < sequence.size(); i++) {
-                    p.append(" /");
-                    p.append((String)sequence.get(i));
-                }
+        
+        /**
+         * Adds a character name to the current difference.
+         * @param name the character name
+         * @return this builder instance
+         */
+        public DifferencesBuilder addName(String name) {
+            if (this.currentCode < 0) {
+                throw new IllegalStateException("addDifference(int) must be called first");
             }
-            p.append(" ]");
+            this.differences.add(new PDFName(name));
+            return this;
+        }
+        
+        /**
+         * Creates and returns the PDFArray representing the Differences entry.
+         * @return the Differences entry
+         */
+        public PDFArray toPDFArray() {
+            return this.differences;
         }
-        p.append(" >>\nendobj\n");
-        return p.toString();
     }
-
+    
     /*
      * example (p. 214)
      * 25 0 obj

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java Thu Feb 14 00:12:34 2008
@@ -40,15 +40,18 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.apache.xmlgraphics.fonts.Glyphs;
 import org.apache.xmlgraphics.xmp.Metadata;
 
 import org.apache.fop.fonts.CIDFont;
+import org.apache.fop.fonts.CodePointMapping;
 import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.FontDescriptor;
 import org.apache.fop.fonts.FontMetrics;
 import org.apache.fop.fonts.FontType;
 import org.apache.fop.fonts.LazyFont;
 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.TTFSubSetFile;
@@ -1182,6 +1185,7 @@
         }
 
         if (descriptor == null) {
+            //Usually Base 14 fonts
             PDFFont font = new PDFFont(fontname, FontType.TYPE1, basefont, encoding);
             getDocument().registerObject(font);
             return font;
@@ -1190,30 +1194,11 @@
 
             PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor);
 
-            PDFFontNonBase14 font = null;
-            if (fonttype == FontType.TYPE0) {
-                /*
-                 * Temporary commented out - customized CMaps
-                 * isn't needed until /ToUnicode support is added
-                 * PDFCMap cmap = new PDFCMap(++this.objectcount,
-                 * "fop-ucs-H",
-                 * new PDFCIDSystemInfo("Adobe",
-                 * "Identity",
-                 * 0));
-                 * cmap.addContents();
-                 * this.objects.add(cmap);
-                 */
-                font = (PDFFontNonBase14)PDFFont.createFont(fontname, fonttype,
-                                                            basefont, "Identity-H");
-            } else {
-
-                font = (PDFFontNonBase14)PDFFont.createFont(fontname, fonttype,
-                                                            basefont, encoding);
-            }
+            PDFFont font = null;
+            font = (PDFFont)PDFFont.createFont(fontname, fonttype,
+                                                        basefont, encoding);
             getDocument().registerObject(font);
 
-            font.setDescriptor(pdfdesc);
-
             if (fonttype == FontType.TYPE0) {
                 CIDFont cidMetrics;
                 if (metrics instanceof LazyFont) {
@@ -1233,7 +1218,7 @@
                                    (PDFCIDFontDescriptor)pdfdesc);
                 getDocument().registerObject(cidFont);
 
-                PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics, "fop-ucs-H",
+                PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics.getCharsUsed(), "fop-ucs-H",
                     new PDFCIDSystemInfo("Adobe",
                         "Identity",
                         0));
@@ -1241,16 +1226,57 @@
                 ((PDFFontType0)font).setCMAP(cmap);
                 ((PDFFontType0)font).setDescendantFonts(cidFont);
             } else {
-                int firstChar = 0;
-                int lastChar = 255;
-                if (metrics instanceof CustomFont) {
-                    CustomFont cf = (CustomFont)metrics;
-                    firstChar = cf.getFirstChar();
-                    lastChar = cf.getLastChar();
+                PDFFontNonBase14 nonBase14 = (PDFFontNonBase14)font;
+                nonBase14.setDescriptor(pdfdesc);
+
+                SingleByteFont singleByteFont;
+                if (metrics instanceof LazyFont) {
+                    singleByteFont = (SingleByteFont)((LazyFont)metrics).getRealFont();
+                } else {
+                    singleByteFont = (SingleByteFont)metrics;
                 }
-                font.setWidthMetrics(firstChar,
+                int firstChar = singleByteFont.getFirstChar();
+                int lastChar = singleByteFont.getLastChar();
+                nonBase14.setWidthMetrics(firstChar,
                                      lastChar,
                                      makeArray(metrics.getWidths()));
+                
+                //Handle encoding
+                CodePointMapping mapping = singleByteFont.getCodePointMapping();
+                if (PDFEncoding.isPredefinedEncoding(mapping.getName())) {
+                    font.setEncoding(mapping.getName());
+                } else {
+                    CodePointMapping winansi = CodePointMapping.getMapping(
+                            CodePointMapping.WIN_ANSI_ENCODING);
+                    PDFEncoding pdfEncoding = new PDFEncoding(winansi.getName());
+                    PDFEncoding.DifferencesBuilder builder
+                            = pdfEncoding.createDifferencesBuilder();
+                    int start = -1;
+                    for (int i = 0; i < 256; i++) {
+                        char wac = winansi.getUnicodeForIndex(i);
+                        char c = mapping.getUnicodeForIndex(i);
+                        if (wac != c) {
+                            if (start != i) {
+                                builder.addDifference(i);
+                                start = i;
+                            }
+                            builder.addName(Glyphs.charToGlyphName(c));
+                            start++;
+                        }
+                    }
+                    pdfEncoding.setDifferences(builder.toPDFArray());
+                    font.setEncoding(pdfEncoding);
+                    
+                    /* JM: What I thought would be a necessity with custom encodings turned out to
+                     * be a bug in Adobe Acrobat 8. The following section just demonstrates how
+                     * to generate a ToUnicode CMap for a Type 1 font. 
+                    PDFCMap cmap = new PDFToUnicodeCMap(mapping.getUnicodeCharMap(),
+                            "fop-ucs-H",
+                            new PDFCIDSystemInfo("Adobe", "Identity", 0));
+                    getDocument().registerObject(cmap);
+                    nonBase14.setToUnicode(cmap);
+                    */
+                }
             }
 
             return font;

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFont.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFont.java Thu Feb 14 00:12:34 2008
@@ -30,38 +30,11 @@
  * <p>
  * Fonts are specified on page 198 and onwards of the PDF 1.3 spec.
  */
-public class PDFFont extends PDFObject {
-
-    /**
-     * the internal name for the font (eg "F1")
-     */
-    protected String fontname;
-
-    /**
-     * the font's subtype
-     * (as defined by the constants FontType: TYPE0, TYPE1, MMTYPE1, TYPE3, TRUETYPE)
-     */
-    protected FontType subtype;
-
-    /**
-     * the base font name (eg "Helvetica")
-     */
-    protected String basefont;
-
-    /**
-     * the character encoding scheme used by the font.
-     * It can be a String for standard encodings, or
-     * a PDFEncoding for a more complex scheme, or
-     * a PDFStream containing a CMap in a Type0 font.
-     * If <code>null</code> then not written out in the PDF.
-     */
-    protected Object encoding;
-
-    /**
-     * the Unicode mapping mechanism
-     */
-    // protected PDFToUnicode mapping;
+public class PDFFont extends PDFDictionary {
 
+    /** Internal F-number for each font (it is not written to the font dict) */
+    private String fontname;
+    
     /**
      * create the /Font object
      *
@@ -72,20 +45,46 @@
      */
     public PDFFont(String fontname, FontType subtype,
                    String basefont,
-                   Object encoding /* , PDFToUnicode mapping */) {
+                   Object encoding) {
 
         /* generic creation of PDF object */
         super();
 
-        /* set fields using paramaters */
         this.fontname = fontname;
-        this.subtype = subtype;
-        this.basefont = basefont;
-        this.encoding = encoding;
-        // this.mapping = mapping;
+        put("Type", new PDFName("Font"));
+        put("Subtype", getPDFNameForFontType(subtype));
+        //put("Name", new PDFName(fontname));
+        put("BaseFont", new PDFName(basefont));
+        if (encoding instanceof PDFEncoding) {
+            setEncoding((PDFEncoding)encoding);
+        } else if (encoding instanceof String) {
+            setEncoding((String)encoding);
+        } else {
+            throw new IllegalArgumentException("Illegal value for encoding");
+        }
     }
 
     /**
+     * Sets the Encoding value of the font.
+     * @param encoding the encoding
+     */
+    public void setEncoding(String encoding) {
+        if (encoding != null) {
+            put("Encoding", new PDFName(encoding));
+        }
+    }
+    
+    /**
+     * Sets the Encoding value of the font.
+     * @param encoding the encoding
+     */
+    public void setEncoding(PDFEncoding encoding) {
+        if (encoding != null) {
+            put("Encoding", encoding);
+        }
+    }
+    
+    /**
      * factory method with the basic parameters
      *
      * @param fontname the internal name for the font
@@ -111,80 +110,42 @@
             return new PDFFontTrueType(fontname, basefont,
                                        encoding);
         } else {
-            return null;    // should not happend
-        }
-    }
-
-    /**
-     * factory method with the extended parameters
-     * for Type1, MMType1 and TrueType
-     *
-     * @param fontname the internal name for the font
-     * @param subtype the font's subtype
-     * @param basefont the base font name
-     * @param encoding the character encoding schema used by the font
-     * @param firstChar the first character code in the font
-     * @param lastChar the last character code in the font
-     * @param widths an array of size (lastChar - firstChar +1)
-     * @param descriptor the descriptor for other font's metrics
-     * @return the generated PDFFont object
-     */
-    public static PDFFont createFont(String fontname,
-                                     FontType subtype, String basefont,
-                                     Object encoding, int firstChar,
-                                     int lastChar, PDFArray widths,
-                                     PDFFontDescriptor descriptor) {
-
-        PDFFontNonBase14 font;
-        if (subtype == FontType.TYPE0) {
-            font = new PDFFontType0(fontname, basefont,
-                                    encoding);
-            font.setDescriptor(descriptor);
-            return font;
-        } else if ((subtype == FontType.TYPE1) 
-                || (subtype == FontType.MMTYPE1)) {
-            font = new PDFFontType1(fontname, basefont,
-                                    encoding);
-            font.setWidthMetrics(firstChar, lastChar, widths);
-            font.setDescriptor(descriptor);
-            return font;
-        } else if (subtype == FontType.TYPE3) {
-            return null; //NYI, should not happend
-        } else if (subtype == FontType.TRUETYPE) {
-            font = new PDFFontTrueType(fontname, basefont,
-                                       encoding);
-            font.setWidthMetrics(firstChar, lastChar, widths);
-            font.setDescriptor(descriptor);
-            return font;
-        } else {
-            return null;    // should not happend
+            return null;    // should not happen
         }
     }
 
     /**
-     * get the internal name used for this font
+     * Get the internal name used for this font.
      * @return the internal name
      */
     public String getName() {
         return this.fontname;
     }
+    
+    /**
+     * Returns the name of the BaseFont.
+     * @return the BaseFont
+     */
+    public PDFName getBaseFont() {
+        return (PDFName)get("BaseFont");
+    }
 
     /**
      * Returns the PDF name for a certain font type.
      * @param fontType font type
      * @return String corresponding PDF name
      */
-    protected String getPDFNameForFontType(FontType fontType) {
+    protected PDFName getPDFNameForFontType(FontType fontType) {
         if (fontType == FontType.TYPE0) {
-            return fontType.getName();
+            return new PDFName(fontType.getName());
         } else if (fontType == FontType.TYPE1) {
-            return fontType.getName();
+            return new PDFName(fontType.getName());
         } else if (fontType == FontType.MMTYPE1) {
-            return fontType.getName();
+            return new PDFName(fontType.getName());
         } else if (fontType == FontType.TYPE3) {
-            return fontType.getName();
+            return new PDFName(fontType.getName());
         } else if (fontType == FontType.TRUETYPE) {
-            return fontType.getName();
+            return new PDFName(fontType.getName());
         } else {
             throw new IllegalArgumentException("Unsupported font type: " + fontType.getName());
         }
@@ -198,46 +159,9 @@
             if (this.getClass() == PDFFont.class) {
                 throw new PDFConformanceException("For " + getDocumentSafely().getProfile() 
                     + ", all fonts, even the base 14"
-                    + " fonts, have to be embedded! Offending font: " + this.basefont);
+                    + " fonts, have to be embedded! Offending font: " + getBaseFont());
             }
         }
     }
     
-    /**
-     * {@inheritDoc}
-     */
-    public String toPDFString() {
-        validate();
-        StringBuffer p = new StringBuffer(128);
-        p.append(getObjectID());
-        p.append("<< /Type /Font\n/Subtype /"
-                 + getPDFNameForFontType(this.subtype)
-                 + "\n/Name /" + this.fontname
-                 + "\n/BaseFont /" + this.basefont);
-        if (encoding != null) {
-            p.append("\n/Encoding ");
-            if (encoding instanceof PDFEncoding) {
-                p.append(((PDFEncoding)this.encoding).referencePDF());
-            } else if (encoding instanceof PDFStream) {
-                p.append(((PDFStream)this.encoding).referencePDF());
-            } else {
-                p.append("/").append((String)encoding);
-            }
-        }
-        fillInPDF(p);
-        p.append(" >>\nendobj\n");
-        return p.toString();
-    }
-
-    /**
-     * This method is called to receive the specifics for the font's subtype.
-     * <p>
-     * The given buffer already contains the fields common to all font types.
-     *
-     * @param target the buffer to be completed with the type specific fields
-     */
-    protected void fillInPDF(StringBuffer target) {
-        //nop
-    }
-
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontDescriptor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontDescriptor.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontDescriptor.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontDescriptor.java Thu Feb 14 00:12:34 2008
@@ -26,29 +26,7 @@
  * <p>
  * Font descriptors are specified on page 222 and onwards of the PDF 1.3 spec.
  */
-public class PDFFontDescriptor extends PDFObject {
-
-    // Required fields
-    private int ascent;
-    private int capHeight;
-    private int descent;
-    private int flags;
-    private PDFRectangle fontBBox;
-    private String basefont;    // PDF-spec: FontName
-    private int italicAngle;
-    private int stemV;
-    // Optional fields
-    private int stemH = 0;
-    private int xHeight = 0;
-    private int leading = 0;
-    private int avgWidth = 0;
-    private int maxWidth = 0;
-    private int missingWidth = 0;
-    private AbstractPDFStream fontfile;
-    private AbstractPDFStream cidSet;
-    // private String charSet = null;
-
-    private FontType subtype;
+public class PDFFontDescriptor extends PDFDictionary {
 
     /**
      * Create the /FontDescriptor object
@@ -66,19 +44,17 @@
                              int descent, int capHeight, int flags,
                              PDFRectangle fontBBox, int italicAngle,
                              int stemV) {
-
-        /* generic creation of PDF object */
         super();
 
-        /* set fields using paramaters */
-        this.basefont = basefont;
-        this.ascent = ascent;
-        this.descent = descent;
-        this.capHeight = capHeight;
-        this.flags = flags;
-        this.fontBBox = fontBBox;
-        this.italicAngle = italicAngle;
-        this.stemV = stemV;
+        put("Type", new PDFName("FontDescriptor"));
+        put("FontName", new PDFName(basefont));
+        put("FontBBox", fontBBox);
+        put("Flags", flags);
+        put("CapHeight", capHeight);
+        put("Ascent", ascent);
+        put("Descent", descent);
+        put("ItalicAngle", italicAngle);
+        put("StemV", stemV);
     }
 
     /**
@@ -97,12 +73,24 @@
      */
     public void setMetrics(int avgWidth, int maxWidth, int missingWidth,
                            int leading, int stemH, int xHeight) {
-        this.avgWidth = avgWidth;
-        this.maxWidth = maxWidth;
-        this.missingWidth = missingWidth;
-        this.leading = leading;
-        this.stemH = stemH;
-        this.xHeight = xHeight;
+        if (avgWidth != 0) {
+            put("AvgWidth", avgWidth);
+        }
+        if (maxWidth != 0) {
+            put("MaxWidth", maxWidth);
+        }
+        if (missingWidth != 0) {
+            put("MissingWidth", missingWidth);
+        }
+        if (leading != 0) {
+            put("Leading", leading);
+        }
+        if (stemH != 0) {
+            put("StemH", stemH);
+        }
+        if (xHeight != 0) {
+            put("XHeight", xHeight);
+        }
     }
 
     /**
@@ -112,13 +100,24 @@
      * @param fontfile the stream containing an embedded font
      */
     public void setFontFile(FontType subtype, AbstractPDFStream fontfile) {
-        this.subtype = subtype;
-        this.fontfile = fontfile;
+        if (subtype == FontType.TYPE1) {
+            put("FontFile", fontfile);
+        } else {
+            put("FontFile2", fontfile);
+        }
     }
 
     /** @return the FontFile or null if the font is not embedded */
     public AbstractPDFStream getFontFile() {
-        return this.fontfile;
+        AbstractPDFStream stream;
+        stream = (AbstractPDFStream)get("FontFile");
+        if (stream == null) {
+            stream = (AbstractPDFStream)get("FontFile2");
+        }
+        if (stream == null) {
+            stream = (AbstractPDFStream)get("FontFile3");
+        }
+        return stream;
     }
     
     /**
@@ -126,19 +125,18 @@
      * @param cidSet the CIDSet stream
      */
     public void setCIDSet(AbstractPDFStream cidSet) {
-        this.cidSet = cidSet;
+        put("CIDSet", cidSet);
     }
     
     /** @return the CIDSet stream or null if not applicable */
     public AbstractPDFStream getCIDSet() {
-        return this.cidSet;
+        return (AbstractPDFStream)get("CIDSet");
     }
     
-    // public void setCharSet(){}//for subset fonts
-
     /**
      * {@inheritDoc}
      */
+    /*
     public String toPDFString() {
         StringBuffer p = new StringBuffer(128);
         p.append(getObjectID() 
@@ -201,7 +199,7 @@
         fillInPDF(p);
         p.append(" >>\nendobj\n");
         return p.toString();
-    }
+    }*/
 
     /**
      * Fill in the specifics for the font's descriptor.
@@ -209,9 +207,9 @@
      * The given buffer already contains the fields common to all descriptors.
      *
      * @param begin the buffer to be completed with the specific fields
-     */
+     *//*
     protected void fillInPDF(StringBuffer begin) {
         //nop
-    }
+    }*/
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontNonBase14.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontNonBase14.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontNonBase14.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontNonBase14.java Thu Feb 14 00:12:34 2008
@@ -28,26 +28,6 @@
 public abstract class PDFFontNonBase14 extends PDFFont {
 
     /**
-     * first character code in the font
-     */
-    protected int firstChar;
-
-    /**
-     * last character code in the font
-     */
-    protected int lastChar;
-
-    /**
-     * widths of characters from firstChar to lastChar
-     */
-    protected PDFArray widths;
-
-    /**
-     * descriptor of font metrics
-     */
-    protected PDFFontDescriptor descriptor;
-
-    /**
      * Create the /Font object
      *
      * @param fontname the internal name for the font
@@ -61,8 +41,6 @@
 
         /* generic creation of PDF object */
         super(fontname, subtype, basefont, encoding);
-
-        this.descriptor = null;
     }
 
     /**
@@ -74,10 +52,9 @@
      */
     public void setWidthMetrics(int firstChar, int lastChar,
                                 PDFArray widths) {
-        /* set fields using paramaters */
-        this.firstChar = firstChar;
-        this.lastChar = lastChar;
-        this.widths = widths;
+        put("FirstChar", new Integer(firstChar));
+        put("LastChar", new Integer(lastChar));
+        put("Widths", widths);
     }
 
     /**
@@ -86,12 +63,20 @@
      * @param descriptor the descriptor for other font's metrics
      */
     public void setDescriptor(PDFFontDescriptor descriptor) {
-        this.descriptor = descriptor;
+        put("FontDescriptor", descriptor);
     }
 
     /** @return the FontDescriptor or null if there is none */
     public PDFFontDescriptor getDescriptor() {
-        return this.descriptor;
+        return (PDFFontDescriptor)get("FontDescriptor");
+    }
+    
+    /**
+     * Sets a ToUnicode CMap.
+     * @param cmap the ToUnicode character map
+     */
+    public void setToUnicode(PDFCMap cmap) {
+        put("ToUnicode", cmap);
     }
     
     /** {@inheritDoc} */
@@ -104,20 +89,4 @@
         }
     }
     
-    /**
-     * {@inheritDoc}
-     */
-    protected void fillInPDF(StringBuffer target) {
-        target.append("\n/FirstChar ");
-        target.append(firstChar);
-        target.append("\n/LastChar ");
-        target.append(lastChar);
-        target.append("\n/Widths ");
-        target.append(this.widths.referencePDF());
-        if (descriptor != null) {
-            target.append("\n/FontDescriptor ");
-            target.append(this.descriptor.referencePDF());
-        }
-    }
-
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontTrueType.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontTrueType.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontTrueType.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontTrueType.java Thu Feb 14 00:12:34 2008
@@ -39,9 +39,7 @@
     public PDFFontTrueType(String fontname, 
                            String basefont,
                            Object encoding) {
-
-        /* generic creation of PDF object */
-        super(fontname, FontType.TRUETYPE, basefont, encoding /* , mapping */);
+        super(fontname, FontType.TRUETYPE, basefont, encoding);
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontType0.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontType0.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontType0.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontType0.java Thu Feb 14 00:12:34 2008
@@ -26,17 +26,7 @@
  * <p>
  * Type0 fonts are specified on page 208 and onwards of the PDF 1.3 spec.
  */
-public class PDFFontType0 extends PDFFontNonBase14 {
-
-    /**
-     * This should be an array of CIDFont but only the first one is used
-     */
-    protected PDFCIDFont descendantFonts;
-
-    /**
-     * The character map
-     */
-    protected PDFCMap cmap;
+public class PDFFontType0 extends PDFFont {
 
     /**
      * Create the /Font object
@@ -48,13 +38,7 @@
     public PDFFontType0(String fontname, 
                         String basefont,
                         Object encoding) {
-
-        /* generic creation of PDF object */
-        super(fontname, FontType.TYPE0, basefont, encoding /* , mapping */);
-
-        /* set fields using paramaters */
-        this.descendantFonts = null;
-        cmap = null;
+        super(fontname, FontType.TYPE0, basefont, encoding);
     }
 
     /**
@@ -69,12 +53,9 @@
                         String basefont,
                         Object encoding, 
                         PDFCIDFont descendantFonts) {
+        super(fontname, FontType.TYPE0, basefont, encoding);
 
-        /* generic creation of PDF object */
-        super(fontname, FontType.TYPE0, basefont, encoding /* , mapping */);
-
-        /* set fields using paramaters */
-        this.descendantFonts = descendantFonts;
+        setDescendantFonts(descendantFonts);
     }
 
     /**
@@ -82,7 +63,7 @@
      * @param descendantFonts the CIDFont upon which this font is based
      */
     public void setDescendantFonts(PDFCIDFont descendantFonts) {
-        this.descendantFonts = descendantFonts;
+        put("DescendantFonts", new PDFArray(this, new PDFObject[] {descendantFonts}));
     }
 
     /**
@@ -90,20 +71,7 @@
      * @param cmap the character map
      */
     public void setCMAP(PDFCMap cmap) {
-        this.cmap = cmap;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void fillInPDF(StringBuffer target) {
-        if (descendantFonts != null) {
-            target.append("\n/DescendantFonts [ "
-                     + this.descendantFonts.referencePDF() + " ] ");
-        }
-        if (cmap != null) {
-            target.append("\n/ToUnicode " + cmap.referencePDF());
-        }
+        put("ToUnicode", cmap);
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontType3.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontType3.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontType3.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFontType3.java Thu Feb 14 00:12:34 2008
@@ -32,26 +32,6 @@
 public class PDFFontType3 extends PDFFontNonBase14 {
 
     /**
-     * font's required /FontBBox bounding box
-     */
-    protected PDFRectangle fontBBox;
-
-    /**
-     * font's required /FontMatrix array
-     */
-    protected PDFArray fontMatrix;
-
-    /**
-     * font's required /CharProcs dictionary
-     */
-    protected PDFCharProcs charProcs;
-
-    /**
-     * font's optional /Resources object
-     */
-    protected PDFResources resources;
-
-    /**
      * Create the /Font object
      *
      * @param fontname the internal name for the font
@@ -61,13 +41,7 @@
     public PDFFontType3(String fontname, 
                         String basefont,
                         Object encoding) {
-
-        /* generic creation of PDF object */
-        super(fontname, FontType.TYPE3, basefont, encoding /* , mapping */);
-
-        this.fontBBox = null;
-        this.fontMatrix = null;
-        this.charProcs = null;
+        super(fontname, FontType.TYPE3, basefont, encoding);
     }
 
     /**
@@ -89,9 +63,9 @@
         /* generic creation of PDF object */
         super(fontname, FontType.TYPE3, basefont, encoding /* , mapping */);
 
-        this.fontBBox = fontBBox;
-        this.fontMatrix = fontMatrix;
-        this.charProcs = charProcs;
+        setFontBBox(fontBBox);
+        setFontMatrix(fontMatrix);
+        setCharProcs(charProcs);
     }
 
     /**
@@ -100,7 +74,7 @@
      * @param bbox bounding box for the font
      */
     public void setFontBBox(PDFRectangle bbox) {
-        this.fontBBox = bbox;
+        put("FontBBox", bbox);
     }
 
     /**
@@ -109,7 +83,7 @@
      * @param matrix the transformation matrix for the font
      */
     public void setFontMatrix(PDFArray matrix) {
-        this.fontMatrix = matrix;
+        put("FontMatrix", matrix);
     }
 
     /**
@@ -120,25 +94,7 @@
      * @param chars the glyphs' dictionary
      */
     public void setCharProcs(PDFCharProcs chars) {
-        this.charProcs = chars;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void fillInPDF(StringBuffer target) {
-        if (fontBBox != null) {
-            target.append("\n/FontBBox ");
-            target.append(fontBBox.toPDF());
-        }
-        if (fontMatrix != null) {
-            target.append("\n/FontMatrix ");
-            target.append(fontMatrix.toPDF());
-        }
-        if (charProcs != null) {
-            target.append("\n/CharProcs ");
-            target.append(charProcs.referencePDF());
-        }
+        put("CharProcs", chars);
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java Thu Feb 14 00:12:34 2008
@@ -103,7 +103,9 @@
      */
     public void setObjectNumber(int objnum) {
         this.objnum = objnum;
+        PDFDocument doc = getDocument();
         setParent(null);
+        setDocument(doc); //Restore reference to PDFDocument after setting parent to null
         if (log.isTraceEnabled()) {
             log.trace("Assigning " + this + " object number " + objnum);
         }
@@ -141,7 +143,8 @@
     public final PDFDocument getDocumentSafely() {
         final PDFDocument doc = getDocument();
         if (doc == null) {
-            throw new IllegalStateException("Parent PDFDocument is unavailable");
+            throw new IllegalStateException("Parent PDFDocument is unavailable on "
+                    + getClass().getName());
         }
         return doc;
     }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java Thu Feb 14 00:12:34 2008
@@ -19,12 +19,16 @@
  
 package org.apache.fop.pdf;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
 /**
  * class representing a rectangle
  *
  * Rectangles are specified on page 183 of the PDF 1.3 spec.
  */
-public class PDFRectangle {
+public class PDFRectangle implements PDFWritable {
 
     /**
      * lower left x coordinate
@@ -73,23 +77,17 @@
         this.ury = array[3];
     }
 
-    /**
-     * produce the PDF representation for the object
-     *
-     * @return the PDF
-     */
-    public byte[] toPDF() {
-        return PDFDocument.encode(toPDFString());
+    private String format() {
+        return "[" + llx + " " + lly + " " + urx + " " + ury + "]";
     }
 
-    /**
-     * Create a PDF string for this rectangle.
-     *
-     * @return the pdf string
-     */
-    public String toPDFString() {
-        return new String(" [" + llx + " " + lly + " " + urx + " " + ury
-                          + "] ");
+    /** {@inheritDoc} */
+    public String toString() {
+        return "PDFRectangle" + format();
     }
 
+    /** {@inheritDoc} */
+    public void outputInline(OutputStream out, Writer writer) throws IOException {
+        writer.write(format());
+    }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFT1Stream.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFT1Stream.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFT1Stream.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFT1Stream.java Thu Feb 14 00:12:34 2008
@@ -23,7 +23,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 
-// FOP
 import org.apache.fop.fonts.type1.PFBData;
 
 /**
@@ -54,7 +53,9 @@
         if (pfb == null) {
             throw new IllegalStateException("pfb must not be null at this point");
         }
-        log.debug("Writing " + pfb.getLength() + " bytes of Type 1 font data");
+        if (log.isDebugEnabled()) {
+            log.debug("Writing " + pfb.getLength() + " bytes of Type 1 font data");
+        }
 
         int length = super.output(stream);
         log.debug("Embedded Type1 font");

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTTFStream.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTTFStream.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTTFStream.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTTFStream.java Thu Feb 14 00:12:34 2008
@@ -44,7 +44,9 @@
      */
     protected int output(java.io.OutputStream stream)
             throws java.io.IOException {
-        log.debug("Writing " + origLength + " bytes of TTF font data");
+        if (log.isDebugEnabled()) {
+            log.debug("Writing " + origLength + " bytes of TTF font data");
+        }
 
         int length = super.output(stream);
         log.debug("Embedded TrueType/OpenType font");

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java Thu Feb 14 00:12:34 2008
@@ -19,7 +19,8 @@
  
 package org.apache.fop.pdf;
 
-import org.apache.fop.fonts.CIDFont;
+import java.io.IOException;
+import java.io.Writer;
 
 /**
  * Class representing ToUnicode CMaps.
@@ -37,249 +38,251 @@
 public class PDFToUnicodeCMap extends PDFCMap {
 
     /**
-     * handle to read font
+     * The array of Unicode characters ordered by character code
+     * (maps from character code to Unicode code point).
      */
-    protected CIDFont cidFont;
+    protected char[] unicodeCharMap;
 
     /**
      * Constructor.
      *
-     * @param cidMetrics the CID font for which this Unicode CMap is built
+     * @param unicodeCharMap An array of Unicode characters ordered by character code
+     *                          (maps from character code to Unicode code point)
      * @param name One of the registered names found in Table 5.14 in PDF
      * Reference, Second Edition.
      * @param sysInfo The attributes of the character collection of the CIDFont.
      */
-    public PDFToUnicodeCMap(CIDFont cidMetrics, String name, PDFCIDSystemInfo sysInfo) {
+    public PDFToUnicodeCMap(char[] unicodeCharMap, String name, PDFCIDSystemInfo sysInfo) {
         super(name, sysInfo);
-        cidFont = cidMetrics;
+        this.unicodeCharMap = unicodeCharMap;
     }
 
     /** {@inheritDoc} */
-    public void fillInPDF(StringBuffer p) {
-        writeCIDInit(p);
-        writeCIDSystemInfo(p);
-        writeVersionTypeName(p);
-        writeCodeSpaceRange(p);
-        writeBFEntries(p);
-        writeWrapUp(p);
-        add(p.toString());
+    protected CMapBuilder createCMapBuilder(Writer writer) {
+        return new ToUnicodeCMapBuilder(writer);
     }
-
-    /** {@inheritDoc} */
-    protected void writeCIDSystemInfo(StringBuffer p) {
-        p.append("/CIDSystemInfo\n");
-        p.append("<< /Registry (Adobe)\n");
-        p.append("/Ordering (UCS)\n");
-        p.append("/Supplement 0\n");
-        p.append(">> def\n");
-    }
-
-    /** {@inheritDoc} */
-    protected void writeVersionTypeName(StringBuffer p) {
-        p.append("/CMapName /Adobe-Identity-UCS def\n");
-        p.append("/CMapType 2 def\n");
-    }
-
-    /**
-     * Writes the character mappings for this font.
-     * @param p StingBuffer to write to
-     */
-    protected void writeBFEntries(StringBuffer p) {
-        if (cidFont == null) {
-            return;
+    
+    class ToUnicodeCMapBuilder extends CMapBuilder {
+        
+        public ToUnicodeCMapBuilder(Writer writer) {
+            super(writer, null);
         }
 
-        char[] charArray = cidFont.getCharsUsed();
-
-        if (charArray != null) {
-            writeBFCharEntries(p, charArray);
-            writeBFRangeEntries(p, charArray);
+        /**
+         * Writes the CMap to a Writer.
+         * @param writer the writer
+         * @throws IOException if an I/O error occurs
+         */
+        public void writeCMap() throws IOException {
+            writeCIDInit();
+            writeCIDSystemInfo("Adobe", "UCS", 0);
+            writeName("Adobe-Identity-UCS");
+            writeType("2");
+            writeCodeSpaceRange();
+            writeBFEntries();
+            writeWrapUp();
+        }
+        
+        /**
+         * Writes the character mappings for this font.
+         * @param p StingBuffer to write to
+         */
+        protected void writeBFEntries() throws IOException {
+            if (unicodeCharMap != null) {
+                writeBFCharEntries(unicodeCharMap);
+                writeBFRangeEntries(unicodeCharMap);
+            }
         }
-    }
 
-    /**
-     * Writes the entries for single characters of a base font (only characters which cannot be
-     * expressed as part of a character range).
-     * @param p StringBuffer to write to
-     * @param charArray all the characters to map
-     */
-    protected void writeBFCharEntries(StringBuffer p, char[] charArray) {
-        int totalEntries = 0;
-        for (int i = 0; i < charArray.length; i++) {
-            if (!partOfRange(charArray, i)) {
-                totalEntries++;
+        /**
+         * Writes the entries for single characters of a base font (only characters which cannot be
+         * expressed as part of a character range).
+         * @param p StringBuffer to write to
+         * @param charArray all the characters to map
+         * @throws IOException 
+         */
+        protected void writeBFCharEntries(char[] charArray) throws IOException {
+            int totalEntries = 0;
+            for (int i = 0; i < charArray.length; i++) {
+                if (!partOfRange(charArray, i)) {
+                    totalEntries++;
+                }
             }
-        }
-        if (totalEntries < 1) {
-            return;
-        }
-        int remainingEntries = totalEntries;
-        int charIndex = 0;
-        do {
-            /* Limited to 100 entries in each section */
-            int entriesThisSection = Math.min(remainingEntries, 100);
-            p.append(entriesThisSection + " beginbfchar\n");
-            for (int i = 0; i < entriesThisSection; i++) {
-                /* Go to the next char not in a range */
-                while (partOfRange(charArray, charIndex)) {
+            if (totalEntries < 1) {
+                return;
+            }
+            int remainingEntries = totalEntries;
+            int charIndex = 0;
+            do {
+                /* Limited to 100 entries in each section */
+                int entriesThisSection = Math.min(remainingEntries, 100);
+                writer.write(entriesThisSection + " beginbfchar\n");
+                for (int i = 0; i < entriesThisSection; i++) {
+                    /* Go to the next char not in a range */
+                    while (partOfRange(charArray, charIndex)) {
+                        charIndex++;
+                    }
+                    writer.write("<" + padHexString(Integer.toHexString(charIndex), 4) + "> ");
+                    writer.write("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4)
+                            + ">\n");
                     charIndex++;
                 }
-                p.append("<" + padHexString(Integer.toHexString(charIndex), 4) + "> ");
-                p.append("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4) + ">\n");
-                charIndex++;
-            }
-            remainingEntries -= entriesThisSection;
-            p.append("endbfchar\n");
-        } while (remainingEntries > 0);
-    }
+                remainingEntries -= entriesThisSection;
+                writer.write("endbfchar\n");
+            } while (remainingEntries > 0);
+        }
 
-    /**
-     * Writes the entries for character ranges for a base font.
-     * @param p StringBuffer to write to
-     * @param charArray all the characters to map
-     */
-    protected void writeBFRangeEntries(StringBuffer p, char[] charArray) {
-        int totalEntries = 0;
-        for (int i = 0; i < charArray.length; i++) {
-            if (startOfRange(charArray, i)) {
-                totalEntries++;
+        /**
+         * Writes the entries for character ranges for a base font.
+         * @param p StringBuffer to write to
+         * @param charArray all the characters to map
+         * @throws IOException 
+         */
+        protected void writeBFRangeEntries(char[] charArray) throws IOException {
+            int totalEntries = 0;
+            for (int i = 0; i < charArray.length; i++) {
+                if (startOfRange(charArray, i)) {
+                    totalEntries++;
+                }
             }
-        }
-        if (totalEntries < 1) {
-            return;
-        }
-        int remainingEntries = totalEntries;
-        int charIndex = 0;
-        do {
-            /* Limited to 100 entries in each section */
-            int entriesThisSection = Math.min(remainingEntries, 100);
-            p.append(entriesThisSection + " beginbfrange\n");
-            for (int i = 0; i < entriesThisSection; i++) {
-                /* Go to the next start of a range */
-                while (!startOfRange(charArray, charIndex)) {
+            if (totalEntries < 1) {
+                return;
+            }
+            int remainingEntries = totalEntries;
+            int charIndex = 0;
+            do {
+                /* Limited to 100 entries in each section */
+                int entriesThisSection = Math.min(remainingEntries, 100);
+                writer.write(entriesThisSection + " beginbfrange\n");
+                for (int i = 0; i < entriesThisSection; i++) {
+                    /* Go to the next start of a range */
+                    while (!startOfRange(charArray, charIndex)) {
+                        charIndex++;
+                    }
+                    writer.write("<" + padHexString(Integer.toHexString(charIndex), 4) + "> ");
+                    writer.write("<"
+                            + padHexString(Integer.toHexString(endOfRange(charArray, charIndex)), 4)
+                            + "> ");
+                    writer.write("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4)
+                            + ">\n");
                     charIndex++;
                 }
-                p.append("<" + padHexString(Integer.toHexString(charIndex), 4) + "> ");
-                p.append("<"
-                        + padHexString(Integer.toHexString(endOfRange(charArray, charIndex)), 4)
-                        + "> ");
-                p.append("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4) + ">\n");
-                charIndex++;
-            }
-            remainingEntries -= entriesThisSection;
-            p.append("endbfrange\n");
-        } while (remainingEntries > 0);
-    }
-
-    /**
-     * Find the end of the current range.
-     * @param charArray The array which is being tested.
-     * @param startOfRange The index to the array element that is the start of
-     * the range.
-     * @return The index to the element that is the end of the range.
-     */
-    private int endOfRange(char[] charArray, int startOfRange) {
-        int i = startOfRange;
-        while (i < charArray.length - 1 && sameRangeEntryAsNext(charArray, i)) {
-            i++;
+                remainingEntries -= entriesThisSection;
+                writer.write("endbfrange\n");
+            } while (remainingEntries > 0);
         }
-        return i;
-    }
 
-    /**
-     * Determine whether this array element should be part of a bfchar entry or
-     * a bfrange entry.
-     * @param charArray The array to be tested.
-     * @param arrayIndex The index to the array element to be tested.
-     * @return True if this array element should be included in a range.
-     */
-    private boolean partOfRange(char[] charArray, int arrayIndex) {
-        if (charArray.length < 2) {
-            return false;
-        }
-        if (arrayIndex == 0) {
-            return sameRangeEntryAsNext(charArray, 0);
-        }
-        if (arrayIndex == charArray.length - 1) {
-            return sameRangeEntryAsNext(charArray, arrayIndex - 1);
-        }
-        if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) {
-            return true;
-        }
-        if (sameRangeEntryAsNext(charArray, arrayIndex)) {
-            return true;
+        /**
+         * Find the end of the current range.
+         * @param charArray The array which is being tested.
+         * @param startOfRange The index to the array element that is the start of
+         * the range.
+         * @return The index to the element that is the end of the range.
+         */
+        private int endOfRange(char[] charArray, int startOfRange) {
+            int i = startOfRange;
+            while (i < charArray.length - 1 && sameRangeEntryAsNext(charArray, i)) {
+                i++;
+            }
+            return i;
         }
-        return false;
-    }
 
-    /**
-     * Determine whether two bytes can be written in the same bfrange entry.
-     * @param charArray The array to be tested.
-     * @param firstItem The first of the two items in the array to be tested.
-     * The second item is firstItem + 1.
-     * @return True if both 1) the next item in the array is sequential with
-     * this one, and 2) the first byte of the character in the first position
-     * is equal to the first byte of the character in the second position.
-     */
-    private boolean sameRangeEntryAsNext(char[] charArray, int firstItem) {
-        if (charArray[firstItem] + 1 != charArray[firstItem + 1]) {
-            return false;
-        }
-        if (firstItem / 256 != (firstItem + 1) / 256) {
+        /**
+         * Determine whether this array element should be part of a bfchar entry or
+         * a bfrange entry.
+         * @param charArray The array to be tested.
+         * @param arrayIndex The index to the array element to be tested.
+         * @return True if this array element should be included in a range.
+         */
+        private boolean partOfRange(char[] charArray, int arrayIndex) {
+            if (charArray.length < 2) {
+                return false;
+            }
+            if (arrayIndex == 0) {
+                return sameRangeEntryAsNext(charArray, 0);
+            }
+            if (arrayIndex == charArray.length - 1) {
+                return sameRangeEntryAsNext(charArray, arrayIndex - 1);
+            }
+            if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) {
+                return true;
+            }
+            if (sameRangeEntryAsNext(charArray, arrayIndex)) {
+                return true;
+            }
             return false;
         }
-        return true;
-    }
 
-    /**
-     * Determine whether this array element should be the start of a bfrange
-     * entry.
-     * @param charArray The array to be tested.
-     * @param arrayIndex The index to the array element to be tested.
-     * @return True if this array element is the beginning of a range.
-     */
-    private boolean startOfRange(char[] charArray, int arrayIndex) {
-        // Can't be the start of a range if not part of a range.
-        if (!partOfRange(charArray, arrayIndex)) {
-            return false;
-        }
-        // If first element in the array, must be start of a range
-        if (arrayIndex == 0) {
+        /**
+         * Determine whether two bytes can be written in the same bfrange entry.
+         * @param charArray The array to be tested.
+         * @param firstItem The first of the two items in the array to be tested.
+         * The second item is firstItem + 1.
+         * @return True if both 1) the next item in the array is sequential with
+         * this one, and 2) the first byte of the character in the first position
+         * is equal to the first byte of the character in the second position.
+         */
+        private boolean sameRangeEntryAsNext(char[] charArray, int firstItem) {
+            if (charArray[firstItem] + 1 != charArray[firstItem + 1]) {
+                return false;
+            }
+            if (firstItem / 256 != (firstItem + 1) / 256) {
+                return false;
+            }
             return true;
         }
-        // If last element in the array, cannot be start of a range
-        if (arrayIndex == charArray.length - 1) {
-            return false;
-        }
-        /*
-         * If part of same range as the previous element is, cannot be start
-         * of range.
+
+        /**
+         * Determine whether this array element should be the start of a bfrange
+         * entry.
+         * @param charArray The array to be tested.
+         * @param arrayIndex The index to the array element to be tested.
+         * @return True if this array element is the beginning of a range.
          */
-        if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) {
-            return false;
+        private boolean startOfRange(char[] charArray, int arrayIndex) {
+            // Can't be the start of a range if not part of a range.
+            if (!partOfRange(charArray, arrayIndex)) {
+                return false;
+            }
+            // If first element in the array, must be start of a range
+            if (arrayIndex == 0) {
+                return true;
+            }
+            // If last element in the array, cannot be start of a range
+            if (arrayIndex == charArray.length - 1) {
+                return false;
+            }
+            /*
+             * If part of same range as the previous element is, cannot be start
+             * of range.
+             */
+            if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) {
+                return false;
+            }
+            // Otherwise, this is start of a range.
+            return true;
         }
-        // Otherwise, this is start of a range.
-        return true;
-    }
 
-    /**
-     * Prepends the input string with a sufficient number of "0" characters to
-     * get the returned string to be numChars length.
-     * @param input The input string.
-     * @param numChars The minimum characters in the output string.
-     * @return The padded string.
-     */
-    public static String padHexString(String input, int numChars) {
-        int length = input.length();
-        if (length >= numChars) {
-            return input;
-        }
-        StringBuffer returnString = new StringBuffer();
-        for (int i = 1; i <= numChars - length; i++) {
-            returnString.append("0");
+        /**
+         * Prepends the input string with a sufficient number of "0" characters to
+         * get the returned string to be numChars length.
+         * @param input The input string.
+         * @param numChars The minimum characters in the output string.
+         * @return The padded string.
+         */
+        private String padHexString(String input, int numChars) {
+            int length = input.length();
+            if (length >= numChars) {
+                return input;
+            }
+            StringBuffer returnString = new StringBuffer();
+            for (int i = 1; i <= numChars - length; i++) {
+                returnString.append("0");
+            }
+            returnString.append(input);
+            return returnString.toString();
         }
-        returnString.append(input);
-        return returnString.toString();
-    }
 
+    }    
+    
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java Thu Feb 14 00:12:34 2008
@@ -1565,7 +1565,7 @@
                 startPending = false;
             }
             if (!useMultiByte) {
-                if (ch > 127) {
+                if (ch < 32 || ch > 127) {
                     pdf.append("\\");
                     pdf.append(Integer.toOctalString((int) ch));
                 } else {

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java Thu Feb 14 00:12:34 2008
@@ -31,16 +31,18 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.ps.DSCConstants;
+import org.apache.xmlgraphics.ps.PSGenerator;
+import org.apache.xmlgraphics.ps.PSResource;
+import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
+
 import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontType;
 import org.apache.fop.fonts.LazyFont;
 import org.apache.fop.fonts.Typeface;
-import org.apache.xmlgraphics.ps.DSCConstants;
-import org.apache.xmlgraphics.ps.PSGenerator;
-import org.apache.xmlgraphics.ps.PSResource;
-import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
 
 /**
  * Utility code for font handling in PostScript.
@@ -108,8 +110,10 @@
             } else if ("WinAnsiEncoding".equals(fm.getEncoding())) {
                 redefineFontEncoding(gen, fm.getFontName(), fm.getEncoding());
             } else {
+                /* Don't complain anymore, just use the font's default encoding.
                 gen.commentln("%WARNING: Only WinAnsiEncoding is supported. Font '" 
                     + fm.getFontName() + "' asks for: " + fm.getEncoding());
+                */
             }
         }
         gen.commentln("%FOPEndFontReencode");

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/util/CharUtilities.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/util/CharUtilities.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/util/CharUtilities.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/util/CharUtilities.java Thu Feb 14 00:12:34 2008
@@ -68,7 +68,10 @@
     public static final char ZERO_WIDTH_NOBREAK_SPACE = '\uFEFF';
     /** soft hyphen */
     public static final char SOFT_HYPHEN = '\u00AD';
-
+    /** missing ideograph */
+    public static final char MISSING_IDEOGRAPH = '\u25A1';
+    /** Unicode value indicating the the character is "not a character". */
+    public static final char NOT_A_CHARACTER = '\uFFFF';
 
     /**
      * Utility class: Constructor prevents instantiating when subclassed.

Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Thu Feb 14 00:12:34 2008
@@ -28,6 +28,10 @@
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Fonts" dev="JM" type="add">
+        Added support for unusual font encodings (like for Symbol or Cyrillic fonts) of Type 1
+        fonts in PDF and PostScript output.
+      </action>
       <action context="Layout" dev="VH" type="fix" fixes-bug="44321">
         Moved to the FO tree stage the check for break-before/after on table-row while spanning in
         progress.

Modified: xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java?rev=627679&r1=627678&r2=627679&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java (original)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFCMapTestCase.java Thu Feb 14 00:12:34 2008
@@ -19,14 +19,16 @@
 
 package org.apache.fop.render.pdf;
 
-import org.apache.fop.pdf.PDFCMap;
+import java.io.StringWriter;
 
 import junit.framework.TestCase;
 
+import org.apache.fop.pdf.CMapBuilder;
+
 /** Simple sanity test of the PDFCmap class */
 public class PDFCMapTestCase extends TestCase {
     
-    public void testPDFCMapFillInPDF() {
+    public void testPDFCMapFillInPDF() throws Exception {
         final String EOL = "\n";
         final String expected = 
             "%!PS-Adobe-3.0 Resource-CMap" + EOL
@@ -59,10 +61,10 @@
             +"%%EOF" + EOL
         ;
         
-        final PDFCMap m = new PDFCMap("test", null);
-        final StringBuffer b = new StringBuffer();
-        m.fillInPDF(b);
-        final String actual = b.toString();
+        final StringWriter w = new StringWriter();
+        final CMapBuilder builder = new CMapBuilder(w, "test");
+        builder.writeCMap();
+        final String actual = w.getBuffer().toString();
         assertEquals("PDFCMap output matches expected PostScript code", expected, actual);
     }
 



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org