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 [2/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...

Copied: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java (from r631256, xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java)
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java?p2=xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java&p1=xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java&r1=631256&r2=641742&rev=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java Thu Mar 27 01:49:41 2008
@@ -17,18 +17,15 @@
 
 /* $Id$ */
 
-package org.apache.fop.svg;
+package org.apache.fop.pdf;
 
 import java.awt.geom.AffineTransform;
 
-import org.apache.fop.fonts.Font;
-import org.apache.fop.pdf.PDFNumber;
-import org.apache.fop.pdf.PDFText;
-
 /**
- * Utility class for generating PDF text objects.
+ * Utility class for generating PDF text objects. It needs to be subclassed to add writing
+ * functionality (see {@link #write(String)}).
  */
-public class PDFTextUtil {
+public abstract class PDFTextUtil {
 
     /** The number of decimal places. */ 
     private static final int DEC = 8;
@@ -50,25 +47,29 @@
     /** PDF text rendering mode: Add text to path for clipping */
     public static final int TR_CLIP = 7;
     
-    
-    private PDFGraphics2D g2d;
     private boolean inTextObject = false;
-    private Font[] fonts;
-    private Font font;
     private String startText;
     private String endText;
     private boolean useMultiByte;
     private StringBuffer bufTJ;
-    private int textRenderingMode = 0;
+    private int textRenderingMode = TR_FILL;
+    
+    private String currentFontName;
+    private double currentFontSize;
     
     /**
      * Main constructor.
-     * @param g2d the PDFGraphics2D instance to work with
      */
-    public PDFTextUtil(PDFGraphics2D g2d) {
-        this.g2d = g2d;
+    public PDFTextUtil() {
+        //nop
     }
     
+    /**
+     * Writes PDF code.
+     * @param code the PDF code to write
+     */
+    protected abstract void write(String code);
+    
     private void writeAffineTransform(AffineTransform at, StringBuffer sb) {
         double[] lt = new double[6];
         at.getMatrix(lt);
@@ -82,7 +83,7 @@
 
     private void writeChar(char ch, StringBuffer sb) {
         if (!useMultiByte) {
-            if (ch > 127) {
+            if (ch < 32 || ch > 127) {
                 sb.append("\\").append(Integer.toOctalString((int)ch));
             } else {
                 switch (ch) {
@@ -107,6 +108,14 @@
     }
     
     /**
+     * Indicates whether we are in a text object or not.
+     * @return true if we are in a text object
+     */
+    public boolean isInTextObject() {
+        return inTextObject;
+    }
+    
+    /**
      * Called when a new text object should be started. Be sure to call setFont() before
      * issuing any text painting commands.
      */
@@ -114,7 +123,7 @@
         if (inTextObject) {
             throw new IllegalStateException("Already in text object");
         }
-        g2d.currentStream.write("BT\n");
+        write("BT\n");
         this.inTextObject = true;
     }
     
@@ -123,13 +132,17 @@
      */
     public void endTextObject() {
         checkInTextObject();
-        g2d.currentStream.write("ET\n");
+        write("ET\n");
         this.inTextObject = false;
         initValues();
     }
     
-    private void initValues() {
-        this.font = null;
+    /**
+     * Resets the state fields.
+     */
+    protected void initValues() {
+        this.currentFontName = null;
+        this.currentFontSize = 0.0;
         this.textRenderingMode = TR_FILL;
     }
     
@@ -137,7 +150,7 @@
      * Creates a "q" command, pushing a copy of the entire graphics state onto the stack.
      */
     public void saveGraphicsState() {
-        g2d.currentStream.write("q\n");
+        write("q\n");
     }
     
     /**
@@ -145,70 +158,54 @@
      * it from the stack.
      */
     public void restoreGraphicsState() {
-        g2d.currentStream.write("Q\n");
+        write("Q\n");
     }
     
     /**
-     * Creates a "cm" command using the current transformation as the matrix.
+     * Creates a "cm" command.
+     * @param at the transformation matrix
      */
-    public void concatMatrixCurrentTransform() {
-        StringBuffer sb = new StringBuffer();
-        if (!g2d.getTransform().isIdentity()) {
-            writeAffineTransform(g2d.getTransform(), sb);
+    public void concatMatrix(AffineTransform at) {
+        if (!at.isIdentity()) {
+            writeTJ();
+            StringBuffer sb = new StringBuffer();
+            writeAffineTransform(at, sb);
             sb.append(" cm\n");
+            write(sb.toString());
         }
-        g2d.currentStream.write(sb.toString());
-    }
-    
-    /**
-     * Sets the current fonts for the text object. For every character, the suitable font will
-     * be selected.
-     * @param fonts the new fonts
-     */
-    public void setFonts(Font[] fonts) {
-        this.fonts = fonts;
-    }
-    
-    /**
-     * Sets the current font for the text object.
-     * @param font the new font
-     */
-    public void setFont(Font font) {
-        setFonts(new Font[] {font});
-    }
-    
-    /**
-     * Returns the current font in use.
-     * @return the current font or null if no font is currently active.
-     */
-    public Font getCurrentFont() {
-        return this.font;
-    }
-    
-    /**
-     * Sets the current font.
-     * @param f the new font to use
-     */
-    public void setCurrentFont(Font f) {
-        this.font = f;
     }
     
     /**
      * Writes a "Tf" command, setting a new current font.
-     * @param f the font to select
+     * @param fontName the name of the font to select
+     * @param fontSize the font size (in points)
      */
-    public void writeTf(Font f) {
+    public void writeTf(String fontName, double fontSize) {
         checkInTextObject();
-        String fontName = f.getFontName();
-        float fontSize = (float)f.getFontSize() / 1000f;
-        g2d.currentStream.write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
+        write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
         
-        this.useMultiByte = g2d.isMultiByteFont(fontName);
         this.startText = useMultiByte ? "<" : "(";
         this.endText = useMultiByte ? ">" : ")";
     }
 
     /**
+     * Updates the current font. This method only writes a "Tf" if the current font changes.
+     * @param fontName the name of the font to select
+     * @param fontSize the font size (in points)
+     * @param multiByte true indicates the font is a multi-byte font, false means single-byte
+     */
+    public void updateTf(String fontName, double fontSize, boolean multiByte) {
+        checkInTextObject();
+        if (!fontName.equals(this.currentFontName) || (fontSize != this.currentFontSize)) {
+            writeTJ();
+            this.currentFontName = fontName;
+            this.currentFontSize = fontSize;
+            this.useMultiByte = multiByte;
+            writeTf(fontName, fontSize);
+        }
+    }
+
+    /**
      * Sets the text rendering mode.
      * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*)
      */
@@ -218,8 +215,9 @@
                     "Illegal value for text rendering mode. Expected: 0-7");
         }
         if (mode != this.textRenderingMode) {
+            writeTJ();
             this.textRenderingMode = mode;
-            g2d.currentStream.write(this.textRenderingMode + " Tr\n");
+            write(this.textRenderingMode + " Tr\n");
         }
     }
     
@@ -249,37 +247,22 @@
     public void writeTextMatrix(AffineTransform localTransform) {
         StringBuffer sb = new StringBuffer();
         writeAffineTransform(localTransform, sb);
-        sb.append(" Tm\n");
-        g2d.currentStream.write(sb.toString());
+        sb.append(" Tm ");
+        write(sb.toString());
     }
 
     /**
-     * Selects a font from the font list suitable to display the given character.
-     * @param ch the character
-     * @return the recommended Font to use
-     */
-    public Font selectFontForChar(char ch) {
-        for (int i = 0, c = fonts.length; i < c; i++) {
-            if (fonts[i].hasChar(ch)) {
-                return fonts[i];
-            }
-        }
-        return fonts[0]; //TODO Maybe fall back to painting with shapes
-    }
-    
-    /**
      * Writes a char to the "TJ-Buffer".
-     * @param ch the unmapped character
+     * @param codepoint the mapped character (code point/character code)
      */
-    public void writeTJChar(char ch) {
+    public void writeTJMappedChar(char codepoint) {
         if (bufTJ == null) {
             bufTJ = new StringBuffer();
         }
         if (bufTJ.length() == 0) {
             bufTJ.append("[").append(startText);
         }
-        char mappedChar = font.mapChar(ch);
-        writeChar(mappedChar, bufTJ);
+        writeChar(codepoint, bufTJ);
     }
 
     /**
@@ -298,11 +281,15 @@
      * positioning values. The buffer is reset afterwards.
      */
     public void writeTJ() {
-        if (bufTJ != null && bufTJ.length() > 0) {
+        if (isInString()) {
             bufTJ.append(endText).append("] TJ\n");
-            g2d.currentStream.write(bufTJ.toString());
+            write(bufTJ.toString());
             bufTJ.setLength(0);
         }
+    }
+
+    private boolean isInString() {
+        return bufTJ != null && bufTJ.length() > 0;
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java Thu Mar 27 01:49:41 2008
@@ -174,11 +174,8 @@
         return charSet.mapChar(c);
     }
 
-    /**
-     * Get the encoding of the font.
-     * @return the encoding
-     */
-    public String getEncoding() {
+    /** {@inheritDoc} */
+    public String getEncodingName() {
         return charSet.getEncoding();
     }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java Thu Mar 27 01:49:41 2008
@@ -25,6 +25,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.apache.fop.fo.properties.FixedLength;
 import org.apache.fop.render.afp.exceptions.FontRuntimeException;
 
@@ -229,11 +230,8 @@
         return charSet.mapChar(c);
     }
 
-    /**
-     * Get the encoding of the font.
-     * @return the encoding
-     */
-    public String getEncoding() {
+    /** {@inheritDoc} */
+    public String getEncodingName() {
         return charSet.getEncoding();
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java Thu Mar 27 01:49:41 2008
@@ -112,7 +112,7 @@
     }
 
     /** {@inheritDoc} */
-    public final String getEncoding() {
+    public final String getEncodingName() {
         return null; //Not applicable to Java2D rendering
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java Thu Mar 27 01:49:41 2008
@@ -172,7 +172,7 @@
     }
 
     /** {@inheritDoc} */
-    public String getEncoding() {
+    public String getEncodingName() {
         return null; //Not applicable to Java2D rendering
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java Thu Mar 27 01:49:41 2008
@@ -89,8 +89,8 @@
         PDFGraphics2D graphics = new PDFGraphics2D(textAsShapes, 
                 pdfInfo.fi, pdfInfo.pdfDoc,
                 pdfInfo.pdfContext, pdfInfo.pdfPage.referencePDF(),
-                renderer.currentFontName,
-                renderer.currentFontSize);
+                pdfInfo.currentFontName,
+                pdfInfo.currentFontSize);
         graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
         
         AffineTransform transform = new AffineTransform();

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=641742&r1=641741&r2=641742&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 Mar 27 01:49:41 2008
@@ -63,7 +63,6 @@
 import org.apache.fop.area.OffDocumentItem;
 import org.apache.fop.area.PageSequence;
 import org.apache.fop.area.PageViewport;
-import org.apache.fop.area.RegionViewport;
 import org.apache.fop.area.Trait;
 import org.apache.fop.area.inline.AbstractTextArea;
 import org.apache.fop.area.inline.Image;
@@ -78,6 +77,8 @@
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 import org.apache.fop.fo.extensions.xmp.XMPMetadata;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteFont;
 import org.apache.fop.fonts.Typeface;
 import org.apache.fop.pdf.PDFAMode;
 import org.apache.fop.pdf.PDFAction;
@@ -106,7 +107,7 @@
 import org.apache.fop.pdf.PDFResources;
 import org.apache.fop.pdf.PDFState;
 import org.apache.fop.pdf.PDFStream;
-import org.apache.fop.pdf.PDFText;
+import org.apache.fop.pdf.PDFTextUtil;
 import org.apache.fop.pdf.PDFXMode;
 import org.apache.fop.pdf.PDFXObject;
 import org.apache.fop.render.AbstractPathOrientedRenderer;
@@ -250,21 +251,14 @@
     /** drawing state */
     protected PDFState currentState = null;
 
-    /** Name of currently selected font */
-    protected String currentFontName = "";
-    /** Size of currently selected font */
-    protected int currentFontSize = 0;
+    /** Text generation utility holding the current font status */
+    protected PDFTextUtil textutil;
     /** page height */
     protected int pageHeight;
 
     /** Registry of PDF filters */
     protected Map filterMap;
 
-    /**
-     * true if a BT command has been written. 
-     */
-    protected boolean inTextMode = false;
-
     /** Image handler registry */
     private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();
     
@@ -527,7 +521,7 @@
         currentContext = null;
         currentPage = null;
         currentState = null;
-        currentFontName = "";
+        this.textutil = null;
 
         idPositions.clear();
         idGoTos.clear();
@@ -665,19 +659,15 @@
 
     /** Indicates the beginning of a text object. */
     protected void beginTextObject() {
-        if (!inTextMode) {
-            currentStream.add("BT\n");
-            currentFontName = "";
-            inTextMode = true;
+        if (!textutil.isInTextObject()) {
+            textutil.beginTextObject();
         }
     }
 
     /** Indicates the end of a text object. */
     protected void endTextObject() {
-        closeText();
-        if (inTextMode) {
-            currentStream.add("ET\n");
-            inTextMode = false;
+        if (textutil.isInTextObject()) {
+            textutil.endTextObject();
         }
     }
 
@@ -787,6 +777,11 @@
 
         currentStream = this.pdfDoc.getFactory()
             .makeStream(PDFFilterList.CONTENT_FILTER, false);
+        this.textutil = new PDFTextUtil() {
+            protected void write(String code) {
+                currentStream.add(code);
+            }
+        };
 
         currentState = new PDFState();
         // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's
@@ -795,9 +790,6 @@
         currentState.concatenate(basicPageTransform);
         currentStream.add(CTMHelper.toPDFString(basicPageTransform, false) + " cm\n");
         
-        
-        currentFontName = "";
-
         super.renderPage(page);
 
         this.pdfDoc.registerObject(currentStream);
@@ -808,6 +800,7 @@
         }
         this.pdfDoc.addObject(currentPage);
         this.pdfDoc.output(ostream);
+        this.textutil = null;
     }
 
     /** {@inheritDoc} */
@@ -841,17 +834,6 @@
     }
     
     /**
-     * Handle the traits for a region
-     * This is used to draw the traits for the given page region.
-     * (See Sect. 6.4.1.2 of XSL-FO spec.)
-     * @param region the RegionViewport whose region is to be drawn
-     */
-    protected void handleRegionTraits(RegionViewport region) {
-        currentFontName = "";
-        super.handleRegionTraits(region);
-    }
-
-    /**
      * Formats a float value (normally coordinates) as Strings.
      * @param value the value
      * @return the formatted value
@@ -866,7 +848,8 @@
         float w = x2 - x1;
         float h = y2 - y1;
         if ((w < 0) || (h < 0)) {
-            log.error("Negative extent received (w=" + w + ", h=" + h + "). Border won't be painted.");
+            log.error("Negative extent received (w=" + w + ", h=" + h
+                    + "). Border won't be painted.");
             return;
         }
         switch (style) {
@@ -1329,12 +1312,9 @@
         super.renderBlock(block);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     protected void renderLineArea(LineArea line) {
         super.renderLineArea(line);
-        closeText();
     }
 
     /**
@@ -1423,11 +1403,20 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    private Typeface getTypeface(String fontName) {
+        Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
+        if (tf instanceof LazyFont) {
+            tf = ((LazyFont)tf).getRealFont();
+        }
+        return tf;
+    }
+    
+    /** {@inheritDoc} */
     public void renderText(TextArea text) {
         renderInlineAreaBackAndBorders(text);
+        Color ct = (Color) text.getTrait(Trait.COLOR);
+        updateColor(ct, true);
+        
         beginTextObject();
         StringBuffer pdf = new StringBuffer();
 
@@ -1435,12 +1424,10 @@
         int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
         
         // This assumes that *all* CIDFonts use a /ToUnicode mapping
-        Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
-        boolean useMultiByte = tf.isMultiByte();
+        Typeface tf = getTypeface(fontName);
+        
+        textutil.updateTf(fontName, size / 1000f, tf.isMultiByte());
         
-        updateFont(fontName, size, pdf);
-        Color ct = (Color) text.getTrait(Trait.COLOR);
-        updateColor(ct, true, pdf);
 
         // word.getOffset() = only height of text itself
         // currentBlockIPPosition: 0 for beginning of line; nonzero
@@ -1448,66 +1435,46 @@
         int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
         int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
 
-        pdf.append("1 0 0 -1 " + format(rx / 1000f) + " " + format(bl / 1000f) + " Tm "
-                   /*+ format(text.getTextLetterSpaceAdjust() / 1000f) + " Tc\n"*/
-                   /*+ format(text.getTextWordSpaceAdjust() / 1000f) + " Tw ["*/);
+        textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, rx / 1000f, bl / 1000f));
 
-        pdf.append("[");
         currentStream.add(pdf.toString());
 
         super.renderText(text);
 
-        currentStream.add("] TJ\n");
+        textutil.writeTJ();
         
         renderTextDecoration(tf, size, text, bl, rx);
     }
-    
-    /**
-     * {@inheritDoc}
-     */
+
+    /** {@inheritDoc} */
     public void renderWord(WordArea word) {
         Font font = getFontFromArea(word.getParentArea());
-        Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
-        boolean useMultiByte = tf.isMultiByte();
-
-        StringBuffer pdf = new StringBuffer();
-        
         String s = word.getWord();
-        escapeText(s, word.getLetterAdjustArray(), 
-                font, (AbstractTextArea)word.getParentArea(), useMultiByte, pdf);
 
-        currentStream.add(pdf.toString());
+        escapeText(s, word.getLetterAdjustArray(), 
+                font, (AbstractTextArea)word.getParentArea());
 
         super.renderWord(word);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public void renderSpace(SpaceArea space) {
         Font font = getFontFromArea(space.getParentArea());
-        Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
-        boolean useMultiByte = tf.isMultiByte();
-
         String s = space.getSpace();
         
-        StringBuffer pdf = new StringBuffer();
-
         AbstractTextArea textArea = (AbstractTextArea)space.getParentArea();
-        escapeText(s, null, font, textArea, useMultiByte, pdf);
+        escapeText(s, null, font, textArea);
 
         if (space.isAdjustable()) {
             int tws = -((TextArea) space.getParentArea()).getTextWordSpaceAdjust()
                          - 2 * textArea.getTextLetterSpaceAdjust();
 
             if (tws != 0) {
-                pdf.append(format(tws / (font.getFontSize() / 1000f)));
-                pdf.append(" ");
+                float adjust = tws / (font.getFontSize() / 1000f);
+                textutil.adjustGlyphTJ(adjust);
             }
         }
 
-        currentStream.add(pdf.toString());
-
         super.renderSpace(space);
     }
 
@@ -1515,101 +1482,77 @@
      * Escapes text according to PDF rules.
      * @param s Text to escape
      * @param letterAdjust an array of widths for letter adjustment (may be null)
-     * @param fs Font state
+     * @param font to font in use
      * @param parentArea the parent text area to retrieve certain traits from
-     * @param useMultiByte Indicates the use of multi byte convention
-     * @param pdf target buffer for the escaped text
      */
-    public void escapeText(String s, int[] letterAdjust,
-                           Font fs, AbstractTextArea parentArea,
-                           boolean useMultiByte, StringBuffer pdf) {
-        String startText = useMultiByte ? "<" : "(";
-        String endText = useMultiByte ? "> " : ") ";
-
-        /*
-        boolean kerningAvailable = false;
-        Map kerning = fs.getKerning();
-        if (kerning != null && !kerning.isEmpty()) {
-            //kerningAvailable = true;
-            //TODO Reenable me when the layout engine supports kerning, too
-            log.warn("Kerning support is disabled until it is supported by the layout engine!");
+    protected void escapeText(String s,
+                           int[] letterAdjust,
+                           Font font, AbstractTextArea parentArea) {
+        escapeText(s, 0, s.length(), letterAdjust, font, parentArea);
+    }
+    
+    /**
+     * Escapes text according to PDF rules.
+     * @param s Text to escape
+     * @param start the start position in the text
+     * @param end the end position in the text
+     * @param letterAdjust an array of widths for letter adjustment (may be null)
+     * @param font to font in use
+     * @param parentArea the parent text area to retrieve certain traits from
+     */
+    protected void escapeText(String s, int start, int end,
+                           int[] letterAdjust,
+                           Font font, AbstractTextArea parentArea) {
+        String fontName = font.getFontName();
+        float fontSize = font.getFontSize() / 1000f;
+        Typeface tf = getTypeface(fontName);
+        SingleByteFont singleByteFont = null;
+        if (tf instanceof SingleByteFont) {
+            singleByteFont = (SingleByteFont)tf;
         }
-        */
 
         int l = s.length();
-
-        float fontSize = fs.getFontSize() / 1000f;
-        boolean startPending = true;
-        for (int i = 0; i < l; i++) {
+        
+        for (int i = start; i < end; i++) {
             char orgChar = s.charAt(i);
             char ch;
             float glyphAdjust = 0;
-            if (fs.hasChar(orgChar)) {
-                ch = fs.mapChar(orgChar);
+            if (font.hasChar(orgChar)) {
+                ch = font.mapChar(orgChar);
+                if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
+                    int encoding = ch / 256;
+                    if (encoding == 0) {
+                        textutil.updateTf(fontName, fontSize, tf.isMultiByte());
+                    } else {
+                        textutil.updateTf(fontName + "_" + Integer.toString(encoding),
+                                fontSize, tf.isMultiByte());
+                        ch = (char)(ch % 256);
+                    }
+                }
                 int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0);
                 glyphAdjust -= tls;
             } else {
                 if (CharUtilities.isFixedWidthSpace(orgChar)) {
                     //Fixed width space are rendered as spaces so copy/paste works in a reader
-                    ch = fs.mapChar(CharUtilities.SPACE);
-                    glyphAdjust = fs.getCharWidth(ch) - fs.getCharWidth(orgChar);
+                    ch = font.mapChar(CharUtilities.SPACE);
+                    glyphAdjust = font.getCharWidth(ch) - font.getCharWidth(orgChar);
                 } else {
-                    ch = fs.mapChar(orgChar);
+                    ch = font.mapChar(orgChar);
                 }
             }
             if (letterAdjust != null && i < l - 1) {
                 glyphAdjust -= letterAdjust[i + 1];
             }
 
-            if (startPending) {
-                pdf.append(startText);
-                startPending = false;
-            }
-            if (!useMultiByte) {
-                if (ch < 32 || ch > 127) {
-                    pdf.append("\\");
-                    pdf.append(Integer.toOctalString((int) ch));
-                } else {
-                    switch (ch) {
-                        case '(':
-                        case ')':
-                        case '\\':
-                            pdf.append("\\");
-                            break;
-                        default:
-                    }
-                    pdf.append(ch);
-                }
-            } else {
-                pdf.append(PDFText.toUnicodeHex(ch));
-            }
+            textutil.writeTJMappedChar(ch);
 
             float adjust = glyphAdjust / fontSize;
 
             if (adjust != 0) {
-                pdf.append(endText).append(format(adjust)).append(' ');
-                startPending = true;
+                textutil.adjustGlyphTJ(adjust);
             }
 
         }
-        if (!startPending) {
-            pdf.append(endText);
-        }
-    }
-
-    /**
-     * Checks to see if we have some text rendering commands open
-     * still and writes out the TJ command to the stream if we do
-     */
-    protected void closeText() {
-        /*
-        if (textOpen) {
-            currentStream.add("] TJ\n");
-            textOpen = false;
-            prevWordX = 0;
-            prevWordY = 0;
-            currentFontName = "";
-        }*/
     }
 
     /**
@@ -1623,8 +1566,6 @@
     protected void setColor(Color col, boolean fill, StringBuffer pdf) {
         PDFColor color = new PDFColor(this.pdfDoc, col);
 
-        closeText();
-        
         if (pdf != null) {
             pdf.append(color.getColorSpaceOut(fill));
         } else {
@@ -1656,22 +1597,10 @@
     }
 
     /** {@inheritDoc} */
-    protected  void updateColor(Color col, boolean fill) {
+    protected void updateColor(Color col, boolean fill) {
         updateColor(col, fill, null);
     }
     
-    private void updateFont(String name, int size, StringBuffer pdf) {
-        if ((!name.equals(this.currentFontName))
-                || (size != this.currentFontSize)) {
-            closeText();
-
-            this.currentFontName = name;
-            this.currentFontSize = size;
-            pdf = pdf.append("/" + name + " " + format((float) size / 1000f)
-                              + " Tf\n");
-        }
-    }
-
     /** {@inheritDoc} */
     public void renderImage(Image image, Rectangle2D pos) {
         endTextObject();
@@ -1727,8 +1656,6 @@
             ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
             info = manager.getImageInfo(uri, sessionContext);
             
-            
-            
             Map hints = ImageUtil.getDefaultHints(sessionContext);
             org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
                         info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext);
@@ -1802,9 +1729,8 @@
         context.setProperty(PDFRendererContextConstants.PDF_CONTEXT, currentContext);
         context.setProperty(PDFRendererContextConstants.PDF_STREAM, currentStream);
         context.setProperty(PDFRendererContextConstants.PDF_FONT_INFO, fontInfo);
-        context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, currentFontName);
-        context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE,
-                            new Integer(currentFontSize));
+        context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, "");
+        context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE, new Integer(0));
         return context;
     }
 

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=641742&r1=641741&r2=641742&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 Mar 27 01:49:41 2008
@@ -32,16 +32,20 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.apache.xmlgraphics.fonts.Glyphs;
 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.Base14Font;
 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.SingleByteEncoding;
+import org.apache.fop.fonts.SingleByteFont;
 import org.apache.fop.fonts.Typeface;
 
 /**
@@ -81,9 +85,21 @@
         while (iter.hasNext()) {
             String key = (String)iter.next();
             Typeface tf = getTypeFace(fontInfo, fonts, key);
-            PSResource fontRes = new PSResource("font", tf.getFontName());
+            PSResource fontRes = new PSResource(PSResource.TYPE_FONT, tf.getFontName());
             fontResources.put(key, fontRes);
             embedFont(gen, tf, fontRes);
+            
+            if (tf instanceof SingleByteFont) {
+                SingleByteFont sbf = (SingleByteFont)tf;
+                for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) {
+                    SingleByteEncoding encoding = sbf.getAdditionalEncoding(i);
+                    defineEncoding(gen, encoding);
+                    String postFix = "_" + (i + 1);
+                    PSResource derivedFontRes = defineDerivedFont(gen, tf.getFontName(),
+                            tf.getFontName() + postFix, encoding.getName());
+                    fontResources.put(key + postFix, derivedFontRes);
+                }
+            }
         }
         gen.commentln("%FOPEndFontDict");
         reencodeFonts(gen, fonts);
@@ -91,29 +107,35 @@
     }
 
     private static void reencodeFonts(PSGenerator gen, Map fonts) throws IOException {
+        ResourceTracker tracker = gen.getResourceTracker();
+        
+        if (!tracker.isResourceSupplied(WINANSI_ENCODING_RESOURCE)) {
+            defineWinAnsiEncoding(gen);
+        }
         gen.commentln("%FOPBeginFontReencode");
-        defineWinAnsiEncoding(gen);
         
         //Rewrite font encodings
         Iterator iter = fonts.keySet().iterator();
         while (iter.hasNext()) {
             String key = (String)iter.next();
-            Typeface fm = (Typeface)fonts.get(key);
-            if (fm instanceof LazyFont && ((LazyFont)fm).getRealFont() == null) {
-                continue;
-            } else if (null == fm.getEncoding()) {
+            Typeface tf = (Typeface)fonts.get(key);
+            if (tf instanceof LazyFont) {
+                tf = ((LazyFont)tf).getRealFont();
+                if (tf == null) {
+                    continue;
+                }
+            }
+            if (null == tf.getEncodingName()) {
                 //ignore (ZapfDingbats and Symbol used to run through here, kept for safety reasons)
-            } else if ("SymbolEncoding".equals(fm.getEncoding())) {
+            } else if ("SymbolEncoding".equals(tf.getEncodingName())) {
                 //ignore (no encoding redefinition)
-            } else if ("ZapfDingbatsEncoding".equals(fm.getEncoding())) {
+            } else if ("ZapfDingbatsEncoding".equals(tf.getEncodingName())) {
                 //ignore (no encoding redefinition)
-            } 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());
-                */
+                if (tf instanceof Base14Font) {
+                    //Our Base 14 fonts don't use the default encoding 
+                    redefineFontEncoding(gen, tf.getFontName(), tf.getEncodingName());
+                }
             }
         }
         gen.commentln("%FOPEndFontReencode");
@@ -233,10 +255,88 @@
                     if (isEmbeddable(cf)) {
                         resTracker.registerSuppliedResource(fontRes);
                     }
+                    if (tf instanceof SingleByteFont) {
+                        SingleByteFont sbf = (SingleByteFont)tf;
+                        for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) {
+                            SingleByteEncoding encoding = sbf.getAdditionalEncoding(i);
+                            PSResource encodingRes = new PSResource(
+                                    PSResource.TYPE_ENCODING, encoding.getName());
+                            resTracker.registerSuppliedResource(encodingRes);
+                            PSResource derivedFontRes = new PSResource(
+                                    PSResource.TYPE_FONT, tf.getFontName() + "_" + (i + 1));
+                            resTracker.registerSuppliedResource(derivedFontRes);
+                        }
+                    }
                 }
             }
         }
         return fontResources;
     }
 
+    /**
+     * Defines the single-byte encoding for use in PostScript files.
+     * @param gen the PostScript generator
+     * @param encoding the single-byte encoding
+     * @return the PSResource instance that represents the encoding
+     * @throws IOException In case of an I/O problem
+     */
+    public static PSResource defineEncoding(PSGenerator gen, SingleByteEncoding encoding)
+            throws IOException {
+        PSResource res = new PSResource(PSResource.TYPE_ENCODING, encoding.getName());
+        gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res);
+        gen.writeln("/" + encoding.getName() + " [");
+        String[] charNames = encoding.getCharNameMap();
+        for (int i = 0; i < 256; i++) {
+            if (i > 0) {
+                if ((i % 5) == 0) {
+                    gen.newLine();
+                } else {
+                    gen.write(" ");
+                }
+            }
+            String glyphname = null;
+            if (i < charNames.length) {
+                glyphname = charNames[i];
+            }
+            if (glyphname == null || "".equals(glyphname)) {
+                glyphname = Glyphs.NOTDEF;
+            }
+            gen.write("/");
+            gen.write(glyphname);
+        }
+        gen.newLine();
+        gen.writeln("] def");
+        gen.writeDSCComment(DSCConstants.END_RESOURCE);
+        gen.getResourceTracker().registerSuppliedResource(res);
+        return res;
+    }
+
+    /**
+     * Derives a new font based on an existing font with a given encoding. The encoding must
+     * have been registered before.
+     * @param gen the PostScript generator
+     * @param baseFontName the font name of the font to derive from
+     * @param fontName the font name of the new font to be define
+     * @param encoding the new encoding (must be predefined in the PS file)
+     * @return the PSResource representing the derived font
+     * @throws IOException In case of an I/O problem
+     */
+    public static PSResource defineDerivedFont(PSGenerator gen, String baseFontName, String fontName,
+            String encoding) throws IOException {
+        PSResource res = new PSResource(PSResource.TYPE_FONT, fontName);
+        gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res);
+        gen.commentln("%XGCDependencies: font " + baseFontName);
+        gen.commentln("%XGC+ encoding " + encoding);
+        gen.writeln("/" + baseFontName + " findfont");
+        gen.writeln("dup length dict begin");
+        gen.writeln("  {1 index /FID ne {def} {pop pop} ifelse} forall");
+        gen.writeln("  /Encoding " + encoding + " def");
+        gen.writeln("  currentdict");
+        gen.writeln("end");
+        gen.writeln("/" + fontName + " exch definefont pop");
+        gen.writeDSCComment(DSCConstants.END_RESOURCE);
+        gen.getResourceTracker().registerSuppliedResource(res);
+        return res;
+    }
+    
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java Thu Mar 27 01:49:41 2008
@@ -89,6 +89,7 @@
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteFont;
 import org.apache.fop.fonts.Typeface;
 import org.apache.fop.render.AbstractPathOrientedRenderer;
 import org.apache.fop.render.Graphics2DAdapter;
