Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java?rev=766594&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java 
(added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java 
Mon Apr 20 06:50:59 2009
@@ -0,0 +1,224 @@
+/*
+ * 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.svg;
+
+import java.awt.Graphics2D;
+import java.awt.font.TextAttribute;
+import java.io.IOException;
+import java.text.AttributedCharacterIterator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.batik.bridge.SVGFontFamily;
+import org.apache.batik.gvt.font.GVTFont;
+import org.apache.batik.gvt.font.GVTFontFamily;
+import org.apache.batik.gvt.renderer.StrokingTextPainter;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.text.TextSpanLayout;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.util.CharUtilities;
+
+/**
+ * Abstract base class for text painters that use specialized text commands 
native to an output
+ * format to render text.
+ */
+public abstract class NativeTextPainter extends StrokingTextPainter {
+
+    /** the logger for this class */
+    protected Log log = LogFactory.getLog(NativeTextPainter.class);
+
+    /** the font collection */
+    protected final FontInfo fontInfo;
+
+    /**
+     * Creates a new instance.
+     * @param fontInfo the font collection
+     */
+    public NativeTextPainter(FontInfo fontInfo) {
+        this.fontInfo = fontInfo;
+    }
+
+    /**
+     * Indicates whether the given {...@link Graphics2D} instance if 
compatible with this text painter
+     * implementation.
+     * @param g2d the instance to check
+     * @return true if the instance is compatible.
+     */
+    protected abstract boolean isSupported(Graphics2D g2d);
+
+    /**
+     * Paints a single text run.
+     * @param textRun the text run
+     * @param g2d the target Graphics2D instance
+     * @throws IOException if an I/O error occurs while rendering the text
+     */
+    protected abstract void paintTextRun(TextRun textRun, Graphics2D g2d) 
throws IOException;
+
+    /** {...@inheritdoc} */
+    protected void paintTextRuns(List textRuns, Graphics2D g2d) {
+        if (log.isTraceEnabled()) {
+            log.trace("paintTextRuns: count = " + textRuns.size());
+        }
+        if (!isSupported(g2d)) {
+            super.paintTextRuns(textRuns, g2d);
+            return;
+        }
+        for (int i = 0; i < textRuns.size(); i++) {
+            TextRun textRun = (TextRun)textRuns.get(i);
+            try {
+                paintTextRun(textRun, g2d);
+            } catch (IOException ioe) {
+                //No other possibility than to use a RuntimeException
+                throw new RuntimeException(ioe);
+            }
+        }
+    }
+
+    /**
+     * Finds an array of suitable fonts for a given 
AttributedCharacterIterator.
+     * @param aci the character iterator
+     * @return the array of fonts
+     */
+    protected Font[] findFonts(AttributedCharacterIterator aci) {
+        List fonts = new java.util.ArrayList();
+        List gvtFonts = (List) aci.getAttribute(
+                
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
+        Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE);
+        Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT);
+        Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE);
+
+        String style = ((posture != null) && (posture.floatValue() > 0.0))
+                       ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
+        int weight = ((taWeight != null)
+                       &&  (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD
+                       : Font.WEIGHT_NORMAL;
+
+        String firstFontFamily = null;
+
+        //GVT_FONT can sometimes be different from the fonts in 
GVT_FONT_FAMILIES
+        //or GVT_FONT_FAMILIES can even be empty and only GVT_FONT is set
+        /* The following code section is not available until Batik 1.7 is 
released. */
+        GVTFont gvtFont = (GVTFont)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.GVT_FONT);
+        if (gvtFont != null) {
+            try {
+                String gvtFontFamily = gvtFont.getFamilyName(); //Not 
available in Batik 1.6!
+                if (log.isDebugEnabled()) {
+                    log.debug("Matching font family: " + gvtFontFamily);
+                }
+                if (fontInfo.hasFont(gvtFontFamily, style, weight)) {
+                    FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily, 
style,
+                                                       weight);
+                    int fsize = (int)(fontSize.floatValue() * 1000);
+                    fonts.add(fontInfo.getFontInstance(triplet, fsize));
+                }
+                firstFontFamily = gvtFontFamily;
+            } catch (Exception e) {
+                //Most likely NoSuchMethodError here when using Batik 1.6
+                //Just skip this section in this case
+            }
+        }
+
+        if (gvtFonts != null) {
+            Iterator i = gvtFonts.iterator();
+            while (i.hasNext()) {
+                GVTFontFamily fam = (GVTFontFamily) i.next();
+                if (fam instanceof SVGFontFamily) {
+                    return null; //Let Batik paint this text!
+                }
+                String fontFamily = fam.getFamilyName();
+                if (log.isDebugEnabled()) {
+                    log.debug("Matching font family: " + fontFamily);
+                }
+                if (fontInfo.hasFont(fontFamily, style, weight)) {
+                    FontTriplet triplet = fontInfo.fontLookup(fontFamily, 
style,
+                                                       weight);
+                    int fsize = (int)(fontSize.floatValue() * 1000);
+                    fonts.add(fontInfo.getFontInstance(triplet, fsize));
+                }
+                if (firstFontFamily == null) {
+                    firstFontFamily = fontFamily;
+                }
+            }
+        }
+        if (fonts.size() == 0) {
+            if (firstFontFamily == null) {
+                //This will probably never happen. Just to be on the safe side.
+                firstFontFamily = "any";
+            }
+            //lookup with fallback possibility (incl. substitution 
notification)
+            FontTriplet triplet = fontInfo.fontLookup(firstFontFamily, style, 
weight);
+            int fsize = (int)(fontSize.floatValue() * 1000);
+            fonts.add(fontInfo.getFontInstance(triplet, fsize));
+        }
+        return (Font[])fonts.toArray(new Font[fonts.size()]);
+    }
+
+    /**
+     * Collects all characters from an {...@link AttributedCharacterIterator}.
+     * @param runaci the character iterator
+     * @return the characters
+     */
+    protected CharSequence collectCharacters(AttributedCharacterIterator 
runaci) {
+        StringBuffer chars = new StringBuffer();
+        for (runaci.first(); runaci.getIndex() < runaci.getEndIndex();) {
+            chars.append(runaci.current());
+            runaci.next();
+        }
+        return chars;
+    }
+
+    protected final void logTextRun(AttributedCharacterIterator runaci, 
TextSpanLayout layout) {
+        if (log.isTraceEnabled()) {
+            int charCount = runaci.getEndIndex() - runaci.getBeginIndex();
+            log.trace("================================================");
+            log.trace("New text run:");
+            log.trace("char count: " + charCount);
+            log.trace("range: "
+                    + runaci.getBeginIndex() + " - " + runaci.getEndIndex());
+            log.trace("glyph count: " + layout.getGlyphCount()); 
//=getNumGlyphs()
+        }
+    }
+
+    protected final void logCharacter(char ch, TextSpanLayout layout, int 
index,
+            boolean visibleChar) {
+        if (log.isTraceEnabled()) {
+            log.trace("glyph " + index
+                    + " -> " + layout.getGlyphIndex(index) + " => " + ch);
+            if (CharUtilities.isAnySpace(ch) && ch != 32) {
+                log.trace("Space found: " + Integer.toHexString(ch));
+            } else if (ch == CharUtilities.ZERO_WIDTH_JOINER) {
+                log.trace("ZWJ found: " + Integer.toHexString(ch));
+            } else if (ch == CharUtilities.SOFT_HYPHEN) {
+                log.trace("Soft hyphen found: " + Integer.toHexString(ch));
+            }
+            if (!visibleChar) {
+                log.trace("Invisible glyph found: " + Integer.toHexString(ch));
+            }
+        }
+    }
+
+
+}

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

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

