pdfbox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From le...@apache.org
Subject svn commit: r735325 - in /incubator/pdfbox/trunk/src/main: java/org/apache/pdfbox/pdmodel/font/ resources/Resources/
Date Sat, 17 Jan 2009 18:49:41 GMT
Author: lehmi
Date: Sat Jan 17 10:49:41 2009
New Revision: 735325

URL: http://svn.apache.org/viewvc?rev=735325&view=rev
Log:
PDFBOX-302: improved font-handling

Added:
    incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/FontManager.java 
 (with props)
    incubator/pdfbox/trunk/src/main/resources/Resources/FontMapping.properties   (with props)
Modified:
    incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
    incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java

Added: incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/FontManager.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/FontManager.java?rev=735325&view=auto
==============================================================================
--- incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/FontManager.java (added)
+++ incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/FontManager.java Sat
Jan 17 10:49:41 2009
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+package org.apache.pdfbox.pdmodel.font;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.apache.pdfbox.util.ResourceLoader;
+
+/**
+ *  This class is used as font manager.
+ *
+ */
+
+public class FontManager {
+
+	// HashMap with all known fonts
+    private static HashMap envFonts = new HashMap();
+	// the standard font
+    private static String standardFont = null;
+    
+    static {
+    	loadFonts();
+    	loadFontMapping();
+    	loadBasefontMapping();
+    }
+    
+    /**
+     * Get the standard font from the environment, usually Arial or Times New Roman  
+     *
+     * @return The standard font 
+     * 
+     */
+    public static java.awt.Font getStandardFont() {
+    	if (standardFont != null)
+    		return getAwtFont(standardFont);
+    	return null;
+    }
+    
+    /**
+     * Get the font for the given fontname
+     *
+     * @param font The name of the font.
+     *
+     * @return The font we are looking for or a similar font or null if nothing is found.
+     * 
+     */
+    public static java.awt.Font getAwtFont(String font) {
+   	 
+    	String fontname = normalizeFontname(font);
+	    if (envFonts.containsKey(fontname)) 
+	    	return (java.awt.Font)envFonts.get(fontname);
+    	return null;
+    }
+
+    /**
+     * Load all available fonts from the environment
+     */
+    private static void loadFonts() {
+    	java.awt.Font[] allFonts = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
+		int numberOfFonts = allFonts.length;
+		for (int i=0;i<numberOfFonts;i++) {
+			java.awt.Font font = allFonts[i];
+			String family = normalizeFontname(font.getFamily());
+			if (isBoldItalic(font)) {
+				envFonts.put(family+"bolditalic", font);
+			}
+			else if (isBold(font)) {
+				envFonts.put(family+"bold", font);
+			}
+			else if (isItalic(font)) {
+				envFonts.put(family+"italic", font);
+			}
+			else { 
+				envFonts.put(family, font);
+			}
+		}
+		// One of the following fonts will be the standard-font 
+		if (envFonts.containsKey("arial"))
+			standardFont = "arial";
+		else if (envFonts.containsKey("timesnewroman"))
+			standardFont = "timesnewroman";
+    }
+    
+    /**
+     * Normalize the fontname
+     *
+     * @param fontname The name of the font.
+     *
+     * @return The normalized name of the font.
+     * 
+     */
+    private static String normalizeFontname(String fontname) {
+    	// Terminate all whitespaces, commas and hyphens
+    	String normalizedFontname = fontname.toLowerCase().replaceAll(" ","").replaceAll(",","").replaceAll("-","");
+    	// Terminate trailing characters up to the "+".
+    	// As far as I know, these characters are used in names of embedded fonts
+    	// If the embedded font can't be read, we'll try to find it here
+    	if (normalizedFontname.contains("+"))
+    		normalizedFontname = normalizedFontname.substring(normalizedFontname.indexOf("+")+1);
+    	// normalize all kinds of fonttypes. There are several possible version which have to
be normalized
+    	// e.g. Arial,Bold Arial-BoldMT Helevtica-oblique ...
+    	boolean isBold = normalizedFontname.contains("bold");
+		boolean isItalic = normalizedFontname.contains("italic") || normalizedFontname.contains("oblique");
+		normalizedFontname = normalizedFontname.toLowerCase().replaceAll("bold" , "").replaceAll("italic"
, "").replaceAll("oblique" , "");
+    	if (isBold)
+    		normalizedFontname += "bold";
+    	if (isItalic)
+    		normalizedFontname += "italic";
+		return normalizedFontname;
+    }
+    
+    
+    /**
+     * Add a font-mapping
+     *
+     * @param font The name of the font.
+     *
+     * @param mappedName The name of the mapped font.
+     * 
+     */
+    private static void addFontMapping(String font, String mappedName) {
+    	String fontname = normalizeFontname(font);
+    	// is there already a font mapping ?
+    	if (envFonts.containsKey(fontname))
+    		return;
+    	String mappedFontname = normalizeFontname(mappedName);
+    	// is the mapped font available ?
+    	if (!envFonts.containsKey(mappedFontname))
+    		return;
+    	envFonts.put(fontname, envFonts.get(mappedFontname));
+    }
+    
+    /**
+     * Load the mapping for the well knwon font-substitutions
+     *
+     */
+    private static void loadFontMapping() {
+    	Properties fontMapping = new Properties();; 
+        try
+        {
+            ResourceLoader.loadProperties( "Resources/FontMapping.properties", fontMapping
);
+        }
+        catch( IOException io )
+        {
+            io.printStackTrace();
+            throw new RuntimeException( "Error loading font mapping" );
+        }
+        Enumeration keys = fontMapping.keys();
+        while (keys.hasMoreElements()) {
+        	String key = (String)keys.nextElement();
+        	addFontMapping(key,(String)fontMapping.get(key));
+        }
+    }
+
+    /**
+     * Mapping for the basefonts
+     */
+    private static void loadBasefontMapping() {
+    	addFontMapping("Times-Roman","TimesNewRoman");
+    	addFontMapping("Times-Bold","TimesNewRoman,Bold");
+    	addFontMapping("Times-Italic","TimesNewRoman,Italic");
+    	addFontMapping("Times-BoldItalic","TimesNewRoman,Bold,Italic");
+    	addFontMapping("Helvetica-Oblique","Helvetica,Italic");
+    	addFontMapping("Helvetica-BoldOblique","Helvetica,Bold,Italic");
+    	addFontMapping("Courier-Oblique","Courier,Italic");
+    	addFontMapping("Courier-BoldOblique","Courier,Bold,Italic");
+    }
+
+    /**
+     * Try to determine if the font has both a BOLD and an ITALIC-type
+     *
+     * @param name The font.
+     *
+     * @return font has BOLD and ITALIC-type or not
+     */
+    private static boolean isBoldItalic(java.awt.Font font) {
+    	return isBold(font) && isItalic(font);
+    }
+    
+    /**
+     * Try to determine if the font has a BOLD-type
+     *
+     * @param name The font.
+     *
+     * @return font has BOLD-type or not
+     */
+    private static boolean isBold(java.awt.Font font) {
+    	String name = font.getName().toLowerCase();
+    	if (name.contains("bold"))
+    		return true;
+    	String psname = font.getPSName().toLowerCase();
+    	if (psname.contains("bold"))
+    		return true;
+    	return false;
+    }
+    
+    /**
+     * Try to determine if the font has an ITALIC-type
+     *
+     * @param name The font.
+     *
+     * @return font has ITALIC-type or not
+     */
+    private static boolean isItalic(java.awt.Font font) {
+    	String name = font.getName().toLowerCase();
+    	// oblique is the same as italic
+    	if (name.contains("italic") || name.contains("oblique"))
+    		return true;
+    	String psname = font.getPSName().toLowerCase();
+    	if (psname.contains("italic") || psname.contains("oblique"))
+    		return true;
+    	return false;
+    }
+}