@@ -660,6 +661,12 @@
     }
     
     private String getPostScriptNameForFontKey(String key) {
+        int pos = key.indexOf('_');
+        String postFix = null;
+        if (pos > 0) {
+            postFix = key.substring(pos);
+            key = key.substring(0, pos);
+        }
         Map fonts = fontInfo.getFonts();
         Typeface tf = (Typeface)fonts.get(key);
         if (tf instanceof LazyFont) {
@@ -668,7 +675,11 @@
         if (tf == null) {
             throw new IllegalStateException("Font not available: " + key);
         }
-        return tf.getFontName();
+        if (postFix == null) {
+            return tf.getFontName();
+        } else {
+            return tf.getFontName() + postFix;
+        }
     }
     
     /**
@@ -698,7 +709,6 @@
     protected void useFont(String key, int size) {
         try {
             PSResource res = getPSResourceForFontKey(key);
-            //gen.useFont(key, size / 1000f);
             gen.useFont("/" + res.getName(), size / 1000f);
             gen.getResourceTracker().notifyResourceUsageOnPage(res);
         } catch (IOException ioe) {
@@ -951,7 +961,7 @@
         if (!isOptimizeResources()) {
             this.fontResources = PSFontUtils.writeFontDict(gen, fontInfo);
         } else {
-            gen.commentln("%FOPFontSetup");
+            gen.commentln("%FOPFontSetup"); //Place-holder, will be replaced in the second pass
         }
         gen.writeDSCComment(DSCConstants.END_SETUP);
     }
@@ -1292,17 +1302,16 @@
      */
     public void renderText(TextArea area) {
         renderInlineAreaBackAndBorders(area);
-        String fontname = getInternalFontNameForArea(area);
+        String fontkey = getInternalFontNameForArea(area);
         int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
 
         // This assumes that *all* CIDFonts use a /ToUnicode mapping
-        Typeface tf = (Typeface) fontInfo.getFonts().get(fontname);
+        Typeface tf = (Typeface) fontInfo.getFonts().get(fontkey);
 
         //Determine position
         int rx = currentIPPosition + area.getBorderAndPaddingWidthStart();
         int bl = currentBPPosition + area.getOffset() + area.getBaselineOffset();
 
-        useFont(fontname, fontsize);
         Color ct = (Color)area.getTrait(Trait.COLOR);
         if (ct != null) {
             try {
@@ -1347,30 +1356,75 @@
         super.renderSpace(space);
     }
 
+    private Typeface getTypeface(String fontName) {
+        Typeface tf = (Typeface)fontInfo.getFonts().get(fontName);
+        if (tf instanceof LazyFont) {
+            tf = ((LazyFont)tf).getRealFont();
+        }
+        return tf;
+    }
+    
     private void renderText(AbstractTextArea area, String text, int[] letterAdjust) {
+        String fontkey = getInternalFontNameForArea(area);
+        int fontSize = area.getTraitAsInteger(Trait.FONT_SIZE);
         Font font = getFontFromArea(area);
-        Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
+        Typeface tf = getTypeface(font.getFontName());
+        SingleByteFont singleByteFont = null;
+        if (tf instanceof SingleByteFont) {
+            singleByteFont = (SingleByteFont)tf;
+        }
 
+        int textLen = text.length();
+        if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
+            int start = 0;
+            int currentEncoding = -1;
+            for (int i = 0; i < textLen; i++) {
+                char c = text.charAt(i);
+                char mapped = tf.mapChar(c);
+                int encoding = mapped / 256;
+                if (currentEncoding != encoding) {
+                    if (i > 0) {
+                        writeText(area, text, start, i - start, letterAdjust, fontSize, tf);
+                    }
+                    if (encoding == 0) {
+                        useFont(fontkey, fontSize);
+                    } else {
+                        useFont(fontkey + "_" + Integer.toString(encoding), fontSize);
+                    }
+                    currentEncoding = encoding;
+                    start = i;
+                }
+            }
+            writeText(area, text, start, textLen - start, letterAdjust, fontSize, tf);
+        } else {
+            useFont(fontkey, fontSize);
+            writeText(area, text, 0, textLen, letterAdjust, fontSize, tf);
+        }
+    }
+
+    private void writeText(AbstractTextArea area, String text, int start, int len,
+            int[] letterAdjust, int fontsize, Typeface tf) {
+        int end = start + len;
         int initialSize = text.length();
         initialSize += initialSize / 2;
         StringBuffer sb = new StringBuffer(initialSize);
-        int textLen = text.length();
         if (letterAdjust == null 
                 && area.getTextLetterSpaceAdjust() == 0 
                 && area.getTextWordSpaceAdjust() == 0) {
             sb.append("(");
-            for (int i = 0; i < textLen; i++) {
+            for (int i = start; i < end; i++) {
                 final char c = text.charAt(i);
-                final char mapped = tf.mapChar(c);
+                final char mapped = (char)(tf.mapChar(c) % 256);
                 PSGenerator.escapeChar(mapped, sb);
             }
             sb.append(") t");
         } else {
             sb.append("(");
-            int[] offsets = new int[textLen];
-            for (int i = 0; i < textLen; i++) {
+            int[] offsets = new int[len];
+            for (int i = start; i < end; i++) {
                 final char c = text.charAt(i);
                 final char mapped = tf.mapChar(c);
+                char codepoint = (char)(mapped % 256);
                 int wordSpace;
 
                 if (CharUtilities.isAdjustableSpace(mapped)) {
@@ -1378,14 +1432,14 @@
                 } else {
                     wordSpace = 0;
                 }
-                int cw = tf.getWidth(mapped, font.getFontSize()) / 1000;
-                int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0);
-                int tls = (i < textLen - 1 ? area.getTextLetterSpaceAdjust() : 0); 
-                offsets[i] = cw + ladj + tls + wordSpace;
-                PSGenerator.escapeChar(mapped, sb);
+                int cw = tf.getWidth(mapped, fontsize) / 1000;
+                int ladj = (letterAdjust != null && i < end - 1 ? letterAdjust[i + 1] : 0);
+                int tls = (i < end - 1 ? area.getTextLetterSpaceAdjust() : 0); 
+                offsets[i - start] = cw + ladj + tls + wordSpace;
+                PSGenerator.escapeChar(codepoint, sb);
             }
             sb.append(")" + PSGenerator.LF + "[");
-            for (int i = 0; i < textLen; i++) {
+            for (int i = 0; i < len; i++) {
                 if (i > 0) {
                     if (i % 8 == 0) {
                         sb.append(PSGenerator.LF);
@@ -1398,7 +1452,6 @@
             sb.append("]" + PSGenerator.LF + "xshow");
         }
         writeln(sb.toString());
-
     }
 
     /** {@inheritDoc} */

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java Thu Mar 27 01:49:41 2008
@@ -70,12 +70,10 @@
 import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
 import org.apache.xmlgraphics.java2d.GraphicContext;
 
-import org.apache.fop.fonts.CIDFont;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontSetup;
 import org.apache.fop.fonts.FontTriplet;
-import org.apache.fop.fonts.LazyFont;
 import org.apache.fop.pdf.BitmapImage;
 import org.apache.fop.pdf.PDFAnnotList;
 import org.apache.fop.pdf.PDFColor;
@@ -1473,14 +1471,7 @@
         // This assumes that *all* CIDFonts use a /ToUnicode mapping
         org.apache.fop.fonts.Typeface f
             = (org.apache.fop.fonts.Typeface)fontInfo.getFonts().get(name);
-        if (f instanceof LazyFont) {
-            if (((LazyFont) f).getRealFont() instanceof CIDFont) {
-                return true;
-            }
-        } else if (f instanceof CIDFont) {
-            return true;
-        }
-        return false;
+        return f.isMultiByte();
     }
 
     private void addKerning(StringWriter buf, Integer ch1, Integer ch2,

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java Thu Mar 27 01:49:41 2008
@@ -43,6 +43,7 @@
 import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
 import org.apache.batik.gvt.text.TextPaintInfo;
 import org.apache.batik.gvt.text.TextSpanLayout;
+
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontTriplet;
@@ -83,8 +84,12 @@
             super.paintTextRuns(textRuns, g2d);
             return;
         }
-        PDFGraphics2D pdf = (PDFGraphics2D)g2d;
-        PDFTextUtil textUtil = new PDFTextUtil(pdf);
+        final PDFGraphics2D pdf = (PDFGraphics2D)g2d;
+        PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) {
+            protected void write(String code) {
+                pdf.currentStream.write(code);
+            }
+        };
         for (int i = 0; i < textRuns.size(); i++) {
             TextRun textRun = (TextRun)textRuns.get(i);
             AttributedCharacterIterator runaci = textRun.getACI();
@@ -134,7 +139,7 @@
             }
             
             textUtil.saveGraphicsState();
-            textUtil.concatMatrixCurrentTransform();
+            textUtil.concatMatrix(g2d.getTransform());
             Shape imclip = g2d.getClip();
             pdf.writeClip(imclip);
             

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java Thu Mar 27 01:49:41 2008
@@ -19,145 +19,33 @@
 
 package org.apache.fop.svg;
 
-import java.awt.geom.AffineTransform;
-
 import org.apache.fop.fonts.Font;
-import org.apache.fop.pdf.PDFNumber;
-import org.apache.fop.pdf.PDFText;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.Typeface;
 
 /**
- * Utility class for generating PDF text objects.
+ * Utility class for generating PDF text objects. It needs to be subclassed to add writing
+ * functionality (see {@link #write(String)}).
  */
-public class PDFTextUtil {
+public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil {
 
-    /** The number of decimal places. */ 
-    private static final int DEC = 8;
-    
-    /** PDF text rendering mode: Fill text */
-    public static final int TR_FILL = 0;
-    /** PDF text rendering mode: Stroke text */
-    public static final int TR_STROKE = 1;
-    /** PDF text rendering mode: Fill, then stroke text */
-    public static final int TR_FILL_STROKE = 2;
-    /** PDF text rendering mode: Neither fill nor stroke text (invisible) */
-    public static final int TR_INVISIBLE = 3;
-    /** PDF text rendering mode: Fill text and add to path for clipping */
-    public static final int TR_FILL_CLIP = 4;
-    /** PDF text rendering mode: Stroke text and add to path for clipping */
-    public static final int TR_STROKE_CLIP = 5;
-    /** PDF text rendering mode: Fill, then stroke text and add to path for clipping */
-    public static final int TR_FILL_STROKE_CLIP = 6;
-    /** PDF text rendering mode: Add text to path for clipping */
-    public static final int TR_CLIP = 7;
-    
-    
-    private PDFGraphics2D g2d;
-    private boolean inTextObject = false;
+    private FontInfo fontInfo;
     private Font[] fonts;
     private Font font;
-    private String startText;
-    private String endText;
-    private boolean useMultiByte;
-    private StringBuffer bufTJ;
-    private int textRenderingMode = 0;
     
     /**
      * Main constructor.
-     * @param g2d the PDFGraphics2D instance to work with
+     * @param fontInfo the font catalog
      */
-    public PDFTextUtil(PDFGraphics2D g2d) {
-        this.g2d = g2d;
+    public PDFTextUtil(FontInfo fontInfo) {
+        super();
+        this.fontInfo = fontInfo;
     }
     
-    private void writeAffineTransform(AffineTransform at, StringBuffer sb) {
-        double[] lt = new double[6];
-        at.getMatrix(lt);
-        sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" ");
-        sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" ");
-        sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" ");
-        sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" ");
-        sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" ");
-        sb.append(PDFNumber.doubleOut(lt[5], DEC));
-    }
-
-    private void writeChar(char ch, StringBuffer sb) {
-        if (!useMultiByte) {
-            if (ch > 127) {
-                sb.append("\\").append(Integer.toOctalString((int)ch));
-            } else {
-                switch (ch) {
-                case '(':
-                case ')':
-                case '\\':
-                    sb.append("\\");
-                    break;
-                default:
-                }
-                sb.append(ch);
-            }
-        } else {
-            sb.append(PDFText.toUnicodeHex(ch));
-        }
-    }
-    
-    private void checkInTextObject() {
-        if (!inTextObject) {
-            throw new IllegalStateException("Not in text object");
-        }
-    }
-    
-    /**
-     * Called when a new text object should be started. Be sure to call setFont() before
-     * issuing any text painting commands.
-     */
-    public void beginTextObject() {
-        if (inTextObject) {
-            throw new IllegalStateException("Already in text object");
-        }
-        g2d.currentStream.write("BT\n");
-        this.inTextObject = true;
-    }
-    
-    /**
-     * Called when a text object should be ended.
-     */
-    public void endTextObject() {
-        checkInTextObject();
-        g2d.currentStream.write("ET\n");
-        this.inTextObject = false;
-        initValues();
-    }
-    
-    private void initValues() {
+    /** {@inheritDoc} */
+    protected void initValues() {
+        super.initValues();
         this.font = null;
-        this.textRenderingMode = TR_FILL;
-    }
-    
-    /**
-     * Creates a "q" command, pushing a copy of the entire graphics state onto the stack.
-     */
-    public void saveGraphicsState() {
-        g2d.currentStream.write("q\n");
-    }
-    
-    /**
-     * Creates a "Q" command, restoring the entire graphics state to its former value by popping
-     * it from the stack.
-     */
-    public void restoreGraphicsState() {
-        g2d.currentStream.write("Q\n");
-    }
-    
-    /**
-     * Creates a "cm" command using the current transformation as the matrix.
-     */
-    public void concatMatrixCurrentTransform() {
-        StringBuffer sb = new StringBuffer();
-        if (!g2d.getTransform().isIdentity()) {
-            writeAffineTransform(g2d.getTransform(), sb);
-            sb.append(" cm\n");
-        }
-        g2d.currentStream.write(sb.toString());
     }
     
     /**
@@ -194,63 +82,23 @@
     }
     
     /**
+     * Determines whether the font with the given name is a multi-byte font.
+     * @param name the name of the font
+     * @return true if it's a multi-byte font
+     */
+    protected boolean isMultiByteFont(String name) {
+        Typeface f = (Typeface)fontInfo.getFonts().get(name);
+        return f.isMultiByte();
+    }
+
+    /**
      * Writes a "Tf" command, setting a new current font.
      * @param f the font to select
      */
     public void writeTf(Font f) {
-        checkInTextObject();
         String fontName = f.getFontName();
         float fontSize = (float)f.getFontSize() / 1000f;
-        g2d.currentStream.write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
-        
-        this.useMultiByte = g2d.isMultiByteFont(fontName);
-        this.startText = useMultiByte ? "<" : "(";
-        this.endText = useMultiByte ? ">" : ")";
-    }
-
-    /**
-     * Sets the text rendering mode.
-     * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*)
-     */
-    public void setTextRenderingMode(int mode) {
-        if (mode < 0 || mode > 7) {
-            throw new IllegalArgumentException(
-                    "Illegal value for text rendering mode. Expected: 0-7");
-        }
-        if (mode != this.textRenderingMode) {
-            this.textRenderingMode = mode;
-            g2d.currentStream.write(this.textRenderingMode + " Tr\n");
-        }
-    }
-    
-    /**
-     * Sets the text rendering mode.
-     * @param fill true if the text should be filled
-     * @param stroke true if the text should be stroked
-     * @param addToClip true if the path should be added for clipping
-     */
-    public void setTextRenderingMode(boolean fill, boolean stroke, boolean addToClip) {
-        int mode;
-        if (fill) {
-            mode = (stroke ? 2 : 0);
-        } else {
-            mode = (stroke ? 1 : 3);
-        }
-        if (addToClip) {
-            mode += 4;
-        }
-        setTextRenderingMode(mode);
-    }
-    
-    /**
-     * Writes a "Tm" command, setting a new text transformation matrix.
-     * @param localTransform the new text transformation matrix
-     */
-    public void writeTextMatrix(AffineTransform localTransform) {
-        StringBuffer sb = new StringBuffer();
-        writeAffineTransform(localTransform, sb);
-        sb.append(" Tm\n");
-        g2d.currentStream.write(sb.toString());
+        updateTf(fontName, fontSize, isMultiByteFont(fontName));
     }
 
     /**
@@ -272,37 +120,8 @@
      * @param ch the unmapped character
      */
     public void writeTJChar(char ch) {
-        if (bufTJ == null) {
-            bufTJ = new StringBuffer();
-        }
-        if (bufTJ.length() == 0) {
-            bufTJ.append("[").append(startText);
-        }
         char mappedChar = font.mapChar(ch);
-        writeChar(mappedChar, bufTJ);
-    }
-
-    /**
-     * Writes a glyph adjust value to the "TJ-Buffer".
-     * @param adjust the glyph adjust value in thousands of text unit space.
-     */
-    public void adjustGlyphTJ(double adjust) {
-        bufTJ.append(endText).append(" ");
-        bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4));
-        bufTJ.append(" ");
-        bufTJ.append(startText);
-    }
-
-    /**
-     * Writes a "TJ" command, writing out the accumulated buffer with the characters and glyph
-     * positioning values. The buffer is reset afterwards.
-     */
-    public void writeTJ() {
-        if (bufTJ != null && bufTJ.length() > 0) {
-            bufTJ.append(endText).append("] TJ\n");
-            g2d.currentStream.write(bufTJ.toString());
-            bufTJ.setLength(0);
-        }
+        writeTJMappedChar(mappedChar);
     }
 
 }

Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Thu Mar 27 01:49:41 2008
@@ -52,13 +52,17 @@
   </contexts>
   
   <changes>
-    <!--release version="FOP Trunk" date="TBD"-->
+    <release version="FOP Trunk" date="TBD">
       <!-- change reverted, to be added back later
         <action context="Renderers" dev="AC" importance="high" type="add">
         Added SVG support for AFP (GOCA).
         </action>
       -->
-    <!--/release-->
+      <action context="Fonts" dev="JM" type="add">
+        Added support for addressing all glyphs available in a Type 1 font, not just the ones
+        in the font's primary encoding.
+      </action>
+    </release>
     <release version="0.95beta" date="22 March 2008">
       <notes>
         <section>

Modified: xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java (original)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java Thu Mar 27 01:49:41 2008
@@ -65,7 +65,7 @@
          *  The following array is used to look for these patterns
          */ 
         final String[] testPatterns = { 
-                TEST_MARKER + "1", "(Standard)",
+                TEST_MARKER + "1", "Standard",
                 TEST_MARKER + "2", "XX_\\351_XX", 
                 TEST_MARKER + "3", "XX_\\342\\352\\356\\364\\373_XX" 
               };
@@ -75,7 +75,9 @@
 
     /**
      * TODO test disabled for now, fails due (probably) do different PDF
-     * encoding when custom font is used
+     * encoding when custom font is used.
+     * TODO This should be tested using PDFBox. If PDFBox can extract the text correctly,
+     * everything is fine. The tests here are too unstable.
      * 
      * @throws Exception
      *             checkstyle wants a comment here, even a silly one



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