Modified: 
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFBridgeContext.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFBridgeContext.java?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFBridgeContext.java 
(original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFBridgeContext.java Mon 
Apr 20 06:50:59 2009
@@ -26,10 +26,12 @@
 import org.apache.batik.bridge.SVGTextElementBridge;
 import org.apache.batik.bridge.UserAgent;
 import org.apache.batik.gvt.TextPainter;
-import org.apache.fop.fonts.FontInfo;
+
 import org.apache.xmlgraphics.image.loader.ImageManager;
 import org.apache.xmlgraphics.image.loader.ImageSessionContext;
 
+import org.apache.fop.fonts.FontInfo;
+
 /**
  * BridgeContext which registers the custom bridges for PDF output.
  */
@@ -38,11 +40,9 @@
     /**
      * Constructs a new bridge context.
      * @param userAgent the user agent
-     * @param loader the Document Loader to use for referenced documents.
+     * @param documentLoader the Document Loader to use for referenced 
documents.
      * @param fontInfo the font list for the text painter, may be null
      *                 in which case text is painted as shapes
-     * @param linkTransform AffineTransform to properly place links,
-     *                      may be null
      * @param imageManager an image manager
      * @param imageSessionContext an image session context
      * @param linkTransform AffineTransform to properly place links,
@@ -52,7 +52,8 @@
             FontInfo fontInfo, ImageManager imageManager,
             ImageSessionContext imageSessionContext,
             AffineTransform linkTransform) {
-        super(userAgent, documentLoader, fontInfo, imageManager, 
imageSessionContext, linkTransform);
+        super(userAgent, documentLoader, fontInfo,
+                imageManager, imageSessionContext, linkTransform);
     }
 
     /**

Modified: 
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
--- 
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
 (original)
+++ 
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
 Mon Apr 20 06:50:59 2009
@@ -55,6 +55,22 @@
 
         //Fonts
         try {
+            FontInfo fontInfo = createFontInfo(cfg);
+            graphics.setFontInfo(fontInfo);
+        } catch (FOPException e) {
+            throw new ConfigurationException("Error while setting up fonts", 
e);
+        }
+    }
+
+    /**
+     * Creates the {...@link FontInfo} instance for the given configuration.
+     * @param cfg the configuration
+     * @return the font collection
+     * @throws FOPException if an error occurs while setting up the fonts
+     */
+    public static FontInfo createFontInfo(Configuration cfg) throws 
FOPException {
+        FontInfo fontInfo = new FontInfo();
+        if (cfg != null) {
             FontResolver fontResolver = 
FontManager.createMinimalFontResolver();
             //TODO The following could be optimized by retaining the 
FontManager somewhere
             FontManager fontManager = new FontManager();
@@ -73,12 +89,11 @@
             if (fontManager.useCache()) {
                 fontManager.getFontCache().save();
             }
-            FontInfo fontInfo = new FontInfo();
             FontSetup.setup(fontInfo, fontInfoList, fontResolver);
-            graphics.setFontInfo(fontInfo);
-        } catch (FOPException e) {
-            throw new ConfigurationException("Error while setting up fonts", 
e);
+        } else {
+            FontSetup.setup(fontInfo);
         }
+        return fontInfo;
     }
 
 }

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=766594&r1=766593&r2=766594&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 Mon 
Apr 20 06:50:59 2009
@@ -25,28 +25,18 @@
 import java.awt.Paint;
 import java.awt.Shape;
 import java.awt.Stroke;