Propchange: incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/FontManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java?rev=735325&r1=735324&r2=735325&view=diff
==============================================================================
--- incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
(original)
+++ incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
Sat Jan 17 10:49:41 2009
@@ -32,15 +32,10 @@
 
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
-
 import org.apache.pdfbox.pdmodel.PDDocument;
-
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.common.PDStream;
-
 import org.apache.pdfbox.encoding.WinAnsiEncoding;
-import org.apache.pdfbox.exceptions.WrappedIOException;
-
 import org.apache.pdfbox.util.ResourceLoader;
 
 import java.awt.Font;
@@ -325,34 +320,46 @@
         PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary)getFontDescriptor();
         if( awtFont == null )
         {
-            try
+            PDStream ff2Stream = fd.getFontFile2();
+            if( ff2Stream != null )
             {
-                PDStream ff2Stream = fd.getFontFile2();
-                String fontName = fd.getFontName();
-                if( ff2Stream != null )
+                try
                 {
-                    awtFont = Font.createFont( Font.TRUETYPE_FONT, ff2Stream.createInputStream()
);
+                	// create a font with the embedded data
+                	awtFont = Font.createFont( Font.TRUETYPE_FONT, ff2Stream.createInputStream()
);
                 }
-                else
+                catch( FontFormatException f )
                 {
-                    //throw new IOException( "Error:TTF Stream is null");
-                    // Embedded true type programs are optional,
-                    // if there is no stream, we must use an external
-                    // file.
+					logger().info("Can't read the embedded font " + fd.getFontName() );
+                }
+            }
+            else
+            {
+            	// check if the font is part of our environment
+				awtFont = FontManager.getAwtFont(fd.getFontName());
+				if (awtFont == null) 
+				{ 
+					logger().info("Can't find the specified font " + fd.getFontName() );
+                    // check if there is a font mapping for an external font file
                     TrueTypeFont ttf = getExternalFontFile2( fd );
-                    if( ttf != null )
-                    {
-                        awtFont = Font.createFont( Font.TRUETYPE_FONT, ttf.getOriginalData()
);
-                    }
-                    else
+                    if( ttf != null ) 
                     {
-                        awtFont = Font.getFont( fontName, null );
+                        try
+                    	{
+                        	awtFont = Font.createFont( Font.TRUETYPE_FONT, ttf.getOriginalData()
);
+                        }
+	                    catch( FontFormatException f )
+	                    {
+	    					logger().info("Can't read the external fontfile " + fd.getFontName() );
+	                    }
                     }
-                }
+				}
             }
