You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2006/05/10 15:46:15 UTC

svn commit: r405763 - in /xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d: Java2DFontMetrics.java Java2DGraphicsState.java Java2DRenderer.java

Author: jeremias
Date: Wed May 10 06:45:46 2006
New Revision: 405763

URL: http://svn.apache.org/viewcvs?rev=405763&view=rev
Log:
Important improvements for the Java2DRenderer:
Support for letter- and word-spacing which also enables justified text.
Fix for font metric access. Fractional metrics was off. charWidth() only returned integers.
Removed the obscure 1.4 factor (Thanks to Chris Dail for the hint!)
Dispose of Graphics2D instance if no longer used to free up resources.

Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DRenderer.java

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java?rev=405763&r1=405762&r2=405763&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java Wed May 10 06:45:46 2006
@@ -189,17 +189,17 @@
     public int width(int i, String family, int style, int size) {
         int w;
         setFont(family, style, size);
-        // the output seems to look a little better if the
-        // space is rendered larger than given by
-        // the FontMetrics object
-        if (i <= 32) {
-            w = (int)(1.4 * fmt.charWidth(i) * FONT_FACTOR);
-        } else {
-            w = (int)(fmt.charWidth(i) * FONT_FACTOR);
-        }
+        w = internalCharWidth(i) * 1000;
         return w;
     }
 
+    private int internalCharWidth(int i) {
+        //w = (int)(fmt.charWidth(i) * 1000); //Not accurate enough!
+        char[] ch = {(char)i};
+        Rectangle2D rect = fmt.getStringBounds(ch, 0, 1, this.graphics);
+        return (int)Math.round(rect.getWidth() * 1000);
+    }
+    
     /**
      * Return widths (in 1/1000ths of point size) of all
      * characters
@@ -216,7 +216,7 @@
         }
         setFont(family, style, size);
         for (i = 0; i < 256; i++) {
-            width[i] = FONT_FACTOR * fmt.charWidth(i);
+            width[i] = 1000 * internalCharWidth(i);
         }
         return width;
     }
@@ -234,6 +234,7 @@
         boolean changed = false;
         Rectangle2D rect;
         TextLayout layout;
+        //TODO this seems bad. It rounds font sizes down to the next integer value (=pt)
         int s = (int)(size / 1000f);
 
         if (f1 == null) {

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java?rev=405763&r1=405762&r2=405763&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java Wed May 10 06:45:46 2006
@@ -89,6 +89,7 @@
             Graphics2D popped = (Graphics2D) stateStack.remove(stateStack
                     .size() - 1);
 
+            currentGraphics.dispose();
             currentGraphics = popped;
             return popped;
         } else {

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DRenderer.java?rev=405763&r1=405762&r2=405763&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/Java2DRenderer.java Wed May 10 06:45:46 2006
@@ -25,9 +25,11 @@
 import java.awt.Graphics2D;
 import java.awt.RenderingHints;
 import java.awt.color.ColorSpace;
+import java.awt.font.GlyphVector;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 import java.awt.image.ColorModel;
@@ -54,10 +56,12 @@
 import org.apache.fop.area.CTM;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.area.Trait;
-import org.apache.fop.area.inline.ForeignObject;
 import org.apache.fop.area.inline.Image;
+import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.Leader;
+import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
@@ -69,7 +73,7 @@
 import org.apache.fop.render.Graphics2DAdapter;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.render.pdf.CTMHelper;
-import org.apache.fop.render.pdf.PDFRendererContextConstants;
+import org.apache.fop.util.CharUtilities;
 
 /**
  * The <code>Java2DRenderer</code> class provides the abstract technical
@@ -155,7 +159,11 @@
         fontInfo = inFontInfo;
         BufferedImage fontImage = new BufferedImage(100, 100,
                 BufferedImage.TYPE_INT_RGB);
-        FontSetup.setup(fontInfo, fontImage.createGraphics());
+        Graphics2D g = fontImage.createGraphics();
+        //The next line is important to get accurate font metrics!
+        g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
+                RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+        FontSetup.setup(fontInfo, g);
     }
 
     /** @see org.apache.fop.render.Renderer#getGraphics2DAdapter() */
@@ -664,23 +672,103 @@
 
         int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
         int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
