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 ac...@apache.org on 2008/11/18 15:13:52 UTC

svn commit: r718598 - in /xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop: afp/ afp/modca/ afp/svg/ image/loader/batik/ render/ render/afp/ svg/

Author: acumiskey
Date: Tue Nov 18 06:13:51 2008
New Revision: 718598

URL: http://svn.apache.org/viewvc?rev=718598&view=rev
Log:
Removed AbstractGraphics2DImagePainter and Graphics2DImagePainterGOCA (painting preparator mechanism).
Adjusted AFPGraphics2D to TextHandler changes in XG commons.
Factored an AbstractFOPTextPainter which is extended by AFPTextPainter.

Added:
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java   (with props)
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/FOPTextHandler.java   (with props)
Removed:
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/Graphics2DImagePainterGOCA.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/AbstractGraphics2DImagePainter.java
Modified:
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPDataObjectFactory.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPGraphics2D.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextHandler.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextPainter.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java
    xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPDataObjectFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPDataObjectFactory.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPDataObjectFactory.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPDataObjectFactory.java Tue Nov 18 06:13:51 2008
@@ -130,6 +130,8 @@
         // paint to graphics object
         Graphics2DImagePainter painter = graphicsObjectInfo.getPainter();
         Rectangle2D area = graphicsObjectInfo.getArea();
+        g2d.scale(1, -1);
+        g2d.translate(0, -area.getHeight());
         painter.paint(g2d, area);
 
         // return painted graphics object

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPGraphics2D.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPGraphics2D.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPGraphics2D.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/AFPGraphics2D.java Tue Nov 18 06:13:51 2008
@@ -88,7 +88,7 @@
     private GraphicsObject graphicsObj = null;
 
     /** Fallback text handler */
-    protected TextHandler fallbackTextHandler = new StrokingTextHandler(this);
+    protected TextHandler fallbackTextHandler = new StrokingTextHandler();
 
     /** Custom text handler */
     protected TextHandler customTextHandler = null;