-import java.awt.font.TextAttribute;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Point2D;
-import java.lang.reflect.Method;
 import java.text.AttributedCharacterIterator;
-import java.util.Iterator;
-import java.util.List;
 
-import org.apache.batik.bridge.SVGFontFamily;
-import org.apache.batik.gvt.font.GVTFont;
-import org.apache.batik.gvt.font.GVTFontFamily;
 import org.apache.batik.gvt.font.GVTGlyphVector;
-import org.apache.batik.gvt.renderer.StrokingTextPainter;
-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;
 import org.apache.fop.util.CharUtilities;
 
 /**
@@ -59,193 +49,159 @@
  *
  * @version $Id$
  */
-public class PDFTextPainter extends StrokingTextPainter {
+class PDFTextPainter extends NativeTextPainter {
 
     private static final boolean DEBUG = false;
 
-    private final boolean strokeText = false;
-    private final FontInfo fontInfo;
-
     /**
      * Create a new PDF text painter with the given font information.
      * @param fi the font info
      */
     public PDFTextPainter(FontInfo fi) {
-        fontInfo = fi;
+        super(fi);
     }
 
     /** {...@inheritdoc} */
-    protected void paintTextRuns(List textRuns, Graphics2D g2d) {
-        if (DEBUG) {
-            System.out.println("paintTextRuns: count = " + textRuns.size());
-            //fontInfo.dumpAllTripletsToSystemOut();
-        }
-        if (!(g2d instanceof PDFGraphics2D) || strokeText) {
-            super.paintTextRuns(textRuns, g2d);
+    protected boolean isSupported(Graphics2D g2d) {
+        return g2d instanceof PDFGraphics2D;
+    }
+
+    /** {...@inheritdoc} */
+    protected void paintTextRun(TextRun textRun, Graphics2D g2d) {
+        AttributedCharacterIterator runaci = textRun.getACI();
+        runaci.first();
+
+        TextPaintInfo tpi = (TextPaintInfo)runaci.getAttribute(PAINT_INFO);
+        if (tpi == null || !tpi.visible) {
             return;
         }
+        if ((tpi != null) && (tpi.composite != null)) {
+            g2d.setComposite(tpi.composite);
+        }
+
+        //------------------------------------
+        TextSpanLayout layout = textRun.getLayout();
+        logTextRun(runaci, layout);
+        CharSequence chars = collectCharacters(runaci);
+        runaci.first(); //Reset ACI
+
         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();
-            runaci.first();
 
-            TextPaintInfo tpi = (TextPaintInfo)runaci.getAttribute(PAINT_INFO);
-            if (tpi == null || !tpi.visible) {
-                continue;
-            }
-            if ((tpi != null) && (tpi.composite != null)) {
-                g2d.setComposite(tpi.composite);
-            }
+        if (DEBUG) {
+            log.debug("Text: " + chars);
+            pdf.currentStream.write("%Text: " + chars + "\n");
+        }
 
-            //------------------------------------
-            TextSpanLayout layout = textRun.getLayout();
-            if (DEBUG) {
-                int charCount = runaci.getEndIndex() - runaci.getBeginIndex();
-                
System.out.println("================================================");
-                System.out.println("New text run:");
-                System.out.println("char count: " + charCount);
-                System.out.println("range: "
-                        + runaci.getBeginIndex() + " - " + 
runaci.getEndIndex());
-                System.out.println("glyph count: " + layout.getGlyphCount()); 
//=getNumGlyphs()
-            }
-            //Gather all characters of the run
-            StringBuffer chars = new StringBuffer();
-            for (runaci.first(); runaci.getIndex() < runaci.getEndIndex();) {
-                chars.append(runaci.current());
-                runaci.next();
-            }
-            runaci.first();
-            if (DEBUG) {
-                System.out.println("Text: " + chars);
-                pdf.currentStream.write("%Text: " + chars + "\n");
-            }
+        GeneralPath debugShapes = null;
+        if (DEBUG) {
+            debugShapes = new GeneralPath();
+        }
 
-            GeneralPath debugShapes = null;
-            if (DEBUG) {
-                debugShapes = new GeneralPath();
-            }
+        Font[] fonts = findFonts(runaci);
+        if (fonts == null || fonts.length == 0) {
+            //Draw using Java2D when no native fonts are available
+            textRun.getLayout().draw(g2d);
+            return;
+        }
 
-            Font[] fonts = findFonts(runaci);
-            if (fonts == null || fonts.length == 0) {
-                //Draw using Java2D
-                textRun.getLayout().draw(g2d);
+        textUtil.saveGraphicsState();
+        textUtil.concatMatrix(g2d.getTransform());
+        Shape imclip = g2d.getClip();
+        pdf.writeClip(imclip);
+
+        applyColorAndPaint(tpi, pdf);
+
+        textUtil.beginTextObject();
+        textUtil.setFonts(fonts);
+        boolean stroke = (tpi.strokePaint != null)
+            && (tpi.strokeStroke != null);
+        textUtil.setTextRenderingMode(tpi.fillPaint != null, stroke, false);
+
+        AffineTransform localTransform = new AffineTransform();
+        Point2D prevPos = null;
+        double prevVisibleCharWidth = 0.0;
+        GVTGlyphVector gv = layout.getGlyphVector();
+        for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) {
+            char ch = chars.charAt(index);
+            boolean visibleChar = gv.isGlyphVisible(index)
+                || (CharUtilities.isAnySpace(ch) && 
!CharUtilities.isZeroWidthSpace(ch));
+            logCharacter(ch, layout, index, visibleChar);
+            if (!visibleChar) {
                 continue;
             }
+            Point2D glyphPos = gv.getGlyphPosition(index);
 
-            textUtil.saveGraphicsState();
-            textUtil.concatMatrix(g2d.getTransform());
-            Shape imclip = g2d.getClip();
-            pdf.writeClip(imclip);
-
-            applyColorAndPaint(tpi, pdf);
-
-            textUtil.beginTextObject();
-            textUtil.setFonts(fonts);
-            boolean stroke = (tpi.strokePaint != null)
-                && (tpi.strokeStroke != null);
-            textUtil.setTextRenderingMode(tpi.fillPaint != null, stroke, 
false);
-
-            AffineTransform localTransform = new AffineTransform();
-            Point2D prevPos = null;
-            double prevVisibleCharWidth = 0.0;
-            GVTGlyphVector gv = layout.getGlyphVector();
-            for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) {
-                char ch = chars.charAt(index);
-                boolean visibleChar = gv.isGlyphVisible(index)
-                    || (CharUtilities.isAnySpace(ch) && 
!CharUtilities.isZeroWidthSpace(ch));
-                if (DEBUG) {
-                    System.out.println("glyph " + index
-                            + " -> " + layout.getGlyphIndex(index) + " => " + 
ch);
-                    if (CharUtilities.isAnySpace(ch) && ch != 32) {
-                        System.out.println("Space found: " + 
Integer.toHexString(ch));
-                    }
-                    if (ch == CharUtilities.ZERO_WIDTH_JOINER) {
-                        System.out.println("ZWJ found: " + 
Integer.toHexString(ch));
-                    }
-                    if (ch == CharUtilities.SOFT_HYPHEN) {
-                        System.out.println("Soft hyphen found: " + 
Integer.toHexString(ch));
-                    }
-                    if (!visibleChar) {
-                        System.out.println("Invisible glyph found: " + 
Integer.toHexString(ch));
-                    }
-                }
-                if (!visibleChar) {
-                    continue;
-                }
-                Point2D p = gv.getGlyphPosition(index);
-
-                AffineTransform glyphTransform = gv.getGlyphTransform(index);
-                //TODO Glyph transforms could be refined so not every char has 
to be painted
-                //with its own TJ command (stretch/squeeze case could be 
optimized)
-                if (DEBUG) {
-                    System.out.println("pos " + p + ", transform " + 
glyphTransform);
-                    Shape sh;
-                    sh = gv.getGlyphLogicalBounds(index);
-                    if (sh == null) {
-                        sh = new Ellipse2D.Double(p.getX(), p.getY(), 2, 2);
-                    }
-                    debugShapes.append(sh, false);
-                }
-
-                //Exact position of the glyph
-                localTransform.setToIdentity();
-                localTransform.translate(p.getX(), p.getY());
-                if (glyphTransform != null) {
-                    localTransform.concatenate(glyphTransform);
-                }
-                localTransform.scale(1, -1);
-
-                boolean yPosChanged = (prevPos == null
-                        || prevPos.getY() != p.getY()
-                        || glyphTransform != null);
-                if (yPosChanged) {
-                    if (index > 0) {
-                        textUtil.writeTJ();
-                        textUtil.writeTextMatrix(localTransform);
-                    }
-                } else {
-                    double xdiff = p.getX() - prevPos.getX();
-                    //Width of previous character
-                    Font font = textUtil.getCurrentFont();
-                    double cw = prevVisibleCharWidth;
-                    double effxdiff = (1000 * xdiff) - cw;
-                    if (effxdiff != 0) {
-                        double adjust = (-effxdiff / font.getFontSize());
-                        textUtil.adjustGlyphTJ(adjust * 1000);
-                    }
-                    if (DEBUG) {
-                        System.out.println("==> x diff: " + xdiff + ", " + 
effxdiff
-                                + ", charWidth: " + cw);
-                    }
-                }
-                Font f = textUtil.selectFontForChar(ch);
-                if (f != textUtil.getCurrentFont()) {
+            AffineTransform glyphTransform = gv.getGlyphTransform(index);
+            //TODO Glyph transforms could be refined so not every char has to 
be painted
+            //with its own TJ command (stretch/squeeze case could be optimized)
+            if (log.isTraceEnabled()) {
+                log.trace("pos " + glyphPos + ", transform " + glyphTransform);
+            }
+            if (DEBUG) {
+                Shape sh = gv.getGlyphLogicalBounds(index);
+                if (sh == null) {
+                    sh = new Ellipse2D.Double(glyphPos.getX(), 
glyphPos.getY(), 2, 2);
+                }
+                debugShapes.append(sh, false);
+            }
+
+            //Exact position of the glyph
+            localTransform.setToIdentity();
+            localTransform.translate(glyphPos.getX(), glyphPos.getY());
+            if (glyphTransform != null) {
+                localTransform.concatenate(glyphTransform);
+            }
+            localTransform.scale(1, -1);
+
+            boolean yPosChanged = (prevPos == null
+                    || prevPos.getY() != glyphPos.getY()
+                    || glyphTransform != null);
+            if (yPosChanged) {
+                if (index > 0) {
                     textUtil.writeTJ();
-                    textUtil.setCurrentFont(f);
-                    textUtil.writeTf(f);
                     textUtil.writeTextMatrix(localTransform);
                 }
-                char paintChar = (CharUtilities.isAnySpace(ch) ? ' ' : ch);
-                textUtil.writeTJChar(paintChar);
-
-                //Update last position
-                prevPos = p;
-                prevVisibleCharWidth = 
textUtil.getCurrentFont().getCharWidth(chars.charAt(index));
-            }
-            textUtil.writeTJ();
-            textUtil.endTextObject();
-            textUtil.restoreGraphicsState();
-            if (DEBUG) {
-                g2d.setStroke(new BasicStroke(0));
-                g2d.setColor(Color.LIGHT_GRAY);
-                g2d.draw(debugShapes);
-            }
+            } else {
+                double xdiff = glyphPos.getX() - prevPos.getX();
+                //Width of previous character
+                Font font = textUtil.getCurrentFont();
+                double cw = prevVisibleCharWidth;
+                double effxdiff = (1000 * xdiff) - cw;
+                if (effxdiff != 0) {
+                    double adjust = (-effxdiff / font.getFontSize());
+                    textUtil.adjustGlyphTJ(adjust * 1000);
+                }
+                if (log.isTraceEnabled()) {
+                    log.trace("==> x diff: " + xdiff + ", " + effxdiff
+                            + ", charWidth: " + cw);
+                }
+            }
+            Font f = textUtil.selectFontForChar(ch);
+            if (f != textUtil.getCurrentFont()) {
+                textUtil.writeTJ();
+                textUtil.setCurrentFont(f);
+                textUtil.writeTf(f);
+                textUtil.writeTextMatrix(localTransform);
+            }
+            char paintChar = (CharUtilities.isAnySpace(ch) ? ' ' : ch);
+            textUtil.writeTJChar(paintChar);
+
+            //Update last position
+            prevPos = glyphPos;
+            prevVisibleCharWidth = 
textUtil.getCurrentFont().getCharWidth(chars.charAt(index));
+        }
+        textUtil.writeTJ();
+        textUtil.endTextObject();
+        textUtil.restoreGraphicsState();
+        if (DEBUG) {
+            g2d.setStroke(new BasicStroke(0));
+            g2d.setColor(Color.LIGHT_GRAY);
+            g2d.draw(debugShapes);
         }
     }
 
@@ -271,85 +227,4 @@
         pdf.applyAlpha(fillAlpha, PDFGraphics2D.OPAQUE);
     }
 
-    private Font[] findFonts(AttributedCharacterIterator aci) {
-        List fonts = new java.util.ArrayList();
-        List gvtFonts = (List) aci.getAttribute(
-                
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
-        Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE);
-        Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT);
-        Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE);
-
-        String style = ((posture != null) && (posture.floatValue() > 0.0))
-                       ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
-        int weight = ((taWeight != null)
-                       &&  (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD
-                       : Font.WEIGHT_NORMAL;
-
-        String firstFontFamily = null;
-
-        //GVT_FONT can sometimes be different from the fonts in 
GVT_FONT_FAMILIES
-        //or GVT_FONT_FAMILIES can even be empty and only GVT_FONT is set
-        /* The following code section is not available until Batik 1.7 is 
released. */
-        GVTFont gvtFont = (GVTFont)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.GVT_FONT);
-        if (gvtFont != null) {
-            try {
-                Method method = gvtFont.getClass().getMethod("getFamilyName", 
null);
-                String gvtFontFamily = (String)method.invoke(gvtFont, null);
-                //TODO Uncomment the following line when Batik 1.7 is shipped 
with FOP
-                //String gvtFontFamily = gvtFont.getFamilyName(); //Not 
available in Batik 1.6
-                if (DEBUG) {
-                    System.out.print(gvtFontFamily + ", ");
-                }
-                if (fontInfo.hasFont(gvtFontFamily, style, weight)) {
-                    FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily, 
style,
-                                                       weight);
-                    int fsize = (int)(fontSize.floatValue() * 1000);
-                    fonts.add(fontInfo.getFontInstance(triplet, fsize));
-                }
-                firstFontFamily = gvtFontFamily;
-            } catch (Exception e) {
-                //Most likely NoSuchMethodError here when using Batik 1.6
-                //Just skip this section in this case
-            }
-        }
-
-        if (gvtFonts != null) {
-            Iterator i = gvtFonts.iterator();
-            while (i.hasNext()) {
-                GVTFontFamily fam = (GVTFontFamily) i.next();
-                if (fam instanceof SVGFontFamily) {
-                    return null; //Let Batik paint this text!
-                }
-                String fontFamily = fam.getFamilyName();
-                if (DEBUG) {
-                    System.out.print(fontFamily + ", ");
-                }
-                if (fontInfo.hasFont(fontFamily, style, weight)) {
-                    FontTriplet triplet = fontInfo.fontLookup(fontFamily, 
style,
-                                                       weight);
-                    int fsize = (int)(fontSize.floatValue() * 1000);
-                    fonts.add(fontInfo.getFontInstance(triplet, fsize));
-                }
-                if (firstFontFamily == null) {
-                    firstFontFamily = fontFamily;
-                }
-            }
-        }
-        if (fonts.size() == 0) {
-            if (firstFontFamily == null) {
-                //This will probably never happen. Just to be on the safe side.
-                firstFontFamily = "any";
-            }
-            //lookup with fallback possibility (incl. substitution 
notification)
-            FontTriplet triplet = fontInfo.fontLookup(firstFontFamily, style, 
weight);
-            int fsize = (int)(fontSize.floatValue() * 1000);
-            fonts.add(fontInfo.getFontInstance(triplet, fsize));
-        }
-        if (DEBUG) {
-            System.out.println();
-        }
-        return (Font[])fonts.toArray(new Font[fonts.size()]);
-    }
-
 }
