]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Improved font selection strategy when matching AWT Font against FontTriplet.
authorAdrian Cumiskey <acumiskey@apache.org>
Wed, 5 Nov 2008 13:41:13 +0000 (13:41 +0000)
committerAdrian Cumiskey <acumiskey@apache.org>
Wed, 5 Nov 2008 13:41:13 +0000 (13:41 +0000)
Fonts looking too big still when processed through AFPTextHandler.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@711563 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/afp/AFPTextHandler.java
src/java/org/apache/fop/afp/AFPTextPainter.java
src/java/org/apache/fop/fonts/FontInfo.java
src/java/org/apache/fop/svg/PDFGraphics2D.java

index be6aba51cfe0fddbfb320b46e924b3788acd564a..77dc641b9e9b6a0af3ab16d228eda3ce67562835 100644 (file)
@@ -51,6 +51,7 @@ public class AFPTextHandler implements TextHandler {
 
     /**
      * Main constructor.
+     *
      * @param g2d the AFPGraphics2D instance
      */
     public AFPTextHandler(AFPGraphics2D g2d) {
@@ -66,6 +67,27 @@ public class AFPTextHandler implements TextHandler {
         return g2d.getFontInfo();
     }
 
+    /**
+     * Registers a page font
+     *
+     * @param internalFontName the internal font name
+     * @param fontSize the font size
+     * @return a font reference
+     */
+    private int registerPageFont(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,
+                afpFont,
+                fontSize
+        );
+        return afpFontAttributes.getFontReference();
+    }
+
     /**
      * Add a text string to the current data object of the AFP datastream.
      * The text is painted using text operations.
@@ -77,26 +99,28 @@ public class AFPTextHandler implements TextHandler {
         GraphicsObject graphicsObj = g2d.getGraphicsObject();
         Color color = g2d.getColor();
 
+        // set the color
         AFPPaintingState paintingState = g2d.getPaintingState();
         if (paintingState.setColor(color)) {
             graphicsObj.setColor(color);
         }
+
+        // set the character set
+        int fontReference = 0;
         if (overrideFont != null) {
-            FontInfo fontInfo = getFontInfo();
-            AFPPageFonts pageFonts = paintingState.getPageFonts();
             String internalFontName = overrideFont.getFontName();
             int fontSize = overrideFont.getFontSize();
-            if (paintingState.setFontName(internalFontName) || paintingState.setFontSize(fontSize)) {
-                AFPFont font = (AFPFont)fontInfo.getFonts().get(internalFontName);
-                AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
-                        internalFontName,
-                        font,
-                        fontSize
-                );
-                int fontReference = afpFontAttributes.getFontReference();
-                graphicsObj.setCharacterSet(fontReference);
-            }
+            fontReference = registerPageFont(internalFontName, fontSize);
+        } else {
+            java.awt.Font awtFont = g2d.getFont();
+            AffineTransform fontTransform = awtFont.getTransform();
+            FontInfo fontInfo = getFontInfo();
+            Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
+            String internalFontName = fopFont.getFontName();
+            int fontSize = fopFont.getFontSize();
+            fontReference = registerPageFont(internalFontName, fontSize);
         }
+        graphicsObj.setCharacterSet(fontReference);
 
         // calculate x, y plotting coordinates from graphics context
         AffineTransform at = g2d.getTransform();
@@ -104,6 +128,7 @@ public class AFPTextHandler implements TextHandler {
         float[] dstPts = new float[srcPts.length];
         at.transform(srcPts, 0, dstPts, 0, 1);
 
+        // add the character string
         graphicsObj.addString(str, Math.round(dstPts[X]), Math.round(dstPts[Y]));
     }
 
index d0d54fd756ae3d0d05f1ef6a423d05823bbda74f..7e3f3405f911c5eac976824345f64f4e6e1148ff 100644 (file)
@@ -5,9 +5,9 @@
  * 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.
 
 package org.apache.fop.afp;
 
+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.Point2D;
 import java.awt.geom.Rectangle2D;
+import java.io.IOException;
 import java.text.AttributedCharacterIterator;
 import java.text.CharacterIterator;
-import java.awt.font.TextAttribute;
-import java.awt.Shape;
-import java.awt.Paint;
-import java.awt.Color;
-import java.io.IOException;
-import java.util.List;
 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.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontTriplet;
 
-import org.apache.batik.dom.svg.SVGOMTextElement;
-import org.apache.batik.gvt.text.Mark;
-import org.apache.batik.gvt.TextPainter;
-import org.apache.batik.gvt.TextNode;
-import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
-import org.apache.batik.gvt.text.TextPaintInfo;
-import org.apache.batik.gvt.font.GVTFontFamily;
-import org.apache.batik.gvt.renderer.StrokingTextPainter;
-
 
 /**
  * Renders the attributed character iterator of a <tt>TextNode</tt>.
@@ -57,17 +56,17 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter;
  * 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 AFPTextHandler nativeTextHandler;
+
+    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 
+    protected static final TextPainter
         PROXY_PAINTER = StrokingTextPainter.getInstance();
 
     /**
@@ -95,11 +94,11 @@ public class AFPTextPainter implements TextPainter {
             paintTextRuns(node.getTextRuns(), g2d, loc);
         }
     }
-    
+
     private boolean hasUnsupportedAttributes(TextNode node) {
         Iterator iter = node.getTextRuns().iterator();
         while (iter.hasNext()) {
-            StrokingTextPainter.TextRun 
+            StrokingTextPainter.TextRun
                     run = (StrokingTextPainter.TextRun)iter.next();
             AttributedCharacterIterator aci = run.getACI();
             boolean hasUnsupported = hasUnsupportedAttributes(aci);
@@ -111,24 +110,24 @@ public class AFPTextPainter implements TextPainter {
     }
 
     private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
-        boolean hasunsupported = false;
-        
+        boolean hasUnsupported = false;
+
         String text = getText(aci);
         Font font = makeFont(aci);
         if (hasUnsupportedGlyphs(text, font)) {
             log.trace("-> Unsupported glyphs found");
-            hasunsupported = true;
+            hasUnsupported = true;
         }
-        
+
         TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
             GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
-        if ((tpi != null) 
+        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;
+            hasUnsupported = true;
         }
 
         //Alpha is not supported
@@ -137,7 +136,7 @@ public class AFPTextPainter implements TextPainter {
             Color col = (Color)foreground;
             if (col.getAlpha() != 255) {
                 log.trace("-> transparency found");
-                hasunsupported = true;
+                hasUnsupported = true;
             }
         }
 
@@ -145,30 +144,30 @@ public class AFPTextPainter implements TextPainter {
                             GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
         if (letSpace != null) {
             log.trace("-> letter spacing found");
-            hasunsupported = true;
+            hasUnsupported = true;
         }
 
         Object wordSpace = aci.getAttribute(
                              GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
         if (wordSpace != null) {
             log.trace("-> word spacing found");
-            hasunsupported = true;
+            hasUnsupported = true;
         }
-        
+
         Object lengthAdjust = aci.getAttribute(
                             GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
         if (lengthAdjust != null) {
             log.trace("-> length adjustments found");
-            hasunsupported = true;
+            hasUnsupported = true;
         }
 
         Object writeMod = aci.getAttribute(
                 GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
-        if (writeMod != null 
+        if (writeMod != null
             && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
                   writeMod)) {
             log.trace("-> Unsupported writing modes found");
-            hasunsupported = true;
+            hasUnsupported = true;
         }
 
         Object vertOr = aci.getAttribute(
@@ -176,22 +175,22 @@ public class AFPTextPainter implements TextPainter {
         if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
                   vertOr)) {
             log.trace("-> vertical orientation found");
-            hasunsupported = true;
+            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
+            hasUnsupported = true; //Filter spans
         }
-        
-        if (hasunsupported) {
+
+        if (hasUnsupported) {
             log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
         }
-        return hasunsupported;
+        return hasUnsupported;
     }
 
     /**
@@ -204,7 +203,7 @@ public class AFPTextPainter implements TextPainter {
         Point2D currentloc = loc;
         Iterator i = textRuns.iterator();
         while (i.hasNext()) {
-            StrokingTextPainter.TextRun 
+            StrokingTextPainter.TextRun
                     run = (StrokingTextPainter.TextRun)i.next();
             currentloc = paintTextRun(run, g2d, currentloc);
         }
@@ -227,7 +226,7 @@ public class AFPTextPainter implements TextPainter {
         // font
         Font font = makeFont(aci);
         nativeTextHandler.setOverrideFont(font);
-        
+
         // color
         TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
                 GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
@@ -240,7 +239,7 @@ public class AFPTextPainter implements TextPainter {
             g2d.setColor(col);
         }
         g2d.setPaint(foreground);
-        
+
         String txt = getText(aci);
         float advance = getStringWidth(txt, font);
         float tx = 0;
@@ -270,7 +269,7 @@ public class AFPTextPainter implements TextPainter {
         } finally {
             nativeTextHandler.setOverrideFont(null);
         }
-        loc.setLocation(loc.getX() + (double)advance, loc.getY());
+        loc.setLocation(loc.getX() + advance, loc.getY());
         return loc;
     }
 
@@ -304,25 +303,25 @@ public class AFPTextPainter implements TextPainter {
         }
         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))
-                       ? "italic" 
-                       : "normal";
+                       ? 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)) 
+        return ((taWeight != null) &&  (taWeight.floatValue() > 1.0))
                        ? Font.WEIGHT_BOLD
                        : Font.WEIGHT_NORMAL;
     }
@@ -415,8 +414,8 @@ public class AFPTextPainter implements TextPainter {
      * @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 
+        /* (todo) getBounds2D() is too slow
+         * because it uses the StrokingTextPainter. We should implement this
          * method ourselves. */
         return PROXY_PAINTER.getBounds2D(node);
     }
