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/03/27 09:49:44 UTC

svn commit: r641742 [1/2] - in /xmlgraphics/fop/trunk: ./ lib/ src/codegen/fonts/ src/java/org/apache/fop/fo/properties/ 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...

Author: jeremias
Date: Thu Mar 27 01:49:41 2008
New Revision: 641742

URL: http://svn.apache.org/viewvc?rev=641742&view=rev
Log:
Added support for addressing all glyphs available in a Type 1 font, not just the ones in the font's primary encoding.
Typeface: getEncoding() changed to getEncodingName() to make clearer what is held here.
Some cleanup in the font classes to put the various things in more appropriate places.
Created a common base class for all Base 14 fonts (makes the hierarchy clearer).
Made PDFTextUtil more universally useful and made use of it in PDFRenderer, too.
Made PDFStream.add(String) more efficient. The encoding converter is not called for each invocation anymore as the whole thing get buffered by a BufferedWriter (as suggested by the javadoc of OutputStreamWriter).

Added:
    xmlgraphics/fop/trunk/lib/xmlgraphics-commons-1.4svn.jar   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Base14Font.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDSubset.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/NamedCharacter.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteEncoding.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java
      - copied, changed from r631256, xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java
Removed:
    xmlgraphics/fop/trunk/lib/xmlgraphics-commons-1.3.jar
Modified:
    xmlgraphics/fop/trunk/fop.bat
    xmlgraphics/fop/trunk/src/codegen/fonts/font-file.xsl
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDFont.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteFont.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Typeface.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMFile.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMParser.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFCMap.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEncoding.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFResources.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFStream.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTTFStream.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java
    xmlgraphics/fop/trunk/status.xml
    xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java

Modified: xmlgraphics/fop/trunk/fop.bat
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/fop.bat?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/fop.bat (original)
+++ xmlgraphics/fop/trunk/fop.bat Thu Mar 27 01:49:41 2008
@@ -61,7 +61,7 @@
 set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xalan-2.7.0.jar
 set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\serializer-2.7.0.jar
 set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\batik-all-1.7.jar
-set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xmlgraphics-commons-1.3.jar
+set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xmlgraphics-commons-1.4svn.jar
 set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\avalon-framework-4.2.0.jar
 set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-io-1.3.1.jar
 set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-logging-1.0.4.jar

Added: xmlgraphics/fop/trunk/lib/xmlgraphics-commons-1.4svn.jar
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/lib/xmlgraphics-commons-1.4svn.jar?rev=641742&view=auto
==============================================================================
Binary file - no diff available.

Propchange: xmlgraphics/fop/trunk/lib/xmlgraphics-commons-1.4svn.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: xmlgraphics/fop/trunk/src/codegen/fonts/font-file.xsl
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/codegen/fonts/font-file.xsl?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/codegen/fonts/font-file.xsl (original)
+++ xmlgraphics/fop/trunk/src/codegen/fonts/font-file.xsl Thu Mar 27 01:49:41 2008
@@ -40,10 +40,10 @@
 </xsl:if>
 import java.util.Set;
 import org.apache.fop.fonts.FontType;
-import org.apache.fop.fonts.Typeface;
+import org.apache.fop.fonts.Base14Font;
 import org.apache.fop.fonts.CodePointMapping;
 