\ No newline at end of file

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTranscoder.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTranscoder.java?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTranscoder.java 
(original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTranscoder.java Mon 
Apr 20 06:50:59 2009
@@ -23,34 +23,19 @@
 import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.InputStream;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.svg.SVGLength;
 
 import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.configuration.DefaultConfiguration;
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.UnitProcessor;
 import org.apache.batik.bridge.UserAgent;
 import org.apache.batik.ext.awt.RenderingHintsKeyExt;
 import org.apache.batik.transcoder.TranscoderException;
 import org.apache.batik.transcoder.TranscoderOutput;
-import org.apache.batik.transcoder.TranscodingHints;
 import org.apache.batik.transcoder.image.ImageTranscoder;
-import org.apache.batik.transcoder.keys.BooleanKey;
-import org.apache.batik.transcoder.keys.FloatKey;
-import org.apache.batik.util.ParsedURL;
-
-import org.apache.xmlgraphics.image.loader.ImageContext;
-import org.apache.xmlgraphics.image.loader.ImageManager;
-import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext;
 
 import org.apache.fop.Version;
 import org.apache.fop.fonts.FontInfo;
@@ -91,27 +76,9 @@
 public class PDFTranscoder extends AbstractFOPTranscoder
         implements Configurable {
 
-    /**
-     * The key is used to specify the resolution for on-the-fly images 
generated
-     * due to complex effects like gradients and filters.
-     */
-    public static final TranscodingHints.Key KEY_DEVICE_RESOLUTION = new 
FloatKey();
-
-    /**
-     * The key is used to specify whether the available fonts should be 
automatically
-     * detected. The alternative is to configure the transcoder manually using 
a configuration
-     * file.
-     */
-    public static final TranscodingHints.Key KEY_AUTO_FONTS = new BooleanKey();
-
-    private Configuration cfg = null;
-
     /** Graphics2D instance that is used to paint to */
     protected PDFDocumentGraphics2D graphics = null;
 
-    private ImageManager imageManager;
-    private ImageSessionContext imageSessionContext;
-
     /**
      * Constructs a new <tt>PDFTranscoder</tt>.
      */
@@ -133,11 +100,6 @@
         };
     }
 
-    /** {...@inheritdoc} */
-    public void configure(Configuration cfg) throws ConfigurationException {
-        this.cfg = cfg;
-    }
-
     /**
      * Transcodes the specified Document as an image in the specified output.
      *
@@ -155,28 +117,13 @@
                 + Version.getVersion()
                 + ": PDF Transcoder for Batik");
         if (hints.containsKey(KEY_DEVICE_RESOLUTION)) {
-            
graphics.setDeviceDPI(((Float)hints.get(KEY_DEVICE_RESOLUTION)).floatValue());
+            graphics.setDeviceDPI(getDeviceResolution());
         }
 
         setupImageInfrastructure(uri);
 
         try {
-            Configuration effCfg = this.cfg;
-            if (effCfg == null) {
-                //By default, enable font auto-detection if no cfg is given
-                boolean autoFonts = true;
-                if (hints.containsKey(KEY_AUTO_FONTS)) {
-                    autoFonts = 
((Boolean)hints.get(KEY_AUTO_FONTS)).booleanValue();
-                }
-                if (autoFonts) {
-                    DefaultConfiguration c = new 
DefaultConfiguration("pdf-transcoder");
-                    DefaultConfiguration fonts = new 
DefaultConfiguration("fonts");
-                    c.addChild(fonts);
-                    DefaultConfiguration autodetect = new 
DefaultConfiguration("auto-detect");
-                    fonts.addChild(autodetect);
-                    effCfg = c;
-                }
-            }
+            Configuration effCfg = getEffectiveConfiguration();
 
             if (effCfg != null) {
                 PDFDocumentGraphics2DConfigurator configurator
@@ -242,39 +189,6 @@
         }
     }
 
-    private void setupImageInfrastructure(final String baseURI) {
-        final ImageContext imageContext = new ImageContext() {
-            public float getSourceResolution() {
-                return 25.4f / userAgent.getPixelUnitToMillimeter();
-            }
-        };
-        this.imageManager = new ImageManager(imageContext);
-        this.imageSessionContext = new AbstractImageSessionContext() {
-
-            public ImageContext getParentContext() {
-                return imageContext;
-            }
-
-            public float getTargetResolution() {
-                return graphics.getDeviceDPI();
-            }
-
-            public Source resolveURI(String uri) {
-                System.out.println("resolve " + uri);
-                try {
-                    ParsedURL url = new ParsedURL(baseURI, uri);
-                    InputStream in = url.openStream();
-                    StreamSource source = new StreamSource(in, url.toString());
-                    return source;
-                } catch (IOException ioe) {
-                    userAgent.displayError(ioe);
-                    return null;
-                }
-            }
-
-        };
-    }
-
     /** {...@inheritdoc} */
     protected BridgeContext createBridgeContext() {
         //For compatibility with Batik 1.6
@@ -288,7 +202,7 @@
             fontInfo = null;
         }
         BridgeContext ctx = new PDFBridgeContext(userAgent, fontInfo,
-                this.imageManager, this.imageSessionContext);
+                getImageManager(), getImageSessionContext());
         return ctx;
     }
 

Modified: xmlgraphics/fop/trunk/status.xml
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Mon Apr 20 06:50:59 2009
@@ -58,6 +58,10 @@
       documents. Example: the fix of marks layering will be such a case when 
it's done.
     -->
     <release version="FOP Trunk" date="TBD">
+      <action context="Renderers" dev="JM" type="add">
+        Added a custom text painter for rendering SVG text using text 
operators when rendering
+        to PostScript or EPS. Text is no longer painted as shapes, thus 
creating much smaller files. 
+      </action>
       <action context="Renderers" dev="JM" type="fix">
         Fixed a bug that left the PrintRenderer unconfigured even if a 
configuration was
         specified for "application/X-fop-print". 



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to