@@ -367,9 +367,9 @@
     public void drawString(String str, float x, float y) {
         try {
             if (customTextHandler != null && !textAsShapes) {
-                customTextHandler.drawString(str, x, y);
+                customTextHandler.drawString(this, str, x, y);
             } else {
-                fallbackTextHandler.drawString(str, x, y);
+                fallbackTextHandler.drawString(this, str, x, y);
             }
         } catch (IOException ioe) {
             handleIOException(ioe);

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java Tue Nov 18 06:13:51 2008
@@ -138,8 +138,7 @@
         }
         os.write(data);
 
-        // Triplets
-        super.writeContent(os);
+        writeTriplets(os);
     }
 
 }

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java Tue Nov 18 06:13:51 2008
@@ -81,7 +81,7 @@
         super.registerSVGBridges();
 
         if (fontInfo != null) {
-            AFPTextHandler textHandler = new AFPTextHandler(g2d);
+            AFPTextHandler textHandler = new AFPTextHandler(fontInfo);
             g2d.setCustomTextHandler(textHandler);
 
             TextPainter textPainter = new AFPTextPainter(textHandler);

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextHandler.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextHandler.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextHandler.java Tue Nov 18 06:13:51 2008
@@ -20,6 +20,7 @@
 package org.apache.fop.afp.svg;
 
 import java.awt.Color;
+import java.awt.Graphics2D;
 import java.io.IOException;
 
 import org.apache.commons.logging.Log;
@@ -32,29 +33,30 @@
 import org.apache.fop.afp.modca.GraphicsObject;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
-import org.apache.xmlgraphics.java2d.TextHandler;
+import org.apache.fop.svg.FOPTextHandler;
 
 /**
  * Specialized TextHandler implementation that the AFPGraphics2D class delegates to to paint text
  * using AFP GOCA text operations.
  */
-public class AFPTextHandler implements TextHandler {
+public class AFPTextHandler implements FOPTextHandler {
 
     /** logging instance */
     private static Log log = LogFactory.getLog(AFPTextHandler.class);
 
-    private AFPGraphics2D g2d = null;
-
     /** Overriding FontState */
     protected Font overrideFont = null;
 
+    /** Font information */
+    private final FontInfo fontInfo;
+
     /**
      * Main constructor.
      *
-     * @param g2d the AFPGraphics2D instance
+     * @param fontInfo the AFPGraphics2D instance
      */
-    public AFPTextHandler(AFPGraphics2D g2d) {
-        this.g2d = g2d;
+    public AFPTextHandler(FontInfo fontInfo) {
+        this.fontInfo = fontInfo;
     }
 
     /**
@@ -63,21 +65,20 @@
      * @return the FontInfo object
      */
     public FontInfo getFontInfo() {
-        return g2d.getFontInfo();
+        return fontInfo;
     }
 
     /**
      * Registers a page font
      *
      * @param internalFontName the internal font name
+     * @param internalFontName the internal font name
      * @param fontSize the font size
      * @return a font reference
      */
-    private int registerPageFont(String internalFontName, int fontSize) {
+    private int registerPageFont(AFPPageFonts pageFonts, String internalFontName, int fontSize) {
         FontInfo fontInfo = getFontInfo();
         AFPFont afpFont = (AFPFont)fontInfo.getFonts().get(internalFontName);
-        AFPPaintingState paintingState = g2d.getPaintingState();
-        AFPPageFonts pageFonts = paintingState.getPageFonts();
         // register if necessary
         AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
                 internalFontName,
@@ -87,14 +88,21 @@
         return afpFontAttributes.getFontReference();
     }
 
+    /** {@inheritDoc} */
+    public void drawString(String text, float x, float y) throws IOException {
+        // TODO Remove me after removing the deprecated method in TextHandler.
+        throw new UnsupportedOperationException("Deprecated method!");
+    }
+
     /**
      * Add a text string to the current data object of the AFP datastream.
      * The text is painted using text operations.
      *
      * {@inheritDoc}
      */
-    public void drawString(String str, float x, float y) throws IOException {
+    public void drawString(Graphics2D g, String str, float x, float y) throws IOException {
         log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y);
+        AFPGraphics2D g2d = (AFPGraphics2D)g;
         GraphicsObject graphicsObj = g2d.getGraphicsObject();
         Color color = g2d.getColor();
 
@@ -106,10 +114,11 @@
 
         // set the character set
         int fontReference = 0;
+        AFPPageFonts pageFonts = paintingState.getPageFonts();
         if (overrideFont != null) {
             String internalFontName = overrideFont.getFontName();
             int fontSize = overrideFont.getFontSize();
-            fontReference = registerPageFont(internalFontName, fontSize);
+            fontReference = registerPageFont(pageFonts, internalFontName, fontSize);
         } else {
             java.awt.Font awtFont = g2d.getFont();
 //            AffineTransform fontTransform = awtFont.getTransform();
@@ -117,7 +126,7 @@
             Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
             String internalFontName = fopFont.getFontName();
             int fontSize = fopFont.getFontSize();
-            fontReference = registerPageFont(internalFontName, fontSize);
+            fontReference = registerPageFont(pageFonts, internalFontName, fontSize);
         }
         graphicsObj.setCharacterSet(fontReference);
 

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextPainter.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextPainter.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/afp/svg/AFPTextPainter.java Tue Nov 18 06:13:51 2008
@@ -19,34 +19,8 @@
 
 package org.apache.fop.afp.svg;
 
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.Paint;
-import java.awt.Shape;
-import java.awt.font.TextAttribute;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.io.IOException;
-import java.text.AttributedCharacterIterator;
-import java.text.CharacterIterator;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.batik.dom.svg.SVGOMTextElement;
-import org.apache.batik.gvt.TextNode;
-import org.apache.batik.gvt.TextPainter;
-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.Mark;
-import org.apache.batik.gvt.text.TextPaintInfo;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.afp.AFPGraphics2D;
-import org.apache.fop.fonts.Font;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.svg.AbstractFOPTextPainter;
+import org.apache.fop.svg.FOPTextHandler;
 
 
 /**
@@ -57,472 +31,14 @@
  * drawString. If the text is complex or the cannot be translated
  * into a simple drawString the StrokingTextPainter is used instead.
  */
-public class AFPTextPainter implements TextPainter {
-
-    /** the logger for this class */
-    protected Log log = LogFactory.getLog(AFPTextPainter.class);
-
-    private final AFPTextHandler nativeTextHandler;
-
-    /**
-     * Use the stroking text painter to get the bounds and shape.
-     * Also used as a fallback to draw the string with strokes.
-     */
-    protected static final TextPainter
-        PROXY_PAINTER = StrokingTextPainter.getInstance();
+public class AFPTextPainter extends AbstractFOPTextPainter {
 
     /**
-     * Create a new PS text painter with the given font information.
+     * Create a new text painter with the given font information.
      * @param nativeTextHandler the NativeTextHandler instance used for text painting
      */
-    public AFPTextPainter(AFPTextHandler nativeTextHandler) {
-        this.nativeTextHandler = nativeTextHandler;
-    }
-
-    /**
-     * Paints the specified attributed character iterator using the
-     * specified Graphics2D and context and font context.
-     *
-     * @param node the TextNode to paint
-     * @param g2d the Graphics2D to use
-     */
-    public void paint(TextNode node, Graphics2D g2d) {
-        Point2D loc = node.getLocation();
-        log.debug("painting text node " + node);
-        if (hasUnsupportedAttributes(node)) {
-            log.debug("hasUnsuportedAttributes");
-            PROXY_PAINTER.paint(node, g2d);
-        } else {
-            log.debug("allAttributesSupported");
-            paintTextRuns(node.getTextRuns(), g2d, loc);
-        }
-    }
-
-    private boolean hasUnsupportedAttributes(TextNode node) {
-        Iterator iter = node.getTextRuns().iterator();
-        while (iter.hasNext()) {
-            StrokingTextPainter.TextRun
-                    run = (StrokingTextPainter.TextRun)iter.next();
-            AttributedCharacterIterator aci = run.getACI();
-            boolean hasUnsupported = hasUnsupportedAttributes(aci);
-            if (hasUnsupported) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
-        boolean hasUnsupported = false;
-
-        Font font = getFont(aci);
-        String text = getText(aci);
-        if (hasUnsupportedGlyphs(text, font)) {
-            log.trace("-> Unsupported glyphs found");
-            hasUnsupported = true;
-        }
-
-        TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
-            GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
-        if ((tpi != null)
-                && ((tpi.strokeStroke != null && tpi.strokePaint != null)
-                    || (tpi.strikethroughStroke != null)
-                    || (tpi.underlineStroke != null)
-                    || (tpi.overlineStroke != null))) {
-                        log.trace("-> under/overlines etc. found");
-            hasUnsupported = true;
-        }
-
-        //Alpha is not supported
-        Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
-        if (foreground instanceof Color) {
-            Color col = (Color)foreground;
-            if (col.getAlpha() != 255) {
-                log.trace("-> transparency found");
-                hasUnsupported = true;
-            }
-        }
-
-        Object letSpace = aci.getAttribute(
-                            GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
-        if (letSpace != null) {
-            log.trace("-> letter spacing found");
-            hasUnsupported = true;
-        }
-
-        Object wordSpace = aci.getAttribute(
-                             GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
-        if (wordSpace != null) {
-            log.trace("-> word spacing found");
-            hasUnsupported = true;
-        }
-
-        Object lengthAdjust = aci.getAttribute(
-                            GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
-        if (lengthAdjust != null) {
-            log.trace("-> length adjustments found");
-            hasUnsupported = true;
-        }
-
-        Object writeMod = aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
-        if (writeMod != null
-            && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
-                  writeMod)) {
-            log.trace("-> Unsupported writing modes found");
-            hasUnsupported = true;
-        }
-
-        Object vertOr = aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
-        if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
-                  vertOr)) {
-            log.trace("-> vertical orientation found");
-            hasUnsupported = true;
-        }
-
-        Object rcDel = aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
-        //Batik 1.6 returns null here which makes it impossible to determine whether this can
-        //be painted or not, i.e. fall back to stroking. :-(
-        if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
-            log.trace("-> spans found");
-            hasUnsupported = true; //Filter spans
-        }
-
-        if (hasUnsupported) {
-            log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
-        }
-        return hasUnsupported;
-    }
-
-    /**
-     * Paint a list of text runs on the Graphics2D at a given location.
-     * @param textRuns the list of text runs
-     * @param g2d the Graphics2D to paint to
-     * @param loc the current location of the "cursor"
-     */
-    protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
-        Point2D currentloc = loc;
-        Iterator i = textRuns.iterator();
-        while (i.hasNext()) {
-            StrokingTextPainter.TextRun
-                    run = (StrokingTextPainter.TextRun)i.next();
-            currentloc = paintTextRun(run, g2d, currentloc);
-        }
-    }
-
-    /**
-     * Paint a single text run on the Graphics2D at a given location.
-     * @param run the text run to paint
-     * @param g2d the Graphics2D to paint to
-     * @param loc the current location of the "cursor"
-     * @return the new location of the "cursor" after painting the text run
-     */
-    protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
-        AttributedCharacterIterator aci = run.getACI();
-        aci.first();
-
-        updateLocationFromACI(aci, loc);
-        AffineTransform at = g2d.getTransform();
-        loc = at.transform(loc, null);
-
-        // font
-        Font font = getFont(aci);
-        if (font != null) {
-            nativeTextHandler.setOverrideFont(font);
-        }
-
-        // color
-        TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
-        if (tpi == null) {
-            return loc;
-        }
-        Paint foreground = tpi.fillPaint;
-        if (foreground instanceof Color) {
-            Color col = (Color)foreground;
-            g2d.setColor(col);
-        }
-        g2d.setPaint(foreground);
-
-        // text
-        String txt = getText(aci);
-        float advance = getStringWidth(txt, font);
-        float tx = 0;
-        TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
-        if (anchor != null) {
-            switch (anchor.getType()) {
-            case TextNode.Anchor.ANCHOR_MIDDLE:
-                tx = -advance / 2;
-                break;
-            case TextNode.Anchor.ANCHOR_END:
-                tx = -advance;
-                break;
-            default: //nop
-            }
-        }
-
-        // draw string
-        double x = loc.getX();
-        double y = loc.getY();
-        try {
-            try {
-                nativeTextHandler.drawString(txt, (float)x + tx, (float)y);
-            } catch (IOException ioe) {
-                if (g2d instanceof AFPGraphics2D) {
-                    ((AFPGraphics2D)g2d).handleIOException(ioe);
-                }
-            }
-        } finally {
-            nativeTextHandler.setOverrideFont(null);
-        }
-        loc.setLocation(loc.getX() + advance, loc.getY());
-        return loc;
-    }
-
-    /**
-     * Extract the raw text from an ACI.
-     * @param aci ACI to inspect
-     * @return the extracted text
-     */
-    protected String getText(AttributedCharacterIterator aci) {
-        StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex());
-        for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
-            sb.append(c);
-        }
-        return sb.toString();
-    }
-
-    private void updateLocationFromACI(
-                AttributedCharacterIterator aci,
-                Point2D loc) {
-        //Adjust position of span
-        Float xpos = (Float)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.X);
-        Float ypos = (Float)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.Y);
-        Float dxpos = (Float)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.DX);
-        Float dypos = (Float)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.DY);
-        if (xpos != null) {
-            loc.setLocation(xpos.doubleValue(), loc.getY());
-        }
-        if (ypos != null) {
-            loc.setLocation(loc.getX(), ypos.doubleValue());
-        }
-        if (dxpos != null) {
-            loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
-        }
-        if (dypos != null) {
-            loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
-        }
-    }
-
-    private String getStyle(AttributedCharacterIterator aci) {
-        Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
-        return ((posture != null) && (posture.floatValue() > 0.0))
-                       ? Font.STYLE_ITALIC
-                       : Font.STYLE_NORMAL;
-    }
-
-    private int getWeight(AttributedCharacterIterator aci) {
-        Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
-        return ((taWeight != null) &&  (taWeight.floatValue() > 1.0))
-                       ? Font.WEIGHT_BOLD
-                       : Font.WEIGHT_NORMAL;
-    }
-
-    private Font getFont(AttributedCharacterIterator aci) {
-        Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
-        String style = getStyle(aci);
-        int weight = getWeight(aci);
-
-        FontInfo fontInfo = nativeTextHandler.getFontInfo();
-        String fontFamily = null;
-        List gvtFonts = (List) aci.getAttribute(
-                      GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
-        if (gvtFonts != null) {
-            Iterator i = gvtFonts.iterator();
-            while (i.hasNext()) {
-                GVTFontFamily fam = (GVTFontFamily) i.next();
-                /* (todo) Enable SVG Font painting
-                if (fam instanceof SVGFontFamily) {
-                    PROXY_PAINTER.paint(node, g2d);
-                    return;
-                }*/
-                fontFamily = fam.getFamilyName();
-                if (fontInfo.hasFont(fontFamily, style, weight)) {
-                    FontTriplet triplet = fontInfo.fontLookup(
-                            fontFamily, style, weight);
-                    int fsize = (int)(fontSize.floatValue() * 1000);
-                    return fontInfo.getFontInstance(triplet, fsize);
-                }
-            }
-        }
-        FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
-        int fsize = (int)(fontSize.floatValue() * 1000);
-        return fontInfo.getFontInstance(triplet, fsize);
-    }
-
-    private float getStringWidth(String str, Font font) {
-        float wordWidth = 0;
-        float whitespaceWidth = font.getWidth(font.mapChar(' '));
-
-        for (int i = 0; i < str.length(); i++) {
-            float charWidth;
-            char c = str.charAt(i);
-            if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
-                charWidth = font.getWidth(font.mapChar(c));
-                if (charWidth <= 0) {
-                    charWidth = whitespaceWidth;
-                }
-            } else {
-                charWidth = whitespaceWidth;
-            }
-            wordWidth += charWidth;
-        }
-        return wordWidth / 1000f;
-    }
-
-    private boolean hasUnsupportedGlyphs(String str, Font font) {
-        for (int i = 0; i < str.length(); i++) {
-            char c = str.charAt(i);
-            if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
-                if (!font.hasChar(c)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Get the outline shape of the text characters.
-     * This uses the StrokingTextPainter to get the outline
-     * shape since in theory it should be the same.
-     *
-     * @param node the text node
-     * @return the outline shape of the text characters
-     */
-    public Shape getOutline(TextNode node) {
-        return PROXY_PAINTER.getOutline(node);
-    }
-
-    /**
-     * Get the bounds.
-     * This uses the StrokingTextPainter to get the bounds
-     * since in theory it should be the same.
-     *
-     * @param node the text node
-     * @return the bounds of the text
-     */
-    public Rectangle2D getBounds2D(TextNode node) {
-        /* (todo) getBounds2D() is too slow
-         * because it uses the StrokingTextPainter. We should implement this
-         * method ourselves. */
-        return PROXY_PAINTER.getBounds2D(node);
-    }
-
-    /**
-     * Get the geometry bounds.
-     * This uses the StrokingTextPainter to get the bounds
-     * since in theory it should be the same.
-     *
-     * @param node the text node
-     * @return the bounds of the text
-     */
-    public Rectangle2D getGeometryBounds(TextNode node) {
-        return PROXY_PAINTER.getGeometryBounds(node);
-    }
-
-    // Methods that have no purpose for PS
-
-    /**
-     * Get the mark.
-     * This does nothing since the output is AFP and not interactive.
-     *
-     * @param node the text node
-     * @param pos the position
-     * @param all select all
-     * @return null
-     */
-    public Mark getMark(TextNode node, int pos, boolean all) {
-        return null;
-    }
-
-    /**
-     * Select at.
-     * This does nothing since the output is AFP and not interactive.
-     *
-     * @param x the x position
-     * @param y the y position
-     * @param node the text node
-     * @return null
-     */
-    public Mark selectAt(double x, double y, TextNode node) {
-        return null;
-    }
-
-    /**
-     * Select to.
-     * This does nothing since the output is AFP and not interactive.
-     *
-     * @param x the x position
-     * @param y the y position
-     * @param beginMark the start mark
-     * @return null
-     */
-    public Mark selectTo(double x, double y, Mark beginMark) {
-        return null;
-    }
-
-    /**
-     * Selec first.
-     * This does nothing since the output is AFP and not interactive.
-     *
-     * @param node the text node
-     * @return null
-     */
-    public Mark selectFirst(TextNode node) {
-        return null;
-    }
-
-    /**
-     * Select last.
-     * This does nothing since the output is AFP and not interactive.
-     *
-     * @param node the text node
-     * @return null
-     */
-    public Mark selectLast(TextNode node) {
-        return null;
-    }
-
-    /**
-     * Get selected.
-     * This does nothing since the output is AFP and not interactive.
-     *
-     * @param start the start mark
-     * @param finish the finish mark
-     * @return null
-     */
-    public int[] getSelected(Mark start, Mark finish) {
-        return null;
-    }
-
-    /**
-     * Get the highlighted shape.
-     * This does nothing since the output is AFP and not interactive.
-     *
-     * @param beginMark the start mark
-     * @param endMark the end mark
-     * @return null
-     */
-    public Shape getHighlightShape(Mark beginMark, Mark endMark) {
-        return null;
+    public AFPTextPainter(FOPTextHandler nativeTextHandler) {
+        super(nativeTextHandler);
     }
 
 }

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java Tue Nov 18 06:13:51 2008
@@ -6,15 +6,18 @@
 
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.gvt.GraphicsNode;
-import org.apache.fop.render.AbstractGraphics2DImagePainter;
-import org.apache.xmlgraphics.java2d.Graphics2DPainterPreparator;
+
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
 
 /**
  * A generic graphics 2D image painter implementation
  */
-public class Graphics2DImagePainterImpl extends AbstractGraphics2DImagePainter {
+public class Graphics2DImagePainterImpl implements Graphics2DImagePainter {
 
+    private final GraphicsNode root;
+    /** the Batik bridge context */
     protected final BridgeContext ctx;
+    /** the intrinsic size of the image */
     protected final Dimension imageSize;
 
     /**
@@ -25,7 +28,7 @@
      * @param imageSize the image size
      */
     public Graphics2DImagePainterImpl(GraphicsNode root, BridgeContext ctx, Dimension imageSize) {
-        super(root);
+        this.root = root;
         this.imageSize = imageSize;
         this.ctx = ctx;
     }
@@ -35,30 +38,30 @@
         return imageSize;
     }
 
-    /** {@inheritDoc} */
-    protected Graphics2DPainterPreparator getPreparator() {
-        return new Graphics2DPainterPreparator() {
+    private void prepare(Graphics2D g2d, Rectangle2D area) {
+        // If no viewbox is defined in the svg file, a viewbox of 100x100 is
+        // assumed, as defined in SVGUserAgent.getViewportSize()
+        double tx = area.getX();
+        double ty = area.getY();
+        if (tx != 0 || ty != 0) {
+            g2d.translate(tx, ty);
+        }
+
+        float iw = (float) ctx.getDocumentSize().getWidth();
+        float ih = (float) ctx.getDocumentSize().getHeight();
+        float w = (float) area.getWidth();
+        float h = (float) area.getHeight();
+        float sx = w / iw;
+        float sy = h / ih;
+        if (sx != 1.0 || sy != 1.0) {
+            g2d.scale(sx, sy);
+        }
+    }
 
-            public void prepare(Graphics2D g2d, Rectangle2D area) {
-                // If no viewbox is defined in the svg file, a viewbox of 100x100 is
-                // assumed, as defined in SVGUserAgent.getViewportSize()
-                double tx = area.getX();
-                double ty = area.getY();
-                if (tx != 0 || ty != 0) {
-                    g2d.translate(tx, ty);
-                }
-
-                float iw = (float) ctx.getDocumentSize().getWidth();
-                float ih = (float) ctx.getDocumentSize().getHeight();
-                float w = (float) area.getWidth();
-                float h = (float) area.getHeight();
-                float sx = w / iw;
-                float sy = h / ih;
-                if (sx != 1.0 || sy != 1.0) {
-                    g2d.scale(sx, sy);
-                }
-            }
-        };
+    /** {@inheritDoc} */
+    public void paint(Graphics2D g2d, Rectangle2D area) {
+        prepare(g2d, area);
+        root.paint(g2d);
     }
 
 }
\ No newline at end of file

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java Tue Nov 18 06:13:51 2008
@@ -19,13 +19,11 @@
 
 package org.apache.fop.render.afp;
 
-import java.awt.geom.AffineTransform;
 import java.io.IOException;
 
 import org.apache.fop.afp.AFPDataObjectInfo;
 import org.apache.fop.afp.AFPGraphics2D;
 import org.apache.fop.afp.AFPGraphicsObjectInfo;
-import org.apache.fop.afp.AFPObjectAreaInfo;
 import org.apache.fop.afp.AFPPaintingState;
 import org.apache.fop.afp.AFPResourceInfo;
 import org.apache.fop.afp.AFPResourceLevel;
@@ -51,7 +49,8 @@
     public AFPDataObjectInfo generateDataObjectInfo(
             AFPRendererImageInfo rendererImageInfo) throws IOException {
 
-        AFPRendererContext rendererContext = (AFPRendererContext)rendererImageInfo.getRendererContext();
+        AFPRendererContext rendererContext
+            = (AFPRendererContext)rendererImageInfo.getRendererContext();
         AFPInfo afpInfo = rendererContext.getInfo();
         ImageGraphics2D imageG2D = (ImageGraphics2D)rendererImageInfo.getImage();
         Graphics2DImagePainter painter = imageG2D.getGraphics2DImagePainter();
@@ -67,11 +66,11 @@
             return null;
         } else {
             AFPGraphicsObjectInfo graphicsObjectInfo
-            = (AFPGraphicsObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+                = (AFPGraphicsObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
 
             AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo();
             //level not explicitly set/changed so default to inline for GOCA graphic objects
-            // (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07) - hard copy works just fine)
+            // (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07), hard copy works just fine)
             if (!resourceInfo.levelChanged()) {
                 resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
             }
@@ -86,22 +85,9 @@
 
             graphicsObjectInfo.setGraphics2D(g2d);
 
-            // translate to current location
-            AFPPaintingState paintingState = afpInfo.getPaintingState();
-            AffineTransform at = paintingState.getData().getTransform();
-            g2d.translate(at.getTranslateX(), at.getTranslateY());
-
             // set painter
             graphicsObjectInfo.setPainter(painter);
 
-            // invert y-axis for GOCA
-            final int sx = 1;
-            final int sy = -1;
-            AFPObjectAreaInfo objectAreaInfo = graphicsObjectInfo.getObjectAreaInfo();
-            int height = objectAreaInfo.getHeight();
-            g2d.translate(0, height);
-            g2d.scale(sx, sy);
-
             return graphicsObjectInfo;
         }
     }

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPRenderer.java Tue Nov 18 06:13:51 2008
@@ -333,37 +333,6 @@
     }
 
     /** {@inheritDoc} */
-    public void clip() {
-        // TODO
-        log.debug("NYI clip()");
-    }
-
-    /** {@inheritDoc} */
-    public void clipRect(float x, float y, float width, float height) {
-        // TODO
-        log.debug("NYI clipRect(x=" + x + ",y=" + y
-                    + ",width=" + width + ", height=" + height + ")");
-    }
-
-    /** {@inheritDoc} */
-    public void moveTo(float x, float y) {
-        // TODO
-        log.debug("NYI moveTo(x=" + x + ",y=" + y + ")");
-    }
-
-    /** {@inheritDoc} */
-    public void lineTo(float x, float y) {
-        // TODO
-        log.debug("NYI lineTo(x=" + x + ",y=" + y + ")");
-    }
-
-    /** {@inheritDoc} */
-    public void closePath() {
-        // TODO
-        log.debug("NYI closePath()");
-    }
-
-    /** {@inheritDoc} */
     public void drawBorderLine(float x1, float y1, float x2, float y2,
             boolean horz, boolean startOrBefore, int style, Color col) {
         BorderPaintInfo borderPaintInfo = new BorderPaintInfo(x1, y1, x2, y2, horz, style, col);
@@ -535,18 +504,6 @@
         paintingState.pop();
     }
 
-    /** Indicates the beginning of a text object. */
-    public void beginTextObject() {
-        //TODO PDF specific maybe?
-        log.debug("NYI beginTextObject()");
-    }
-
-    /** Indicates the end of a text object. */
-    public void endTextObject() {
-        //TODO PDF specific maybe?
-        log.debug("NYI endTextObject()");
-    }
-
     /** {@inheritDoc} */
     public void renderImage(Image image, Rectangle2D pos) {
         drawImage(image.getURL(), pos, image.getForeignAttributes());
@@ -809,4 +766,47 @@
         concatenateTransformationMatrix(at);
     }
 
+    /** {@inheritDoc} */
+    public void clip() {
+        // TODO
+//        log.debug("NYI clip()");
+    }
+
+    /** {@inheritDoc} */
+    public void clipRect(float x, float y, float width, float height) {
+        // TODO
+//        log.debug("NYI clipRect(x=" + x + ",y=" + y
+//                    + ",width=" + width + ", height=" + height + ")");
+    }
+
+    /** {@inheritDoc} */
+    public void moveTo(float x, float y) {
+        // TODO
+//        log.debug("NYI moveTo(x=" + x + ",y=" + y + ")");
+    }
+
+    /** {@inheritDoc} */
+    public void lineTo(float x, float y) {
+        // TODO
+//        log.debug("NYI lineTo(x=" + x + ",y=" + y + ")");
+    }
+
+    /** {@inheritDoc} */
+    public void closePath() {
+        // TODO
+//        log.debug("NYI closePath()");
+    }
+
+    /** Indicates the beginning of a text object. */
+    public void beginTextObject() {
+        //TODO PDF specific maybe?
+//        log.debug("NYI beginTextObject()");
+    }
+
+    /** Indicates the end of a text object. */
+    public void endTextObject() {
+        //TODO PDF specific maybe?
+//        log.debug("NYI endTextObject()");
+    }
+
 }

Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java?rev=718598&r1=718597&r2=718598&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java Tue Nov 18 06:13:51 2008
@@ -34,10 +34,10 @@
 import org.apache.fop.afp.AFPResourceInfo;
 import org.apache.fop.afp.AFPResourceManager;
 import org.apache.fop.afp.AFPUnitConverter;
-import org.apache.fop.afp.Graphics2DImagePainterGOCA;
 import org.apache.fop.afp.svg.AFPBridgeContext;
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.image.loader.batik.Graphics2DImagePainterImpl;
 import org.apache.fop.render.AbstractGenericSVGHandler;
 import org.apache.fop.render.Renderer;
 import org.apache.fop.render.RendererContext;
@@ -67,9 +67,6 @@
         }
     }
 
-    private static final int X = 0;
-    private static final int Y = 1;
-
     /**
      * Render the SVG document.
      *
@@ -101,7 +98,7 @@
         }
 
         // Create a new AFPGraphics2D
-        final boolean textAsShapes = false;
+        final boolean textAsShapes = afpInfo.strokeText();
         AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);
 
         AFPPaintingState paintingState = g2d.getPaintingState();
@@ -220,7 +217,7 @@
             painter = super.createGraphics2DImagePainter(root, ctx, imageSize);
         } else {
             // paint as GOCA Graphics
-            painter = new Graphics2DImagePainterGOCA(root, ctx, imageSize);
+            painter = new Graphics2DImagePainterImpl(root, ctx, imageSize);
         }
         return painter;
     }

Added: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java?rev=718598&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java (added)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java Tue Nov 18 06:13:51 2008
@@ -0,0 +1,528 @@
+/*
+ * 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.Color;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.font.TextAttribute;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.batik.dom.svg.SVGOMTextElement;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.TextPainter;
+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.Mark;
+import org.apache.batik.gvt.text.TextPaintInfo;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+
+
+/**
+ * Renders the attributed character iterator of a <tt>TextNode</tt>.
+ * This class draws the text directly into the Graphics2D so that
+ * the text is not drawn using shapes.
+ * If the text is simple enough to draw then it sets the font and calls
+ * drawString. If the text is complex or the cannot be translated
+ * into a simple drawString the StrokingTextPainter is used instead.
+ */
+public abstract class AbstractFOPTextPainter implements TextPainter {
+
+    /** the logger for this class */
+    protected Log log = LogFactory.getLog(AbstractFOPTextPainter.class);
+
+    private final FOPTextHandler nativeTextHandler;
+
+    /**
+     * Use the stroking text painter to get the bounds and shape.
+     * Also used as a fallback to draw the string with strokes.
+     */
+    protected static final TextPainter
+        PROXY_PAINTER = StrokingTextPainter.getInstance();
+
+    /**
+     * Create a new PS text painter with the given font information.
+     * @param nativeTextHandler the NativeTextHandler instance used for text painting
+     */
+    public AbstractFOPTextPainter(FOPTextHandler nativeTextHandler) {
+        this.nativeTextHandler = nativeTextHandler;
+    }
+
+    /**
+     * Paints the specified attributed character iterator using the
+     * specified Graphics2D and context and font context.
+     *
+     * @param node the TextNode to paint
+     * @param g2d the Graphics2D to use
+     */
+    public void paint(TextNode node, Graphics2D g2d) {
+        Point2D loc = node.getLocation();
+        log.debug("painting text node " + node);
+        if (hasUnsupportedAttributes(node)) {
+            log.debug("hasUnsuportedAttributes");
+            PROXY_PAINTER.paint(node, g2d);
+        } else {
+            log.debug("allAttributesSupported");
+            paintTextRuns(node.getTextRuns(), g2d, loc);
+        }
+    }
+
+    private boolean hasUnsupportedAttributes(TextNode node) {
+        Iterator iter = node.getTextRuns().iterator();
+        while (iter.hasNext()) {
+            StrokingTextPainter.TextRun
+                    run = (StrokingTextPainter.TextRun)iter.next();
+            AttributedCharacterIterator aci = run.getACI();
+            boolean hasUnsupported = hasUnsupportedAttributes(aci);
+            if (hasUnsupported) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
+        boolean hasUnsupported = false;
+
+        Font font = getFont(aci);
+        String text = getText(aci);
+        if (hasUnsupportedGlyphs(text, font)) {
+            log.trace("-> Unsupported glyphs found");
+            hasUnsupported = true;
+        }
+
+        TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+            GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+        if ((tpi != null)
+                && ((tpi.strokeStroke != null && tpi.strokePaint != null)
+                    || (tpi.strikethroughStroke != null)
+                    || (tpi.underlineStroke != null)
+                    || (tpi.overlineStroke != null))) {
+                        log.trace("-> under/overlines etc. found");
+            hasUnsupported = true;
+        }
+
+        //Alpha is not supported
+        Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
+        if (foreground instanceof Color) {
+            Color col = (Color)foreground;
+            if (col.getAlpha() != 255) {
+                log.trace("-> transparency found");
+                hasUnsupported = true;
+            }
+        }
+
+        Object letSpace = aci.getAttribute(
+                            GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
+        if (letSpace != null) {
+            log.trace("-> letter spacing found");
+            hasUnsupported = true;
+        }
+
+        Object wordSpace = aci.getAttribute(
+                             GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
+        if (wordSpace != null) {
+            log.trace("-> word spacing found");
+            hasUnsupported = true;
+        }
+
+        Object lengthAdjust = aci.getAttribute(
+                            GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
+        if (lengthAdjust != null) {
+            log.trace("-> length adjustments found");
+            hasUnsupported = true;
+        }
+
+        Object writeMod = aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
+        if (writeMod != null
+            && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
+                  writeMod)) {
+            log.trace("-> Unsupported writing modes found");
+            hasUnsupported = true;
+        }
+
+        Object vertOr = aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
+        if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
+                  vertOr)) {
+            log.trace("-> vertical orientation found");
+            hasUnsupported = true;
+        }
+
+        Object rcDel = aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
+        //Batik 1.6 returns null here which makes it impossible to determine whether this can
+        //be painted or not, i.e. fall back to stroking. :-(
+        if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
+            log.trace("-> spans found");
+            hasUnsupported = true; //Filter spans
+        }
+
+        if (hasUnsupported) {
+            log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
+        }
+        return hasUnsupported;
+    }
+
+    /**
+     * Paint a list of text runs on the Graphics2D at a given location.
+     * @param textRuns the list of text runs
+     * @param g2d the Graphics2D to paint to
+     * @param loc the current location of the "cursor"
+     */
+    protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
+        Point2D currentloc = loc;
+        Iterator i = textRuns.iterator();
+        while (i.hasNext()) {
+            StrokingTextPainter.TextRun
+                    run = (StrokingTextPainter.TextRun)i.next();
+            currentloc = paintTextRun(run, g2d, currentloc);
+        }
+    }
+
+    /**
+     * Paint a single text run on the Graphics2D at a given location.
+     * @param run the text run to paint
+     * @param g2d the Graphics2D to paint to
+     * @param loc the current location of the "cursor"
+     * @return the new location of the "cursor" after painting the text run
+     */
+    protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
+        AttributedCharacterIterator aci = run.getACI();
+        aci.first();
+
+        updateLocationFromACI(aci, loc);
+        AffineTransform at = g2d.getTransform();
+        loc = at.transform(loc, null);
+
+        // font
+        Font font = getFont(aci);
+        if (font != null) {
+            nativeTextHandler.setOverrideFont(font);
+        }
+
+        // color
+        TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+        if (tpi == null) {
+            return loc;
+        }
+        Paint foreground = tpi.fillPaint;
+        if (foreground instanceof Color) {
+            Color col = (Color)foreground;
+            g2d.setColor(col);
+        }
+        g2d.setPaint(foreground);
+
+        // text
+        String txt = getText(aci);
+        float advance = getStringWidth(txt, font);
+        float tx = 0;
+        TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+        if (anchor != null) {
+            switch (anchor.getType()) {
+            case TextNode.Anchor.ANCHOR_MIDDLE:
+                tx = -advance / 2;
+                break;
+            case TextNode.Anchor.ANCHOR_END:
+                tx = -advance;
+                break;
+            default: //nop
+            }
+        }
+
+        // draw string
+        double x = loc.getX();
+        double y = loc.getY();
+        try {
+            try {
+                nativeTextHandler.drawString(g2d, txt, (float)x + tx, (float)y);
+            } catch (IOException ioe) {
+                if (g2d instanceof AFPGraphics2D) {
+                    ((AFPGraphics2D)g2d).handleIOException(ioe);
+                }
+            }
+        } finally {
+            nativeTextHandler.setOverrideFont(null);
+        }
+        loc.setLocation(loc.getX() + advance, loc.getY());
+        return loc;
+    }
+
+    /**
+     * Extract the raw text from an ACI.
+     * @param aci ACI to inspect
+     * @return the extracted text
+     */
+    protected String getText(AttributedCharacterIterator aci) {
+        StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex());
+        for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    private void updateLocationFromACI(
+                AttributedCharacterIterator aci,
+                Point2D loc) {
+        //Adjust position of span
+        Float xpos = (Float)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.X);
+        Float ypos = (Float)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.Y);
+        Float dxpos = (Float)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.DX);
+        Float dypos = (Float)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.DY);
+        if (xpos != null) {
+            loc.setLocation(xpos.doubleValue(), loc.getY());
+        }
+        if (ypos != null) {
+            loc.setLocation(loc.getX(), ypos.doubleValue());
+        }
+        if (dxpos != null) {
+            loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
+        }
+        if (dypos != null) {
+            loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
+        }
+    }
+
+    private String getStyle(AttributedCharacterIterator aci) {
+        Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
+        return ((posture != null) && (posture.floatValue() > 0.0))
+                       ? Font.STYLE_ITALIC
+                       : Font.STYLE_NORMAL;
+    }
+
+    private int getWeight(AttributedCharacterIterator aci) {
+        Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
+        return ((taWeight != null) &&  (taWeight.floatValue() > 1.0))
+                       ? Font.WEIGHT_BOLD
+                       : Font.WEIGHT_NORMAL;
+    }
+
+    private Font getFont(AttributedCharacterIterator aci) {
+        Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
+        String style = getStyle(aci);
+        int weight = getWeight(aci);
+
+        FontInfo fontInfo = nativeTextHandler.getFontInfo();
+        String fontFamily = null;
+        List gvtFonts = (List) aci.getAttribute(
+                      GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
+        if (gvtFonts != null) {
+            Iterator i = gvtFonts.iterator();
+            while (i.hasNext()) {
+                GVTFontFamily fam = (GVTFontFamily) i.next();
+                /* (todo) Enable SVG Font painting
+                if (fam instanceof SVGFontFamily) {
+                    PROXY_PAINTER.paint(node, g2d);
+                    return;
+                }*/
+                fontFamily = fam.getFamilyName();
+                if (fontInfo.hasFont(fontFamily, style, weight)) {
+                    FontTriplet triplet = fontInfo.fontLookup(
+                            fontFamily, style, weight);
+                    int fsize = (int)(fontSize.floatValue() * 1000);
+                    return fontInfo.getFontInstance(triplet, fsize);
+                }
+            }
+        }
+        FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
+        int fsize = (int)(fontSize.floatValue() * 1000);
+        return fontInfo.getFontInstance(triplet, fsize);
+    }
+
+    private float getStringWidth(String str, Font font) {
+        float wordWidth = 0;
+        float whitespaceWidth = font.getWidth(font.mapChar(' '));
+
+        for (int i = 0; i < str.length(); i++) {
+            float charWidth;
+            char c = str.charAt(i);
+            if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+                charWidth = font.getWidth(font.mapChar(c));
+                if (charWidth <= 0) {
+                    charWidth = whitespaceWidth;
+                }
+            } else {
+                charWidth = whitespaceWidth;
+            }
+            wordWidth += charWidth;
+        }
+        return wordWidth / 1000f;
+    }
+
+    private boolean hasUnsupportedGlyphs(String str, Font font) {
+        for (int i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+                if (!font.hasChar(c)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Get the outline shape of the text characters.
+     * This uses the StrokingTextPainter to get the outline
+     * shape since in theory it should be the same.
+     *
+     * @param node the text node
+     * @return the outline shape of the text characters
+     */
+    public Shape getOutline(TextNode node) {
+        return PROXY_PAINTER.getOutline(node);
+    }
+
+    /**
+     * Get the bounds.
+     * This uses the StrokingTextPainter to get the bounds
+     * since in theory it should be the same.
+     *
+     * @param node the text node
+     * @return the bounds of the text
+     */
+    public Rectangle2D getBounds2D(TextNode node) {
+        /* (todo) getBounds2D() is too slow
+         * because it uses the StrokingTextPainter. We should implement this
+         * method ourselves. */
+        return PROXY_PAINTER.getBounds2D(node);
+    }
+
+    /**
+     * Get the geometry bounds.
+     * This uses the StrokingTextPainter to get the bounds
+     * since in theory it should be the same.
+     *
+     * @param node the text node
+     * @return the bounds of the text
+     */
+    public Rectangle2D getGeometryBounds(TextNode node) {
+        return PROXY_PAINTER.getGeometryBounds(node);
+    }
+
+    // Methods that have no purpose for PS
+
+    /**
+     * Get the mark.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param node the text node
+     * @param pos the position
+     * @param all select all
+     * @return null
+     */
+    public Mark getMark(TextNode node, int pos, boolean all) {
+        return null;
+    }
+
+    /**
+     * Select at.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param x the x position
+     * @param y the y position
+     * @param node the text node
+     * @return null
+     */
+    public Mark selectAt(double x, double y, TextNode node) {
+        return null;
+    }
+
+    /**
+     * Select to.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param x the x position
+     * @param y the y position
+     * @param beginMark the start mark
+     * @return null
+     */
+    public Mark selectTo(double x, double y, Mark beginMark) {
+        return null;
+    }
+
+    /**
+     * Selec first.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param node the text node
+     * @return null
+     */
+    public Mark selectFirst(TextNode node) {
+        return null;
+    }
+
+    /**
+     * Select last.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param node the text node
+     * @return null
+     */
+    public Mark selectLast(TextNode node) {
+        return null;
+    }
+
+    /**
+     * Get selected.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param start the start mark
+     * @param finish the finish mark
+     * @return null
+     */
+    public int[] getSelected(Mark start, Mark finish) {
+        return null;
+    }
+
+    /**
+     * Get the highlighted shape.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param beginMark the start mark
+     * @param endMark the end mark
+     * @return null
+     */
+    public Shape getHighlightShape(Mark beginMark, Mark endMark) {
+        return null;
+    }
+
+}

Propchange: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Added: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/FOPTextHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/FOPTextHandler.java?rev=718598&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/FOPTextHandler.java (added)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/FOPTextHandler.java Tue Nov 18 06:13:51 2008
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg;
+
+public interface FOPTextHandler extends org.apache.xmlgraphics.java2d.TextHandler {
+
+    void setOverrideFont(org.apache.fop.fonts.Font font);
+
+    org.apache.fop.fonts.FontInfo getFontInfo();
+}

Propchange: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/FOPTextHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/FOPTextHandler.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id



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