package com.adobe.dp.epub.web.font; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Hashtable; import java.util.Iterator; import com.adobe.dp.epub.web.util.Initializer; import com.adobe.dp.otf.FileFontInputStream; import com.adobe.dp.otf.FontInputStream; import com.adobe.dp.otf.FontLocator; import com.adobe.dp.otf.FontProperties; import com.adobe.dp.otf.FontPropertyConstants; import com.adobe.dp.otf.OpenTypeFont; public class SharedFontSet { static private SharedFontSet instance = new SharedFontSet(); private File fontFolder; private Hashtable fontNameToKeyMap = new Hashtable(); class SharedFontLocator extends FontLocator { Hashtable keyToName; FontLocator base; SharedFontLocator(Hashtable keyToName, FontLocator base) { this.keyToName = keyToName; this.base = base; } FontProperties substitute(FontProperties key) { if (key.getStyle() == FontPropertyConstants.STYLE_ITALIC && key.getFamilyName().equals("Tahoma")) { // workaround: Tahoma does not have italic, replace with Verdana key = new FontProperties("Verdana", key.getWeight(), key.getStyle()); } return key; } String getFontSource(FontProperties key) { key = substitute(key); String name = (String) keyToName.get(key); if (name == null) { // try a bit bolder... FontProperties key1 = new FontProperties(key.getFamilyName(), key.getWeight() + 100, key.getStyle()); name = (String) keyToName.get(key1); if (name == null) { // ...and a bit lighter key1 = new FontProperties(key.getFamilyName(), key.getWeight() - 100, key.getStyle()); name = (String) keyToName.get(key); if (name == null) return null; } } return name; } public FontInputStream locateFont(FontProperties key) throws IOException { String src = getFontSource(key); if (src == null) { if (base == null) return null; return base.locateFont(key); } File file = new File(fontFolder, src); return new FileFontInputStream(file); } public boolean hasFont(FontProperties key) { return getFontSource(key) != null || (base != null && base.hasFont(key)); } } private SharedFontSet() { File home = Initializer.getEPubGenHome(); fontFolder = new File(home, "uploadedFonts"); fontFolder.mkdirs(); String[] list = fontFolder.list(); if (list != null) { for (int i = 0; i < list.length; i++) if (list[i].endsWith("=")) { loadFont(list[i]); } } } private boolean loadFont(String name) { File fontFile = new File(fontFolder, name); FontProperties key = loadFont(fontFile); if (key == null) return false; fontNameToKeyMap.put(name, key); return true; } private FontProperties loadFont(File fontFile) { try { if (!fontFile.exists()) return null; FontInputStream fin = new FileFontInputStream(fontFile); OpenTypeFont font = new OpenTypeFont(fin, true); fin.close(); if (!font.canEmbedForReading()) return null; return new FontProperties(font.getFamilyName(), font.getWeight(), font.getStyle()); } catch (Exception e) { e.printStackTrace(); return null; } } public FontProperties getFontProperties(String sha1str) { FontProperties prop = (FontProperties) fontNameToKeyMap.get(sha1str); if (prop == null) { loadFont(sha1str); prop = (FontProperties) fontNameToKeyMap.get(sha1str); } return prop; } public boolean addFont(String sha1str, InputStream in) { try { if (getFontProperties(sha1str) != null) { in.close(); return false; } File fontFile = File.createTempFile("fnt", ".tmp", fontFolder); FileOutputStream out = new FileOutputStream(fontFile); byte[] buffer = new byte[4096]; int len; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } out.close(); in.close(); FontProperties prop = loadFont(fontFile); if (prop == null) { fontFile.delete(); return false; } fontNameToKeyMap.put(sha1str, prop); File dest = new File(fontFolder, sha1str); if (!fontFile.renameTo(dest)) { fontFile.delete(); return false; } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public FontLocator getFontLocator(FontCookieSet cookies, FontLocator base) { Iterator it = cookies.hashes(); Hashtable fontSet = new Hashtable(); while (it.hasNext()) { String hash = (String) it.next(); FontProperties key = (FontProperties) fontNameToKeyMap.get(hash); if (key != null) { fontSet.put(key, hash); } } return new SharedFontLocator(fontSet, base); } public static SharedFontSet getInstance() { return instance; } }