-            catch( FontFormatException f )
-            {
-                throw new WrappedIOException( f );
+			if (awtFont == null) 
+			{
+				// we can't find anything, so we have to use the standard font
+				awtFont = FontManager.getStandardFont();
+				logger().info("Using font "+awtFont.getName()+ " instead");
             }
         }
         Graphics2D g2d = (Graphics2D)g;

Modified: incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java?rev=735325&r1=735324&r2=735325&view=diff
==============================================================================
--- incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java (original)
+++ incubator/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java Sat
Jan 17 10:49:41 2009
@@ -185,88 +185,43 @@
     {
         if( awtFont == null )
         {
-            String baseFont = this.getBaseFont();
-            if( baseFont.equals( TIMES_ROMAN.getBaseFont() ) )
-            {
-                awtFont = new Font( "Times New Roman", Font.PLAIN, 1 );
-            }
-            else if( baseFont.equals( TIMES_ITALIC.getBaseFont() ) )
-            {
-                awtFont = new Font( "Times New Roman", Font.ITALIC, 1 );
-            }
-            else if( baseFont.equals( TIMES_BOLD.getBaseFont() ) )
-            {
-                awtFont = new Font( "Times New Roman", Font.BOLD, 1 );
-            }
-            else if( baseFont.equals( TIMES_BOLD_ITALIC.getBaseFont() ) )
-            {
-                awtFont = new Font( "Times New Roman", Font.BOLD | Font.ITALIC, 1 );
-            }
-            else if( baseFont.equals( HELVETICA.getBaseFont() ) )
-            {
-                awtFont = new Font( "Helvetica", Font.PLAIN, 1 );
-            }
-            else if( baseFont.equals( HELVETICA_BOLD.getBaseFont() ) )
-            {
-                awtFont = new Font( "Helvetica", Font.BOLD, 1 );
-            }
-            else if( baseFont.equals( HELVETICA_BOLD_OBLIQUE.getBaseFont() ) )
-            {
-                awtFont = new Font( "Helvetica", Font.BOLD | Font.ITALIC, 1 );
-            }
-            else if( baseFont.equals( HELVETICA_OBLIQUE.getBaseFont() ) )
-            {
-                awtFont = new Font( "Helvetica", Font.ITALIC, 1 );
-            }
-            else if( baseFont.equals( COURIER.getBaseFont() ) )
-            {
-                awtFont = new Font( "Courier", Font.PLAIN, 1 );
-            }
-            else if( baseFont.equals( COURIER_BOLD.getBaseFont() ) )
-            {
-                awtFont = new Font( "Courier", Font.BOLD, 1 );
-            }
-            else if( baseFont.equals( COURIER_BOLD_OBLIQUE.getBaseFont() ) )
-            {
-                awtFont = new Font( "Courier", Font.BOLD | Font.ITALIC, 1 );
-            }
-            else if( baseFont.equals( COURIER_OBLIQUE.getBaseFont() ) )
-            {
-                awtFont = new Font( "Courier", Font.ITALIC, 1 );
-            }
-            else if( baseFont.equals( SYMBOL.getBaseFont() ) )
-            {
-                awtFont = new Font( "Symbol", Font.PLAIN, 1 );
-            }
-            else if( baseFont.equals( ZAPF_DINGBATS.getBaseFont() ) )
-            {
-                awtFont = new Font( "ZapfDingbats", Font.PLAIN, 1 );
-            }
-            else
-            {
-                PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary)getFontDescriptor();
-		if (fd != null){
-			PDStream ffStream = fd.getFontFile();
-			if( ffStream != null )
-			{
-			    try {
-					awtFont = Font.createFont( TYPE1_FONT, ffStream.createInputStream() );
-				} catch (FontFormatException e) {
-					logger().info("substituting Arial because we couldn't read the embedded Font " + fd.getFontName()
);
-					awtFont = new Font( "Arial", Font.PLAIN, 1 );
+            String baseFont = getBaseFont();
+        	PDFontDescriptor fd = getFontDescriptor();
+			if (fd != null && fd instanceof PDFontDescriptorDictionary){
+				PDFontDescriptorDictionary fdDictionary = (PDFontDescriptorDictionary)fd;
+				PDStream ffStream = fdDictionary.getFontFile();
+				if( ffStream == null && fdDictionary.getFontFile3() != null)
+					// TODO FontFile3-streams containing CIDFontType0C or OpenType fonts aren't yet supported

+					logger().info("Embedded font-type is not supported " + fd.getFontName() );
+				if( ffStream != null )
+				{
+				    try {
+	                	// create a font with the embedded data
+						awtFont = Font.createFont( TYPE1_FONT, ffStream.createInputStream() );
+					} catch (FontFormatException e) {
+						logger().info("Can't read the embedded font " + fd.getFontName() );
+					}
+				}
+				else {
+	            	// check if the font is part of our environment
+					awtFont = FontManager.getAwtFont(fd.getFontName());
+					if (awtFont == null) 
+						logger().info("Can't find the specified font " + fd.getFontName() );
 				}
 			}
-			else {
-				// TODO try to load external Font. see also PDTrueTypeFont
-						logger().info("substituting Arial because the specified font isn't embedded " + fd.getFontName()
);
-				awtFont = new Font( "Arial", Font.PLAIN, 1 );
+			else
+			{
+            	// check if the font is part of our environment
+				awtFont = FontManager.getAwtFont(baseFont);
+				if (awtFont == null) 
+					logger().info("Can't find the specified basefont " + baseFont );
+			}
+			if (awtFont == null) 
+			{
+				// we can't find anything, so we have to use the standard font
+				awtFont = FontManager.getStandardFont();
+				logger().info("Using font "+awtFont.getName()+ " instead");
 			}
-		}
-		else{
-			logger().info("substituting Arial because we failed to get a FontDescriptor" );
-			awtFont = new Font( "Arial", Font.PLAIN, 1 );
-		}
-            }
         }
         Graphics2D g2d = (Graphics2D)g;
         g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
@@ -274,4 +229,5 @@
 
         g2d.drawString( string, x, y );
     }
+    
 }

Added: incubator/pdfbox/trunk/src/main/resources/Resources/FontMapping.properties
URL: http://svn.apache.org/viewvc/incubator/pdfbox/trunk/src/main/resources/Resources/FontMapping.properties?rev=735325&view=auto
==============================================================================
--- incubator/pdfbox/trunk/src/main/resources/Resources/FontMapping.properties (added)
+++ incubator/pdfbox/trunk/src/main/resources/Resources/FontMapping.properties Sat Jan 17
10:49:41 2009
@@ -0,0 +1,15 @@
+# This file contaions well known font substitutions. 
+# If a needed font isn't embedded in the pdf and not available in the running environment
+# it will be substituted with an other suitable font, if available
+#
+Helvetica=Arial
+Helvetica,Bold=Arial,Bold
+Helvetica,Italic=Arial,Italic
+Helvetica,Bold,Italic=Arial,Bold,Italic
+SymbolMT=StandardSymbolsL
+ArialMT=Arial
+ArialMT,Bold=Arial,Bold
+ArialMT,Italic=Arial,Italic
+ArialMT,Bold,Italic=Arial,Bold,Italic
+TimesNewRomanPSMT=Verdana
+TimesNewRomanPSMT,Bold=Verdana,Bold
\ No newline at end of file

Propchange: incubator/pdfbox/trunk/src/main/resources/Resources/FontMapping.properties
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message