@@ -436,7 +435,7 @@ public class AFPTextPainter implements TextPainter {
 
     /**
      * Get the mark.
-     * This does nothing since the output is pdf and not interactive.
+     * This does nothing since the output is AFP and not interactive.
      * @param node the text node
      * @param pos the position
      * @param all select all
@@ -448,7 +447,7 @@ public class AFPTextPainter implements TextPainter {
 
     /**
      * Select at.
-     * This does nothing since the output is pdf and not interactive.
+     * 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
@@ -460,7 +459,7 @@ public class AFPTextPainter implements TextPainter {
 
     /**
      * Select to.
-     * This does nothing since the output is pdf and not interactive.
+     * 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
@@ -472,7 +471,7 @@ public class AFPTextPainter implements TextPainter {
 
     /**
      * Selec first.
-     * This does nothing since the output is pdf and not interactive.
+     * This does nothing since the output is AFP and not interactive.
      * @param node the text node
      * @return null
      */
@@ -482,7 +481,7 @@ public class AFPTextPainter implements TextPainter {
 
     /**
      * Select last.
-     * This does nothing since the output is pdf and not interactive.
+     * This does nothing since the output is AFP and not interactive.
      * @param node the text node
      * @return null
      */
@@ -492,7 +491,7 @@ public class AFPTextPainter implements TextPainter {
 
     /**
      * Get selected.
-     * This does nothing since the output is pdf and not interactive.
+     * This does nothing since the output is AFP and not interactive.
      * @param start the start mark
      * @param finish the finish mark
      * @return null
@@ -503,7 +502,7 @@ public class AFPTextPainter implements TextPainter {
 
     /**
      * Get the highlighted shape.
-     * This does nothing since the output is pdf and not interactive.
+     * This does nothing since the output is AFP and not interactive.
      * @param beginMark the start mark
      * @param endMark the end mark
      * @return null
index ad838708d938690629a230ed840519fd369503d7..1a04d129a3626c6e798a3d4926dd7a19f46ab458 100644 (file)
@@ -318,6 +318,7 @@ public class FontInfo {
 
     /**
      * Retrieves a (possibly cached) Font instance based on a FontTriplet and a font size.
+     *
      * @param triplet the font triplet designating the requested font
      * @param fontSize the font size
      * @return the requested Font instance
@@ -341,6 +342,57 @@ public class FontInfo {
         return font;
     }
 
+    private List/*<FontTriplet>*/ getTripletsForName(String fontName) {
+        List/*<FontTriplet>*/ matchedTriplets = new java.util.ArrayList/*<FontTriplet>*/();
+        Iterator it = triplets.keySet().iterator();
+        while (it.hasNext()) {
+            FontTriplet triplet = (FontTriplet)it.next();
+            String tripletName = triplet.getName();
+            if (tripletName.toLowerCase().equals(fontName.toLowerCase())) {
+                matchedTriplets.add(triplet);
+            }
+        }
+        return matchedTriplets;
+    }
+
+    /**
+     * Returns a suitable internal font given an AWT Font instance.
+     *
+     * @param awtFont the AWT font
+     * @return a best matching internal Font
+     */
+    public Font getFontInstanceForAWTFont(java.awt.Font awtFont) {
+        String awtFontName = awtFont.getName();
+        String awtFontFamily = awtFont.getFamily();
+        String awtFontStyle = awtFont.isItalic() ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
+        int awtFontWeight = awtFont.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL;
+
+        FontTriplet matchedTriplet = null;
+        List/*<FontTriplet>*/ triplets = getTripletsForName(awtFontName);
+        if (!triplets.isEmpty()) {
+            Iterator it = triplets.iterator();
+            while (it.hasNext()) {
+                FontTriplet triplet = (FontTriplet)it.next();
+                boolean styleMatched = triplet.getStyle().equals(awtFontStyle);
+                boolean weightMatched = triplet.getWeight() == awtFontWeight;
+                if (styleMatched && weightMatched) {
+                    matchedTriplet = triplet;
+                    break;
+                }
+            }
+        }
+
+        // not matched on font name so do a lookup using family
+        if (matchedTriplet == null) {
+            if (awtFontFamily.equals("sanserif")) {
+                awtFontFamily = "sans-serif";
+            }
+            matchedTriplet = fontLookup(awtFontFamily, awtFontStyle, awtFontWeight);
+        }
+        float awtFontSize = awtFont.getSize2D();
+        return getFontInstance(matchedTriplet, (int)(awtFontSize * 1000 + 0.5));
+    }
+
     /**
      * Lookup a font.
      * <br>
index 179ebb90abe42424f0bf643d01b64fa10962f2c1..172fafd0c2c51b31a66f4356b7a48c2901e09e6b 100644 (file)
@@ -1325,7 +1325,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
         if (ovFontState == null) {
             java.awt.Font gFont = getFont();
             fontTransform = gFont.getTransform();
-            fontState = getInternalFontForAWTFont(gFont);
+            fontState = fontInfo.getFontInstanceForAWTFont(gFont);
         } else {
             fontState = fontInfo.getFontInstance(
                     ovFontState.getFontTriplet(), ovFontState.getFontSize());