1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.pdfbox.pdmodel.font; 18 19 import java.io.IOException; 20 import java.util.Map; 21 22 import org.apache.pdfbox.cos.COSDictionary; 23 import org.apache.pdfbox.cos.COSName; 24 import org.apache.pdfbox.cos.COSStream; 25 import org.apache.commons.logging.Log; 26 import org.apache.commons.logging.LogFactory; 27 28 /** 29 * This will create the correct type of font based on information in the dictionary. 30 * 31 * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a> 32 * @version $Revision: 1.6 $ 33 */ 34 public class PDFontFactory 35 { 36 /** 37 * private constructor, should only use static methods in this class. 38 */ 39 private PDFontFactory() 40 { 41 } 42 43 /** 44 * Logger instance. 45 */ 46 private static final Log log = LogFactory.getLog(PDFontFactory.class); 47 48 /** 49 * This will create the correct font based on information in the dictionary. 50 * 51 * @param dic The populated dictionary. 52 * 53 * @param fontCache A Map to cache already created fonts 54 * 55 * @return The corrent implementation for the font. 56 * 57 * @throws IOException If the dictionary is not valid. 58 */ 59 public static PDFont createFont(COSDictionary dic, Map fontCache) throws IOException 60 { 61 PDFont retval = null; 62 if (fontCache != null) 63 { 64 String fontKey = dic.getNameAsString(COSName.BASE_FONT) + dic.getNameAsString(COSName.NAME) 65 + dic.getNameAsString(COSName.SUBTYPE); 66 if (dic.getItem(COSName.ENCODING) != null) 67 { 68 fontKey += dic.getItem(COSName.ENCODING).toString(); 69 } 70 if (fontCache.containsKey(fontKey)) 71 { 72 retval = (PDFont)fontCache.get(fontKey); 73 } 74 else 75 { 76 retval = PDFontFactory.createFont( dic ); 77 fontCache.put(fontKey, retval); 78 } 79 } 80 else 81 { 82 retval = PDFontFactory.createFont( dic ); 83 } 84 return retval; 85 } 86 87 /** 88 * This will create the correct font based on information in the dictionary. 89 * 90 * @param dic The populated dictionary. 91 * 92 * @return The corrent implementation for the font. 93 * 94 * @throws IOException If the dictionary is not valid. 95 */ 96 public static PDFont createFont( COSDictionary dic ) throws IOException 97 { 98 PDFont retval = null; 99 100 COSName type = (COSName)dic.getDictionaryObject( COSName.TYPE ); 101 if( !type.equals( COSName.FONT ) ) 102 { 103 throw new IOException( "Cannot create font if /Type is not /Font. Actual=" +type ); 104 } 105 106 COSName subType = (COSName)dic.getDictionaryObject( COSName.SUBTYPE ); 107 if( subType.equals( COSName.TYPE1) ) 108 { 109 retval = new PDType1Font( dic ); 110 111 COSDictionary fontDic = (COSDictionary)dic.getDictionaryObject(COSName.FONT_DESC); 112 if( fontDic != null ) 113 { 114 COSStream ffStream = (COSStream)fontDic.getDictionaryObject("FontFile"); 115 COSStream ff3Stream = (COSStream)fontDic.getDictionaryObject("FontFile3"); 116 117 if( ffStream == null && ff3Stream != null ) 118 { 119 String ff3SubType = ff3Stream.getNameAsString(COSName.SUBTYPE); 120 if( ff3SubType.equals("Type1C") ) 121 { 122 try 123 { 124 retval = new PDType1CFont( dic ); 125 } 126 catch( Exception e ) 127 { 128 log.warn("Failed to create Type1C font. Falling back to Type1 font", e); 129 } 130 } 131 } 132 } 133 } 134 else if( subType.equals( COSName.MM_TYPE1 ) ) 135 { 136 retval = new PDMMType1Font( dic ); 137 } 138 else if( subType.equals( COSName.TRUE_TYPE ) ) 139 { 140 retval = new PDTrueTypeFont( dic ); 141 } 142 else if( subType.equals( COSName.TYPE3 ) ) 143 { 144 retval = new PDType3Font( dic ); 145 } 146 else if( subType.equals( COSName.TYPE0 ) ) 147 { 148 retval = new PDType0Font( dic ); 149 } 150 else if( subType.equals( COSName.CID_FONT_TYPE0 ) ) 151 { 152 retval = new PDCIDFontType0Font( dic ); 153 } 154 else if( subType.equals( COSName.CID_FONT_TYPE2 ) ) 155 { 156 retval = new PDCIDFontType2Font( dic ); 157 } 158 else 159 { 160 log.warn("Substituting TrueType for unknown font subtype=" + dic.getDictionaryObject( COSName.SUBTYPE ).toString()); 161 //throw new IOException( "Unknown font subtype=" + subType ); 162 retval = new PDTrueTypeFont( dic ); 163 } 164 return retval; 165 } 166 }