aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-pdfbox
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-pdfbox')
-rw-r--r--pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/FontInfoCache.java7
-rw-r--r--pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxFont.java227
-rw-r--r--pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java27
-rw-r--r--pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java4
-rw-r--r--pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java9
5 files changed, 207 insertions, 67 deletions
diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/FontInfoCache.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/FontInfoCache.java
new file mode 100644
index 00000000..10a5c9f8
--- /dev/null
+++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/FontInfoCache.java
@@ -0,0 +1,7 @@
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox;
+
+public class FontInfoCache {
+ String filename;
+ String fontName;
+ String fontFamily;
+}
diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxFont.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxFont.java
index 8fcca9b7..fdbf40e2 100644
--- a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxFont.java
+++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxFont.java
@@ -24,11 +24,22 @@
package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox;
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.PDDocument;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
@@ -39,10 +50,10 @@ import org.slf4j.LoggerFactory;
import at.gv.egiz.pdfas.common.settings.ISettings;
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";
@@ -50,32 +61,34 @@ public class PDFBoxFont {
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);
+ 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()) {
+ while (it.hasNext()) {
logger.info(it.next());
}
}
-
+
PDFont font;
PDFont cachedfont = null;
float fontSize;
@@ -83,11 +96,97 @@ public class PDFBoxFont {
String ttfFontDesc;
PDDocument doc;
ISettings settings;
-
- private PDFont generateTTF(String fonttype, PDDocument doc) throws IOException {
+
+ 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.parseTTF(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;
+ fontInfoCache.put(pathName, fontInfo);
+ return fontInfo;
+ } catch (Throwable e) {
+ logger.warn("Failed to generate FontInfo from file: {}", pathName);
+ }
+ return null;
+ }
+ }
+ }
+
+ private PDFont findCachedFont(PDDocument doc, FontInfoCache fontInfo) {
+ try {
+ List<COSObject> cosObjects = doc.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, PDDocument doc)
+ throws IOException {
boolean cacheNow = false;
- if(doc == null) {
- if(this.doc == null) {
+ if (doc == null) {
+ if (this.doc == null) {
this.doc = new PDDocument();
}
doc = this.doc;
@@ -96,73 +195,97 @@ public class PDFBoxFont {
}
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(doc, fontInfo);
+
+ if (font != null) {
+ return font;
+ }
+ }
logger.debug("Instantiating font.");
- String fontPath = this.settings.getWorkingDirectory() + File.separator + "fonts" + File.separator + fontName;
- logger.debug("Instantiating \"" + fontPath + "\".");
-
- if(cacheNow) {
- cachedfont = PDTrueTypeFont.loadTTF(doc, fontPath);
- return cachedfont;
- } else {
- return PDTrueTypeFont.loadTTF(doc, fontPath);
- }
+
+ //if (cacheNow) {
+ cachedfont = PDTrueTypeFont.loadTTF(doc, fontPath);
+ fontStyleMap.put(fontPath, cachedfont);
+ return cachedfont;
+ //} else {
+ // return PDTrueTypeFont.loadTTF(doc, fontPath);
+ //}
+
}
-
- private PDFont generateFont(String fonttype, String fontder) throws IOException {
- if(fonttype.startsWith("TTF:")) {
+
+ private PDFont generateFont(String fonttype, String fontder,
+ PDDocument originalDoc) throws IOException {
+ if (fonttype.startsWith("TTF:")) {
// Load TTF Font
- return generateTTF(fonttype, null);
+ return generateTTF(fonttype, originalDoc);
} else {
- if(fontder == null) {
+ if (fontder == null) {
fontder = NORMAL;
}
-
+
String fontDesc = fonttype + SEP + fontder;
PDFont font = fontStyleMap.get(fontDesc);
- if(font == null) {
+ if (font == null) {
showBuildinFonts();
throw new IOException("Invalid font descriptor");
}
return font;
}
}
-
- private void setFont(String desc) throws IOException {
+
+ private void setFont(String desc, PDDocument originalDoc)
+ throws IOException {
String[] fontArr = desc.split(",");
-
- if(fontArr.length == 3) {
- font = generateFont(fontArr[0], fontArr[2]);
+
+ if (fontArr.length == 3) {
+ font = generateFont(fontArr[0], fontArr[2], originalDoc);
fontSize = Float.parseFloat(fontArr[1]);
- } else if(fontArr.length == 2 && fontArr[0].startsWith("TTF:")) {
- font = generateFont(fontArr[0], null);
+ } else if (fontArr.length == 2 && fontArr[0].startsWith("TTF:")) {
+ font = generateFont(fontArr[0], null, originalDoc);
fontSize = Float.parseFloat(fontArr[1]);
} else {
- logger.warn("Using default font because: {} is not a valid font descriptor.", desc);
+ 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) throws IOException {
+ public PDFBoxFont(String fontDesc, ISettings settings,
+ PDDocument originalDoc) throws IOException {
this.settings = settings;
this.fontDesc = fontDesc;
logger.debug("Creating Font: " + fontDesc);
- this.setFont(fontDesc);
+ this.setFont(fontDesc, originalDoc);
}
-
+
public PDFont getFont(PDDocument doc) throws IOException {
- if(cachedfont != null) {
+ if (cachedfont != null) {
return cachedfont;
}
- if(font instanceof PDTrueTypeFont && doc != null) {
+ if (font instanceof PDTrueTypeFont && doc != null) {
return generateTTF(ttfFontDesc, doc);
} else {
return font;
}
}
-
+
public float getFontSize() {
return fontSize;
}
diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java
index 2fec7083..22947643 100644
--- a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java
+++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java
@@ -32,6 +32,7 @@ import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
+import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,6 +68,8 @@ public class PDFBoxTable {
float[] rowHeights;
float[] colWidths;
+ PDDocument originalDoc;
+
private void normalizeContent(Table abstractTable) throws PdfAsException {
try {
int rows = abstractTable.getRows().size();
@@ -90,7 +93,7 @@ public class PDFBoxTable {
}
}
- private void initializeStyle(Table abstractTable, PDFBoxTable parent)
+ private void initializeStyle(Table abstractTable, PDFBoxTable parent, PDDocument originalDoc)
throws IOException {
this.table = abstractTable;
try {
@@ -127,7 +130,7 @@ public class PDFBoxTable {
+ abstractTable.getName());
}
- font = new PDFBoxFont(fontString, settings);
+ font = new PDFBoxFont(fontString, settings, originalDoc);
if (vfontString == null && parent != null && parent.style != null) {
vfontString = parent.style.getValueFont();
@@ -137,7 +140,7 @@ public class PDFBoxTable {
+ abstractTable.getName());
}
- valueFont = new PDFBoxFont(vfontString, settings);
+ valueFont = new PDFBoxFont(vfontString, settings, originalDoc);
}
padding = style.getPadding();
@@ -145,9 +148,10 @@ public class PDFBoxTable {
}
public PDFBoxTable(Table abstractTable, PDFBoxTable parent, float fixSize,
- ISettings settings) throws IOException, PdfAsException {
+ ISettings settings, PDDocument originalDoc) throws IOException, PdfAsException {
this.settings = settings;
- initializeStyle(abstractTable, parent);
+ this.originalDoc = originalDoc;
+ initializeStyle(abstractTable, parent, originalDoc);
float[] relativSizes = abstractTable.getColsRelativeWith();
if (relativSizes != null) {
colWidths = new float[relativSizes.length];
@@ -178,9 +182,10 @@ public class PDFBoxTable {
}
public PDFBoxTable(Table abstractTable, PDFBoxTable parent,
- ISettings settings) throws IOException, PdfAsException {
+ ISettings settings, PDDocument originalDoc) throws IOException, PdfAsException {
this.settings = settings;
- initializeStyle(abstractTable, parent);
+ this.originalDoc = originalDoc;
+ initializeStyle(abstractTable, parent, originalDoc);
this.calculateWidthHeight();
}
@@ -342,7 +347,7 @@ public class PDFBoxTable {
PDFBoxTable pdfBoxTable = null;
if (cell.getValue() instanceof Table) {
pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this,
- this.settings);
+ this.settings, originalDoc);
cell.setValue(pdfBoxTable);
} else if (cell.getValue() instanceof PDFBoxTable) {
pdfBoxTable = (PDFBoxTable) cell.getValue();
@@ -550,13 +555,13 @@ public class PDFBoxTable {
PDFBoxTable pdfBoxTable = null;
if (cell.getValue() instanceof Table) {
pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this,
- width, this.settings);
+ width, this.settings, this.originalDoc);
cell.setValue(pdfBoxTable);
} else if (cell.getValue() instanceof PDFBoxTable) {
// recreate here beacuse of fixed width!
pdfBoxTable = (PDFBoxTable) cell.getValue();
pdfBoxTable = new PDFBoxTable(pdfBoxTable.table, this, width,
- this.settings);
+ this.settings, this.originalDoc);
cell.setValue(pdfBoxTable);
} else {
throw new IOException("Failed to build PDFBox Table");
@@ -614,7 +619,7 @@ public class PDFBoxTable {
PDFBoxTable pdfBoxTable = null;
if (cell.getValue() instanceof Table) {
pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this,
- this.settings);
+ this.settings, originalDoc);
cell.setValue(pdfBoxTable);
} else if (cell.getValue() instanceof PDFBoxTable) {
pdfBoxTable = (PDFBoxTable) cell.getValue();
diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java
index 5c190883..3dd1f0a4 100644
--- a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java
+++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java
@@ -28,6 +28,7 @@ import java.io.IOException;
import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
import at.gv.egiz.pdfas.common.exceptions.PdfAsWrappedIOException;
import at.gv.egiz.pdfas.common.settings.ISettings;
+import at.gv.egiz.pdfas.lib.impl.pdfbox.PDFBOXObject;
import at.gv.egiz.pdfas.lib.impl.stamping.IPDFStamper;
import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject;
import at.gv.egiz.pdfas.lib.impl.status.PDFObject;
@@ -46,7 +47,8 @@ public class PdfBoxStamper implements IPDFStamper {
public IPDFVisualObject createVisualPDFObject(PDFObject pdf, Table table) throws IOException {
try {
- return new PdfBoxVisualObject(table, pdf.getStatus().getSettings());
+ PDFBOXObject pdfboxObject = (PDFBOXObject)pdf;
+ return new PdfBoxVisualObject(table, pdf.getStatus().getSettings(), pdfboxObject.getDocument());
} catch (PdfAsException e) {
throw new PdfAsWrappedIOException(e);
}
diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java
index ca363a8e..9fd8ed84 100644
--- a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java
+++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java
@@ -25,6 +25,7 @@ package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox;
import java.io.IOException;
+import org.apache.pdfbox.pdmodel.PDDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,11 +46,13 @@ public class PdfBoxVisualObject implements IPDFVisualObject {
private float y;
private int page;
private ISettings settings;
+ private PDDocument originalDoc;
- public PdfBoxVisualObject(Table table, ISettings settings)
+ public PdfBoxVisualObject(Table table, ISettings settings, PDDocument originalDoc)
throws IOException, PdfAsException {
this.abstractTable = table;
- this.table = new PDFBoxTable(table, null, settings);
+ this.originalDoc = originalDoc;
+ this.table = new PDFBoxTable(table, null, settings, originalDoc);
this.settings = settings;
}
@@ -59,7 +62,7 @@ public class PdfBoxVisualObject implements IPDFVisualObject {
public void fixWidth() {
try {
- table = new PDFBoxTable(abstractTable, null, this.width, settings);
+ table = new PDFBoxTable(abstractTable, null, this.width, settings, this.originalDoc);
} catch (IOException e) {
logger.warn("Failed to fix width of Table!", e);
} catch (PdfAsException e) {