+        int saveIP = currentIPPosition;
 
         Font font = getFontFromArea(text);
         state.updateFont(font.getFontName(), font.getFontSize(), null);
-
-        Color col = (Color) text.getTrait(Trait.COLOR);
-        state.updateColor(col);
-
-        String s = text.getText();
-        state.getGraph().drawString(s, rx / 1000f, bl / 1000f);
-
-        super.renderText(text);
+        saveGraphicsState();
+        AffineTransform at = new AffineTransform();
+        at.translate(rx / 1000f, bl / 1000f);
+        state.transform(at);
+        renderText(text, state.getGraph(), font);
+        restoreGraphicsState();
+        
+        currentIPPosition = saveIP + text.getAllocIPD();
+        //super.renderText(text);
 
         // rendering text decorations
         Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
         int fontsize = text.getTraitAsInteger(Trait.FONT_SIZE);
         renderTextDecoration(tf, fontsize, text, bl, rx);
     }
+
+    /**
+     * Renders a TextArea to a Graphics2D instance. Adjust the coordinate system so that the
+     * start of the baseline of the first character is at coordinate (0,0).
+     * @param text the TextArea
+     * @param g2d the Graphics2D to render to
+     * @param font the font to paint with
+     */
+    public static void renderText(TextArea text, Graphics2D g2d, Font font) {
+
+        Color col = (Color) text.getTrait(Trait.COLOR);
+        g2d.setColor(col);
+
+        float textCursor = 0;
+
+        Iterator iter = text.getChildAreas().iterator();
+        while (iter.hasNext()) {
+            InlineArea child = (InlineArea)iter.next();
+            if (child instanceof WordArea) {
+                WordArea word = (WordArea)child;
+                String s = word.getWord();
+                int[] letterAdjust = word.getLetterAdjustArray();
+                GlyphVector gv = g2d.getFont().createGlyphVector(g2d.getFontRenderContext(), s);
+                double additionalWidth = 0.0;
+                if (letterAdjust == null 
+                        && text.getTextLetterSpaceAdjust() == 0 
+                        && text.getTextWordSpaceAdjust() == 0) {
+                    //nop
+                } else {
+                    int[] offsets = getGlyphOffsets(s, font, text, letterAdjust);
+                    float cursor = 0.0f;
+                    for (int i = 0; i < offsets.length; i++) {
+                        Point2D pt = gv.getGlyphPosition(i);
+                        pt.setLocation(cursor, pt.getY());
+                        gv.setGlyphPosition(i, pt);
+                        cursor += offsets[i] / 1000f;
+                    }
+                    additionalWidth = cursor - gv.getLogicalBounds().getWidth();
+                }
+                g2d.drawGlyphVector(gv, textCursor, 0);
+                textCursor += gv.getLogicalBounds().getWidth() + additionalWidth;
+            } else if (child instanceof SpaceArea) {
+                SpaceArea space = (SpaceArea)child;
+                String s = space.getSpace();
+                char sp = s.charAt(0);
+                int tws = (space.isAdjustable() 
+                        ? text.getTextWordSpaceAdjust() 
+                                + 2 * text.getTextLetterSpaceAdjust()
+                        : 0);
+
+                textCursor += (font.getCharWidth(sp) + tws) / 1000f;
+            } else {
+                throw new IllegalStateException("Unsupported child element: " + child);
+            }
+        }
+    }
+    
+    private static int[] getGlyphOffsets(String s, Font font, TextArea text, 
+            int[] letterAdjust) {
+        int textLen = s.length();
+        int[] offsets = new int[textLen];
+        for (int i = 0; i < textLen; i++) {
+            final char c = s.charAt(i);
+            final char mapped = font.mapChar(c);
+            int wordSpace;
+
+            if (CharUtilities.isAdjustableSpace(mapped)) {
+                wordSpace = text.getTextWordSpaceAdjust();
+            } else {
+                wordSpace = 0;
+            }
+            int cw = font.getWidth(mapped);
+            int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0);
+            int tls = (i < textLen - 1 ? text.getTextLetterSpaceAdjust() : 0); 
+            offsets[i] = cw + ladj + tls + wordSpace;
+        }
+        return offsets;
+    }    
 
     /**
      * Render leader area. This renders a leader area which is an area with a



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