diff options
Diffstat (limited to 'pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java')
-rw-r--r-- | pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java new file mode 100644 index 00000000..8b46d56a --- /dev/null +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java @@ -0,0 +1,299 @@ +/******************************************************************************* + * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright> + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.fontbox.ttf.NameRecord; +import org.apache.fontbox.ttf.NamingTable; +import org.apache.fontbox.ttf.TTFParser; +import org.apache.fontbox.ttf.TrueTypeFont; +import org.apache.pdfbox.cos.COSBase; +import org.apache.pdfbox.cos.COSDictionary; +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.cos.COSObject; +import org.apache.pdfbox.pdmodel.font.PDFont; +import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont; +import org.apache.pdfbox.pdmodel.font.PDType1Font; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.settings.ISettings; +import at.gv.egiz.pdfas.lib.impl.pdfbox2.PDFBOXObject; + +public class PDFBoxFont { + + private static final Logger logger = LoggerFactory + .getLogger(PDFBoxFont.class); + + private static final String HELVETICA = "HELVETICA"; + private static final String COURIER = "COURIER"; + private static final String TIMES_ROMAN = "TIMES_ROMAN"; + private static final String BOLD = "BOLD"; + private static final String NORMAL = "NORMAL"; + private static final String ITALIC = "ITALIC"; + private static final String SEP = ":"; + + public static PDFont defaultFont = PDType1Font.HELVETICA; + public static float defaultFontSize = 8; + + private static Map<String, PDFont> fontStyleMap = new HashMap<String, PDFont>(); + + private static Map<String, FontInfoCache> fontInfoCache = new HashMap<String, FontInfoCache>(); + + static { + fontStyleMap.put(HELVETICA + SEP + NORMAL, PDType1Font.HELVETICA); + fontStyleMap.put(HELVETICA + SEP + BOLD, PDType1Font.HELVETICA_BOLD); + + fontStyleMap.put(COURIER + SEP + NORMAL, PDType1Font.COURIER); + fontStyleMap.put(COURIER + SEP + BOLD, PDType1Font.COURIER_BOLD); + + fontStyleMap.put(TIMES_ROMAN + SEP + NORMAL, PDType1Font.TIMES_ROMAN); + fontStyleMap.put(TIMES_ROMAN + SEP + BOLD, PDType1Font.TIMES_BOLD); + fontStyleMap.put(TIMES_ROMAN + SEP + ITALIC, PDType1Font.TIMES_ITALIC); + } + + public static void showBuildinFonts() { + Iterator<String> it = fontStyleMap.keySet().iterator(); + logger.info("Available Fonts:"); + while (it.hasNext()) { + logger.info(it.next()); + } + } + + PDFont font; + PDFont cachedfont = null; + float fontSize; + String fontDesc; + String ttfFontDesc; + ISettings settings; + + private FontInfoCache getFontInfo(String pathName) { + synchronized (fontInfoCache) { + + if (fontInfoCache.containsKey(pathName)) { + return fontInfoCache.get(pathName); + } else { + try { + String fontNameToLoad = null; + String fontFamilyToLoad = null; + InputStream ttfData = new FileInputStream(pathName); + try { + TrueTypeFont ttf = null; + TTFParser parser = new TTFParser(); + ttf = parser.parse(ttfData); + NamingTable naming = ttf.getNaming(); + List<NameRecord> records = naming.getNameRecords(); + for (int i = 0; i < records.size(); i++) { + NameRecord nr = records.get(i); + if (nr.getNameId() == NameRecord.NAME_POSTSCRIPT_NAME) { + fontNameToLoad = nr.getString(); + } else if (nr.getNameId() == NameRecord.NAME_FONT_FAMILY_NAME) { + fontFamilyToLoad = nr.getString(); + } + } + } finally { + ttfData.close(); + } + FontInfoCache fontInfo = new FontInfoCache(); + fontInfo.filename = pathName; + fontInfo.fontFamily = fontFamilyToLoad; + fontInfo.fontName = fontNameToLoad; + fontInfo.fontPath = pathName; + fontInfoCache.put(pathName, fontInfo); + return fontInfo; + } catch (Throwable e) { + logger.warn("Failed to generate FontInfo from file: {}", pathName); + } + return null; + } + } + } + + private PDFont findCachedFont(PDFBOXObject pdfObject, FontInfoCache fontInfo) { + try { + if(pdfObject.getFontCache().containsKey(fontInfo.fontPath)) { + return pdfObject.getFontCache().get(fontInfo.fontPath); + } + + List<COSObject> cosObjects = pdfObject.getDocument().getDocument().getObjectsByType( + COSName.FONT); + + //COSName cosFontName = COSName.getPDFName(fontInfo.fontName); + //COSName cosFontFamily = COSName.getPDFName(fontInfo.fontFamily); + + Iterator<COSObject> cosObjectIt = cosObjects.iterator(); + + while (cosObjectIt.hasNext()) { + COSObject cosObject = cosObjectIt.next(); + COSDictionary baseObject = (COSDictionary) cosObject + .getObject(); + if (baseObject instanceof COSDictionary) { + COSDictionary fontDictionary = (COSDictionary) baseObject; + COSBase subType = cosObject.getItem(COSName.SUBTYPE); + COSDictionary fontDescriptor = (COSDictionary)cosObject.getDictionaryObject(COSName.FONT_DESC); + String fontName = fontDescriptor.getNameAsString(COSName.FONT_NAME); + String fontFamily = fontDescriptor.getNameAsString(COSName.FONT_FAMILY); + logger.debug("Checking Font {} - {}", fontFamily, fontName); + if (COSName.TRUE_TYPE.equals(subType)) { + if (fontInfo.fontName != null && fontInfo.fontName.equals(fontName) && + fontInfo.fontFamily != null && fontInfo.fontFamily.equals(fontFamily)) { + // Found it! :) + logger.info("Found Font {}", fontInfo.fontName); + return new PDTrueTypeFont(fontDictionary); + } else { + logger.debug("Font not found: {} is {}", + fontInfo.fontName, fontName); + } + } else { + logger.debug("Font not a TTF"); + } + } else { + logger.debug("Font not a COSDictionary"); + } + } + } catch (Throwable e) { + logger.info("Failed to find existing TTF fonts!", e); + } + return null; + } + + private PDFont generateTTF(String fonttype, PDFBOXObject pdfObject) + throws IOException { + /*boolean cacheNow = true; + if (pdfObject == null) { + if (this.doc == null) { + this.doc = new PDDocument(); + } + doc = this.doc; + } else { + cacheNow = true; + }*/ + ttfFontDesc = fonttype; + String fontName = fonttype.replaceFirst("TTF:", ""); + String fontPath = this.settings.getWorkingDirectory() + File.separator + + "fonts" + File.separator + fontName; + + logger.debug("Font from: \"" + fontPath + "\"."); + + if(fontStyleMap.containsKey(fontPath)) { + return fontStyleMap.get(fontPath); + } + + FontInfoCache fontInfo = getFontInfo(fontPath); + + if(fontInfo != null) { + + PDFont font = findCachedFont(pdfObject, fontInfo); + + if (font != null) { + return font; + } + } + + logger.debug("Instantiating font."); + + //if (cacheNow) { + cachedfont = PDTrueTypeFont.loadTTF(pdfObject.getDocument(), new File(fontPath)); + + fontStyleMap.put(fontPath, cachedfont); + return cachedfont; + //} else { + // return PDTrueTypeFont.loadTTF(doc, fontPath); + //} + + } + + private PDFont generateFont(String fonttype, String fontder, + PDFBOXObject pdfObject) throws IOException { + if (fonttype.startsWith("TTF:")) { + // Load TTF Font + return generateTTF(fonttype, pdfObject); + } else { + if (fontder == null) { + fontder = NORMAL; + } + + String fontDesc = fonttype + SEP + fontder; + PDFont font = fontStyleMap.get(fontDesc); + if (font == null) { + showBuildinFonts(); + throw new IOException("Invalid font descriptor"); + } + return font; + } + } + + private void setFont(String desc, PDFBOXObject pdfObject) + throws IOException { + String[] fontArr = desc.split(","); + + if (fontArr.length == 3) { + font = generateFont(fontArr[0], fontArr[2], pdfObject); + fontSize = Float.parseFloat(fontArr[1]); + } else if (fontArr.length == 2 && fontArr[0].startsWith("TTF:")) { + font = generateFont(fontArr[0], null, pdfObject); + fontSize = Float.parseFloat(fontArr[1]); + } else { + logger.warn( + "Using default font because: {} is not a valid font descriptor.", + desc); + this.font = defaultFont; + this.fontSize = defaultFontSize; + } + + } + + public PDFBoxFont(String fontDesc, ISettings settings, + PDFBOXObject pdfObject) throws IOException { + this.settings = settings; + this.fontDesc = fontDesc; + logger.debug("Creating Font: " + fontDesc); + this.setFont(fontDesc, pdfObject); + } + + public PDFont getFont(/*PDFBOXObject pdfObject*/) throws IOException { + if (cachedfont != null) { + return cachedfont; + } + return font; + /* + if (font instanceof PDTrueTypeFont && pdfObject != null) { + return generateTTF(ttfFontDesc, pdfObject); + } else { + return font; + }*/ + } + + public float getFontSize() { + return fontSize; + } +} |