001/*
002 * $Id: DefaultFontMapper.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf;
045
046import java.awt.Font;
047import java.io.File;
048import java.util.HashMap;
049
050import com.itextpdf.text.ExceptionConverter;
051/** Default class to map awt fonts to BaseFont.
052 * @author Paulo Soares
053 */
054
055public class DefaultFontMapper implements FontMapper {
056
057    /** A representation of BaseFont parameters.
058     */
059    public static class BaseFontParameters {
060        /** The font name.
061         */
062        public String fontName;
063        /** The encoding for that font.
064         */
065        public String encoding;
066        /** The embedding for that font.
067         */
068        public boolean embedded;
069        /** Whether the font is cached of not.
070         */
071        public boolean cached;
072        /** The font bytes for ttf and afm.
073         */
074        public byte ttfAfm[];
075        /** The font bytes for pfb.
076         */
077        public byte pfb[];
078
079        /** Constructs default BaseFont parameters.
080         * @param fontName the font name or location
081         */
082        public BaseFontParameters(String fontName) {
083            this.fontName = fontName;
084            encoding = BaseFont.CP1252;
085            embedded = BaseFont.EMBEDDED;
086            cached = BaseFont.CACHED;
087        }
088    }
089
090    /** Maps aliases to names.
091     */
092    private HashMap<String, String> aliases = new HashMap<String, String>();
093    /** Maps names to BaseFont parameters.
094     */
095    private HashMap<String, BaseFontParameters> mapper = new HashMap<String, BaseFontParameters>();
096    /**
097     * Returns a BaseFont which can be used to represent the given AWT Font
098     *
099     * @param   font            the font to be converted
100     * @return  a BaseFont which has similar properties to the provided Font
101     */
102
103    public BaseFont awtToPdf(Font font) {
104        try {
105            BaseFontParameters p = getBaseFontParameters(font.getFontName());
106            if (p != null)
107                return BaseFont.createFont(p.fontName, p.encoding, p.embedded, p.cached, p.ttfAfm, p.pfb);
108            String fontKey = null;
109            String logicalName = font.getName();
110
111            if (logicalName.equalsIgnoreCase("DialogInput") || logicalName.equalsIgnoreCase("Monospaced") || logicalName.equalsIgnoreCase("Courier")) {
112
113                if (font.isItalic()) {
114                    if (font.isBold()) {
115                        fontKey = BaseFont.COURIER_BOLDOBLIQUE;
116
117                    } else {
118                        fontKey = BaseFont.COURIER_OBLIQUE;
119                    }
120
121                } else {
122                    if (font.isBold()) {
123                        fontKey = BaseFont.COURIER_BOLD;
124
125                    } else {
126                        fontKey = BaseFont.COURIER;
127                    }
128                }
129
130            } else if (logicalName.equalsIgnoreCase("Serif") || logicalName.equalsIgnoreCase("TimesRoman")) {
131
132                if (font.isItalic()) {
133                    if (font.isBold()) {
134                        fontKey = BaseFont.TIMES_BOLDITALIC;
135
136                    } else {
137                        fontKey = BaseFont.TIMES_ITALIC;
138                    }
139
140                } else {
141                    if (font.isBold()) {
142                        fontKey = BaseFont.TIMES_BOLD;
143
144                    } else {
145                        fontKey = BaseFont.TIMES_ROMAN;
146                    }
147                }
148
149            } else {  // default, this catches Dialog and SansSerif
150
151                if (font.isItalic()) {
152                    if (font.isBold()) {
153                        fontKey = BaseFont.HELVETICA_BOLDOBLIQUE;
154
155                    } else {
156                        fontKey = BaseFont.HELVETICA_OBLIQUE;
157                    }
158
159                } else {
160                    if (font.isBold()) {
161                        fontKey = BaseFont.HELVETICA_BOLD;
162                    } else {
163                        fontKey = BaseFont.HELVETICA;
164                    }
165                }
166            }
167            return BaseFont.createFont(fontKey, BaseFont.CP1252, false);
168        }
169        catch (Exception e) {
170            throw new ExceptionConverter(e);
171        }
172    }
173
174    /**
175     * Returns an AWT Font which can be used to represent the given BaseFont
176     *
177     * @param   font            the font to be converted
178     * @param   size            the desired point size of the resulting font
179     * @return  a Font which has similar properties to the provided BaseFont
180     */
181
182    public Font pdfToAwt(BaseFont font, int size) {
183        String names[][] = font.getFullFontName();
184        if (names.length == 1)
185            return new Font(names[0][3], 0, size);
186        String name10 = null;
187        String name3x = null;
188        for (int k = 0; k < names.length; ++k) {
189            String name[] = names[k];
190            if (name[0].equals("1") && name[1].equals("0"))
191                name10 = name[3];
192            else if (name[2].equals("1033")) {
193                name3x = name[3];
194                break;
195            }
196        }
197        String finalName = name3x;
198        if (finalName == null)
199            finalName = name10;
200        if (finalName == null)
201            finalName = names[0][3];
202        return new Font(finalName, 0, size);
203    }
204
205    /** Maps a name to a BaseFont parameter.
206     * @param awtName the name
207     * @param parameters the BaseFont parameter
208     */
209    public void putName(String awtName, BaseFontParameters parameters) {
210        mapper.put(awtName, parameters);
211    }
212
213    /** Maps an alias to a name.
214     * @param alias the alias
215     * @param awtName the name
216     */
217    public void putAlias(String alias, String awtName) {
218        aliases.put(alias, awtName);
219    }
220
221    /** Looks for a BaseFont parameter associated with a name.
222     * @param name the name
223     * @return the BaseFont parameter or <CODE>null</CODE> if not found.
224     */
225    public BaseFontParameters getBaseFontParameters(String name) {
226        String alias = aliases.get(name);
227        if (alias == null)
228            return mapper.get(name);
229        BaseFontParameters p = mapper.get(alias);
230        if (p == null)
231            return mapper.get(name);
232        else
233            return p;
234    }
235
236    /**
237     * Inserts the names in this map.
238     * @param allNames the returned value of calling {@link BaseFont#getAllFontNames(String, String, byte[])}
239     * @param path the full path to the font
240     */
241    public void insertNames(Object allNames[], String path) {
242        String names[][] = (String[][])allNames[2];
243        String main = null;
244        for (int k = 0; k < names.length; ++k) {
245            String name[] = names[k];
246            if (name[2].equals("1033")) {
247                main = name[3];
248                break;
249            }
250        }
251        if (main == null)
252            main = names[0][3];
253        BaseFontParameters p = new BaseFontParameters(path);
254        mapper.put(main, p);
255        for (int k = 0; k < names.length; ++k) {
256            aliases.put(names[k][3], main);
257        }
258        aliases.put((String)allNames[0], main);
259    }
260
261    /** Inserts one font file into the map. The encoding
262     * will be <CODE>BaseFont.CP1252</CODE> but can be
263     * changed later.
264     * @param file the file to insert
265     * @return the number of files inserted
266     * @since 5.0.5
267     */
268    public int insertFile(File file) {
269        String name = file.getPath().toLowerCase();
270        try {
271            if (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".afm")) {
272                Object allNames[] = BaseFont.getAllFontNames(file.getPath(), BaseFont.CP1252, null);
273                insertNames(allNames, file.getPath());
274                return 1;
275            } else if (name.endsWith(".ttc")) {
276                String ttcs[] = BaseFont.enumerateTTCNames(file.getPath());
277                for (int j = 0; j < ttcs.length; ++j) {
278                    String nt = file.getPath() + "," + j;
279                    Object allNames[] = BaseFont.getAllFontNames(nt, BaseFont.CP1252, null);
280                    insertNames(allNames, nt);
281                }
282                return 1;
283            }
284        } catch (Exception e) {
285        }
286        return 0;
287    }
288
289    /** Inserts all the fonts recognized by iText in the
290     * <CODE>directory</CODE> into the map. The encoding
291     * will be <CODE>BaseFont.CP1252</CODE> but can be
292     * changed later.
293     * @param dir the directory to scan
294     * @return the number of files processed
295     */
296    public int insertDirectory(String dir) {
297        File file = new File(dir);
298        if (!file.exists() || !file.isDirectory())
299            return 0;
300        File files[] = file.listFiles();
301        if (files == null)
302            return 0;
303        int count = 0;
304        for (int k = 0; k < files.length; ++k) {
305            count += insertFile(files[k]);
306        }
307        return count;
308    }
309
310    public HashMap<String, BaseFontParameters> getMapper() {
311        return mapper;
312    }
313
314    public HashMap<String, String> getAliases() {
315        return aliases;
316    }
317}