-public class <xsl:value-of select="class-name"/> extends Typeface {
+public class <xsl:value-of select="class-name"/> extends Base14Font {
     private final static String fontName = "<xsl:value-of select="font-name"/>";
     private final static String fullName = "<xsl:value-of select="full-name"/>";
     private final static Set familyNames;
@@ -84,7 +84,7 @@
         this.enableKerning = enableKerning;
     }
 
-    public String getEncoding() {
+    public String getEncodingName() {
         return encoding;
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonHyphenation.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonHyphenation.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonHyphenation.java Thu Mar 27 01:49:41 2008
@@ -21,6 +21,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.expr.PropertyException;
@@ -142,7 +143,7 @@
             FontMetrics metrics = font.getFontMetrics();
             if (metrics instanceof Typeface) {
                 Typeface typeface = (Typeface)metrics;
-                if ("SymbolEncoding".equals(typeface.getEncoding())) {
+                if ("SymbolEncoding".equals(typeface.getEncodingName())) {
                     //SymbolEncoding doesn't have HYPHEN_MINUS, so replace by MINUS_SIGN
                 } else {
                     //only warn if the encoding is not SymbolEncoding
@@ -154,7 +155,7 @@
             FontMetrics metrics = font.getFontMetrics();
             if (metrics instanceof Typeface) {
                 Typeface typeface = (Typeface)metrics;
-                if ("ZapfDingbatsEncoding".equals(typeface.getEncoding())) {
+                if ("ZapfDingbatsEncoding".equals(typeface.getEncodingName())) {
                     //ZapfDingbatsEncoding doesn't have HYPHEN_MINUS, so replace by ' '
                 } else {
                     //only warn if the encoding is not ZapfDingbatsEncoding

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java Thu Mar 27 01:49:41 2008
@@ -29,7 +29,7 @@
 /**
  * Abstract base class for code point mapping classes (1-byte character encodings).
  */
-public class AbstractCodePointMapping {
+public class AbstractCodePointMapping implements SingleByteEncoding {
 
     private String name;
     private char[] latin1Map;
@@ -114,19 +114,12 @@
         }
     }
 
-    /**
-     * Returns the encoding's name.
-     * @return the name of the encoding
-     */
+    /** {@inheritDoc} */
     public String getName() {
         return this.name;
     }
 
-    /**
-     * Maps a Unicode character to a code point in the encoding.
-     * @param c the Unicode character to map
-     * @return the coid point in the encoding or 0 (=.notdef) if not found
-     */
+    /** {@inheritDoc} */
     public final char mapChar(char c) {
         if (c < 256) {
             char latin1 = latin1Map[c];
@@ -172,8 +165,8 @@
             }
         }
         
-        putFallbackCharacter(c, '\0');
-        return 0;
+        putFallbackCharacter(c, NOT_FOUND_CODE_POINT);
+        return NOT_FOUND_CODE_POINT;
     }
 
     private void putFallbackCharacter(char c, char mapTo) {
@@ -227,11 +220,7 @@
         return -1;
     }
     
-    /**
-     * Returns the array of character names for this encoding.
-     * @return the array of character names
-     *                  (unmapped code points are represented by a ".notdef" value)
-     */
+    /** {@inheritDoc} */
     public String[] getCharNameMap() {
         if (this.charNameMap != null) {
             String[] copy = new String[this.charNameMap.length];

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Base14Font.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Base14Font.java?rev=641742&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Base14Font.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Base14Font.java Thu Mar 27 01:49:41 2008
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+ 
+package org.apache.fop.fonts;
+
+/**
+ * Base class for all Base 14 fonts.
+ */
+public abstract class Base14Font extends Typeface {
+
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Base14Font.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Base14Font.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDFont.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDFont.java Thu Mar 27 01:49:41 2008
@@ -20,31 +20,14 @@
 package org.apache.fop.fonts;
 
 //Java
-import java.util.Map;
 
 /**
  * Abstract base class for CID fonts.
  */
 public abstract class CIDFont extends CustomFont {
 
-    /**
-     * usedGlyphs contains orginal, new glyph index
-     */
-    public Map usedGlyphs = new java.util.HashMap();
-
-    /**
-     * usedGlyphsIndex contains new glyph, original index
-     */
-    public Map usedGlyphsIndex = new java.util.HashMap();
-    public int usedGlyphsCount = 0;
-
-    /**
-     * usedCharsIndex contains new glyph, original char
-     */
-    public Map usedCharsIndex = new java.util.HashMap();
-
-    //private PDFWArray warray = new PDFWArray();
-    public int width[] = null;
+    /** Contains the character widths for all characters in the font */
+    protected int[] width = null;
 
     // ---- Required ----
     /**
@@ -73,6 +56,11 @@
      */
     public abstract int getSupplement();
 
+    /**
+     * Returns the subset information for this font.
+     * @return the subset information
+     */
+    public abstract CIDSubset getCIDSubset();
 
     // ---- Optional ----
     /**
@@ -88,9 +76,4 @@
         return true;
     }
 
-    /**
-     * Returns a char array containing all Unicode characters that have been accessed.
-     * @return a char array with all used Unicode characters
-     */
-    public abstract char[] getCharsUsed();
 }

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDSubset.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDSubset.java?rev=641742&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDSubset.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDSubset.java Thu Mar 27 01:49:41 2008
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts;
+
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.fop.util.CharUtilities;
+
+//Naming:
+//glyph index: original index of the glyph in the non-subset font (!= unicode index)
+//character selector: index into a set of glyphs. For subset CID fonts, this starts at 0. For
+//  non-subset fonts, this is the same as the glyph index.
+//Unicode index: The Unicode codepoint of a character.
+//Glyph name: the Adobe glyph name (as found in Glyphs.java)
+
+/**
+ * Keeps track of the glyphs used in a document. This information is later used to build
+ * a subset of a font.
+ */
+public class CIDSubset {
+
+    /**
+     * usedGlyphs contains orginal, new glyph index (glyph index -> char selector)
+     */
+    private Map/*<Integer, Integer>*/ usedGlyphs = new java.util.HashMap();
+
+    /**
+     * usedGlyphsIndex contains new glyph, original index (char selector -> glyph index)
+     */
+    private Map/*<Integer, Integer>*/ usedGlyphsIndex = new java.util.HashMap();
+    private int usedGlyphsCount = 0;
+
+    /**
+     * usedCharsIndex contains new glyph, original char (char selector -> Unicode)
+     */
+    private Map/*<Integer, Character>*/ usedCharsIndex = new java.util.HashMap();
+    
+    public CIDSubset() {
+    }
+    
+    /**
+     * Adds the initial 3 glyphs which are the same for all CID subsets.
+     */
+    public void setupFirstThreeGlyphs() {
+        // Make sure that the 3 first glyphs are included
+        usedGlyphs.put(new Integer(0), new Integer(0));
+        usedGlyphsIndex.put(new Integer(0), new Integer(0));
+        usedGlyphsCount++;
+        usedGlyphs.put(new Integer(1), new Integer(1));
+        usedGlyphsIndex.put(new Integer(1), new Integer(1));
+        usedGlyphsCount++;
+        usedGlyphs.put(new Integer(2), new Integer(2));
+        usedGlyphsIndex.put(new Integer(2), new Integer(2));
+        usedGlyphsCount++;
+    }
+    
+    /**
+     * Returns the original index of the glyph inside the (non-subset) font's glyph list. This
+     * index can be used to access the character width information, for example.
+     * @param subsetIndex the subset index (character selector) to access the glyph
+     * @return the original index (or -1 if no glyph index is available for the subset index)
+     */
+    public int getGlyphIndexForSubsetIndex(int subsetIndex) {
+        Integer glyphIndex = (Integer)usedGlyphsIndex.get(new Integer(subsetIndex));
+        if (glyphIndex != null) {
+            return glyphIndex.intValue();
+        } else {
+            return -1;
+        }
+    }
+    
+    /**
+     * Returns the Unicode value for a subset index (character selector). If there's no such
+     * Unicode value, the "NOT A CHARACTER" (0xFFFF) is returned.
+     * @param subsetIndex the subset index (character selector)
+     * @return the Unicode value or "NOT A CHARACTER" (0xFFFF)
+     */
+    public char getUnicodeForSubsetIndex(int subsetIndex) {
+        Character mapValue = (Character)usedCharsIndex.get(new Integer(subsetIndex));
+        if (mapValue != null) {
+            return mapValue.charValue();
+        } else {
+            return CharUtilities.NOT_A_CHARACTER;
+        }
+    }
+    
+    /**
+     * 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
+     * allocated character selector is returned from the existing map/subset.
+     * @param glyphIndex the glyph index of the character
+     * @param unicode the Unicode index of the character
+     * @return the subset index
+     */
+    public int mapSubsetChar(int glyphIndex, char unicode) {
+        // Reencode to a new subset font or get the reencoded value
+        // IOW, accumulate the accessed characters and build a character map for them
+        Integer subsetCharSelector = (Integer)usedGlyphs.get(new Integer(glyphIndex));
+        if (subsetCharSelector == null) {
+            int selector = usedGlyphsCount;
+            usedGlyphs.put(new Integer(glyphIndex),
+                           new Integer(selector));
+            usedGlyphsIndex.put(new Integer(selector),
+                                new Integer(glyphIndex));
+            usedCharsIndex.put(new Integer(selector),
+                                new Character(unicode));
+            usedGlyphsCount++;
+            return selector;
+        } else {
+            return subsetCharSelector.intValue();
+        }
+    }
+
+    /**
+     * Returns an unmodifiable Map of the font subset. It maps from glyph index to
+     * character selector (i.e. the subset index in this case).
+     * @return Map Map&lt;Integer, Integer&gt; of the font subset
+     */
+    public Map/*<Integer, Integer>*/ getSubsetGlyphs() {
+        return Collections.unmodifiableMap(this.usedGlyphs);
+    }
+    
+    /**
+     * Returns a char array containing all Unicode characters that are in the subset.
+     * @return a char array with all used Unicode characters
+     */
+    public char[] getSubsetChars() {
+        char[] charArray = new char[usedGlyphsCount];
+        for (int i = 0; i < usedGlyphsCount; i++) {
+            charArray[i] = getUnicodeForSubsetIndex(i);
+        }
+        return charArray;
+    }
+
+    /**
+     * Returns the number of glyphs in the subset.
+     * @return the number of glyphs in the subset
+     */
+    public int getSubsetSize() {
+        return this.usedGlyphsCount;
+    }
+    
+    /**
+     * Returns a BitSet with bits set for each available glyph index.
+     * @return a BitSet indicating available glyph indices
+     */
+    public BitSet getGlyphIndexBitSet() {
+        BitSet bitset = new BitSet();
+        Iterator iter = usedGlyphs.keySet().iterator();
+        while (iter.hasNext()) {
+            Integer cid = (Integer)iter.next();
+            bitset.set(cid.intValue());
+        }
+        return bitset;
+    }
+    
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDSubset.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/CIDSubset.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java Thu Mar 27 01:49:41 2008
@@ -199,7 +199,7 @@
 
         // Use default CodePointMapping
         char d = CodePointMapping.getMapping("WinAnsiEncoding").mapChar(c);
-        if (d != 0) {
+        if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
             c = d;
         } else {
             log.warn("Glyph " + (int) c + " not available in font " + fontName);

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java Thu Mar 27 01:49:41 2008
@@ -64,11 +64,10 @@
         this.resolver = resolver;
     }
 
-    /**
-     * String representation of LazyFont
-     */
+    /** {@inheritDoc} */
     public String toString() {
-        return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath + ", kerning=" + useKerning );
+        return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath
+                + ", kerning=" + useKerning );
     }
         
     private void load(boolean fail) {
@@ -80,8 +79,9 @@
                     if (resolver != null) {
                         Source source = resolver.resolve(metricsFileName);
                         if (source == null) {
-                            String err = "Cannot load font: failed to create Source from metrics file " 
-                                + metricsFileName; 
+                            String err
+                                = "Cannot load font: failed to create Source from metrics file " 
+                                    + metricsFileName; 
                             if (fail) {
                                 throw new RuntimeException(err);
                             } else {
@@ -112,8 +112,8 @@
                         src.setSystemId(source.getSystemId()); 
                         reader = new FontReader(src);
                     } else {
-                        reader 
-                            = new FontReader(new InputSource(new URL(metricsFileName).openStream()));
+                        reader = new FontReader(new InputSource(
+                                    new URL(metricsFileName).openStream()));
                     }
                     reader.setKerningEnabled(useKerning);
                     reader.setFontEmbedPath(fontEmbedPath);
@@ -153,12 +153,10 @@
     }
 
     // ---- Font ----
-    /**
-     * {@inheritDoc}
-     */
-    public String getEncoding() {
+    /** {@inheritDoc} */
+    public String getEncodingName() {
         load(true);
-        return realFont.getEncoding();
+        return realFont.getEncodingName();
     }
 
     /**

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java Thu Mar 27 01:49:41 2008
@@ -39,6 +39,9 @@
 
     private String namePrefix = null;    // Quasi unique prefix
 
+    private CIDSubset subset = new CIDSubset();
+    
+    /** A map from Unicode indices to glyph indices */
     private BFEntry[] bfentries = null;
 
     /**
@@ -46,15 +49,7 @@
      */
     public MultiByteFont() {
         // Make sure that the 3 first glyphs are included
-        usedGlyphs.put(new Integer(0), new Integer(0));
-        usedGlyphsIndex.put(new Integer(0), new Integer(0));
-        usedGlyphsCount++;
-        usedGlyphs.put(new Integer(1), new Integer(1));
-        usedGlyphsIndex.put(new Integer(1), new Integer(1));
-        usedGlyphsCount++;
-        usedGlyphs.put(new Integer(2), new Integer(2));
-        usedGlyphsIndex.put(new Integer(2), new Integer(2));
-        usedGlyphsCount++;
+        subset.setupFirstThreeGlyphs();
         
         // Create a quasiunique prefix for fontname
         synchronized (this.getClass()) {
@@ -77,37 +72,27 @@
         setFontType(FontType.TYPE0);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public int getDefaultWidth() {
         return defaultWidth;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public String getRegistry() {
         return "Adobe";
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public String getOrdering() {
         return "UCS";
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public int getSupplement() {
         return 0;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public CIDFontType getCIDType() {
         return cidType;
     }
@@ -133,68 +118,47 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public boolean isEmbeddable() {
         return !(getEmbedFileName() == null && getEmbedResourceName() == null);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public String getEncoding() {
+    /** {@inheritDoc} */
+    public CIDSubset getCIDSubset() {
+        return this.subset;
+    }
+    
+    /** {@inheritDoc} */
+    public String getEncodingName() {
         return encoding;
     }
 
-    /**
-     * {@inheritDoc} 
-     */
+    /** {@inheritDoc} */
     public int getWidth(int i, int size) {
         if (isEmbeddable()) {
-            Integer idx = (Integer)usedGlyphsIndex.get(new Integer(i));
-            return size * width[idx.intValue()];
+            int glyphIndex = subset.getGlyphIndexForSubsetIndex(i);
+            return size * width[glyphIndex];
         } else {
             return size * width[i];
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public int[] getWidths() {
         int[] arr = new int[width.length];
         System.arraycopy(width, 0, arr, 0, width.length - 1);
-        /*
-        for (int i = 0; i < arr.length; i++)
-            arr[i] *= size;
-        */
         return arr;
     }
 
     /**
-     * Remaps a codepoint based.
-     * @param i codepoint to remap
-     * @return new codepoint
+     * Returns the glyph index for a Unicode character. The method returns 0 if there's no
+     * such glyph in the character map.
+     * @param c the Unicode character index
+     * @return the glyph index (or 0 if the glyph is not available)
      */
-/* unused
-    public Integer reMap(Integer i) {
-        if (isEmbeddable()) {
-            Integer ret = (Integer)usedGlyphsIndex.get(i);
-            if (ret == null) {
-                ret = i;
-            }
-            return ret;
-        } else {
-            return i;
-        }
-
-    }
-*/
-
     private int findGlyphIndex(char c) {
         int idx = (int)c;
-        int retIdx = 0;
+        int retIdx = 0; //.notdef
 
         for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) {
             if (bfentries[i].getUnicodeStart() <= idx
@@ -208,48 +172,30 @@
         return retIdx;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public char mapChar(char c) {
         notifyMapOperation();
-        int retIdx = findGlyphIndex(c);
+        int glyphIndex = findGlyphIndex(c);
 
         if (isEmbeddable()) {
-            // Reencode to a new subset font or get
-            // the reencoded value
-            Integer newIdx = (Integer)usedGlyphs.get(new Integer(retIdx));
-            if (newIdx == null) {
-                usedGlyphs.put(new Integer(retIdx),
-                               new Integer(usedGlyphsCount));
-                usedGlyphsIndex.put(new Integer(usedGlyphsCount),
-                                    new Integer(retIdx));
-                usedCharsIndex.put(new Integer(usedGlyphsCount),
-                                    new Integer((int) c));
-                retIdx = usedGlyphsCount;
-                usedGlyphsCount++;
-            } else {
-                retIdx = newIdx.intValue();
-            }
+            glyphIndex = subset.mapSubsetChar(glyphIndex, c);
         }
 
-        return (char)retIdx;
+        return (char)glyphIndex;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public boolean hasChar(char c) {
         return (findGlyphIndex(c) > 0);
     }
 
-
     /**
-     * Sets the bfentries.
-     * @param bfentries The bfentries to set
+     * Sets the array of BFEntry instances which constitutes the Unicode to glyph index map for
+     * a font. ("BF" means "base font")
+     * @param entries the Unicode to glyph index map
      */
-    public void setBFEntries(BFEntry[] bfentries) {
-        this.bfentries = bfentries;
+    public void setBFEntries(BFEntry[] entries) {
+        this.bfentries = entries;
     }
 
     /**
@@ -277,17 +223,6 @@
     }
 
     /**
-     * Adds a new CID width entry to the font.
-     * @param cidWidthIndex index
-     * @param wds array of widths
-     */
-    /*
-    public void addCIDWidthEntry(int cidWidthIndex, int[] wds) {
-        this.warray.addEntry(cidWidthIndex, wds);
-    }*/
-
-
-    /**
      * Sets the width array.
      * @param wds array of widths.
      */
@@ -300,30 +235,15 @@
      * @return Map Map of used Glyphs
      */
     public Map getUsedGlyphs() {
-        return usedGlyphs;
+        return subset.getSubsetGlyphs();
     }
 
-    /** The invalid Unicode character, suitable as a return value in methods
-     * that need to return an invalid character. */
-    public static final char INVALID_UNICODE_CHAR = 0xFFFF;
-
     /** {@inheritDoc} */
     public char[] getCharsUsed() {
         if (!isEmbeddable()) {
             return null;
         }
-        char[] charArray = new char[usedGlyphsCount];
-        for (int i = 0; i < usedGlyphsCount; i++) {
-            Integer mapValue = (Integer)usedCharsIndex.get(new Integer(i));
-            if (mapValue != null) {
-                char arrayItem = (char) mapValue.intValue();
-                charArray[i] = arrayItem;
-            }
-            else {
-                charArray[i] = INVALID_UNICODE_CHAR;
-            }
-        }
-        return charArray;
+        return subset.getSubsetChars();
     }
 }
 

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/NamedCharacter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/NamedCharacter.java?rev=641742&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/NamedCharacter.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/NamedCharacter.java Thu Mar 27 01:49:41 2008
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts;
+
+import org.apache.xmlgraphics.fonts.Glyphs;
+
+import org.apache.fop.util.CharUtilities;
+
+/**
+ * Represents an named character with character name (from the Adobe glyph list) and a Unicode
+ * sequence that this character represents.
+ */
+public class NamedCharacter {
+    
+    private String charName;
+    private String unicodeSequence;
+    
+    /**
+     * Main constructor.
+     * @param charName the character name
+     * @param unicodeSequence the Unicode sequence associated with this character
+     */
+    public NamedCharacter(String charName, String unicodeSequence) {
+        if (charName == null) {
+            throw new NullPointerException("charName must not be null");
+        }
+        this.charName = charName;
+        if (unicodeSequence != null) {
+            this.unicodeSequence = unicodeSequence;
+        } else {
+            this.unicodeSequence = Glyphs.getUnicodeSequenceForGlyphName(charName);
+        }
+    }
+    
+    /**
+     * Simple constructor.
+     * @param charName the character name
+     */
+    public NamedCharacter(String charName) {
+        this(charName, null);
+    }
+    
+    /** {@inheritDoc} */
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((charName == null) ? 0 : charName.hashCode());
+        return result;
+    }
+
+    /** {@inheritDoc} */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final NamedCharacter other = (NamedCharacter)obj;
+        return charName.equals(other.charName);
+    }
+
+    /**
+     * Returns the character name (as defined by the Adobe glyph list).
+     * @return the character name
+     */
+    public String getName() {
+        return this.charName;
+    }
+    
+    /**
+     * Returns the Unicode sequence associated with this character.
+     * @return the Unicode sequence (or null if no Unicode sequence is associated)
+     */
+    public String getUnicodeSequence() {
+        return this.unicodeSequence;
+    }
+    
+    /**
+     * Indicates whether a single Unicode value is associated with this character.
+     * @return true if exactly one Unicode value is associated with this character, false otherwise
+     */
+    public boolean hasSingleUnicodeValue() {
+        return (this.unicodeSequence != null && this.unicodeSequence.length() == 1);
+    }
+    
+    /**
+     * Returns the single Unicode value associated with this named character. Check
+     * {@link #hasSingleUnicodeValue()} before you call this method because an
+     * IllegalStateException is thrown is a Unicode sequence with more than one character is
+     * associated with this character.
+     * @return the single Unicode value (or FFFF ("NOT A CHARACTER") if no Unicode value is
+     *             available)
+     * @throws IllegalStateException if a Unicode sequence with more than one value is associated
+     *             with the named character
+     */
+    public char getSingleUnicodeValue() throws IllegalStateException {
+        if (this.unicodeSequence == null) {
+            return CharUtilities.NOT_A_CHARACTER;
+        }
+        if (this.unicodeSequence.length() > 1) {
+            throw new IllegalStateException("getSingleUnicodeValue() may not be called for a"
+                    + " named character that has more than one Unicode value (a sequence)"
+                    + " associated with the named character!");
+        }
+        return this.unicodeSequence.charAt(0);
+    }
+    
+    /** {@inheritDoc} */
+    public String toString() {
+        StringBuffer sb = new StringBuffer(this.unicodeSequence);
+        sb.append(" (");
+        if (this.unicodeSequence != null) {
+            for (int i = 0, c = this.unicodeSequence.length(); i < c; i++) {
+                sb.append("0x").append(Integer.toHexString(this.unicodeSequence.charAt(0)));
+            }
+            sb.append(", ");
+        }
+        sb.append(getName()).append(')');
+        return sb.toString();
+    }
+}
\ No newline at end of file

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/NamedCharacter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/NamedCharacter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java?rev=641742&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java Thu Mar 27 01:49:41 2008
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.xmlgraphics.fonts.Glyphs;
+
+/**
+ * A simple implementation of the OneByteEncoding mostly used for encodings that are constructed
+ * on-the-fly.
+ */
+public class SimpleSingleByteEncoding implements SingleByteEncoding {
+
+    private String name;
+    private List mapping = new java.util.ArrayList();
+    //List<NamedCharacter>
+    private Map charMap = new java.util.HashMap();
+    //Map<Character(Unicode), Character(code point)>
+    
+    /**
+     * Main constructor.
+     * @param name the encoding's name
+     */
+    public SimpleSingleByteEncoding(String name) {
+        this.name = name;
+    }
+    
+    /** {@inheritDoc} */
+    public String getName() {
+        return this.name;
+    }
+
+    /** {@inheritDoc} */
+    public char mapChar(char c) {
+        Character nc = (Character)charMap.get(new Character(c));
+        if (nc != null) {
+            return nc.charValue();
+        }
+        return NOT_FOUND_CODE_POINT;
+    }
+
+    /** {@inheritDoc} */
+    public String[] getCharNameMap() {
+        String[] map = new String[getSize()];
+        Arrays.fill(map, Glyphs.NOTDEF);
+        for (int i = getFirstChar(); i <= getLastChar(); i++) {
+            NamedCharacter ch = (NamedCharacter)this.mapping.get(i - 1);
+            map[i] = ch.getName(); 
+        }
+        return map;
+    }
+    
+    /**
+     * Returns the index of the first defined character.
+     * @return the index of the first defined character (always 1 for this class)
+     */
+    public int getFirstChar() {
+        return 1;
+    }
+    
+    /**
+     * Returns the index of the last defined character.
+     * @return the index of the last defined character
+     */
+    public int getLastChar() {
+        return this.mapping.size();
+    }
+    
+    /**
+     * Returns the number of characters defined by this encoding.
+     * @return the number of characters
+     */
+    public int getSize() {
+        return this.mapping.size() + 1;
+    }
+    
+    /**
+     * Indicates whether the encoding is full (with 256 code points).
+     * @return true if the encoding is full
+     */
+    public boolean isFull() {
+        return (getSize() == 256);
+    }
+    
+    /**
+     * Adds a new character to the encoding.
+     * @param ch the named character
+     * @return the code point assigned to the character
+     */
+    public char addCharacter(NamedCharacter ch) {
+        if (!ch.hasSingleUnicodeValue()) {
+            throw new IllegalArgumentException("Only NamedCharacters with a single Unicode value"
+                    + " are currently supported!");
+        }
+        if (isFull()) {
+            throw new IllegalStateException("Encoding is full!");
+        }
+        char newSlot = (char)(getLastChar() + 1);
+        this.mapping.add(ch);
+        this.charMap.put(new Character(ch.getSingleUnicodeValue()), new Character(newSlot));
+        return newSlot;
+    }
+
+    /**
+     * Returns the named character at a given code point in the encoding.
+     * @param codePoint the code point of the character
+     * @return the NamedCharacter (or null if no character is at this position)
+     */
+    public NamedCharacter getCharacterForIndex(int codePoint) {
+        if (codePoint < 0 || codePoint > 255) {
+            throw new IllegalArgumentException("codePoint must be between 0 and 255");
+        }
+        if (codePoint <= getLastChar()) {
+            return (NamedCharacter)this.mapping.get(codePoint - 1);
+        } else {
+            return null;
+        }
+    }
+    
+    /** {@inheritDoc} */
+    public String toString() {
+        return getName() + " (" + getSize() + " chars)";
+    }
+    
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteEncoding.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteEncoding.java?rev=641742&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteEncoding.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteEncoding.java Thu Mar 27 01:49:41 2008
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fonts;
+
+/**
+ * The interface defines a 1-byte character encoding (with 256 characters).
+ */
+public interface SingleByteEncoding {
+
+    /** Code point that is used if no code point for a specific character has been found. */
+    char NOT_FOUND_CODE_POINT = '\0';
+
+    /**
+     * Returns the encoding's name.
+     * @return the name of the encoding
+     */
+    String getName();
+
+    /**
+     * Maps a Unicode character to a code point in the encoding.
+     * @param c the Unicode character to map
+     * @return the code point in the encoding or 0 (=.notdef) if not found
+     */
+    char mapChar(char c);
+
+    /**
+     * Returns the array of character names for this encoding.
+     * @return the array of character names
+     *                  (unmapped code points are represented by a ".notdef" value)
+     */
+    String[] getCharNameMap();
+    
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteEncoding.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteEncoding.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteFont.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/SingleByteFont.java Thu Mar 27 01:49:41 2008
@@ -19,6 +19,8 @@
 
 package org.apache.fop.fonts;
 
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.logging.Log;
@@ -31,14 +33,21 @@
  */
 public class SingleByteFont extends CustomFont {
 
+    /** Code point that is used if no code point for a specific character has been found. */
+    public static final char NOT_FOUND = '#';
+
     /** logger */
     private  static Log log = LogFactory.getLog(SingleByteFont.class);
 
-    private CodePointMapping mapping;
+    private SingleByteEncoding mapping;
 
     private int[] width = null;
 
     private Set warnedChars;
+
+    private Map unencodedCharacters;
+    //Map<Character, UnencodedCharacter>
+    private List additionalEncodings;
     
     /**
      * Main constructor.
@@ -54,7 +63,7 @@
     }
 
     /** {@inheritDoc} */
-    public String getEncoding() {
+    public String getEncodingName() {
         return this.mapping.getName();
     }
 
@@ -62,18 +71,28 @@
      * Returns the code point mapping (encoding) of this font.
      * @return the code point mapping
      */
-    public CodePointMapping getCodePointMapping() {
+    public SingleByteEncoding getEncoding() {
         return this.mapping;
     }
     
     /** {@inheritDoc} */
     public int getWidth(int i, int size) {
-        int idx = i - getFirstChar();
-        if (idx >= 0 && idx < width.length) {
-            return size * width[i - getFirstChar()];
-        } else {
-            return 0;
+        if (i < 256) {
+            int idx = i - getFirstChar();
+            if (idx >= 0 && idx < width.length) {
+                return size * width[i - getFirstChar()];
+            }
+        } else if (this.additionalEncodings != null) {
+            int encodingIndex = (i / 256) - 1;
+            SimpleSingleByteEncoding encoding = getAdditionalEncoding(encodingIndex);
+            int codePoint = i % 256;
+            NamedCharacter nc = encoding.getCharacterForIndex(codePoint);
+            UnencodedCharacter uc
+                = (UnencodedCharacter)this.unencodedCharacters.get(
+                        new Character(nc.getSingleUnicodeValue()));
+            return size * uc.getWidth();
         }
+        return 0;
     }
 
     /** {@inheritDoc} */
@@ -87,30 +106,80 @@
     public char mapChar(char c) {
         notifyMapOperation();
         char d = mapping.mapChar(c);
-        if (d != 0) {
+        if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
             return d;
-        } else {
-            Character ch = new Character(c);
-            if (warnedChars == null) {
-                warnedChars = new java.util.HashSet();
+        }
+        
+        //Check unencoded characters which are available in the font by character name
+        d = mapUnencodedChar(c);
+        if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
+            return d;
+        }
+        
+        //Give up, character is not available
+        Character ch = new Character(c);
+        if (warnedChars == null) {
+            warnedChars = new java.util.HashSet();
+        }
+        if (warnedChars.size() < 8 && !warnedChars.contains(ch)) {
+            warnedChars.add(ch);
+            if (warnedChars.size() == 8) {
+                log.warn("Many requested glyphs are not available in font " + getFontName());
+            } else {
+                log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) 
+                        + ", " + Glyphs.charToGlyphName(c)
+                        + ") not available in font " + getFontName());
             }
-            if (warnedChars.size() < 8 && !warnedChars.contains(ch)) {
-                warnedChars.add(ch);
-                if (warnedChars.size() == 8) {
-                    log.warn("Many requested glyphs are not available in font " + getFontName());
-                } else {
-                    log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) 
-                            + ", " + Glyphs.charToGlyphName(c)
-                            + ") not available in font " + getFontName());
+        }
+        return NOT_FOUND;
+    }
+
+    private char mapUnencodedChar(char ch) {
+        if (this.unencodedCharacters != null) {
+            UnencodedCharacter unencoded
+                = (UnencodedCharacter)this.unencodedCharacters.get(new Character(ch));
+            if (unencoded != null) {
+                if (this.additionalEncodings == null) {
+                    this.additionalEncodings = new java.util.ArrayList();
+                }
+                SimpleSingleByteEncoding encoding = null;
+                char mappedStart = 0;
+                int additionalsCount = this.additionalEncodings.size(); 
+                for (int i = 0; i < additionalsCount; i++) {
+                    mappedStart += 256;
+                    encoding = getAdditionalEncoding(i);
+                    char alt = encoding.mapChar(ch);
+                    if (alt != 0) {
+                        return (char)(mappedStart + alt);
+                    }
+                }
+                if (encoding != null && encoding.isFull()) {
+                    encoding = null;
                 }
+                if (encoding == null) {
+                    encoding = new SimpleSingleByteEncoding(
+                            getFontName() + "EncodingSupp" + (additionalsCount + 1));
+                    this.additionalEncodings.add(encoding);
+                    mappedStart += 256;
+                }
+                return (char)(mappedStart + encoding.addCharacter(unencoded.getCharacter()));
             }
-            return '#';
         }
+        return 0;
     }
 
     /** {@inheritDoc} */
     public boolean hasChar(char c) {
-        return (mapping.mapChar(c) > 0);
+        char d = mapping.mapChar(c);
+        if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
+            return true;
+        }
+        //Check unencoded characters which are available in the font by character name
+        d = mapUnencodedChar(c);
+        if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
+            return true;
+        }
+        return false;
     }
 
     /* ---- single byte font specific setters --- */
@@ -146,13 +215,106 @@
     /**
      * Sets a width for a character.
      * @param index index of the character
-     * @param width the width of the character
+     * @param w the width of the character
      */
-    public void setWidth(int index, int width) {
+    public void setWidth(int index, int w) {
         if (this.width == null) {
             this.width = new int[getLastChar() - getFirstChar() + 1];
         }
-        this.width[index - getFirstChar()] = width;
+        this.width[index - getFirstChar()] = w;
+    }
+
+    /**
+     * Adds an unencoded character (one that is not supported by the primary encoding).
+     * @param ch the named character
+     * @param width the width of the character
+     */
+    public void addUnencodedCharacter(NamedCharacter ch, int width) {
+        if (this.unencodedCharacters == null) {
+            this.unencodedCharacters = new java.util.HashMap();
+        }
+        if (ch.hasSingleUnicodeValue()) {
+            UnencodedCharacter uc = new UnencodedCharacter(ch, width);
+            this.unencodedCharacters.put(new Character(ch.getSingleUnicodeValue()), uc);
+        } else {
+            //Cannot deal with unicode sequences, so ignore this character
+        }
+    }
+
+    /**
+     * Indicates whether the encoding has additional encodings besides the primary encoding.
+     * @return true if there are additional encodings.
+     */
+    public boolean hasAdditionalEncodings() {
+        return (this.additionalEncodings != null) && (this.additionalEncodings.size() > 0);
+    }
+    
+    /**
+     * Returns the number of additional encodings this single-byte font maintains.
+     * @return the number of additional encodings
+     */
+    public int getAdditionalEncodingCount() {
+        if (hasAdditionalEncodings()) {
+            return this.additionalEncodings.size();
+        } else {
+            return 0;
+        }
+    }
+    
+    /**
+     * Returns an additional encoding.
+     * @param index the index of the additional encoding
+     * @return the additional encoding
+     * @throws IndexOutOfBoundsException if the index is out of bounds
+     */
+    public SimpleSingleByteEncoding getAdditionalEncoding(int index)
+            throws IndexOutOfBoundsException {
+        if (hasAdditionalEncodings()) {
+            return (SimpleSingleByteEncoding)this.additionalEncodings.get(index);
+        } else {
+            throw new IndexOutOfBoundsException("No additional encodings available");
+        }
+    }
+    
+    /**
+     * Returns an array with the widths for an additional encoding.
+     * @param index the index of the additional encoding
+     * @return the width array
+     */
+    public int[] getAdditionalWidths(int index) {
+        SimpleSingleByteEncoding enc = getAdditionalEncoding(index);
+        int[] arr = new int[enc.getLastChar() - enc.getFirstChar() + 1];
+        for (int i = 0, c = arr.length; i < c; i++) {
+            NamedCharacter nc = enc.getCharacterForIndex(enc.getFirstChar() + i);
+            UnencodedCharacter uc = (UnencodedCharacter)this.unencodedCharacters.get(
+                    new Character(nc.getSingleUnicodeValue()));
+            arr[i] = uc.getWidth();
+        }
+        return arr;
+    }
+    
+    private static final class UnencodedCharacter {
+        
+        private NamedCharacter character;
+        private int width;
+        
+        public UnencodedCharacter(NamedCharacter character, int width) {
+            this.character = character;
+            this.width = width;
+        }
+        
+        public NamedCharacter getCharacter() {
+            return this.character;
+        }
+        
+        public int getWidth() {
+            return this.width;
+        }
+        
+        /** {@inheritDoc} */
+        public String toString() {
+            return getCharacter().toString();
+        }
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Typeface.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Typeface.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Typeface.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Typeface.java Thu Mar 27 01:49:41 2008
@@ -19,11 +19,8 @@
  
 package org.apache.fop.fonts;
 
-// FOP
-
-
 /**
- * Base class for PDF font classes
+ * Base class for font classes
  */
 public abstract class Typeface implements FontMetrics {
 
@@ -37,7 +34,7 @@
      * Get the encoding of the font.
      * @return the encoding
      */
-    public abstract String getEncoding();
+    public abstract String getEncodingName();
 
     /**
      * Map a Unicode character to a code point in the font.

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java Thu Mar 27 01:49:41 2008
@@ -592,8 +592,8 @@
                                         + mtxTab[origIndex.intValue()].getOffset()) < 0) {
                         // origIndex is a composite glyph
                         allComposites.put(origIndex, glyphs.get(origIndex));
-                        List composites =
-                            getIncludedGlyphs(in, (int)entry.getOffset(),
+                        List composites
+                            = getIncludedGlyphs(in, (int)entry.getOffset(),
                                               origIndex);
 
                         // Iterate through all composites pointed to
@@ -651,6 +651,9 @@
         if (!checkTTC(in, name)) {
             throw new IOException("Failed to read font");
         }
+        
+        //Copy the Map as we're going to modify it
+        Map subsetGlyphs = new java.util.HashMap(glyphs);
 
         output = new byte[in.getFileSize()];
 
@@ -661,14 +664,14 @@
         readHorizontalMetrics(in);
         readIndexToLocation(in);
 
-        scanGlyphs(in, glyphs);
+        scanGlyphs(in, subsetGlyphs);
 
         createDirectory();                // Create the TrueType header and directory
 
         createHead(in);
-        createHhea(in, glyphs.size());    // Create the hhea table
-        createHmtx(in, glyphs);           // Create hmtx table
-        createMaxp(in, glyphs.size());    // copy the maxp table
+        createHhea(in, subsetGlyphs.size());    // Create the hhea table
+        createHmtx(in, subsetGlyphs);           // Create hmtx table
+        createMaxp(in, subsetGlyphs.size());    // copy the maxp table
 
         boolean optionalTableFound;
         optionalTableFound = createCvt(in);    // copy the cvt table
@@ -689,8 +692,8 @@
             log.debug("TrueType: prep table not present. Skipped.");
         }
 
-        createLoca(glyphs.size());    // create empty loca table
-        createGlyf(in, glyphs);       //create glyf table and update loca table
+        createLoca(subsetGlyphs.size());    // create empty loca table
+        createGlyf(in, subsetGlyphs);       //create glyf table and update loca table
 
         pad4();
         createCheckSumAdjustment();

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java Thu Mar 27 01:49:41 2008
@@ -21,6 +21,8 @@
 
 import java.awt.geom.RectangularShape;
 
+import org.apache.fop.fonts.NamedCharacter;
+
 
 /**
  * Holds the metrics of a single character from an AFM file.
@@ -28,8 +30,7 @@
 public class AFMCharMetrics {
 
     private int charCode = -1;
-    private String unicodeSequence;
-    private String charName;
+    private NamedCharacter character;
     private double widthX;
     private double widthY;
     private RectangularShape bBox;
@@ -59,36 +60,45 @@
     }
     
     /**
-     * Returns the Unicode sequence for this character.
-     * @return the Unicode characters
-     *                  (or null if no such Unicode sequence exists for this character)
+     * Returns the named character represented by this instance.
+     * @return the named character (or null if no named character is associated)
      */
-    public String getUnicodeSequence() {
-        return this.unicodeSequence;
+    public NamedCharacter getCharacter() {
+        return this.character;
+    }
+    
+    /**
+     * Sets the named character represented by this instance.
+     * @param ch the named character
+     */
+    public void setCharacter(NamedCharacter ch) {
+        this.character = ch;
     }
     
     /**
-     * Sets the Unicode sequence for this character.
+     * Sets the named character represented by this instance.
+     * @param charName the character name (as defined in the Adobe glyph list)
      * @param unicodeSequence the Unicode sequence
      */
-    public void setUnicodeSequence(String unicodeSequence) {
-        this.unicodeSequence = unicodeSequence;
+    public void setCharacter(String charName, String unicodeSequence) {
+        setCharacter(new NamedCharacter(charName, unicodeSequence));
     }
     
     /**
-     * Returns the PostScript character name.
-     * @return the charName
+     * Returns the Unicode sequence for this character.
+     * @return the Unicode characters
+     *                  (or null if no such Unicode sequence exists for this character)
      */
-    public String getCharName() {
-        return charName;
+    public String getUnicodeSequence() {
+        return (getCharacter() != null ? getCharacter().getUnicodeSequence() : null);
     }
     
     /**
-     * Sets the PostScript character name.
-     * @param charName the charName to set
+     * Returns the PostScript character name.
+     * @return the charName (or null if no character name is associated)
      */
-    public void setCharName(String charName) {
-        this.charName = charName;
+    public String getCharName() {
+        return (getCharacter() != null ? getCharacter().getName() : null);
     }
     
     /**

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMFile.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMFile.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMFile.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMFile.java Thu Mar 27 01:49:41 2008
@@ -26,7 +26,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.xmlgraphics.fonts.Glyphs;
 import org.apache.xmlgraphics.java2d.Dimension2DDouble;
 
 /**
@@ -315,15 +314,8 @@
     public void addCharMetrics(AFMCharMetrics metrics) {
         String name = metrics.getCharName();
         if (metrics.getUnicodeSequence() == null) {
-            if (name != null) {
-                String u = Glyphs.getUnicodeSequenceForGlyphName(metrics.getCharName());
-                if (u != null) {
-                    metrics.setUnicodeSequence(u);
-                }
-            } else {
-                //Ignore as no Unicode assignment is possible
-                return;
-            }
+            //Ignore as no Unicode assignment is possible
+            return;
         }
         this.charMetrics.add(metrics);
         if (name != null) {

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMParser.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMParser.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMParser.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/AFMParser.java Thu Mar 27 01:49:41 2008
@@ -31,6 +31,8 @@
 
 import org.apache.commons.io.IOUtils;
 
+import org.apache.fop.fonts.NamedCharacter;
+
 /**
  * Parses the contents of a Type 1 AFM font metrics file into an object structure ({@link AFMFile}).
  */
@@ -126,7 +128,7 @@
         VALUE_PARSERS.put(W, new NotImplementedYet(W));
         VALUE_PARSERS.put(W0, new NotImplementedYet(W0));
         VALUE_PARSERS.put(W1, new NotImplementedYet(W1));
-        VALUE_PARSERS.put(N, new StringSetter("CharName"));
+        VALUE_PARSERS.put(N, new NamedCharacterSetter("Character"));
         VALUE_PARSERS.put(B, new CharBBox());
         VALUE_PARSERS.put(START_TRACK_KERN, new NotImplementedYet(START_TRACK_KERN));
         VALUE_PARSERS.put(END_TRACK_KERN, new NotImplementedYet(END_TRACK_KERN));
@@ -376,6 +378,19 @@
             String s = getStringValue(line, startpos);
             Object obj = stack.peek();
             setValue(obj, s);
+        }
+    }
+    
+    private static class NamedCharacterSetter extends BeanSetter {
+        
+        public NamedCharacterSetter(String variable) {
+            super(variable);
+        }
+        
+        public void parse(String line, int startpos, Stack stack) throws IOException {
+            NamedCharacter ch = new NamedCharacter(getStringValue(line, startpos));
+            Object obj = stack.peek();
+            setValue(obj, ch);
         }
     }
     

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java Thu Mar 27 01:49:41 2008
@@ -127,12 +127,17 @@
         singleFont.setEmbedFileName(this.fontFileURI);
         returnFont = singleFont;
         
+        handleEncoding(afm, pfm);
+        handleFontName(afm, pfm);
+        handleMetrics(afm, pfm);
+    }
+
+    private void handleEncoding(AFMFile afm, PFMFile pfm) {
         //Encoding
         if (afm != null) {
             String encoding = afm.getEncodingScheme();
             if ("AdobeStandardEncoding".equals(encoding)) {
-                //Use WinAnsi in this case as it better fits the usual character set people need
-                singleFont.setEncoding(CodePointMapping.WIN_ANSI_ENCODING);
+                singleFont.setEncoding(CodePointMapping.STANDARD_ENCODING);
             } else {
                 String effEncodingName;
                 if ("FontSpecific".equals(encoding)) {
@@ -147,6 +152,14 @@
                 CodePointMapping mapping = buildCustomEncoding(effEncodingName, afm);
                 singleFont.setEncoding(mapping);
             }
+            List charMetrics = afm.getCharMetrics();
+            for (int i = 0, c = afm.getCharCount(); i < c; i++) {
+                AFMCharMetrics metrics = (AFMCharMetrics)charMetrics.get(i);
+                if (!metrics.hasCharCode() && metrics.getCharacter() != null) {
+                    singleFont.addUnencodedCharacter(metrics.getCharacter(),
+                            (int)Math.round(metrics.getWidthX()));
+                }
+            }
         } else {
             if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) {
                 singleFont.setEncoding(pfm.getCharSetName() + "Encoding");
@@ -156,7 +169,9 @@
                 singleFont.setEncoding("WinAnsiEncoding"); //Try fallback, no guarantees!
             }
         }
-        
+    }
+
+    private void handleFontName(AFMFile afm, PFMFile pfm) {
         //Font name
         if (afm != null) {
             returnFont.setFontName(afm.getFontName()); //PostScript font name
@@ -173,7 +188,9 @@
             names.add(pfm.getWindowsName()); //emulate afm.getFamilyName()
             returnFont.setFamilyNames(names);
         }
-        
+    }
+
+    private void handleMetrics(AFMFile afm, PFMFile pfm) {
         //Basic metrics
         if (afm != null) {
             if (afm.getCapHeight() != null) {
@@ -271,8 +288,6 @@
             returnFont.setCapHeight(returnFont.getAscender());
         }
         
-        /* DISABLED because of mismatch with our using WinAnsiEncoding and the AFM
-        delivering the font's default encoding.
         if (afm != null) {
             //TODO returnFont.setFlags(flags);
              
@@ -286,15 +301,15 @@
                 }
             }
             returnFont.replaceKerningMap(afm.createXKerningMapEncoded());
-        } else {*/
-            returnFont.setFlags(pfm.getFlags());
+        } else {
             returnFont.setFirstChar(pfm.getFirstChar());
             returnFont.setLastChar(pfm.getLastChar());
             for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) {
                 singleFont.setWidth(i, pfm.getCharWidth(i));
             }
             returnFont.replaceKerningMap(pfm.getKerning());
-        //}
+        }
+        returnFont.setFlags(pfm.getFlags());
     }
 
     private CodePointMapping buildCustomEncoding(String encodingName, AFMFile afm) {

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=641742&r1=641741&r2=641742&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 Mar 27 01:49:41 2008
@@ -21,7 +21,6 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.StringWriter;
 import java.io.Writer;
 
 /**
@@ -425,10 +424,8 @@
     
     /** {@inheritDoc} */
     protected int output(OutputStream stream) throws IOException {
-        StringWriter writer = new StringWriter();
-        CMapBuilder builder = createCMapBuilder(writer);
+        CMapBuilder builder = createCMapBuilder(getBufferWriter());
         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/PDFEncoding.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEncoding.java?rev=641742&r1=641741&r2=641742&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 Mar 27 01:49:41 2008
@@ -132,6 +132,14 @@
         }
         
         /**
+         * Indicates whether any differences have been recorded.
+         * @return true if there are differences.
+         */
+        public boolean hasDifferences() {
+            return (this.differences.length() > 0);
+        }
+        
+        /**
          * Creates and returns the PDFArray representing the Differences entry.
          * @return the Differences entry
          */

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=641742&r1=641741&r2=641742&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 Mar 27 01:49:41 2008
@@ -43,6 +43,7 @@
 import org.apache.xmlgraphics.xmp.Metadata;
 
 import org.apache.fop.fonts.CIDFont;
+import org.apache.fop.fonts.CIDSubset;
 import org.apache.fop.fonts.CodePointMapping;
 import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.FontDescriptor;
@@ -50,6 +51,8 @@
 import org.apache.fop.fonts.FontType;
 import org.apache.fop.fonts.LazyFont;
 import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.SimpleSingleByteEncoding;
+import org.apache.fop.fonts.SingleByteEncoding;
 import org.apache.fop.fonts.SingleByteFont;
 import org.apache.fop.fonts.Typeface;
 import org.apache.fop.fonts.truetype.FontFileReader;
@@ -1166,7 +1169,7 @@
     }
 
     /**
-     * make a Type1 /Font object
+     * Make a Type1 /Font object.
      *
      * @param fontname internal name to use for this font (eg "F1")
      * @param basefont name of the base font (eg "Helvetica")
@@ -1217,10 +1220,12 @@
                                    (PDFCIDFontDescriptor)pdfdesc);
                 getDocument().registerObject(cidFont);
 
-                PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics.getCharsUsed(), "fop-ucs-H",
-                    new PDFCIDSystemInfo("Adobe",
-                        "Identity",
-                        0));
+                PDFCMap cmap = new PDFToUnicodeCMap(
+                        cidMetrics.getCIDSubset().getSubsetChars(),
+                        "fop-ucs-H",
+                        new PDFCIDSystemInfo("Adobe",
+                            "Identity",
+                            0));
                 getDocument().registerObject(cmap);
                 ((PDFFontType0)font).setCMAP(cmap);
                 ((PDFFontType0)font).setDescendantFonts(cidFont);
@@ -1238,35 +1243,20 @@
                 int lastChar = singleByteFont.getLastChar();
                 nonBase14.setWidthMetrics(firstChar,
                                      lastChar,
-                                     makeArray(metrics.getWidths()));
+                                     new PDFArray(null, metrics.getWidths()));
                 
                 //Handle encoding
-                CodePointMapping mapping = singleByteFont.getCodePointMapping();
+                SingleByteEncoding mapping = singleByteFont.getEncoding();
                 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;
-                    String[] winansiNames = winansi.getCharNameMap();
-                    String[] charNameMap = mapping.getCharNameMap();
-                    for (int i = 0; i < 256; i++) {
-                        String wac = winansiNames[i];
-                        String c = charNameMap[i];
-                        if (!wac.equals(c)) {
-                            if (start != i) {
-                                builder.addDifference(i);
-                                start = i;
-                            }
-                            builder.addName(c);
-                            start++;
-                        }
+                    Object pdfEncoding = createPDFEncoding(mapping,
+                            singleByteFont.getFontName());
+                    if (pdfEncoding instanceof PDFEncoding) {
+                        font.setEncoding((PDFEncoding)pdfEncoding);
+                    } else {
+                        font.setEncoding((String)pdfEncoding);
                     }
-                    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
@@ -1278,21 +1268,88 @@
                     nonBase14.setToUnicode(cmap);
                     */
                 }
+                
+                //Handle additional encodings (characters outside the primary encoding)
+                if (singleByteFont.hasAdditionalEncodings()) {
+                    for (int i = 0, c = singleByteFont.getAdditionalEncodingCount(); i < c; i++) {
+                        SimpleSingleByteEncoding addEncoding
+                            = singleByteFont.getAdditionalEncoding(i);
+                        String name = fontname + "_" + (i + 1);
+                        Object pdfenc = createPDFEncoding(addEncoding,
+                                singleByteFont.getFontName());
+                        PDFFontNonBase14 addFont = (PDFFontNonBase14)PDFFont.createFont(
+                                name, fonttype,
+                                basefont, pdfenc);
+                        addFont.setDescriptor(pdfdesc);
+                        addFont.setWidthMetrics(
+                                addEncoding.getFirstChar(),
+                                addEncoding.getLastChar(),
+                                new PDFArray(null, singleByteFont.getAdditionalWidths(i)));
+                        getDocument().registerObject(addFont);
+                        getDocument().getResources().addFont(addFont);
+                    }
+                }
             }
 
             return font;
         }
     }
 
+    /**
+     * Creates a PDFEncoding instance from a CodePointMapping instance.
+     * @param encoding the code point mapping (encoding)
+     * @return the PDF Encoding dictionary (or a String with the predefined encoding)
+     */
+    public Object createPDFEncoding(SingleByteEncoding encoding, String fontNameHint) {
+        SingleByteEncoding baseEncoding;
+        if (fontNameHint.indexOf("Symbol") >= 0) {
+            baseEncoding = CodePointMapping.getMapping(
+                    CodePointMapping.SYMBOL_ENCODING);
+        } else {
+            baseEncoding = CodePointMapping.getMapping(
+                    CodePointMapping.STANDARD_ENCODING);
+        }
+        PDFEncoding pdfEncoding = new PDFEncoding(baseEncoding.getName());
+        PDFEncoding.DifferencesBuilder builder
+                = pdfEncoding.createDifferencesBuilder();
+        int start = -1;
+        String[] baseNames = baseEncoding.getCharNameMap();
+        String[] charNameMap = encoding.getCharNameMap();
+        for (int i = 0, ci = charNameMap.length; i < ci; i++) {
+            String basec = baseNames[i];
+            String c = charNameMap[i];
+            if (!basec.equals(c)) {
+                if (start != i) {
+                    builder.addDifference(i);
+                    start = i;
+                }
+                builder.addName(c);
+                start++;
+            }
+        }
+        if (builder.hasDifferences()) {
+            pdfEncoding.setDifferences(builder.toPDFArray());
+            return pdfEncoding;
+        } else {
+            return baseEncoding.getName();
+        }
+    }
+
+    /**
+     * Creates and returns a width array with the widths of all the characters in the subset.
+     * @param cidFont the font
+     * @return the width array
+     */
     public PDFWArray getSubsetWidths(CIDFont cidFont) {
         // Create widths for reencoded chars
         PDFWArray warray = new PDFWArray();
-        int[] tmpWidth = new int[cidFont.usedGlyphsCount];
-
-        for (int i = 0; i < cidFont.usedGlyphsCount; i++) {
-            Integer nw = (Integer)cidFont.usedGlyphsIndex.get(new Integer(i));
-            int nwx = (nw == null) ? 0 : nw.intValue();
-            tmpWidth[i] = cidFont.width[nwx];
+        int[] widths = cidFont.getWidths();
+        CIDSubset subset = cidFont.getCIDSubset();
+        int[] tmpWidth = new int[subset.getSubsetSize()];
+
+        for (int i = 0, c = subset.getSubsetSize(); i < c; i++) {
+            int nwx = Math.max(0, subset.getGlyphIndexForSubsetIndex(i));
+            tmpWidth[i] = widths[nwx];
         }
         warray.addEntry(0, tmpWidth);
         return warray;
@@ -1345,12 +1402,7 @@
     }
 
     private void buildCIDSet(PDFFontDescriptor descriptor, CIDFont cidFont) {
-        BitSet cidSubset = new BitSet();
-        Iterator iter = cidFont.usedGlyphs.keySet().iterator();
-        while (iter.hasNext()) {
-            Integer cid = (Integer)iter.next();
-            cidSubset.set(cid.intValue());
-        }
+        BitSet cidSubset = cidFont.getCIDSubset().getGlyphIndexBitSet();
         PDFStream cidSet = makeStream(null, true);
         ByteArrayOutputStream baout = new ByteArrayOutputStream(cidSubset.length() / 8 + 1);
         int value = 0;
@@ -1548,14 +1600,13 @@
     }
 
     /**
-     * make an Array object (ex. Widths array for a font)
+     * Make an Array object (ex. Widths array for a font).
      *
      * @param values the int array values
      * @return the PDF Array with the int values
      */
     public PDFArray makeArray(int[] values) {
         PDFArray array = new PDFArray(null, values);
-
         getDocument().registerObject(array);
         return array;
     }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFResources.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFResources.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFResources.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFResources.java Thu Mar 27 01:49:41 2008
@@ -110,7 +110,7 @@
                     desc = (FontDescriptor)font;
                 }
                 addFont(doc.getFactory().makeFont(
-                    f, font.getEmbedFontName(), font.getEncoding(), font, desc));
+                    f, font.getEmbedFontName(), font.getEncodingName(), font, desc));
             }
         }
     }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFStream.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFStream.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFStream.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFStream.java Thu Mar 27 01:49:41 2008
@@ -19,8 +19,9 @@
  
 package org.apache.fop.pdf;
 
-import java.io.OutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
 
 /**
  * Class representing a PDF stream.
@@ -37,6 +38,8 @@
      */
     protected StreamCache data;
 
+    private transient Writer streamWriter;
+    
     /**
      * Create an empty stream object
      */
@@ -44,6 +47,10 @@
         super();
         try {
             data = StreamCacheFactory.getInstance().createStreamCache();
+            this.streamWriter = new java.io.OutputStreamWriter(
+                    getBufferOutputStream(), PDFDocument.ENCODING);
+            //Buffer to minimize calls to the converter
+            this.streamWriter = new java.io.BufferedWriter(this.streamWriter);
         } catch (IOException ex) {
             //TODO throw the exception and catch it elsewhere
             ex.printStackTrace();
@@ -57,21 +64,35 @@
      */
     public void add(String s) {
         try {
-            data.getOutputStream().write(PDFDocument.encode(s));
+            this.streamWriter.write(s);
         } catch (IOException ex) {
             //TODO throw the exception and catch it elsewhere
             ex.printStackTrace();
         }
-
+    }
+    
+    private void flush() throws IOException {
+        this.streamWriter.flush();
     }
     
     /**
+     * Returns a Writer that writes to the OutputStream of the buffer.
+     * @return the Writer
+     */
+    public Writer getBufferWriter() {
+        return this.streamWriter;
+    }
+
+    /**
      * Returns an OutputStream that can be used to write to the buffer which is used
      * to build up the PDF stream.
      * @return the OutputStream
      * @throws IOException In case of an I/O problem
      */
     public OutputStream getBufferOutputStream() throws IOException {
+        if (this.streamWriter != null) {
+            flush(); //Just to be sure
+        }
         return this.data.getOutputStream();
     }
     
@@ -91,6 +112,7 @@
      */
     public int getDataLength() {
         try {
+            flush();
             return data.getSize();
         } catch (Exception e) {
             //TODO throw the exception and catch it elsewhere
@@ -99,17 +121,15 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     protected int getSizeHint() throws IOException {
+        flush();
         return data.getSize();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     protected void outputRawStreamData(OutputStream out) throws IOException {
+        flush();
         data.outputContents(out);
     }
 

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=641742&r1=641741&r2=641742&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 Mar 27 01:49:41 2008
@@ -67,7 +67,7 @@
      */
     public void setData(byte[] data, int size) throws IOException {
         this.data.clear();
-        this.data.getOutputStream().write(data, 0, size);
+        getBufferOutputStream().write(data, 0, size);
     }
 
 }



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