![JAR search and dependency download from the Maven repository](/logo.png)
org.jpedal.fonts.FontMappings Maven / Gradle / Ivy
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-2017 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
@LICENSE@
*
* ---------------
* FontMappings.java
* ---------------
*/
package org.jpedal.fonts;
import java.awt.GraphicsEnvironment;
import java.io.*;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.jpedal.PdfDecoderInt;
import org.jpedal.exception.PdfFontException;
import org.jpedal.io.ObjectStore;
import org.jpedal.parser.DecoderOptions;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.Strip;
/**
* Holds Maps which are used to map font names onto actual fonts and files
*/
public final class FontMappings {
/**
* ensure fonts setup only once
*/
public static boolean fontsInitialised;
/**
* font to use in preference to Lucida
*/
public static String defaultFont;
/**
* flag to show if there must be a mapping value (program exits if none
* found)
*/
public static boolean enforceFontSubstitution;
/**
* used to remap fonts onto truetype fonts (set internally)
*/
public static Map fontSubstitutionTable;
/**
* hold details of all fonts
*/
public static Map fontPropertiesTable;
public static Map fontPropertiesTableType;
public static Map fontPropertiesTablePath;
/**
* used to ensure substituted fonts unique
*/
public static Map fontPossDuplicates;
/**
* used to store number for subfonts in TTC
*/
public static Map fontSubstitutionFontID;
/**
* used to remap fonts onto truetype fonts (set internally)
*/
public static Map fontSubstitutionLocation = new ConcurrentHashMap();
/**
* used to remap fonts onto truetype fonts (set internally)
*/
public static Map fontSubstitutionAliasTable = new ConcurrentHashMap();
/**
* only upload all fonts once
*/
private static boolean fontsSet;
private static final String separator = System.getProperty("file.separator");
/**
* put fonts in variable so can be altered if needed by Client
*/
public static String[] defaultFontDirs = {"C:/windows/fonts/", "C:/winNT/fonts/",
"/Library/Fonts/",
//"/System/Library/Fonts/", ms 20111013 commented out as breaks forms with Zapf
"/usr/share/fonts/truetype/msttcorefonts/",
//"/usr/share/fonts/truetype/",
//"/windows/D/Windows/Fonts/"
"usr/local/Fonts/",
};
/**
* determine how font substitution is done
*/
private static int fontSubstitutionMode = PdfDecoderInt.SUBSTITUTE_FONT_USING_FILE_NAME;
//private static int fontSubstitutionMode=PdfDecoderInt.SUBSTITUTE_FONT_USING_POSTSCRIPT_NAME;
//private static int fontSubstitutionMode=PdfDecoderInt.SUBSTITUTE_FONT_USING_FULL_FONT_NAME;
//private static int fontSubstitutionMode=PdfDecoderInt.SUBSTITUTE_FONT_USING_FAMILY_NAME;
//private static int fontSubstitutionMode=PdfDecoderInt.SUBSTITUTE_FONT_USING_POSTSCRIPT_NAME_USE_FAMILY_NAME_IF_DUPLICATES;
private FontMappings() {
}
/**
* used internally to pick uo org.jpedal.fontmaps property and set
*/
public static void initFonts() {
// pick up D options and use settings
try {
final String fontMaps = System.getProperty("org.jpedal.fontmaps");
if (fontMaps != null) {
final StringTokenizer fontPaths = new StringTokenizer(fontMaps, ",");
while (fontPaths.hasMoreTokens()) {
final String fontPath = fontPaths.nextToken();
final StringTokenizer values = new StringTokenizer(fontPath, "=:");
final int count = values.countTokens() - 1;
final String[] nameInPDF = new String[count];
final String key = values.nextToken();
for (int i = 0; i < count; i++) {
nameInPDF[i] = values.nextToken();
}
setSubstitutedFontAliases(key, nameInPDF); //$NON-NLS-1$
}
}
} catch (final Exception e) {
LogWriter.writeLog("Unable to read org.jpedal.fontmaps " + e.getMessage());
}
// pick up D options and use settings
try {
final String fontDirs = System.getProperty("org.jpedal.fontdirs");
String failed = null;
if (fontDirs != null) {
failed = FontMappings.addFonts(fontDirs, failed);
}
if (failed != null) {
LogWriter.writeLog("Could not find " + failed);
}
} catch (final Exception e) {
LogWriter.writeLog("Unable to read FontDirs " + e.getMessage());
}
}
/**
* used to ensure we load once
*/
private static final Map isLiberationLoaded = new HashMap();
public static void addLiberationAsFallBackFont(final String family, final String path) throws IOException {
if (isLiberationLoaded.containsKey(family)) {
return;
}
isLiberationLoaded.put(family, path);
checkFontTablesInitialised();
final String[] fontNames = {"-Regular", "-Bold", "-Italic", "-BoldItalic"};
final int fontCount = fontNames.length;
for (int i = 0; i < fontCount; i++) {
final String type = "/TrueType";
final String fontName = family + fontNames[i];
final String rawPath = "org/jpedal/res/" + path + "/" + fontName + ".ttf";
final String outPath = ObjectStore.temp_dir + fontName + ".ttf";
final InputStream url = FontMappings.class.getClassLoader().getResourceAsStream(rawPath);
final BufferedOutputStream to = new BufferedOutputStream(new FileOutputStream(outPath));
ObjectStore.copy(url, to);
to.close();
fontSubstitutionTable.put(fontName, type);
fontSubstitutionLocation.put(fontName, outPath);
//store details under file
fontPropertiesTableType.put(fontName, StandardFonts.TRUETYPE);
fontPropertiesTablePath.put(fontName, outPath);
} /**/
}
/**
* set mode to use when substituting fonts (default is to use Filename (ie arial.ttf)
* Options are SUBSTITUTE_* values from PdfDecoder
*/
public static void setFontSubstitutionMode(final int mode) {
fontSubstitutionMode = mode;
}
/**
* set mode to use when substituting fonts (default is to use Filename (ie arial.ttf)
* Options are SUBSTITUTE_* values from PdfDecoder
*/
public static int getFontSubstitutionMode() {
return fontSubstitutionMode;
}
/**
* allows a number of fonts to be mapped onto an actual font and provides a
* way around slightly differing font naming when substituting fonts - So if
* arialMT existed on the target machine and the PDF contained arial and
* helvetica (which you wished to replace with arialmt), you would use the
* following code -
*
* String[] aliases={"arial","helvetica"};
* currentPdfDecoder.setSubstitutedFontAliases("arialmt",aliases); -
*
* comparison is case-insensitive and file type/ending should not be
* included - For use in conjunction with -Dorg.jpedal.fontdirs options which allows
* user to pass a set of comma separated directories with Truetype fonts
* (directories do not need to exist so can be multi-platform setting)
*/
public static void setSubstitutedFontAliases(final String fontFileName, final String[] aliases) {
if (aliases != null) {
final String name = fontFileName.toLowerCase();
String alias;
for (final String aliase : aliases) {
alias = aliase.toLowerCase();
if (!alias.equals(name)) {
fontSubstitutionAliasTable.put(alias, name);
}
}
}
}
/**
* takes a comma separated list of font directories and add to substitution
*/
public static String addFonts(final String fontDirs, final String failed) {
final StringTokenizer fontPaths = new StringTokenizer(fontDirs, ",");
while (fontPaths.hasMoreTokens()) {
String fontPath = fontPaths.nextToken();
if (!fontPath.endsWith("/") && !fontPath.endsWith("\\")) {
fontPath += separator;
}
//LogWriter.writeLog("Looking in " + fontPath + " for TT fonts");
addTTDir(fontPath, failed);
}
return failed;
}
public static void dispose() {
fontSubstitutionTable = null;
fontPropertiesTable = null;
fontPropertiesTableType = null;
fontPropertiesTablePath = null;
fontPossDuplicates = null;
fontSubstitutionFontID = null;
fontSubstitutionLocation = null;
fontSubstitutionAliasTable = null;
}
/**
* add a truetype font directory and contents to substitution
*/
public static String addTTDir(final String fontPath, String failed) {
checkFontTablesInitialised();
final File currentDir = new File(fontPath);
if ((currentDir.exists()) && (currentDir.isDirectory())) {
final String[] files = currentDir.list();
if (files != null) {
for (final String currentFont : files) {
addFontFile(currentFont, fontPath);
}
}
} else {
if (failed == null) {
failed = fontPath;
} else {
failed = failed + ',' + fontPath;
}
}
return failed;
}
/**
* add a list of settings to map common fonts which can be substituted onto correct platform settings for Windows/MAC/Linux so JPedal
* will try to use the fonts on the computer if possible to produce most accurate display.
*/
public static void setFontReplacements() {
//this is where we setup specific font mapping to use fonts on local machines
//note different settigns for Win, linux, MAC
//general
final String[] aliases6 = {/*"AcArial"}; //,/**/"acarialunicodems__cn"}; //,"acarial,bold"};
setSubstitutedFontAliases("adobeheitistd-regular", aliases6);
//platform settings
if (DecoderOptions.isRunningOnMac) {
//Courier (CourierNew) both on Mac and different
setSubstitutedFontAliases("Courier italic", new String[]{"Courier-Oblique"});
setSubstitutedFontAliases("Courier bold", new String[]{"Courier-Bold"});
setSubstitutedFontAliases("Courier bold italic", new String[]{"Courier-BoldOblique"});
setSubstitutedFontAliases("Courier new italic", new String[]{"CourierNew,italic", "CourierStd-Oblique", "CourierNewPS-ItalicMT"});
setSubstitutedFontAliases("Courier new bold", new String[]{"CourierNew,Bold", "Courier-Bold", "CourierStd-Bold", "CourierNewPS-BoldMT"});
setSubstitutedFontAliases("Courier new bold italic", new String[]{"CourierNew-BoldOblique", "CourierStd-BoldOblique", "CourierNewPS-BoldItalicMT"});
setSubstitutedFontAliases("Courier new", new String[]{"CourierNew", "Courier", "CourierStd", "CourierNewPSMT"});
//Helvetica (Arial)
setSubstitutedFontAliases("arial", new String[]{"Helvetica", "arialmt"});
setSubstitutedFontAliases("arial italic", new String[]{"arial-italic", "arial-italicmt", "Helvetica-Oblique", "Arial,Italic"});
setSubstitutedFontAliases("arial bold", new String[]{"arial-boldmt,bold", "arial-boldmt", "Helvetica-Bold", "Arial,bold"});
setSubstitutedFontAliases("arial bold italic", new String[]{"Arial-BoldItalicMT", "Helvetica-BoldOblique"});
//Arial Narrow - not actually one of fonts but very common so added
setSubstitutedFontAliases("arial Narrow", new String[]{"ArialNarrow"}); //called ArialNarrow in PDF, needs to be arialn for Windows
setSubstitutedFontAliases("arial Narrow italic", new String[]{"ArialNarrow-italic"});
setSubstitutedFontAliases("arial Narrow bold", new String[]{"ArialNarrow-bold", "ArialNarrow,Bold"});
setSubstitutedFontAliases("arial Narrow bold italic", new String[]{"ArialNarrow-bolditalic"});
//Times/TimesNewRoman
setSubstitutedFontAliases("times new roman bold", new String[]{"Times-Bold", "TimesNewRoman,Bold", "TimesNewRomanPS-BoldMT"});
setSubstitutedFontAliases("times new roman bold italic", new String[]{"Times-BoldItalic", "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalicMT"});
setSubstitutedFontAliases("times new roman italic", new String[]{"Times-Italic", "TimesNewRoman,Italic", "TimesNewRomanPS-ItalicMT"});
setSubstitutedFontAliases("times new roman", new String[]{"Times-Roman", "TimesNewRoman", "Times", "TimesNewRomanPSMT"});
setSubstitutedFontAliases("wingdings", new String[]{"ZapfDingbats", "ZaDb"});
//default at present for others as well
} else { //if(PdfDecoder.isRunningOnWindows){
//Courier (CourierNew)
setSubstitutedFontAliases("Couri", new String[]{"Courier-Oblique", "CourierNew,italic", "CourierStd-Oblique", "CourierNewPS-ItalicMT"});
setSubstitutedFontAliases("Courbd", new String[]{"Courier-Bold", "CourierNew,Bold", "CourierStd-Bold", "CourierNewPS-BoldMT"});
setSubstitutedFontAliases("Courbi", new String[]{"Courier-BoldOblique", "CourierNew-BoldOblique", "CourierStd-BoldOblique", "CourierNewPS-BoldItalicMT"});
setSubstitutedFontAliases("Cour", new String[]{"CourierNew", "Courier", "CourierStd", "CourierNewPSMT", "CourierNewPSMT"});
//Helvetica (Arial)
setSubstitutedFontAliases("arial", new String[]{"Helvetica", "arialmt", "ArialNarrow"});
setSubstitutedFontAliases("ariali", new String[]{"arial-italic", "arial-italicmt", "Helvetica-Oblique", "Arial,Italic", "ArialNarrow-Italic"});
setSubstitutedFontAliases("arialbd", new String[]{"arial-boldmt,bold", "arial-boldmt", "Helvetica-Bold", "Arial,bold", "arial bold", "ArialNarrow-Bold"});
setSubstitutedFontAliases("arialbi", new String[]{"Arial-BoldItalicMT", "Helvetica-BoldOblique", "ArialNarrow-BoldItalic"});
//Font doesn't work in generic Windows 8 (commented out by Mark) 14/11/2013
//Arial Narrow - not actually one of fonts but very common so added
//setSubstitutedFontAliases("arialn",new String[]{"ArialNarrow",}); //called ArialNarrow in PDF, needs to be arialn for Windows
//setSubstitutedFontAliases("arialni",new String[]{"ArialNarrow-italic"});
//setSubstitutedFontAliases("arialnb",new String[]{"ArialNarrow-bold","ArialNarrow,Bold"});
//setSubstitutedFontAliases("arialnbi",new String[]{"ArialNarrow-bolditalic"});
//Times/TimesNewRoman
setSubstitutedFontAliases("timesbd", new String[]{"Times-Bold", "TimesNewRoman,Bold", "TimesNewRomanPS-BoldMT"});
setSubstitutedFontAliases("timesi", new String[]{"Times-BoldItalic", "TimesNewRoman,BoldItalic"});
setSubstitutedFontAliases("timesbi", new String[]{"Times-Italic", "TimesNewRoman,Italic"});
setSubstitutedFontAliases("times", new String[]{"Times-Roman", "TimesNewRoman", "Times", "TimesNewRomanPSMT"});
setSubstitutedFontAliases("wingdings", new String[]{"ZapfDingbats", "ZaDb"});
// setSubstitutedFontAliases("wingding",new String[] {"ZapfDingbats","ZaDb","wingdings"});
}
setSubstitutedFontAliases("AdobeSongStd-Light", new String[]{"STSong-Light"});
// setSubstitutedFontAliases("AdobeSongStd-Light",new String[] {"MHei-Medium"});
// setSubstitutedFontAliases("AdobeSongStd-Light",new String[] {"MSung-Light"});
// setSubstitutedFontAliases("AdobeSongStd-Light",new String[] {"HeiseiKakuGo-W5"});
// setSubstitutedFontAliases("AdobeSongStd-Light",new String[] {"HeiseiMin-W3"});
// setSubstitutedFontAliases("AdobeSongStd-Light",new String[] {"HYGoThic-Medium"});
// setSubstitutedFontAliases("AdobeSongStd-Light",new String[] {"HYSMyeongJo-Medium"});
//set general mappings for non-embedded fonts (assumes names the same) - do first time used
if (!fontsSet) {
fontsSet = true;
//now in public static variable so can be altered
setFontDirs(defaultFontDirs);
/*check for any windows fonts lurking in Adobe folders as well*/
if (DecoderOptions.isRunningOnWindows) {
final File adobeFonts = new File("C:\\Program Files\\Adobe\\");
if (adobeFonts.exists()) {
final String[] subdirs = adobeFonts.list();
for (final String path : subdirs) {
final String adobePath = "C:\\Program Files\\Adobe\\" + path + "\\Resource\\CIDFont";
final File testAdobe = new File(adobePath);
//add if it exists
if (testAdobe.exists()) {
addTTDir(adobePath, "");
}
}
}
}
}
}
/**
* takes a String[] of font directories and adds to substitution - Can just
* be called for each JVM - Should be called before file opened - this
* offers an alternative to the call -DFontDirs - Passing a null value
* flushes all settings
*
* @return String which will be null or list of directories it could not
* find
*/
public static String setFontDirs(final String[] fontDirs) {
String failed = null;
checkFontTablesInitialised();
try {
if (fontDirs == null) { // idiot safety test
LogWriter.writeLog("Null font parameter passed");
fontSubstitutionAliasTable.clear();
fontSubstitutionLocation.clear();
fontSubstitutionTable.clear();
fontSubstitutionFontID.clear();
fontPossDuplicates.clear();
fontPropertiesTable.clear();
fontPropertiesTableType.clear();
fontPropertiesTablePath.clear();
fontsSet = false;
} else {
for (final String fontDir : fontDirs) {
String fontPath = fontDir;
// allow for 'wrong' separator
if (!fontPath.endsWith("/") && !fontPath.endsWith("\\")) {
fontPath += separator;
}
failed = addTTDir(fontPath, failed);
}
}
} catch (final Exception e) {
LogWriter.writeLog("Unable to run setFontDirs " + e.getMessage());
}
return failed;
}
private static void checkFontTablesInitialised() {
if (FontMappings.fontSubstitutionTable == null) {
fontSubstitutionTable = new ConcurrentHashMap();
fontSubstitutionFontID = new ConcurrentHashMap();
fontPossDuplicates = new ConcurrentHashMap();
fontPropertiesTable = new ConcurrentHashMap();
fontPropertiesTableType = new ConcurrentHashMap();
fontPropertiesTablePath = new ConcurrentHashMap();
}
}
/**
* This routine allows the user to add truetype,
* type1 or type1C fonts which will be used to disalay the fonts in PDF
* rendering and substitution as if the fonts were embedded in the PDF
* This is very useful for clients looking to keep down the size of PDFs
* transmitted and control display quality -
*
* Thanks to Peter for the idea/code -
*
* How to set it up -
*
* JPedal will look for the existence of the directory fontPath (ie
* com/myCompany/Fonts) -
*
* If this exists, Jpedal will look for 3 possible directories (tt,t1c,t1)
* and make a note of any fonts if these directories exist -
*
* When fonts are resolved, this option will be tested first and if a font
* if found, it will be used to display the font (the effect will be the
* same as if the font was embedded) -
*
* If the enforceMapping is true, JPedal assumes there must be a match and
* will throw a PdfFontException -
*
* Otherwise Jpedal will look in the java font path for a match or
* approximate with Lucida -
*
* The Format is defined as follows: -
*
* fontname = filename
*
* Type1/Type1C Font names exclude any prefix so /OEGPNB+FGHeavyItalic is
* resolved to FGHeavyItalic -
*
* Each font have the same name as the font it replaces (so Arial will
* require a font file such as Arial.ttf) and it must be unique (there
* cannot be an Arial font in each sub-directory) -
*
* So to use this functionality, place the fonts in a jar or add to the
* JPedal jar and call this method after instancing PdfDecoder - JPedal will
* do the rest
*
* @param fontPath -
* root directory for fonts
* @param enforceMapping -
* tell JPedal if all fonts should be in this directory
* @return flag (true if fonts added)
*/
public static boolean addSubstituteFonts(String fontPath, final boolean enforceMapping) {
boolean hasFonts = false;
InputStream in = null, dir = null;
try {
final String[] dirs = {"tt", "t1c", "t1"};
final String[] types = {"/TrueType", "/Type1C", "/Type1"};
// check fontpath ends with separator - we may need to check this.
// if((!fontPath.endsWith("/"))&(!fontPath.endsWith("\\")))
// fontPath=fontPath=fontPath+separator;
enforceFontSubstitution = enforceMapping;
final ClassLoader loader = FontMappings.class.getClass().getClassLoader();
// see if root dir exists
dir = loader.getResourceAsStream(fontPath);
LogWriter.writeLog("Looking for root " + fontPath);
// if it does, look for sub-directories
if (in != null) {
LogWriter.writeLog("Adding fonts fonts found in tt,t1c,t1 sub-directories of " + fontPath);
hasFonts = true;
for (int i = 0; i < dirs.length; i++) {
if (!fontPath.endsWith("/")) {
fontPath += '/';
}
final String path = fontPath + dirs[i] + '/';
// see if it exists
in = loader.getResourceAsStream(path);
// if it does read its contents and store
if (in != null) {
System.out.println("Found " + path + ' ' + in);
final ArrayList fonts;
try {
// works with IDE or jar
if (in instanceof ByteArrayInputStream) {
fonts = readIndirectValues(in);
} else {
fonts = getDirectoryMatches(path);
}
String value, fontName;
// now assign the fonts
for (final String font : fonts) {
value = font;
if (value == null) {
break;
}
final int pointer = value.indexOf('.');
if (pointer == -1) {
fontName = value.toLowerCase();
} else {
fontName = value.substring(0, pointer).toLowerCase();
}
fontSubstitutionTable.put(fontName, types[i]);
fontSubstitutionLocation.put(fontName, path + value);
}
} catch (final Exception e) {
LogWriter.writeLog("Exception " + e + " reading substitute fonts");
} finally {
if (in != null) {
try {
in.close();
} catch (final IOException e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
}
}
}
}
} else {
LogWriter.writeLog("No fonts found at " + fontPath);
}
} catch (final Exception e) {
LogWriter.writeLog("Exception adding substitute fonts " + e.getMessage());
} finally { //close streams if open
if (in != null) {
try {
in.close();
} catch (final IOException e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
}
if (dir != null) {
try {
dir.close();
} catch (final IOException e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
}
}
return hasFonts;
}
/**
* method to add a single file to the PDF renderer
*
* @param currentFont - actual font name we use to identify
* @param fontPath - full path to font file used for this font
*/
public static void addFontFile(final String currentFont, String fontPath) {
checkFontTablesInitialised();
//add separator if needed
if (fontPath != null && !fontPath.endsWith("/") && !fontPath.endsWith("\\")) {
fontPath += separator;
}
final String name = currentFont.toLowerCase();
//decide font type
final int type = StandardFonts.getFontType(name);
InputStream in = null;
if (type != StandardFonts.FONT_UNSUPPORTED && new File(fontPath + currentFont).exists()) {
// see if root dir exists
boolean failed = false;
try {
in = new FileInputStream(fontPath + currentFont);
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
failed = true;
} catch (final Error err) {
LogWriter.writeLog("Error: " + err.getMessage());
failed = true;
}
// if it does, add
if (!failed) {
final String fontName;
//name from file
final int pointer = currentFont.indexOf('.');
if (pointer == -1) {
fontName = currentFont.toLowerCase();
} else {
fontName = currentFont.substring(0, pointer).toLowerCase();
}
//choose filename or over-ride if OpenType
if (fontSubstitutionMode == PdfDecoderInt.SUBSTITUTE_FONT_USING_FILE_NAME || type == StandardFonts.OPENTYPE) {
if (type == StandardFonts.TYPE1) {
fontSubstitutionTable.put(fontName, "/Type1");
} else {
//TT or OTF
fontSubstitutionTable.put(fontName, "/TrueType");
}
fontSubstitutionLocation.put(fontName, fontPath + currentFont);
//store details under file
fontPropertiesTableType.put(fontName, type);
fontPropertiesTablePath.put(fontName, fontPath + currentFont);
} else if (type == StandardFonts.TRUETYPE_COLLECTION || type == StandardFonts.TRUETYPE) {
if (fontSubstitutionMode == PdfDecoderInt.SUBSTITUTE_FONT_USING_POSTSCRIPT_NAME_USE_FAMILY_NAME_IF_DUPLICATES) {
//get both possible values
String[] postscriptNames = null;
try {
postscriptNames = StandardFonts.readNamesFromFont(type, fontPath + currentFont, PdfDecoderInt.SUBSTITUTE_FONT_USING_POSTSCRIPT_NAME);
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
String[] familyNames = null;
try {
familyNames = StandardFonts.readNamesFromFont(type, fontPath + currentFont, PdfDecoderInt.SUBSTITUTE_FONT_USING_FAMILY_NAME);
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
int fontCount = 0;
if (postscriptNames != null) {
fontCount = postscriptNames.length;
}
for (int ii = 0; ii < fontCount; ii++) {
//allow for null and use font name
if (postscriptNames[ii] == null) {
postscriptNames[ii] = Strip.stripAllSpaces(fontName);
}
//allow for null and use font name
if (familyNames[ii] == null) {
familyNames[ii] = Strip.stripAllSpaces(fontName);
}
final String fontSubValue = fontSubstitutionTable.get(postscriptNames[ii]);
final String possDuplicate = fontPossDuplicates.get(postscriptNames[ii]);
if (fontSubValue == null && possDuplicate == null) { //first time so store and track
//System.out.println("store "+postscriptNames[ii]);
fontSubstitutionTable.put(postscriptNames[ii], "/TrueType");
fontSubstitutionLocation.put(postscriptNames[ii], fontPath + currentFont);
fontSubstitutionFontID.put(postscriptNames[ii], ii);
//and remember in case we need to switch
fontPossDuplicates.put(postscriptNames[ii], familyNames[ii]);
} else if (!familyNames[ii].equals(postscriptNames[ii])) {
//if no duplicates,add to mappings with POSTSCRIPT and log filename
//both lists should be in same order and name
//else save as FAMILY_NAME
fontSubstitutionTable.put(postscriptNames[ii], "/TrueType");
fontSubstitutionLocation.put(postscriptNames[ii], fontPath + currentFont);
fontSubstitutionFontID.put(postscriptNames[ii], ii);
//store details under file
fontPropertiesTableType.put(postscriptNames[ii], type);
fontPropertiesTablePath.put(postscriptNames[ii], fontPath + currentFont);
//if second find change first match
if (!possDuplicate.equals("DONE")) {
//System.out.println("replace "+postscriptNames[ii]+" "+familyNames[ii]);
//flag as done
fontPossDuplicates.put(postscriptNames[ii], "DONE");
//swap over
fontSubstitutionTable.remove(postscriptNames[ii]);
fontSubstitutionTable.put(familyNames[ii], "/TrueType");
final String font = fontSubstitutionLocation.get(postscriptNames[ii]);
fontSubstitutionLocation.remove(postscriptNames[ii]);
fontSubstitutionLocation.put(familyNames[ii], font);
fontSubstitutionFontID.remove(postscriptNames[ii]);
fontSubstitutionFontID.put(familyNames[ii], ii);
//store details under file
fontPropertiesTablePath.remove(familyNames[ii]);
fontPropertiesTableType.remove(familyNames[ii]);
fontPropertiesTableType.put(familyNames[ii], type);
fontPropertiesTablePath.put(familyNames[ii], fontPath + currentFont);
}
}
}
} else { //easy version
//read 1 or more font mappings from file
String[] fontNames = null;
try {
fontNames = StandardFonts.readNamesFromFont(type, fontPath + currentFont, fontSubstitutionMode);
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
if (fontNames != null) {
for (int i = 0; i < fontNames.length; i++) {
//allow for null and use font name
if (fontNames[i] == null) {
fontNames[i] = Strip.stripAllSpaces(fontName);
}
fontSubstitutionTable.put(fontNames[i], "/TrueType");
fontSubstitutionLocation.put(fontNames[i], fontPath + currentFont);
fontSubstitutionFontID.put(fontNames[i], i);
//store details under file
fontPropertiesTableType.put(fontNames[i], type);
fontPropertiesTablePath.put(fontNames[i], fontPath + currentFont);
}
}
}
} else if (type == StandardFonts.TYPE1) { // || type == StandardFonts.OPENTYPE){ //type1
//read 1 or more font mappings from file
String[] fontNames = null;
try {
fontNames = StandardFonts.readNamesFromFont(type, fontPath + currentFont, fontSubstitutionMode);
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
if (fontNames != null) {
for (int i = 0; i < fontNames.length; i++) {
//allow for null and use font name
if (fontNames[i] == null) {
fontNames[i] = Strip.stripAllSpaces(fontName);
}
//System.out.println("font="+fontNames[i]);
fontSubstitutionTable.put(fontNames[i], "/Type1");
fontSubstitutionLocation.put(fontNames[i], fontPath + currentFont);
fontSubstitutionFontID.put(fontNames[i], i);
//store details under file
fontPropertiesTableType.put(fontNames[i], type);
fontPropertiesTablePath.put(fontNames[i], fontPath + currentFont);
}
}
}
} else {
LogWriter.writeLog("No fonts found at " + fontPath);
}
}
//finally close
if (in != null) {
try {
in.close();
} catch (final IOException e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
}
}
private static ArrayList getDirectoryMatches(String sDirectoryName) throws IOException {
sDirectoryName = sDirectoryName.replaceAll("\\.", "/");
final URL u = Thread.currentThread().getContextClassLoader().getResource(
sDirectoryName);
final ArrayList retValue = new ArrayList(0);
String s = u.toString();
System.out.println("scanning " + s);
if (s.startsWith("jar:") && s.endsWith(sDirectoryName)) {
final int idx = s.lastIndexOf(sDirectoryName);
s = s.substring(0, idx); // isolate entry name
System.out.println("entry= " + s);
final URL url = new URL(s);
// Get the jar file
final JarURLConnection conn = (JarURLConnection) url.openConnection();
final JarFile jar = conn.getJarFile();
for (final Enumeration e = jar.entries(); e.hasMoreElements(); ) {
final JarEntry entry = e.nextElement();
if ((!entry.isDirectory())
&& (entry.getName().startsWith(sDirectoryName))) { // this
// is how you can match
// to find your fonts.
// System.out.println("Found a match!");
final String fontName = entry.getName();
final int i = fontName.lastIndexOf('/');
retValue.add(fontName.substring(i + 1));
}
}
}
return retValue;
}
/**
* read values from the classpath
*/
private static ArrayList readIndirectValues(final InputStream in)
throws IOException {
final ArrayList fonts;
final BufferedReader inpStream = new BufferedReader(new InputStreamReader(in));
fonts = new ArrayList(0);
while (true) {
final String nextValue = inpStream.readLine();
if (nextValue == null) {
break;
}
fonts.add(nextValue);
}
inpStream.close();
return fonts;
}
/**
* set the font used for default from Java fonts on system - Java fonts are
* case sensitive, but JPedal resolves this internally, so you could use
* Webdings, webdings or webDings for Java font Webdings - checks if it is a
* valid Java font (otherwise it will default to Lucida anyway)
*/
public static void setDefaultDisplayFont(final String fontName) throws PdfFontException {
boolean isFontInstalled = false;
// get list of fonts and see if installed
final String[] fontList = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
final int count = fontList.length;
for (int i = 0; i < count; i++) {
if (fontList[i].equalsIgnoreCase(fontName.toLowerCase())) {
isFontInstalled = true;
defaultFont = fontList[i];
i = count;
}
}
if (!isFontInstalled) {
throw new PdfFontException("Font " + fontName + " is not available.");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy