CharacterWidthEstimator.java
7.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
* Decompiled with CFR 0_118.
*
* Could not load the following classes:
* com.adobe.fontengine.font.Font
* com.adobe.fontengine.font.FontData
* com.adobe.fontengine.font.FontLoadingException
* com.adobe.fontengine.font.InvalidFontException
* com.adobe.fontengine.font.PDFFontDescription
* com.adobe.fontengine.font.UnsupportedFontException
* com.adobe.internal.pdftoolkit.core.exceptions.PDFIOException
* com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidDocumentException
* com.adobe.internal.pdftoolkit.core.exceptions.PDFRuntimeException
* com.adobe.internal.pdftoolkit.core.exceptions.PDFSecurityException
*/
package com.adobe.internal.pdftoolkit.pdf.content.processor;
import com.adobe.fontengine.font.Font;
import com.adobe.fontengine.font.FontData;
import com.adobe.fontengine.font.FontLoadingException;
import com.adobe.fontengine.font.InvalidFontException;
import com.adobe.fontengine.font.PDFFontDescription;
import com.adobe.fontengine.font.UnsupportedFontException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFIOException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidDocumentException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFRuntimeException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFSecurityException;
import com.adobe.internal.pdftoolkit.pdf.content.processor.CosineDistanceComputer;
import com.adobe.internal.pdftoolkit.pdf.content.processor.FontWidthStore;
import com.adobe.internal.pdftoolkit.pdf.content.processor.PDFSimpleFontData;
import com.adobe.internal.pdftoolkit.pdf.content.processor.SimpleFontDataCache;
import com.adobe.internal.pdftoolkit.pdf.graphics.font.PDFFontSimple;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
class CharacterWidthEstimator {
private SimpleFontDataCache simpleFontDataCache;
private static ArrayList<FontWidthStore> base14FontswidthStore;
private static final String[] SERIALIZED_FONT_WIDTHS;
CharacterWidthEstimator(SimpleFontDataCache simpleFontDataCache) {
this.simpleFontDataCache = simpleFontDataCache;
}
double getCharacterWidth(int charcode, PDFFontSimple font) throws InvalidFontException, UnsupportedFontException, FontLoadingException, PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
return this.getClosestFontWidthStoreWidth(font, charcode);
}
private double getRatio(FontWidthStore actualFont, FontWidthStore closest) {
double sum = 0.0;
int count = 0;
Iterator<Integer> i$ = actualFont.getUnicodes().iterator();
while (i$.hasNext()) {
int ch = i$.next();
double baseWidth = actualFont.getWidth(ch) / 1000.0;
double refWidth = closest.getWidth(ch) / 1000.0;
if (baseWidth <= 0.0 || refWidth <= 0.0) continue;
++count;
sum += baseWidth / refWidth;
}
return sum / (double)count;
}
private double getClosestFontWidthStoreWidth(PDFFontSimple font, int charCode) throws InvalidFontException, UnsupportedFontException, FontLoadingException, PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
FontWidthStore fws = this.getFontWidthStore(font);
if (fws == null || fws.getUnicodes().size() <= 0) {
return -1.0;
}
double maxDistance = Double.NEGATIVE_INFINITY;
FontWidthStore closest = null;
CosineDistanceComputer dis = new CosineDistanceComputer();
for (FontWidthStore f : base14FontswidthStore) {
double dist = dis.getDistance(fws, f);
if (dist <= maxDistance) continue;
maxDistance = dist;
closest = f;
}
if (closest == null) {
return 0.0;
}
return closest.getWidth(charCode) * this.getRatio(fws, closest);
}
private FontWidthStore getFontWidthStore(PDFFontSimple simpleFont) throws InvalidFontException, UnsupportedFontException, FontLoadingException, PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
FontWidthStore fws = null;
PDFSimpleFontData simpleFontData = null;
if (this.simpleFontDataCache.isEnabled() && (fws = (simpleFontData = this.simpleFontDataCache.getPDFSimpleFontData(simpleFont)).getFontWidthStore()) != null) {
return fws;
}
FontData fData = simpleFont.getAFEFontData();
Font afeFont = simpleFont.getAFEFont();
if (fData == null || afeFont == null) {
return null;
}
PDFFontDescription desc = afeFont.getPDFFontDescription();
HashMap<Integer, Double> widthMap = new HashMap<Integer, Double>();
for (int i = 32; i <= 127; ++i) {
long gid = fData.getGlyphForChar(i);
if (gid <= 0) continue;
double width = desc.getAdvance((int)gid);
double unitesPerEmX = fData.getUnitsPerEmX();
if (unitesPerEmX != 0.0) {
width = width * 1000.0 / unitesPerEmX;
}
widthMap.put(i, width);
}
fws = new FontWidthStore(simpleFont.getAFEFont(), widthMap);
if (this.simpleFontDataCache.isEnabled()) {
simpleFontData.setFontWidthStore(fws);
}
return fws;
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
static {
SERIALIZED_FONT_WIDTHS = new String[]{"base14fontwidths/courierRegular", "base14fontwidths/courierBoldOblique", "base14fontwidths/courierBold", "base14fontwidths/courierOblique", "base14fontwidths/helveticaRegular", "base14fontwidths/helveticaBold", "base14fontwidths/helveticaBoldOblique", "base14fontwidths/helveticaOblique", "base14fontwidths/symbol", "base14fontwidths/timesBold", "base14fontwidths/timesBoldItalic", "base14fontwidths/timesItalic", "base14fontwidths/timesRegular", "base14fontwidths/zapfDingbats"};
base14FontswidthStore = new ArrayList();
try {
for (String fname : SERIALIZED_FONT_WIDTHS) {
InputStream fontWidthStream = null;
ObjectInputStream ois = null;
try {
fontWidthStream = CharacterWidthEstimator.class.getResourceAsStream(fname);
ois = new ObjectInputStream(fontWidthStream);
FontWidthStore widthStore = (FontWidthStore)ois.readObject();
ois.close();
base14FontswidthStore.add(widthStore);
}
finally {
if (ois != null) {
ois.close();
}
if (fontWidthStream != null) {
fontWidthStream.close();
}
}
}
}
catch (IOException e) {
throw new PDFRuntimeException("Bad configuration - unable to load width map for Base14 fonts.");
}
catch (ClassNotFoundException e) {
throw new PDFRuntimeException("Bad configuration - unable to load width map for Base14 fonts.", (Throwable)e);
}
}
}