You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by gb...@apache.org on 2013/03/06 17:46:37 UTC
svn commit: r1453416 [9/16] - in /pdfbox/trunk/preflight: ./
src/main/java/org/apache/pdfbox/preflight/
src/main/java/org/apache/pdfbox/preflight/action/
src/main/java/org/apache/pdfbox/preflight/annotation/
src/main/java/org/apache/pdfbox/preflight/an...
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1.java Wed Mar 6 16:46:35 2013
@@ -29,431 +29,442 @@ import java.util.Map.Entry;
import org.apache.pdfbox.encoding.Encoding;
import org.apache.pdfbox.preflight.PreflightConstants;
-public class Type1 {
- /**
- * This map links the character identifier to a internal font program label
- * which is different from the standard Encoding
- */
- private Map<Integer, String> cidToLabel = new HashMap<Integer, String>(0);
- /**
- * This map links the character label to a character identifier which is
- * different from the standard Encoding.
- */
- private Map<String, Integer> labelToCid = new HashMap<String, Integer>(0);
- /**
- * This map link the character label to a container containing Glyph
- * description.
- */
- private Map<String, GlyphDescription> labelToMetric = new HashMap<String, GlyphDescription>(0);
-
- /**
- * The character encoding of the Font
- */
- private Encoding encoding = null;
-
- public Type1(Encoding encoding ) {
- this.encoding = encoding;
- }
-
- void addCidWithLabel(Integer cid, String label) {
- this.labelToCid.put(label, cid);
- this.cidToLabel.put(cid, label);
- }
-
- void addGlyphDescription(String glyphLabel, GlyphDescription description) {
- this.labelToMetric.put(glyphLabel, description);
- }
-
- void initEncodingWithStandardEncoding() {
- this.labelToCid.put("/A", 0101);
- this.labelToCid.put("/AE", 0341);
- this.labelToCid.put("/B", 0102);
- this.labelToCid.put("/C", 0103);
- this.labelToCid.put("/D", 0104);
- this.labelToCid.put("/E", 0105);
- this.labelToCid.put("/F", 0106);
- this.labelToCid.put("/G", 0107);
- this.labelToCid.put("/H", 0110);
- this.labelToCid.put("/I", 0111);
- this.labelToCid.put("/J", 0112);
- this.labelToCid.put("/K", 0113);
- this.labelToCid.put("/L", 0114);
- this.labelToCid.put("/Lslash", 0350);
- this.labelToCid.put("/M", 0115);
- this.labelToCid.put("/N", 0116);
- this.labelToCid.put("/O", 0117);
- this.labelToCid.put("/OE", 0352);
- this.labelToCid.put("/Oslash", 0351);
- this.labelToCid.put("/P", 0120);
- this.labelToCid.put("/Q", 0121);
- this.labelToCid.put("/R", 0122);
- this.labelToCid.put("/S", 0123);
- this.labelToCid.put("/T", 0124);
- this.labelToCid.put("/U", 0125);
- this.labelToCid.put("/V", 0126);
- this.labelToCid.put("/W", 0127);
- this.labelToCid.put("/X", 0130);
- this.labelToCid.put("/Y", 0131);
- this.labelToCid.put("/Z", 0132);
- this.labelToCid.put("/a", 0141);
- this.labelToCid.put("/acute", 0302);
- this.labelToCid.put("/acute", 0302);
- this.labelToCid.put("/ae", 0361);
- this.labelToCid.put("/ampersand", 046);
- this.labelToCid.put("/asciicircum", 0136);
- this.labelToCid.put("/asciitilde", 0176);
- this.labelToCid.put("/asterisk", 052);
- this.labelToCid.put("/at", 0100);
- this.labelToCid.put("/b", 0142);
- this.labelToCid.put("/backslash", 0134);
- this.labelToCid.put("/bar", 0174);
- this.labelToCid.put("/braceleft", 0173);
- this.labelToCid.put("/braceright", 0175);
- this.labelToCid.put("/bracketleft", 0133);
- this.labelToCid.put("/bracketright", 0135);
- this.labelToCid.put("/breve", 0306);
- this.labelToCid.put("/bullet", 0267);
- this.labelToCid.put("/c", 0143);
- this.labelToCid.put("/caron", 0317);
- this.labelToCid.put("/cedilla", 0313);
- this.labelToCid.put("/cent", 0242);
- this.labelToCid.put("/circumflex", 0303);
- this.labelToCid.put("/colon", 072);
- this.labelToCid.put("/comma", 054);
- this.labelToCid.put("/currency", 0250);
- this.labelToCid.put("/d", 0144);
- this.labelToCid.put("/dagger", 0262);
- this.labelToCid.put("/daggerdbl", 0263);
- this.labelToCid.put("/dieresis", 0310);
- this.labelToCid.put("/dollar", 044);
- this.labelToCid.put("/dotaccent", 0307);
- this.labelToCid.put("/dotlessi", 0365);
- this.labelToCid.put("/e", 0145);
- this.labelToCid.put("/eight", 070);
- this.labelToCid.put("/ellipsis", 274);
- this.labelToCid.put("/emdash", 0320);
- this.labelToCid.put("/endash", 0261);
- this.labelToCid.put("/equal", 075);
- this.labelToCid.put("/exclam", 041);
- this.labelToCid.put("/exclamdown", 0241);
- this.labelToCid.put("/f", 0146);
- this.labelToCid.put("/fi", 0256);
- this.labelToCid.put("/five", 0065);
- this.labelToCid.put("/fl", 0257);
- this.labelToCid.put("/florin", 0246);
- this.labelToCid.put("/four", 064);
- this.labelToCid.put("/fraction", 0244);
- this.labelToCid.put("/g", 0147);
- this.labelToCid.put("/germandbls", 0373);
- this.labelToCid.put("/grave", 0301);
- this.labelToCid.put("/greater", 0076);
- this.labelToCid.put("/guillemotleft", 0253);
- this.labelToCid.put("/guillemotright", 0273);
- this.labelToCid.put("/guilsinglleft", 0254);
- this.labelToCid.put("/guilsinglright", 0255);
- this.labelToCid.put("/h", 0150);
- this.labelToCid.put("/hungarumlaut", 0315);
- this.labelToCid.put("/hyphen", 055);
- this.labelToCid.put("/i", 0151);
- this.labelToCid.put("/j", 0152);
- this.labelToCid.put("/k", 0153);
- this.labelToCid.put("/l", 0154);
- this.labelToCid.put("/less", 0074);
- this.labelToCid.put("/lslash", 0370);
- this.labelToCid.put("/m", 0155);
- this.labelToCid.put("/macron", 0305);
- this.labelToCid.put("/n", 0156);
- this.labelToCid.put("/nine", 071);
- this.labelToCid.put("/numbersign", 043);
- this.labelToCid.put("/o", 0157);
- this.labelToCid.put("/oe", 0372);
- this.labelToCid.put("/ogonek", 0316);
- this.labelToCid.put("/one", 061);
- this.labelToCid.put("/ordfeminine", 0343);
- this.labelToCid.put("/ordmasculine", 0353);
- this.labelToCid.put("/oslash", 0371);
- this.labelToCid.put("/p", 0160);
- this.labelToCid.put("/paragraph", 0266);
- this.labelToCid.put("/parenleft", 050);
- this.labelToCid.put("/parenright", 051);
- this.labelToCid.put("/percent", 045);
- this.labelToCid.put("/period", 056);
- this.labelToCid.put("/periodcentered", 0264);
- this.labelToCid.put("/perthousand", 0275);
- this.labelToCid.put("/plus", 0053);
- this.labelToCid.put("/q", 0161);
- this.labelToCid.put("/question", 077);
- this.labelToCid.put("/questiondown", 0277);
- this.labelToCid.put("/quotedbl", 0042);
- this.labelToCid.put("/quotedblbase", 0271);
- this.labelToCid.put("/quotedblleft", 0252);
- this.labelToCid.put("/quotedblright", 0272);
- this.labelToCid.put("/quoteleft", 0140);
- this.labelToCid.put("/quoteright", 047);
- this.labelToCid.put("/quotesinglbase", 0270);
- this.labelToCid.put("/quotesingle", 0251);
- this.labelToCid.put("/r", 0162);
- this.labelToCid.put("/ring", 0312);
- this.labelToCid.put("/s", 0163);
- this.labelToCid.put("/section", 0247);
- this.labelToCid.put("/semicolon", 0073);
- this.labelToCid.put("/seven", 0067);
- this.labelToCid.put("/six", 066);
- this.labelToCid.put("/slash", 057);
- this.labelToCid.put("/space", 040);
- this.labelToCid.put("/sterling", 0243);
- this.labelToCid.put("/t", 0164);
- this.labelToCid.put("/three", 063);
- this.labelToCid.put("/tilde", 0304);
- this.labelToCid.put("/two", 062);
- this.labelToCid.put("/u", 0165);
- this.labelToCid.put("/underscore", 0137);
- this.labelToCid.put("/v", 0166);
- this.labelToCid.put("/w", 0167);
- this.labelToCid.put("/x", 0170);
- this.labelToCid.put("/y", 0171);
- this.labelToCid.put("/yen", 0245);
- this.labelToCid.put("/z", 0172);
- this.labelToCid.put("/zero", 060);
- transafertLTOCinCTIL();
- }
-
- private void transafertLTOCinCTIL() {
- for (Entry<String, Integer> entry : this.labelToCid.entrySet()) {
- this.cidToLabel.put(entry.getValue(), entry.getKey());
- }
- }
-
- void initEncodingWithISOLatin1Encoding() {
- this.labelToCid.put("/A", 0101);
- this.labelToCid.put("/AE", 0306);
- this.labelToCid.put("/Aacute", 0301);
- this.labelToCid.put("/Acircumflex", 0302);
- this.labelToCid.put("/Adieresis", 0304);
- this.labelToCid.put("/Agrave", 0300);
- this.labelToCid.put("/Aring", 0305);
- this.labelToCid.put("/Atilde", 0303);
- this.labelToCid.put("/B", 0102);
- this.labelToCid.put("/C", 0103);
- this.labelToCid.put("/Ccedilla", 0307);
- this.labelToCid.put("/D", 0104);
- this.labelToCid.put("/E", 0105);
- this.labelToCid.put("/Eacute", 0311);
- this.labelToCid.put("/Ecircumflex", 0312);
- this.labelToCid.put("/Edieresis", 0313);
- this.labelToCid.put("/Egrave", 0310);
- this.labelToCid.put("/Eth", 0320);
- this.labelToCid.put("/F", 0106);
- this.labelToCid.put("/G", 0107);
- this.labelToCid.put("/H", 0110);
- this.labelToCid.put("/I", 0111);
- this.labelToCid.put("/Iacute", 0315);
- this.labelToCid.put("/Icircumflex", 0316);
- this.labelToCid.put("/Idieresis", 0317);
- this.labelToCid.put("/Igrave", 0314);
- this.labelToCid.put("/J", 0112);
- this.labelToCid.put("/K", 0113);
- this.labelToCid.put("/L", 0114);
- this.labelToCid.put("/M", 0115);
- this.labelToCid.put("/N", 0116);
- this.labelToCid.put("/Ntilde", 0321);
- this.labelToCid.put("/O", 0117);
- this.labelToCid.put("/Oacute", 0323);
- this.labelToCid.put("/Ocircumflex", 0324);
- this.labelToCid.put("/Odieresis", 0326);
- this.labelToCid.put("/Ograve", 0322);
- this.labelToCid.put("/Oslash", 0330);
- this.labelToCid.put("/Otilde", 0325);
- this.labelToCid.put("/P", 0120);
- this.labelToCid.put("/Q", 0121);
- this.labelToCid.put("/R", 0122);
- this.labelToCid.put("/S", 0123);
- this.labelToCid.put("/T", 0124);
- this.labelToCid.put("/Thorn", 0336);
- this.labelToCid.put("/U", 0125);
- this.labelToCid.put("/Uacute", 0332);
- this.labelToCid.put("/Ucircumflex", 0333);
- this.labelToCid.put("/Udieresis", 0334);
- this.labelToCid.put("/Ugrave", 0331);
- this.labelToCid.put("/V", 0126);
- this.labelToCid.put("/W", 0127);
- this.labelToCid.put("/X", 0130);
- this.labelToCid.put("/Y", 0131);
- this.labelToCid.put("/Yacute", 0335);
- this.labelToCid.put("/Z", 0132);
- this.labelToCid.put("/a", 0141);
- this.labelToCid.put("/aacute", 0341);
- this.labelToCid.put("/acircumflex", 0342);
- this.labelToCid.put("/acute", 0222);
- this.labelToCid.put("/acute", 0264);
- this.labelToCid.put("/adieresis", 0344);
- this.labelToCid.put("/ae", 0346);
- this.labelToCid.put("/agrave", 0340);
- this.labelToCid.put("/ampersand", 0046);
- this.labelToCid.put("/aring", 0345);
- this.labelToCid.put("/asciicircum", 0136);
- this.labelToCid.put("/asciitilde", 0176);
- this.labelToCid.put("/asterisk", 0052);
- this.labelToCid.put("/at", 0100);
- this.labelToCid.put("/atilde", 0343);
- this.labelToCid.put("/b", 0142);
- this.labelToCid.put("/backslash", 0134);
- this.labelToCid.put("/bar", 0174);
- this.labelToCid.put("/braceleft", 0173);
- this.labelToCid.put("/braceright", 0175);
- this.labelToCid.put("/bracketleft", 0133);
- this.labelToCid.put("/bracketright", 0135);
- this.labelToCid.put("/breve", 0226);
- this.labelToCid.put("/brokenbar", 0246);
- this.labelToCid.put("/c", 0143);
- this.labelToCid.put("/caron", 0237);
- this.labelToCid.put("/ccedilla", 0347);
- this.labelToCid.put("/cedilla", 0270);
- this.labelToCid.put("/cent", 0242);
- this.labelToCid.put("/circumflex", 0223);
- this.labelToCid.put("/colon", 0072);
- this.labelToCid.put("/comma", 0054);
- this.labelToCid.put("/copyright", 0251);
- this.labelToCid.put("/currency", 0244);
- this.labelToCid.put("/d", 0144);
- this.labelToCid.put("/degree", 0260);
- this.labelToCid.put("/dieresis", 0250);
- this.labelToCid.put("/divide", 0367);
- this.labelToCid.put("/dollar", 0044);
- this.labelToCid.put("/dotaccent", 0227);
- this.labelToCid.put("/dotlessi", 0220);
- this.labelToCid.put("/e", 0145);
- this.labelToCid.put("/eacute", 0351);
- this.labelToCid.put("/ecircumflex", 0352);
- this.labelToCid.put("/edieresis", 0353);
- this.labelToCid.put("/egrave", 0350);
- this.labelToCid.put("/eight", 0070);
- this.labelToCid.put("/equal", 0075);
- this.labelToCid.put("/eth", 0360);
- this.labelToCid.put("/exclam", 0041);
- this.labelToCid.put("/exclamdown", 0241);
- this.labelToCid.put("/f", 0146);
- this.labelToCid.put("/five", 0065);
- this.labelToCid.put("/four", 0064);
- this.labelToCid.put("/g", 0147);
- this.labelToCid.put("/germandbls", 0337);
- this.labelToCid.put("/grave", 0221);
- this.labelToCid.put("/greater", 0076);
- this.labelToCid.put("/guillemotleft", 0253);
- this.labelToCid.put("/guillemotright", 0273);
- this.labelToCid.put("/h", 0150);
- this.labelToCid.put("/hungarumlaut", 0235);
- this.labelToCid.put("/hyphen", 0255);
- this.labelToCid.put("/i", 0151);
- this.labelToCid.put("/iacute", 0355);
- this.labelToCid.put("/icircumflex", 0356);
- this.labelToCid.put("/idieresis", 0357);
- this.labelToCid.put("/igrave", 0354);
- this.labelToCid.put("/j", 0152);
- this.labelToCid.put("/k", 0153);
- this.labelToCid.put("/l", 0154);
- this.labelToCid.put("/less", 0074);
- this.labelToCid.put("/logicalnot", 0254);
- this.labelToCid.put("/m", 0155);
- this.labelToCid.put("/macron", 0257);
- this.labelToCid.put("/minus", 0055);
- this.labelToCid.put("/mu", 0265);
- this.labelToCid.put("/multiply", 0327);
- this.labelToCid.put("/n", 0156);
- this.labelToCid.put("/nine", 0071);
- this.labelToCid.put("/ntilde", 0361);
- this.labelToCid.put("/numbersign", 0043);
- this.labelToCid.put("/o", 0157);
- this.labelToCid.put("/oacute", 0363);
- this.labelToCid.put("/ocircumflex", 0364);
- this.labelToCid.put("/odieresis", 0366);
- this.labelToCid.put("/ogonek", 0236);
- this.labelToCid.put("/ograve", 0362);
- this.labelToCid.put("/one", 0061);
- this.labelToCid.put("/onehalf", 0275);
- this.labelToCid.put("/onequarter", 0274);
- this.labelToCid.put("/onesuperior", 0271);
- this.labelToCid.put("/ordfeminine", 0252);
- this.labelToCid.put("/ordmasculine", 0272);
- this.labelToCid.put("/oslash", 0370);
- this.labelToCid.put("/otilde", 0365);
- this.labelToCid.put("/p", 0160);
- this.labelToCid.put("/paragraph", 0266);
- this.labelToCid.put("/parenleft", 0050);
- this.labelToCid.put("/parenright", 0051);
- this.labelToCid.put("/percent", 0045);
- this.labelToCid.put("/period", 0056);
- this.labelToCid.put("/periodcentered", 0267);
- this.labelToCid.put("/plus", 0053);
- this.labelToCid.put("/plusminus", 0261);
- this.labelToCid.put("/q", 0161);
- this.labelToCid.put("/question", 0077);
- this.labelToCid.put("/questiondown", 0277);
- this.labelToCid.put("/quotedbl", 0042);
- this.labelToCid.put("/quoteleft", 0140);
- this.labelToCid.put("/quoteright", 0047);
- this.labelToCid.put("/r", 0162);
- this.labelToCid.put("/registered", 0256);
- this.labelToCid.put("/ring", 0232);
- this.labelToCid.put("/s", 0163);
- this.labelToCid.put("/section", 0247);
- this.labelToCid.put("/semicolon", 0073);
- this.labelToCid.put("/seven", 0067);
- this.labelToCid.put("/six", 0066);
- this.labelToCid.put("/slash", 0057);
- this.labelToCid.put("/space", 0040);
- this.labelToCid.put("/sterling", 0243);
- this.labelToCid.put("/t", 0164);
- this.labelToCid.put("/thorn", 0376);
- this.labelToCid.put("/three", 0063);
- this.labelToCid.put("/threequarters", 0276);
- this.labelToCid.put("/threesuperior", 0263);
- this.labelToCid.put("/tilde", 0224);
- this.labelToCid.put("/two", 0062);
- this.labelToCid.put("/twosuperior", 0262);
- this.labelToCid.put("/u", 0165);
- this.labelToCid.put("/uacute", 0372);
- this.labelToCid.put("/ucircumflex", 0373);
- this.labelToCid.put("/udieresis", 0374);
- this.labelToCid.put("/ugrave", 0371);
- this.labelToCid.put("/underscore", 0137);
- this.labelToCid.put("/v", 0166);
- this.labelToCid.put("/w", 0167);
- this.labelToCid.put("/x", 0170);
- this.labelToCid.put("/y", 0171);
- this.labelToCid.put("/yacute", 0375);
- this.labelToCid.put("/ydieresis", 0377);
- this.labelToCid.put("/yen", 0245);
- this.labelToCid.put("/z", 0172);
- this.labelToCid.put("/zero", 0060);
- transafertLTOCinCTIL();
- }
-
- public int getWidthOfCID(int cid) throws GlyphException {
- String label = getLabelAsName(cid);
-
- GlyphDescription glyph = this.labelToMetric.get(label);
- if (glyph != null) {
- return glyph.getGlyphWidth();
- }
-
- throw new GlyphException(PreflightConstants.ERROR_FONTS_GLYPH_MISSING,
- cid,
- "Missing glyph for the CID " + cid);
- }
-
- private String getLabelAsName(int cid) {
- String label = null;
-
- try {
- label = this.encoding.getName(cid);
- } catch (IOException e) {
- label = this.cidToLabel.get(cid);
- if (label == null) {
- label = Type1Parser.NOTDEF;
- }
- }
-
- return label.charAt(0) == Type1Parser.NAME_START ? label : Type1Parser.NAME_START + label;
- }
-}
\ No newline at end of file
+public class Type1
+{
+ /**
+ * This map links the character identifier to a internal font program label which is different from the standard
+ * Encoding
+ */
+ private Map<Integer, String> cidToLabel = new HashMap<Integer, String>(0);
+ /**
+ * This map links the character label to a character identifier which is different from the standard Encoding.
+ */
+ private Map<String, Integer> labelToCid = new HashMap<String, Integer>(0);
+ /**
+ * This map link the character label to a container containing Glyph description.
+ */
+ private Map<String, GlyphDescription> labelToMetric = new HashMap<String, GlyphDescription>(0);
+
+ /**
+ * The character encoding of the Font
+ */
+ private Encoding encoding = null;
+
+ public Type1(Encoding encoding)
+ {
+ this.encoding = encoding;
+ }
+
+ void addCidWithLabel(Integer cid, String label)
+ {
+ this.labelToCid.put(label, cid);
+ this.cidToLabel.put(cid, label);
+ }
+
+ void addGlyphDescription(String glyphLabel, GlyphDescription description)
+ {
+ this.labelToMetric.put(glyphLabel, description);
+ }
+
+ void initEncodingWithStandardEncoding()
+ {
+ this.labelToCid.put("/A", 0101);
+ this.labelToCid.put("/AE", 0341);
+ this.labelToCid.put("/B", 0102);
+ this.labelToCid.put("/C", 0103);
+ this.labelToCid.put("/D", 0104);
+ this.labelToCid.put("/E", 0105);
+ this.labelToCid.put("/F", 0106);
+ this.labelToCid.put("/G", 0107);
+ this.labelToCid.put("/H", 0110);
+ this.labelToCid.put("/I", 0111);
+ this.labelToCid.put("/J", 0112);
+ this.labelToCid.put("/K", 0113);
+ this.labelToCid.put("/L", 0114);
+ this.labelToCid.put("/Lslash", 0350);
+ this.labelToCid.put("/M", 0115);
+ this.labelToCid.put("/N", 0116);
+ this.labelToCid.put("/O", 0117);
+ this.labelToCid.put("/OE", 0352);
+ this.labelToCid.put("/Oslash", 0351);
+ this.labelToCid.put("/P", 0120);
+ this.labelToCid.put("/Q", 0121);
+ this.labelToCid.put("/R", 0122);
+ this.labelToCid.put("/S", 0123);
+ this.labelToCid.put("/T", 0124);
+ this.labelToCid.put("/U", 0125);
+ this.labelToCid.put("/V", 0126);
+ this.labelToCid.put("/W", 0127);
+ this.labelToCid.put("/X", 0130);
+ this.labelToCid.put("/Y", 0131);
+ this.labelToCid.put("/Z", 0132);
+ this.labelToCid.put("/a", 0141);
+ this.labelToCid.put("/acute", 0302);
+ this.labelToCid.put("/acute", 0302);
+ this.labelToCid.put("/ae", 0361);
+ this.labelToCid.put("/ampersand", 046);
+ this.labelToCid.put("/asciicircum", 0136);
+ this.labelToCid.put("/asciitilde", 0176);
+ this.labelToCid.put("/asterisk", 052);
+ this.labelToCid.put("/at", 0100);
+ this.labelToCid.put("/b", 0142);
+ this.labelToCid.put("/backslash", 0134);
+ this.labelToCid.put("/bar", 0174);
+ this.labelToCid.put("/braceleft", 0173);
+ this.labelToCid.put("/braceright", 0175);
+ this.labelToCid.put("/bracketleft", 0133);
+ this.labelToCid.put("/bracketright", 0135);
+ this.labelToCid.put("/breve", 0306);
+ this.labelToCid.put("/bullet", 0267);
+ this.labelToCid.put("/c", 0143);
+ this.labelToCid.put("/caron", 0317);
+ this.labelToCid.put("/cedilla", 0313);
+ this.labelToCid.put("/cent", 0242);
+ this.labelToCid.put("/circumflex", 0303);
+ this.labelToCid.put("/colon", 072);
+ this.labelToCid.put("/comma", 054);
+ this.labelToCid.put("/currency", 0250);
+ this.labelToCid.put("/d", 0144);
+ this.labelToCid.put("/dagger", 0262);
+ this.labelToCid.put("/daggerdbl", 0263);
+ this.labelToCid.put("/dieresis", 0310);
+ this.labelToCid.put("/dollar", 044);
+ this.labelToCid.put("/dotaccent", 0307);
+ this.labelToCid.put("/dotlessi", 0365);
+ this.labelToCid.put("/e", 0145);
+ this.labelToCid.put("/eight", 070);
+ this.labelToCid.put("/ellipsis", 274);
+ this.labelToCid.put("/emdash", 0320);
+ this.labelToCid.put("/endash", 0261);
+ this.labelToCid.put("/equal", 075);
+ this.labelToCid.put("/exclam", 041);
+ this.labelToCid.put("/exclamdown", 0241);
+ this.labelToCid.put("/f", 0146);
+ this.labelToCid.put("/fi", 0256);
+ this.labelToCid.put("/five", 0065);
+ this.labelToCid.put("/fl", 0257);
+ this.labelToCid.put("/florin", 0246);
+ this.labelToCid.put("/four", 064);
+ this.labelToCid.put("/fraction", 0244);
+ this.labelToCid.put("/g", 0147);
+ this.labelToCid.put("/germandbls", 0373);
+ this.labelToCid.put("/grave", 0301);
+ this.labelToCid.put("/greater", 0076);
+ this.labelToCid.put("/guillemotleft", 0253);
+ this.labelToCid.put("/guillemotright", 0273);
+ this.labelToCid.put("/guilsinglleft", 0254);
+ this.labelToCid.put("/guilsinglright", 0255);
+ this.labelToCid.put("/h", 0150);
+ this.labelToCid.put("/hungarumlaut", 0315);
+ this.labelToCid.put("/hyphen", 055);
+ this.labelToCid.put("/i", 0151);
+ this.labelToCid.put("/j", 0152);
+ this.labelToCid.put("/k", 0153);
+ this.labelToCid.put("/l", 0154);
+ this.labelToCid.put("/less", 0074);
+ this.labelToCid.put("/lslash", 0370);
+ this.labelToCid.put("/m", 0155);
+ this.labelToCid.put("/macron", 0305);
+ this.labelToCid.put("/n", 0156);
+ this.labelToCid.put("/nine", 071);
+ this.labelToCid.put("/numbersign", 043);
+ this.labelToCid.put("/o", 0157);
+ this.labelToCid.put("/oe", 0372);
+ this.labelToCid.put("/ogonek", 0316);
+ this.labelToCid.put("/one", 061);
+ this.labelToCid.put("/ordfeminine", 0343);
+ this.labelToCid.put("/ordmasculine", 0353);
+ this.labelToCid.put("/oslash", 0371);
+ this.labelToCid.put("/p", 0160);
+ this.labelToCid.put("/paragraph", 0266);
+ this.labelToCid.put("/parenleft", 050);
+ this.labelToCid.put("/parenright", 051);
+ this.labelToCid.put("/percent", 045);
+ this.labelToCid.put("/period", 056);
+ this.labelToCid.put("/periodcentered", 0264);
+ this.labelToCid.put("/perthousand", 0275);
+ this.labelToCid.put("/plus", 0053);
+ this.labelToCid.put("/q", 0161);
+ this.labelToCid.put("/question", 077);
+ this.labelToCid.put("/questiondown", 0277);
+ this.labelToCid.put("/quotedbl", 0042);
+ this.labelToCid.put("/quotedblbase", 0271);
+ this.labelToCid.put("/quotedblleft", 0252);
+ this.labelToCid.put("/quotedblright", 0272);
+ this.labelToCid.put("/quoteleft", 0140);
+ this.labelToCid.put("/quoteright", 047);
+ this.labelToCid.put("/quotesinglbase", 0270);
+ this.labelToCid.put("/quotesingle", 0251);
+ this.labelToCid.put("/r", 0162);
+ this.labelToCid.put("/ring", 0312);
+ this.labelToCid.put("/s", 0163);
+ this.labelToCid.put("/section", 0247);
+ this.labelToCid.put("/semicolon", 0073);
+ this.labelToCid.put("/seven", 0067);
+ this.labelToCid.put("/six", 066);
+ this.labelToCid.put("/slash", 057);
+ this.labelToCid.put("/space", 040);
+ this.labelToCid.put("/sterling", 0243);
+ this.labelToCid.put("/t", 0164);
+ this.labelToCid.put("/three", 063);
+ this.labelToCid.put("/tilde", 0304);
+ this.labelToCid.put("/two", 062);
+ this.labelToCid.put("/u", 0165);
+ this.labelToCid.put("/underscore", 0137);
+ this.labelToCid.put("/v", 0166);
+ this.labelToCid.put("/w", 0167);
+ this.labelToCid.put("/x", 0170);
+ this.labelToCid.put("/y", 0171);
+ this.labelToCid.put("/yen", 0245);
+ this.labelToCid.put("/z", 0172);
+ this.labelToCid.put("/zero", 060);
+ transafertLTOCinCTIL();
+ }
+
+ private void transafertLTOCinCTIL()
+ {
+ for (Entry<String, Integer> entry : this.labelToCid.entrySet())
+ {
+ this.cidToLabel.put(entry.getValue(), entry.getKey());
+ }
+ }
+
+ void initEncodingWithISOLatin1Encoding()
+ {
+ this.labelToCid.put("/A", 0101);
+ this.labelToCid.put("/AE", 0306);
+ this.labelToCid.put("/Aacute", 0301);
+ this.labelToCid.put("/Acircumflex", 0302);
+ this.labelToCid.put("/Adieresis", 0304);
+ this.labelToCid.put("/Agrave", 0300);
+ this.labelToCid.put("/Aring", 0305);
+ this.labelToCid.put("/Atilde", 0303);
+ this.labelToCid.put("/B", 0102);
+ this.labelToCid.put("/C", 0103);
+ this.labelToCid.put("/Ccedilla", 0307);
+ this.labelToCid.put("/D", 0104);
+ this.labelToCid.put("/E", 0105);
+ this.labelToCid.put("/Eacute", 0311);
+ this.labelToCid.put("/Ecircumflex", 0312);
+ this.labelToCid.put("/Edieresis", 0313);
+ this.labelToCid.put("/Egrave", 0310);
+ this.labelToCid.put("/Eth", 0320);
+ this.labelToCid.put("/F", 0106);
+ this.labelToCid.put("/G", 0107);
+ this.labelToCid.put("/H", 0110);
+ this.labelToCid.put("/I", 0111);
+ this.labelToCid.put("/Iacute", 0315);
+ this.labelToCid.put("/Icircumflex", 0316);
+ this.labelToCid.put("/Idieresis", 0317);
+ this.labelToCid.put("/Igrave", 0314);
+ this.labelToCid.put("/J", 0112);
+ this.labelToCid.put("/K", 0113);
+ this.labelToCid.put("/L", 0114);
+ this.labelToCid.put("/M", 0115);
+ this.labelToCid.put("/N", 0116);
+ this.labelToCid.put("/Ntilde", 0321);
+ this.labelToCid.put("/O", 0117);
+ this.labelToCid.put("/Oacute", 0323);
+ this.labelToCid.put("/Ocircumflex", 0324);
+ this.labelToCid.put("/Odieresis", 0326);
+ this.labelToCid.put("/Ograve", 0322);
+ this.labelToCid.put("/Oslash", 0330);
+ this.labelToCid.put("/Otilde", 0325);
+ this.labelToCid.put("/P", 0120);
+ this.labelToCid.put("/Q", 0121);
+ this.labelToCid.put("/R", 0122);
+ this.labelToCid.put("/S", 0123);
+ this.labelToCid.put("/T", 0124);
+ this.labelToCid.put("/Thorn", 0336);
+ this.labelToCid.put("/U", 0125);
+ this.labelToCid.put("/Uacute", 0332);
+ this.labelToCid.put("/Ucircumflex", 0333);
+ this.labelToCid.put("/Udieresis", 0334);
+ this.labelToCid.put("/Ugrave", 0331);
+ this.labelToCid.put("/V", 0126);
+ this.labelToCid.put("/W", 0127);
+ this.labelToCid.put("/X", 0130);
+ this.labelToCid.put("/Y", 0131);
+ this.labelToCid.put("/Yacute", 0335);
+ this.labelToCid.put("/Z", 0132);
+ this.labelToCid.put("/a", 0141);
+ this.labelToCid.put("/aacute", 0341);
+ this.labelToCid.put("/acircumflex", 0342);
+ this.labelToCid.put("/acute", 0222);
+ this.labelToCid.put("/acute", 0264);
+ this.labelToCid.put("/adieresis", 0344);
+ this.labelToCid.put("/ae", 0346);
+ this.labelToCid.put("/agrave", 0340);
+ this.labelToCid.put("/ampersand", 0046);
+ this.labelToCid.put("/aring", 0345);
+ this.labelToCid.put("/asciicircum", 0136);
+ this.labelToCid.put("/asciitilde", 0176);
+ this.labelToCid.put("/asterisk", 0052);
+ this.labelToCid.put("/at", 0100);
+ this.labelToCid.put("/atilde", 0343);
+ this.labelToCid.put("/b", 0142);
+ this.labelToCid.put("/backslash", 0134);
+ this.labelToCid.put("/bar", 0174);
+ this.labelToCid.put("/braceleft", 0173);
+ this.labelToCid.put("/braceright", 0175);
+ this.labelToCid.put("/bracketleft", 0133);
+ this.labelToCid.put("/bracketright", 0135);
+ this.labelToCid.put("/breve", 0226);
+ this.labelToCid.put("/brokenbar", 0246);
+ this.labelToCid.put("/c", 0143);
+ this.labelToCid.put("/caron", 0237);
+ this.labelToCid.put("/ccedilla", 0347);
+ this.labelToCid.put("/cedilla", 0270);
+ this.labelToCid.put("/cent", 0242);
+ this.labelToCid.put("/circumflex", 0223);
+ this.labelToCid.put("/colon", 0072);
+ this.labelToCid.put("/comma", 0054);
+ this.labelToCid.put("/copyright", 0251);
+ this.labelToCid.put("/currency", 0244);
+ this.labelToCid.put("/d", 0144);
+ this.labelToCid.put("/degree", 0260);
+ this.labelToCid.put("/dieresis", 0250);
+ this.labelToCid.put("/divide", 0367);
+ this.labelToCid.put("/dollar", 0044);
+ this.labelToCid.put("/dotaccent", 0227);
+ this.labelToCid.put("/dotlessi", 0220);
+ this.labelToCid.put("/e", 0145);
+ this.labelToCid.put("/eacute", 0351);
+ this.labelToCid.put("/ecircumflex", 0352);
+ this.labelToCid.put("/edieresis", 0353);
+ this.labelToCid.put("/egrave", 0350);
+ this.labelToCid.put("/eight", 0070);
+ this.labelToCid.put("/equal", 0075);
+ this.labelToCid.put("/eth", 0360);
+ this.labelToCid.put("/exclam", 0041);
+ this.labelToCid.put("/exclamdown", 0241);
+ this.labelToCid.put("/f", 0146);
+ this.labelToCid.put("/five", 0065);
+ this.labelToCid.put("/four", 0064);
+ this.labelToCid.put("/g", 0147);
+ this.labelToCid.put("/germandbls", 0337);
+ this.labelToCid.put("/grave", 0221);
+ this.labelToCid.put("/greater", 0076);
+ this.labelToCid.put("/guillemotleft", 0253);
+ this.labelToCid.put("/guillemotright", 0273);
+ this.labelToCid.put("/h", 0150);
+ this.labelToCid.put("/hungarumlaut", 0235);
+ this.labelToCid.put("/hyphen", 0255);
+ this.labelToCid.put("/i", 0151);
+ this.labelToCid.put("/iacute", 0355);
+ this.labelToCid.put("/icircumflex", 0356);
+ this.labelToCid.put("/idieresis", 0357);
+ this.labelToCid.put("/igrave", 0354);
+ this.labelToCid.put("/j", 0152);
+ this.labelToCid.put("/k", 0153);
+ this.labelToCid.put("/l", 0154);
+ this.labelToCid.put("/less", 0074);
+ this.labelToCid.put("/logicalnot", 0254);
+ this.labelToCid.put("/m", 0155);
+ this.labelToCid.put("/macron", 0257);
+ this.labelToCid.put("/minus", 0055);
+ this.labelToCid.put("/mu", 0265);
+ this.labelToCid.put("/multiply", 0327);
+ this.labelToCid.put("/n", 0156);
+ this.labelToCid.put("/nine", 0071);
+ this.labelToCid.put("/ntilde", 0361);
+ this.labelToCid.put("/numbersign", 0043);
+ this.labelToCid.put("/o", 0157);
+ this.labelToCid.put("/oacute", 0363);
+ this.labelToCid.put("/ocircumflex", 0364);
+ this.labelToCid.put("/odieresis", 0366);
+ this.labelToCid.put("/ogonek", 0236);
+ this.labelToCid.put("/ograve", 0362);
+ this.labelToCid.put("/one", 0061);
+ this.labelToCid.put("/onehalf", 0275);
+ this.labelToCid.put("/onequarter", 0274);
+ this.labelToCid.put("/onesuperior", 0271);
+ this.labelToCid.put("/ordfeminine", 0252);
+ this.labelToCid.put("/ordmasculine", 0272);
+ this.labelToCid.put("/oslash", 0370);
+ this.labelToCid.put("/otilde", 0365);
+ this.labelToCid.put("/p", 0160);
+ this.labelToCid.put("/paragraph", 0266);
+ this.labelToCid.put("/parenleft", 0050);
+ this.labelToCid.put("/parenright", 0051);
+ this.labelToCid.put("/percent", 0045);
+ this.labelToCid.put("/period", 0056);
+ this.labelToCid.put("/periodcentered", 0267);
+ this.labelToCid.put("/plus", 0053);
+ this.labelToCid.put("/plusminus", 0261);
+ this.labelToCid.put("/q", 0161);
+ this.labelToCid.put("/question", 0077);
+ this.labelToCid.put("/questiondown", 0277);
+ this.labelToCid.put("/quotedbl", 0042);
+ this.labelToCid.put("/quoteleft", 0140);
+ this.labelToCid.put("/quoteright", 0047);
+ this.labelToCid.put("/r", 0162);
+ this.labelToCid.put("/registered", 0256);
+ this.labelToCid.put("/ring", 0232);
+ this.labelToCid.put("/s", 0163);
+ this.labelToCid.put("/section", 0247);
+ this.labelToCid.put("/semicolon", 0073);
+ this.labelToCid.put("/seven", 0067);
+ this.labelToCid.put("/six", 0066);
+ this.labelToCid.put("/slash", 0057);
+ this.labelToCid.put("/space", 0040);
+ this.labelToCid.put("/sterling", 0243);
+ this.labelToCid.put("/t", 0164);
+ this.labelToCid.put("/thorn", 0376);
+ this.labelToCid.put("/three", 0063);
+ this.labelToCid.put("/threequarters", 0276);
+ this.labelToCid.put("/threesuperior", 0263);
+ this.labelToCid.put("/tilde", 0224);
+ this.labelToCid.put("/two", 0062);
+ this.labelToCid.put("/twosuperior", 0262);
+ this.labelToCid.put("/u", 0165);
+ this.labelToCid.put("/uacute", 0372);
+ this.labelToCid.put("/ucircumflex", 0373);
+ this.labelToCid.put("/udieresis", 0374);
+ this.labelToCid.put("/ugrave", 0371);
+ this.labelToCid.put("/underscore", 0137);
+ this.labelToCid.put("/v", 0166);
+ this.labelToCid.put("/w", 0167);
+ this.labelToCid.put("/x", 0170);
+ this.labelToCid.put("/y", 0171);
+ this.labelToCid.put("/yacute", 0375);
+ this.labelToCid.put("/ydieresis", 0377);
+ this.labelToCid.put("/yen", 0245);
+ this.labelToCid.put("/z", 0172);
+ this.labelToCid.put("/zero", 0060);
+ transafertLTOCinCTIL();
+ }
+
+ public int getWidthOfCID(int cid) throws GlyphException
+ {
+ String label = getLabelAsName(cid);
+
+ GlyphDescription glyph = this.labelToMetric.get(label);
+ if (glyph != null)
+ {
+ return glyph.getGlyphWidth();
+ }
+
+ throw new GlyphException(PreflightConstants.ERROR_FONTS_GLYPH_MISSING, cid, "Missing glyph for the CID " + cid);
+ }
+
+ private String getLabelAsName(int cid)
+ {
+ String label = null;
+
+ try
+ {
+ label = this.encoding.getName(cid);
+ }
+ catch (IOException e)
+ {
+ label = this.cidToLabel.get(cid);
+ if (label == null)
+ {
+ label = Type1Parser.NOTDEF;
+ }
+ }
+
+ return label.charAt(0) == Type1Parser.NAME_START ? label : Type1Parser.NAME_START + label;
+ }
+}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1Parser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1Parser.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1Parser.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1Parser.java Wed Mar 6 16:46:35 2013
@@ -44,548 +44,680 @@ import org.apache.pdfbox.encoding.PdfDoc
import org.apache.pdfbox.encoding.StandardEncoding;
import org.apache.pdfbox.encoding.WinAnsiEncoding;
-public final class Type1Parser {
+public final class Type1Parser
+{
- public static final Logger LOGGER = Logger.getLogger(Type1Parser.class);
-
- protected static final char NAME_START = '/';
- protected static final String NOTDEF = NAME_START + ".notdef";
- protected static final int DEFAULT_LEN_IV = 4;
-
- private static final String PS_STANDARD_ENCODING = "StandardEncoding";
- private static final String PS_ISOLATIN_ENCODING = "ISOLatin1Encoding";
-
- private static final String TOKEN_ENCODING = "US-ASCII";
-
- /**
- * The PostScript font stream.
- */
- private PeekInputStream fontProgram = null;
- /**
- * The length in bytes of the clear-text portion of the Type1 font program.
- */
- private int clearTextSize = 0;
- /**
- * The length in bytes of the eexec encrypted portion of the type1 font
- * program.
- */
- private int eexecSize = 0;
-
- /**
- * This counter is used to know how many byte have been read.
- * It is used to read the clear part of the font. this computer is
- * updated during the parsing of the encoding part too but it is not
- * used.
- */
- private int numberOfReadBytes = 0;
-
- /**
- * Object which contains information coming from the parsing.
- */
- private Type1 type1Font = null;
-
- private Type1Parser(InputStream type1, int length1, int length2, Encoding enc) throws IOException {
- super();
- this.fontProgram = new PeekInputStream(type1);
- this.clearTextSize = length1;
- this.eexecSize = length2;
- // ---- Instantiate the Encoding Map
- if (enc != null) {
- this.type1Font = new Type1(enc);
- } else {
- this.type1Font = new Type1(new StandardEncoding());
- }
- this.type1Font.addCidWithLabel(-1, NOTDEF);
- }
-
- /**
- *
- * @param fontProgram the stream of the font program extracted from the PDF file.
- * @param clearTextLength the length in bytes of the clear part of the font program.
- * @param eexecLength the length in bytes of the encoded part.
- * @return
- * @throws IOException
- */
- public static Type1Parser createParser(
- InputStream fontProgram,
- int clearTextLength,
- int eexecLength) throws IOException {
-
- Encoding encoding = getEncodingObject("");
- return createParserWithEncodingObject(fontProgram, clearTextLength, eexecLength, encoding);
- }
-
- /**
- *
- * @param fontProgram the stream of the font program extracted from the PDF file.
- * @param clearTextLength the length in bytes of the clear part of the font program.
- * @param eexecLength the length in bytes of the encoded part.
- * @param encodingName The name of encoding which is used by this font program.
- * @return
- * @throws IOException
- */
- public static Type1Parser createParserWithEncodingName(
- InputStream fontProgram,
- int clearTextLength,
- int eexecLength,
- String encodingName) throws IOException {
-
- Encoding encoding = getEncodingObject(encodingName);
- return createParserWithEncodingObject(fontProgram, clearTextLength, eexecLength, encoding);
- }
-
- private static Encoding getEncodingObject(String encodingName) {
- Encoding encoding = new StandardEncoding();
- if (FONT_DICTIONARY_VALUE_ENCODING_MAC.equals(encodingName)) {
- encoding = new MacRomanEncoding();
- } else if (FONT_DICTIONARY_VALUE_ENCODING_MAC_EXP.equals(encodingName)) {
- encoding = new MacRomanEncoding();
- } else if (FONT_DICTIONARY_VALUE_ENCODING_WIN.equals(encodingName)) {
- encoding = new WinAnsiEncoding();
- } else if (FONT_DICTIONARY_VALUE_ENCODING_PDFDOC.equals(encodingName)) {
- encoding = new PdfDocEncoding();
- }
- return encoding;
- }
-
- /**
- *
- * @param fontProgram the stream of the font program extracted from the PDF file.
- * @param clearTextLength the length in bytes of the clear part of the font program.
- * @param eexecLength the length in bytes of the encoded part.
- * @param encodingName The encoding object which is used by this font program.
- * @return
- * @throws IOException
- */
- public static Type1Parser createParserWithEncodingObject(
- InputStream fontProgram,
- int clearTextLength,
- int eexecLength,
- Encoding encoding) throws IOException {
-
- return new Type1Parser(fontProgram, clearTextLength, eexecLength, encoding);
- }
-
- public Type1 parse() throws IOException {
- parseClearPartOfFontProgram(this.fontProgram);
- decodeAndParseEExecPart(this.fontProgram);
- return this.type1Font;
- }
-
- private void parseClearPartOfFontProgram(PeekInputStream stream) throws IOException {
- skipComments(stream);
- parseFontInformationUntilEncodingPart(stream);
- }
-
- private void decodeAndParseEExecPart(PeekInputStream stream) throws IOException {
- byte[] eexecPart = readEexec(stream);
- byte[] decodedEExecPart = decodeEexec(eexecPart);
- PeekInputStream eexecStream = new PeekInputStream(new ByteArrayInputStream(decodedEExecPart));
- parseEExecPart(eexecStream);
- }
-
- private void skipComments(PeekInputStream stream) throws IOException {
- int nextChar = stream.peek();
- while (nextChar == '%') {
- if (nextChar == -1) {
- throw new IOException("Unexpected End Of File during a comment parsing");
- }
- readLine(stream);
- nextChar = stream.peek();
- }
- }
-
- private void parseFontInformationUntilEncodingPart(PeekInputStream stream) throws IOException {
- byte[] token = readToken(stream);
- while (!isEExecKeyWord(token)) {
- // add here specific operation to memorize useful information
- if (isEncodingKeyWord(token)) {
- parseEncodingDefinition(stream);
- }
- token = readToken(stream);
- }
-
- while (!isStartOfEExecReached()) {
- readNextCharacter(stream);
- }
- }
-
- private void parseEncodingDefinition(PeekInputStream stream) throws IOException {
- byte[] token = readToken(stream);
- String readableToken = new String(token, TOKEN_ENCODING);
- if (PS_ISOLATIN_ENCODING.equals(readableToken)) {
- this.type1Font.initEncodingWithISOLatin1Encoding();
- } else if (PS_STANDARD_ENCODING.equals(readableToken)) {
- this.type1Font.initEncodingWithStandardEncoding();
- } else {
- try {
- Integer.parseInt(readableToken);
- throwExceptionIfUnexpectedToken("array", readToken(stream));
- readEndSetEncodingValues(stream);
- } catch (NumberFormatException e) {
- throw new IOException("Invalid encoding : Expected int value before \"array\" "
- + "key word if the Encoding isn't Standard or ISOLatin");
- }
- }
- }
-
- private void parseEExecPart(PeekInputStream stream) throws IOException {
- int lenIV = DEFAULT_LEN_IV;
- byte[] previousToken = new byte[0];
- while(!isEndOfStream(stream)) {
- byte[] token = readToken(stream);
- if (isLenIVKeyWord(token)) {
- // lenIV belong to Private Dictionary.
- // If you create a method to parse PrivateDict, please update this function
- byte[] l = readToken(stream);
- lenIV = Integer.parseInt(new String(l, TOKEN_ENCODING));
- } else if (isBeginOfBinaryPart(token)) {
- try {
- int lengthOfBinaryPart = Integer.parseInt(new String(previousToken, TOKEN_ENCODING));
- skipSingleBlankSeparator(stream);
- stream.read(new byte[lengthOfBinaryPart], 0, lengthOfBinaryPart);
- token = readToken(stream); // read the end of binary part
- } catch (NumberFormatException e) {
- throw new IOException("Binary part found but previous token wasn't an integer");
- }
- } else if (isCharStringKeyWord(token)) {
- parseCharStringArray(stream, lenIV);
- }
- previousToken = token;
- }
- }
-
- private void parseCharStringArray(PeekInputStream stream, int lenIV) throws IOException {
- int numberOfElements = readNumberOfCharStrings(stream);
- goToBeginOfCharStringElements(stream);
-
- while (numberOfElements > 0) {
- byte[] labelToken = readToken(stream);
- String label = new String(labelToken, TOKEN_ENCODING);
-
- if (label.equals("end")){
- // TODO thrown exception ? add an error/warning in the PreflightContext ??
- LOGGER.warn("[Type 1] Invalid number of elements in the CharString");
- break;
- }
-
- byte[] sizeOfCharStringToken = readToken(stream);
- int sizeOfCharString = Integer.parseInt(new String(sizeOfCharStringToken,TOKEN_ENCODING));
-
- readToken(stream); // skip "RD" or "-|" token
- skipSingleBlankSeparator(stream); // "RD" or "-|" are followed by a space
-
- byte[] descBinary = new byte[sizeOfCharString];
- stream.read(descBinary, 0, sizeOfCharString);
- byte[] description = Type1FontUtil.charstringDecrypt(descBinary, lenIV);
- Type1CharStringParser t1p = new Type1CharStringParser();
- // TODO provide the local subroutine indexes
- List<Object> operations = t1p.parse(description, new IndexData(0));
- type1Font.addGlyphDescription(label, new GlyphDescription(operations));
-
- readToken(stream); // skip "ND" or "|-" token
- --numberOfElements;
- }
- }
-
- private void goToBeginOfCharStringElements(PeekInputStream stream) throws IOException {
- byte[] token = new byte[0];
- do {
- token = readToken(stream);
- } while(isNotBeginKeyWord(token));
- }
-
- private boolean isNotBeginKeyWord(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return !"begin".equals(word);
- }
-
- private boolean isBeginOfBinaryPart(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return ("RD".equals(word) || "-|".equals(word));
- }
-
- private boolean isLenIVKeyWord(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return "/lenIV".equals(word);
- }
-
- private boolean isCharStringKeyWord(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return "/CharStrings".equals(word);
- }
-
- private int readNumberOfCharStrings(PeekInputStream stream) throws IOException {
- byte[] token = readToken(stream);
- String word = new String(token, TOKEN_ENCODING);
- try {
- return Integer.parseInt(word);
- } catch (NumberFormatException e) {
- throw new IOException("Number of CharStrings elements is expected.");
- }
- }
-
- private void throwExceptionIfUnexpectedToken(String expectedValue, byte[] token) throws IOException {
- String valueToCheck = new String(token, TOKEN_ENCODING);
- if (!expectedValue.equals(valueToCheck)) {
- throw new IOException(expectedValue + " was expected but we received " + valueToCheck);
- }
- }
-
- private void readEndSetEncodingValues(PeekInputStream stream) throws IOException {
- byte[] token = readToken(stream);
- boolean lastTokenWasReadOnly = false;
- while ( !(lastTokenWasReadOnly && isDefKeyWord(token)) ) {
- if (isDupKeyWord(token)) {
- byte[] cidToken = readToken(stream);
- byte[] labelToken = readToken(stream);
- String cid = new String(cidToken, TOKEN_ENCODING);
- String label = new String(labelToken, TOKEN_ENCODING);
- try {
- this.type1Font.addCidWithLabel(Integer.parseInt(cid), label);
- } catch (NumberFormatException e) {
- throw new IOException("Invalid encoding : Expected CID value before \"" + label + "\" label");
- }
- } else {
- lastTokenWasReadOnly = isReadOnlyKeyWord(token);
- }
- token = readToken(stream);
- }
- }
-
- private byte[] readEexec(PeekInputStream stream) throws IOException {
- int BUFFER_SIZE = 1024;
- byte[] buffer = new byte[BUFFER_SIZE];
- ByteArrayOutputStream eexecPart = new ByteArrayOutputStream();
- int lr = 0;
- int total = 0;
- do {
- lr = stream.read(buffer, 0, BUFFER_SIZE);
- if (lr == BUFFER_SIZE && (total + BUFFER_SIZE < eexecSize)) {
- eexecPart.write(buffer, 0, BUFFER_SIZE);
- total += BUFFER_SIZE;
- } else if (lr > 0 && (total + lr < eexecSize)) {
- eexecPart.write(buffer, 0, lr);
- total += lr;
- } else if (lr > 0 && (total + lr >= eexecSize)) {
- eexecPart.write(buffer, 0, eexecSize - total);
- total += (eexecSize - total);
- }
- } while (eexecSize > total && lr > 0);
- IOUtils.closeQuietly(eexecPart);
- return eexecPart.toByteArray();
- }
-
- private byte[] decodeEexec(byte[] eexec) {
- return Type1FontUtil.eexecDecrypt(eexec);
- }
-
- private byte[] readLine(PeekInputStream stream) throws IOException {
- ArrayList<Byte> bytes = new ArrayList<Byte>();
- int currentCharacter = 0;
-
- do {
- currentCharacter = readNextCharacter(stream);
- bytes.add((byte)(currentCharacter & 0xFF));
- } while ( !('\n' == currentCharacter || '\r' == currentCharacter)) ;
-
- if ('\r' == currentCharacter && '\n' == stream.peek()) {
- currentCharacter = readNextCharacter(stream);
- bytes.add((byte)(currentCharacter & 0xFF));
- }
-
- byte[] result = new byte[bytes.size()];
- for (int i = 0 ; i < bytes.size(); ++i) {
- result[i] = bytes.get(i);
- }
- return result;
- }
-
- private byte[] readToken(PeekInputStream stream) throws IOException {
- byte[] token = new byte[0];
- skipBlankSeparators(stream);
-
- int nextByte = stream.peek();
- if (nextByte < 0) {
- throw new IOException("Unexpected End Of File");
- }
-
- if (nextByte == '(') {
- token = readStringLiteral(stream);
- } else if (nextByte == '[') {
- token = readArray(stream);
- } else if (nextByte == '{') {
- token = readProcedure(stream);
- } else {
- token = readNameOrArgument(stream);
- }
-
- return token;
- }
-
- private byte[] readStringLiteral(PeekInputStream stream) throws IOException {
- int opened = 0;
- List<Integer> buffer = new ArrayList<Integer>();
-
- int currentByte = 0;
- do {
- currentByte = readNextCharacter(stream);
- if (currentByte < 0) {
- throw new IOException("Unexpected End Of File");
- }
-
- if (currentByte == '(') {
- opened++;
- } else if (currentByte == ')') {
- opened--;
- }
-
- buffer.add(currentByte);
- } while (opened != 0);
-
- return convertListOfIntToByteArray(buffer);
- }
-
- private byte[] readArray(PeekInputStream stream) throws IOException {
- int opened = 0;
- List<Integer> buffer = new ArrayList<Integer>();
-
- int currentByte = 0;
- do {
- currentByte = readNextCharacter(stream);
- if (currentByte < 0) {
- throw new IOException("Unexpected End Of File");
- }
-
- if (currentByte == '[') {
- opened++;
- } else if (currentByte == ']') {
- opened--;
- }
-
- buffer.add(currentByte);
- } while (opened != 0);
-
- return convertListOfIntToByteArray(buffer);
- }
-
- private byte[] readProcedure(PeekInputStream stream) throws IOException {
- int opened = 0;
- List<Integer> buffer = new ArrayList<Integer>();
-
- int currentByte = 0;
- do {
- currentByte = readNextCharacter(stream);
- if (currentByte < 0) {
- throw new IOException("Unexpected End Of File");
- }
-
- if (currentByte == '{') {
- opened++;
- } else if (currentByte == '}') {
- opened--;
- }
-
- buffer.add(currentByte);
- } while (opened != 0);
-
- return convertListOfIntToByteArray(buffer);
- }
-
- private byte[] readNameOrArgument(PeekInputStream stream) throws IOException {
- List<Integer> buffer = new ArrayList<Integer>();
- int nextByte = 0;
- do {
- int currentByte = readNextCharacter(stream);
- if (currentByte < 0) {
- throw new IOException("Unexpected End Of File");
- }
- buffer.add(currentByte);
- nextByte = stream.peek();
- } while (isNotBlankSperator(nextByte) && isNotBeginOfName(nextByte) && isNotSeparator(nextByte));
-
- return convertListOfIntToByteArray(buffer);
- }
-
- private boolean isNotBeginOfName(int character) {
- return ('/' != character);
- }
-
- private boolean isNotSeparator(int character) {
- return !('{' == character || '}' == character || '[' == character || ']' == character);
- }
-
- private byte[] convertListOfIntToByteArray(List<Integer> input) {
- byte[] res = new byte[input.size()];
- for (int i = 0; i < res.length; ++i) {
- res[i] = input.get(i).byteValue();
- }
- return res;
- }
-
- private int readNextCharacter(PeekInputStream stream) throws IOException {
- int currentByte = stream.read();
- this.numberOfReadBytes++;
- return currentByte;
- }
-
- private void skipBlankSeparators(PeekInputStream stream) throws IOException {
- int nextByte = stream.peek();
- while (isBlankSperator(nextByte)) {
- readNextCharacter(stream);
- nextByte = stream.peek();
- }
- }
-
- private void skipSingleBlankSeparator(PeekInputStream stream) throws IOException {
- int nextByte = stream.peek();
- if(isBlankSperator(nextByte)) {
- readNextCharacter(stream);
- }
- }
- private boolean isBlankSperator(int character) {
- return (character == ' ' || character == '\n' || character == '\r');
- }
-
- private boolean isNotBlankSperator(int character) {
- return !isBlankSperator(character);
- }
-
- private boolean isEExecKeyWord(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return "eexec".equals(word);
- }
-
- private boolean isDefKeyWord(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return "def".equals(word);
- }
-
- private boolean isReadOnlyKeyWord(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return "readonly".equals(word);
- }
-
- private boolean isEncodingKeyWord(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return "/Encoding".equals(word);
- }
-
- private boolean isDupKeyWord(byte[] token) throws IOException {
- String word = new String(token, TOKEN_ENCODING);
- return "dup".equals(word);
- }
-
- private boolean isStartOfEExecReached() {
- return (this.numberOfReadBytes == this.clearTextSize);
- }
-
- private boolean isEndOfStream(PeekInputStream stream) {
- try {
- skipBlankSeparators(stream);
- return false;
- } catch (IOException e) {
- return true;
- }
- }
-}
\ No newline at end of file
+ public static final Logger LOGGER = Logger.getLogger(Type1Parser.class);
+
+ protected static final char NAME_START = '/';
+ protected static final String NOTDEF = NAME_START + ".notdef";
+ protected static final int DEFAULT_LEN_IV = 4;
+
+ private static final String PS_STANDARD_ENCODING = "StandardEncoding";
+ private static final String PS_ISOLATIN_ENCODING = "ISOLatin1Encoding";
+
+ private static final String TOKEN_ENCODING = "US-ASCII";
+
+ /**
+ * The PostScript font stream.
+ */
+ private PeekInputStream fontProgram = null;
+ /**
+ * The length in bytes of the clear-text portion of the Type1 font program.
+ */
+ private int clearTextSize = 0;
+ /**
+ * The length in bytes of the eexec encrypted portion of the type1 font program.
+ */
+ private int eexecSize = 0;
+
+ /**
+ * This counter is used to know how many byte have been read. It is used to read the clear part of the font. this
+ * computer is updated during the parsing of the encoding part too but it is not used.
+ */
+ private int numberOfReadBytes = 0;
+
+ /**
+ * Object which contains information coming from the parsing.
+ */
+ private Type1 type1Font = null;
+
+ private Type1Parser(InputStream type1, int length1, int length2, Encoding enc) throws IOException
+ {
+ super();
+ this.fontProgram = new PeekInputStream(type1);
+ this.clearTextSize = length1;
+ this.eexecSize = length2;
+ // ---- Instantiate the Encoding Map
+ if (enc != null)
+ {
+ this.type1Font = new Type1(enc);
+ }
+ else
+ {
+ this.type1Font = new Type1(new StandardEncoding());
+ }
+ this.type1Font.addCidWithLabel(-1, NOTDEF);
+ }
+
+ /**
+ *
+ * @param fontProgram
+ * the stream of the font program extracted from the PDF file.
+ * @param clearTextLength
+ * the length in bytes of the clear part of the font program.
+ * @param eexecLength
+ * the length in bytes of the encoded part.
+ * @return
+ * @throws IOException
+ */
+ public static Type1Parser createParser(InputStream fontProgram, int clearTextLength, int eexecLength)
+ throws IOException
+ {
+
+ Encoding encoding = getEncodingObject("");
+ return createParserWithEncodingObject(fontProgram, clearTextLength, eexecLength, encoding);
+ }
+
+ /**
+ *
+ * @param fontProgram
+ * the stream of the font program extracted from the PDF file.
+ * @param clearTextLength
+ * the length in bytes of the clear part of the font program.
+ * @param eexecLength
+ * the length in bytes of the encoded part.
+ * @param encodingName
+ * The name of encoding which is used by this font program.
+ * @return
+ * @throws IOException
+ */
+ public static Type1Parser createParserWithEncodingName(InputStream fontProgram, int clearTextLength,
+ int eexecLength, String encodingName) throws IOException
+ {
+
+ Encoding encoding = getEncodingObject(encodingName);
+ return createParserWithEncodingObject(fontProgram, clearTextLength, eexecLength, encoding);
+ }
+
+ private static Encoding getEncodingObject(String encodingName)
+ {
+ Encoding encoding = new StandardEncoding();
+ if (FONT_DICTIONARY_VALUE_ENCODING_MAC.equals(encodingName))
+ {
+ encoding = new MacRomanEncoding();
+ }
+ else if (FONT_DICTIONARY_VALUE_ENCODING_MAC_EXP.equals(encodingName))
+ {
+ encoding = new MacRomanEncoding();
+ }
+ else if (FONT_DICTIONARY_VALUE_ENCODING_WIN.equals(encodingName))
+ {
+ encoding = new WinAnsiEncoding();
+ }
+ else if (FONT_DICTIONARY_VALUE_ENCODING_PDFDOC.equals(encodingName))
+ {
+ encoding = new PdfDocEncoding();
+ }
+ return encoding;
+ }
+
+ /**
+ *
+ * @param fontProgram
+ * the stream of the font program extracted from the PDF file.
+ * @param clearTextLength
+ * the length in bytes of the clear part of the font program.
+ * @param eexecLength
+ * the length in bytes of the encoded part.
+ * @param encodingName
+ * The encoding object which is used by this font program.
+ * @return
+ * @throws IOException
+ */
+ public static Type1Parser createParserWithEncodingObject(InputStream fontProgram, int clearTextLength,
+ int eexecLength, Encoding encoding) throws IOException
+ {
+
+ return new Type1Parser(fontProgram, clearTextLength, eexecLength, encoding);
+ }
+
+ public Type1 parse() throws IOException
+ {
+ parseClearPartOfFontProgram(this.fontProgram);
+ decodeAndParseEExecPart(this.fontProgram);
+ return this.type1Font;
+ }
+
+ private void parseClearPartOfFontProgram(PeekInputStream stream) throws IOException
+ {
+ skipComments(stream);
+ parseFontInformationUntilEncodingPart(stream);
+ }
+
+ private void decodeAndParseEExecPart(PeekInputStream stream) throws IOException
+ {
+ byte[] eexecPart = readEexec(stream);
+ byte[] decodedEExecPart = decodeEexec(eexecPart);
+ PeekInputStream eexecStream = new PeekInputStream(new ByteArrayInputStream(decodedEExecPart));
+ parseEExecPart(eexecStream);
+ }
+
+ private void skipComments(PeekInputStream stream) throws IOException
+ {
+ int nextChar = stream.peek();
+ while (nextChar == '%')
+ {
+ if (nextChar == -1)
+ {
+ throw new IOException("Unexpected End Of File during a comment parsing");
+ }
+ readLine(stream);
+ nextChar = stream.peek();
+ }
+ }
+
+ private void parseFontInformationUntilEncodingPart(PeekInputStream stream) throws IOException
+ {
+ byte[] token = readToken(stream);
+ while (!isEExecKeyWord(token))
+ {
+ // add here specific operation to memorize useful information
+ if (isEncodingKeyWord(token))
+ {
+ parseEncodingDefinition(stream);
+ }
+ token = readToken(stream);
+ }
+
+ while (!isStartOfEExecReached())
+ {
+ readNextCharacter(stream);
+ }
+ }
+
+ private void parseEncodingDefinition(PeekInputStream stream) throws IOException
+ {
+ byte[] token = readToken(stream);
+ String readableToken = new String(token, TOKEN_ENCODING);
+ if (PS_ISOLATIN_ENCODING.equals(readableToken))
+ {
+ this.type1Font.initEncodingWithISOLatin1Encoding();
+ }
+ else if (PS_STANDARD_ENCODING.equals(readableToken))
+ {
+ this.type1Font.initEncodingWithStandardEncoding();
+ }
+ else
+ {
+ try
+ {
+ Integer.parseInt(readableToken);
+ throwExceptionIfUnexpectedToken("array", readToken(stream));
+ readEndSetEncodingValues(stream);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IOException("Invalid encoding : Expected int value before \"array\" "
+ + "key word if the Encoding isn't Standard or ISOLatin");
+ }
+ }
+ }
+
+ private void parseEExecPart(PeekInputStream stream) throws IOException
+ {
+ int lenIV = DEFAULT_LEN_IV;
+ byte[] previousToken = new byte[0];
+ while (!isEndOfStream(stream))
+ {
+ byte[] token = readToken(stream);
+ if (isLenIVKeyWord(token))
+ {
+ // lenIV belong to Private Dictionary.
+ // If you create a method to parse PrivateDict, please update this function
+ byte[] l = readToken(stream);
+ lenIV = Integer.parseInt(new String(l, TOKEN_ENCODING));
+ }
+ else if (isBeginOfBinaryPart(token))
+ {
+ try
+ {
+ int lengthOfBinaryPart = Integer.parseInt(new String(previousToken, TOKEN_ENCODING));
+ skipSingleBlankSeparator(stream);
+ stream.read(new byte[lengthOfBinaryPart], 0, lengthOfBinaryPart);
+ token = readToken(stream); // read the end of binary part
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IOException("Binary part found but previous token wasn't an integer");
+ }
+ }
+ else if (isCharStringKeyWord(token))
+ {
+ parseCharStringArray(stream, lenIV);
+ }
+ previousToken = token;
+ }
+ }
+
+ private void parseCharStringArray(PeekInputStream stream, int lenIV) throws IOException
+ {
+ int numberOfElements = readNumberOfCharStrings(stream);
+ goToBeginOfCharStringElements(stream);
+
+ while (numberOfElements > 0)
+ {
+ byte[] labelToken = readToken(stream);
+ String label = new String(labelToken, TOKEN_ENCODING);
+
+ if (label.equals("end"))
+ {
+ // TODO thrown exception ? add an error/warning in the PreflightContext ??
+ LOGGER.warn("[Type 1] Invalid number of elements in the CharString");
+ break;
+ }
+
+ byte[] sizeOfCharStringToken = readToken(stream);
+ int sizeOfCharString = Integer.parseInt(new String(sizeOfCharStringToken, TOKEN_ENCODING));
+
+ readToken(stream); // skip "RD" or "-|" token
+ skipSingleBlankSeparator(stream); // "RD" or "-|" are followed by a space
+
+ byte[] descBinary = new byte[sizeOfCharString];
+ stream.read(descBinary, 0, sizeOfCharString);
+ byte[] description = Type1FontUtil.charstringDecrypt(descBinary, lenIV);
+ Type1CharStringParser t1p = new Type1CharStringParser();
+ // TODO provide the local subroutine indexes
+ List<Object> operations = t1p.parse(description, new IndexData(0));
+ type1Font.addGlyphDescription(label, new GlyphDescription(operations));
+
+ readToken(stream); // skip "ND" or "|-" token
+ --numberOfElements;
+ }
+ }
+
+ private void goToBeginOfCharStringElements(PeekInputStream stream) throws IOException
+ {
+ byte[] token = new byte[0];
+ do
+ {
+ token = readToken(stream);
+ } while (isNotBeginKeyWord(token));
+ }
+
+ private boolean isNotBeginKeyWord(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return !"begin".equals(word);
+ }
+
+ private boolean isBeginOfBinaryPart(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return ("RD".equals(word) || "-|".equals(word));
+ }
+
+ private boolean isLenIVKeyWord(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return "/lenIV".equals(word);
+ }
+
+ private boolean isCharStringKeyWord(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return "/CharStrings".equals(word);
+ }
+
+ private int readNumberOfCharStrings(PeekInputStream stream) throws IOException
+ {
+ byte[] token = readToken(stream);
+ String word = new String(token, TOKEN_ENCODING);
+ try
+ {
+ return Integer.parseInt(word);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IOException("Number of CharStrings elements is expected.");
+ }
+ }
+
+ private void throwExceptionIfUnexpectedToken(String expectedValue, byte[] token) throws IOException
+ {
+ String valueToCheck = new String(token, TOKEN_ENCODING);
+ if (!expectedValue.equals(valueToCheck))
+ {
+ throw new IOException(expectedValue + " was expected but we received " + valueToCheck);
+ }
+ }
+
+ private void readEndSetEncodingValues(PeekInputStream stream) throws IOException
+ {
+ byte[] token = readToken(stream);
+ boolean lastTokenWasReadOnly = false;
+ while (!(lastTokenWasReadOnly && isDefKeyWord(token)))
+ {
+ if (isDupKeyWord(token))
+ {
+ byte[] cidToken = readToken(stream);
+ byte[] labelToken = readToken(stream);
+ String cid = new String(cidToken, TOKEN_ENCODING);
+ String label = new String(labelToken, TOKEN_ENCODING);
+ try
+ {
+ this.type1Font.addCidWithLabel(Integer.parseInt(cid), label);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IOException("Invalid encoding : Expected CID value before \"" + label + "\" label");
+ }
+ }
+ else
+ {
+ lastTokenWasReadOnly = isReadOnlyKeyWord(token);
+ }
+ token = readToken(stream);
+ }
+ }
+
+ private byte[] readEexec(PeekInputStream stream) throws IOException
+ {
+ int BUFFER_SIZE = 1024;
+ byte[] buffer = new byte[BUFFER_SIZE];
+ ByteArrayOutputStream eexecPart = new ByteArrayOutputStream();
+ int lr = 0;
+ int total = 0;
+ do
+ {
+ lr = stream.read(buffer, 0, BUFFER_SIZE);
+ if (lr == BUFFER_SIZE && (total + BUFFER_SIZE < eexecSize))
+ {
+ eexecPart.write(buffer, 0, BUFFER_SIZE);
+ total += BUFFER_SIZE;
+ }
+ else if (lr > 0 && (total + lr < eexecSize))
+ {
+ eexecPart.write(buffer, 0, lr);
+ total += lr;
+ }
+ else if (lr > 0 && (total + lr >= eexecSize))
+ {
+ eexecPart.write(buffer, 0, eexecSize - total);
+ total += (eexecSize - total);
+ }
+ } while (eexecSize > total && lr > 0);
+ IOUtils.closeQuietly(eexecPart);
+ return eexecPart.toByteArray();
+ }
+
+ private byte[] decodeEexec(byte[] eexec)
+ {
+ return Type1FontUtil.eexecDecrypt(eexec);
+ }
+
+ private byte[] readLine(PeekInputStream stream) throws IOException
+ {
+ ArrayList<Byte> bytes = new ArrayList<Byte>();
+ int currentCharacter = 0;
+
+ do
+ {
+ currentCharacter = readNextCharacter(stream);
+ bytes.add((byte) (currentCharacter & 0xFF));
+ } while (!('\n' == currentCharacter || '\r' == currentCharacter));
+
+ if ('\r' == currentCharacter && '\n' == stream.peek())
+ {
+ currentCharacter = readNextCharacter(stream);
+ bytes.add((byte) (currentCharacter & 0xFF));
+ }
+
+ byte[] result = new byte[bytes.size()];
+ for (int i = 0; i < bytes.size(); ++i)
+ {
+ result[i] = bytes.get(i);
+ }
+ return result;
+ }
+
+ private byte[] readToken(PeekInputStream stream) throws IOException
+ {
+ byte[] token = new byte[0];
+ skipBlankSeparators(stream);
+
+ int nextByte = stream.peek();
+ if (nextByte < 0)
+ {
+ throw new IOException("Unexpected End Of File");
+ }
+
+ if (nextByte == '(')
+ {
+ token = readStringLiteral(stream);
+ }
+ else if (nextByte == '[')
+ {
+ token = readArray(stream);
+ }
+ else if (nextByte == '{')
+ {
+ token = readProcedure(stream);
+ }
+ else
+ {
+ token = readNameOrArgument(stream);
+ }
+
+ return token;
+ }
+
+ private byte[] readStringLiteral(PeekInputStream stream) throws IOException
+ {
+ int opened = 0;
+ List<Integer> buffer = new ArrayList<Integer>();
+
+ int currentByte = 0;
+ do
+ {
+ currentByte = readNextCharacter(stream);
+ if (currentByte < 0)
+ {
+ throw new IOException("Unexpected End Of File");
+ }
+
+ if (currentByte == '(')
+ {
+ opened++;
+ }
+ else if (currentByte == ')')
+ {
+ opened--;
+ }
+
+ buffer.add(currentByte);
+ } while (opened != 0);
+
+ return convertListOfIntToByteArray(buffer);
+ }
+
+ private byte[] readArray(PeekInputStream stream) throws IOException
+ {
+ int opened = 0;
+ List<Integer> buffer = new ArrayList<Integer>();
+
+ int currentByte = 0;
+ do
+ {
+ currentByte = readNextCharacter(stream);
+ if (currentByte < 0)
+ {
+ throw new IOException("Unexpected End Of File");
+ }
+
+ if (currentByte == '[')
+ {
+ opened++;
+ }
+ else if (currentByte == ']')
+ {
+ opened--;
+ }
+
+ buffer.add(currentByte);
+ } while (opened != 0);
+
+ return convertListOfIntToByteArray(buffer);
+ }
+
+ private byte[] readProcedure(PeekInputStream stream) throws IOException
+ {
+ int opened = 0;
+ List<Integer> buffer = new ArrayList<Integer>();
+
+ int currentByte = 0;
+ do
+ {
+ currentByte = readNextCharacter(stream);
+ if (currentByte < 0)
+ {
+ throw new IOException("Unexpected End Of File");
+ }
+
+ if (currentByte == '{')
+ {
+ opened++;
+ }
+ else if (currentByte == '}')
+ {
+ opened--;
+ }
+
+ buffer.add(currentByte);
+ } while (opened != 0);
+
+ return convertListOfIntToByteArray(buffer);
+ }
+
+ private byte[] readNameOrArgument(PeekInputStream stream) throws IOException
+ {
+ List<Integer> buffer = new ArrayList<Integer>();
+ int nextByte = 0;
+ do
+ {
+ int currentByte = readNextCharacter(stream);
+ if (currentByte < 0)
+ {
+ throw new IOException("Unexpected End Of File");
+ }
+ buffer.add(currentByte);
+ nextByte = stream.peek();
+ } while (isNotBlankSperator(nextByte) && isNotBeginOfName(nextByte) && isNotSeparator(nextByte));
+
+ return convertListOfIntToByteArray(buffer);
+ }
+
+ private boolean isNotBeginOfName(int character)
+ {
+ return ('/' != character);
+ }
+
+ private boolean isNotSeparator(int character)
+ {
+ return !('{' == character || '}' == character || '[' == character || ']' == character);
+ }
+
+ private byte[] convertListOfIntToByteArray(List<Integer> input)
+ {
+ byte[] res = new byte[input.size()];
+ for (int i = 0; i < res.length; ++i)
+ {
+ res[i] = input.get(i).byteValue();
+ }
+ return res;
+ }
+
+ private int readNextCharacter(PeekInputStream stream) throws IOException
+ {
+ int currentByte = stream.read();
+ this.numberOfReadBytes++;
+ return currentByte;
+ }
+
+ private void skipBlankSeparators(PeekInputStream stream) throws IOException
+ {
+ int nextByte = stream.peek();
+ while (isBlankSperator(nextByte))
+ {
+ readNextCharacter(stream);
+ nextByte = stream.peek();
+ }
+ }
+
+ private void skipSingleBlankSeparator(PeekInputStream stream) throws IOException
+ {
+ int nextByte = stream.peek();
+ if (isBlankSperator(nextByte))
+ {
+ readNextCharacter(stream);
+ }
+ }
+
+ private boolean isBlankSperator(int character)
+ {
+ return (character == ' ' || character == '\n' || character == '\r');
+ }
+
+ private boolean isNotBlankSperator(int character)
+ {
+ return !isBlankSperator(character);
+ }
+
+ private boolean isEExecKeyWord(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return "eexec".equals(word);
+ }
+
+ private boolean isDefKeyWord(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return "def".equals(word);
+ }
+
+ private boolean isReadOnlyKeyWord(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return "readonly".equals(word);
+ }
+
+ private boolean isEncodingKeyWord(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return "/Encoding".equals(word);
+ }
+
+ private boolean isDupKeyWord(byte[] token) throws IOException
+ {
+ String word = new String(token, TOKEN_ENCODING);
+ return "dup".equals(word);
+ }
+
+ private boolean isStartOfEExecReached()
+ {
+ return (this.numberOfReadBytes == this.clearTextSize);
+ }
+
+ private boolean isEndOfStream(PeekInputStream stream)
+ {
+ try
+ {
+ skipBlankSeparators(stream);
+ return false;
+ }
+ catch (IOException e)
+ {
+ return true;
+ }
+ }
+}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaceHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaceHelper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaceHelper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaceHelper.java Wed Mar 6 16:46:35 2013
@@ -23,13 +23,13 @@ package org.apache.pdfbox.preflight.grap
import org.apache.pdfbox.preflight.exception.ValidationException;
-
-public interface ColorSpaceHelper {
- /**
- * Process the ColorSpace validation.
- *
- * @param result
- */
- public void validate() throws ValidationException;
+public interface ColorSpaceHelper
+{
+ /**
+ * Process the ColorSpace validation.
+ *
+ * @param result
+ */
+ public void validate() throws ValidationException;
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaceHelperFactory.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaceHelperFactory.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaceHelperFactory.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaceHelperFactory.java Wed Mar 6 16:46:35 2013
@@ -21,49 +21,49 @@
package org.apache.pdfbox.preflight.graphic;
-
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
import org.apache.pdfbox.preflight.PreflightContext;
/**
- * This factory create the right Helper according to the owner of the ColorSpace
- * entry.
+ * This factory create the right Helper according to the owner of the ColorSpace entry.
*/
-public class ColorSpaceHelperFactory {
+public class ColorSpaceHelperFactory
+{
- /**
- * Return an instance of ColorSpaceHelper according to the
- * ColorSpaceRestiction value.
- * <UL>
- * <li>ColorSpaceRestiction.NO_PATTERN : returns NoPatternColorSpaceHelper
- * <li>ColorSpaceRestiction.ONLY_DEVICE : returns DeviceColorSpaceHelper
- * <li>default : returns StandardColorSpaceHelper
- * </UL>
- *
- * @param context
- * the PreflightContext to access useful data
- * @param cs
- * the High level PDFBox object which represents the ColorSpace
- * @param csr
- * the color space restriction
- * @return
- */
- public ColorSpaceHelper getColorSpaceHelper(PreflightContext context, PDColorSpace cs, ColorSpaceRestriction csr) {
- switch (csr) {
- case NO_PATTERN:
- return new NoPatternColorSpaceHelper(context, cs);
- case ONLY_DEVICE:
- return new DeviceColorSpaceHelper(context, cs);
- default:
- return new StandardColorSpaceHelper(context, cs);
+ /**
+ * Return an instance of ColorSpaceHelper according to the ColorSpaceRestiction value.
+ * <UL>
+ * <li>ColorSpaceRestiction.NO_PATTERN : returns NoPatternColorSpaceHelper
+ * <li>ColorSpaceRestiction.ONLY_DEVICE : returns DeviceColorSpaceHelper
+ * <li>default : returns StandardColorSpaceHelper
+ * </UL>
+ *
+ * @param context
+ * the PreflightContext to access useful data
+ * @param cs
+ * the High level PDFBox object which represents the ColorSpace
+ * @param csr
+ * the color space restriction
+ * @return
+ */
+ public ColorSpaceHelper getColorSpaceHelper(PreflightContext context, PDColorSpace cs, ColorSpaceRestriction csr)
+ {
+ switch (csr)
+ {
+ case NO_PATTERN:
+ return new NoPatternColorSpaceHelper(context, cs);
+ case ONLY_DEVICE:
+ return new DeviceColorSpaceHelper(context, cs);
+ default:
+ return new StandardColorSpaceHelper(context, cs);
+ }
}
- }
- /**
- * Enum used as argument of methods of this factory to return the right
- * Helper.
- */
- public enum ColorSpaceRestriction {
- NO_RESTRICTION, NO_PATTERN, ONLY_DEVICE;
- }
+ /**
+ * Enum used as argument of methods of this factory to return the right Helper.
+ */
+ public enum ColorSpaceRestriction
+ {
+ NO_RESTRICTION, NO_PATTERN, ONLY_DEVICE;
+ }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaces.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaces.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaces.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/ColorSpaces.java Wed Mar 6 16:46:35 2013
@@ -22,41 +22,42 @@
package org.apache.pdfbox.preflight.graphic;
/**
- * This enum makes ColorSpaces validation easier. Labels represent ColorSpace
- * names as defined in the "PDF Reference 1.4". Enum entries with the "_SHORT"
- * suffix are used to represent color spaces (DeviceGray, DeviceRGB, DeviceCMYK
- * and Indexed) using the InlinedImage notation.
+ * This enum makes ColorSpaces validation easier. Labels represent ColorSpace names as defined in the
+ * "PDF Reference 1.4". Enum entries with the "_SHORT" suffix are used to represent color spaces (DeviceGray, DeviceRGB,
+ * DeviceCMYK and Indexed) using the InlinedImage notation.
*/
-public enum ColorSpaces {
+public enum ColorSpaces
+{
- Lab("Lab"), CalRGB("CalRGB"), CalGray("CalGray"), DeviceN("DeviceN"), Indexed(
- "Indexed"), Indexed_SHORT("I"), Pattern("Pattern"), ICCBased("ICCBased"), DeviceRGB(
- "DeviceRGB"), DeviceRGB_SHORT("RGB"), DeviceGray("DeviceGray"), DeviceGray_SHORT(
- "G"), DeviceCMYK("DeviceCMYK"), DeviceCMYK_SHORT("CMYK"), Separation(
- "Separation");
-
- /**
- * Name of the ColorSpace
- */
- public String label;
-
- private ColorSpaces(String _label) {
- label = _label;
- }
-
- /**
- * @return the label
- */
- public String getLabel() {
- return label;
- }
-
- /**
- * @param label
- * the label to set
- */
- public void setLabel(String label) {
- this.label = label;
- }
+ Lab("Lab"), CalRGB("CalRGB"), CalGray("CalGray"), DeviceN("DeviceN"), Indexed("Indexed"), Indexed_SHORT("I"), Pattern(
+ "Pattern"), ICCBased("ICCBased"), DeviceRGB("DeviceRGB"), DeviceRGB_SHORT("RGB"), DeviceGray("DeviceGray"), DeviceGray_SHORT(
+ "G"), DeviceCMYK("DeviceCMYK"), DeviceCMYK_SHORT("CMYK"), Separation("Separation");
+
+ /**
+ * Name of the ColorSpace
+ */
+ public String label;
+
+ private ColorSpaces(String _label)
+ {
+ label = _label;
+ }
+
+ /**
+ * @return the label
+ */
+ public String getLabel()
+ {
+ return label;
+ }
+
+ /**
+ * @param label
+ * the label to set
+ */
+ public void setLabel(String label)
+ {
+ this.label = label;
+ }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/DeviceColorSpaceHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/DeviceColorSpaceHelper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/DeviceColorSpaceHelper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/DeviceColorSpaceHelper.java Wed Mar 6 16:46:35 2013
@@ -32,54 +32,66 @@ import org.apache.pdfbox.preflight.Prefl
import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
/**
- * This class defines restrictions on Color Spaces. It checks the consistency of
- * the Color space with the DestOutputIntent, if the color space isn't a Device
- * Color space or a Indexed color space using Device the validation will fail.
+ * This class defines restrictions on Color Spaces. It checks the consistency of the Color space with the
+ * DestOutputIntent, if the color space isn't a Device Color space or a Indexed color space using Device the validation
+ * will fail.
*/
-public class DeviceColorSpaceHelper extends StandardColorSpaceHelper {
+public class DeviceColorSpaceHelper extends StandardColorSpaceHelper
+{
- public DeviceColorSpaceHelper(PreflightContext _context, PDColorSpace _cs) {
- super(_context, _cs);
- }
+ public DeviceColorSpaceHelper(PreflightContext _context, PDColorSpace _cs)
+ {
+ super(_context, _cs);
+ }
- /**
- * This method updates the given list with a ValidationError
- * (ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN) and returns false.
- */
- protected void processPatternColorSpace(PDColorSpace pdcs) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_FORBIDDEN, "Pattern ColorSpace is forbidden"));
- }
+ /**
+ * This method updates the given list with a ValidationError (ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN)
+ * and returns false.
+ */
+ protected void processPatternColorSpace(PDColorSpace pdcs)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_FORBIDDEN,
+ "Pattern ColorSpace is forbidden"));
+ }
- /**
- * This method updates the given list with a ValidationError
- * (ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN) and returns false.
- */
- protected void processDeviceNColorSpace(PDColorSpace pdcs) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_FORBIDDEN, "DeviceN ColorSpace is forbidden"));
- }
+ /**
+ * This method updates the given list with a ValidationError (ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN)
+ * and returns false.
+ */
+ protected void processDeviceNColorSpace(PDColorSpace pdcs)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_FORBIDDEN,
+ "DeviceN ColorSpace is forbidden"));
+ }
- /**
- * Indexed color space is authorized only if the BaseColorSpace is a DeviceXXX
- * color space. In all other cases the given list is updated with a
- * ValidationError (ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN) and
- * returns false.
- */
- protected void processIndexedColorSpace(PDColorSpace pdcs) {
- PDIndexed indexed = (PDIndexed) pdcs;
- try {
- PDColorSpace based = indexed.getBaseColorSpace();
- ColorSpaces colorSpace = ColorSpaces.valueOf(based.getName());
- switch (colorSpace) {
- case Indexed:
- case Indexed_SHORT:
- case Pattern:
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_FORBIDDEN, colorSpace.getLabel() + " ColorSpace is forbidden"));
- break;
- default:
- processAllColorSpace(based);
- }
- } catch (IOException e) {
- context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read Indexed Color Space : " + e.getMessage()));
- }
- }
+ /**
+ * Indexed color space is authorized only if the BaseColorSpace is a DeviceXXX color space. In all other cases the
+ * given list is updated with a ValidationError (ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN) and returns
+ * false.
+ */
+ protected void processIndexedColorSpace(PDColorSpace pdcs)
+ {
+ PDIndexed indexed = (PDIndexed) pdcs;
+ try
+ {
+ PDColorSpace based = indexed.getBaseColorSpace();
+ ColorSpaces colorSpace = ColorSpaces.valueOf(based.getName());
+ switch (colorSpace)
+ {
+ case Indexed:
+ case Indexed_SHORT:
+ case Pattern:
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_FORBIDDEN, colorSpace
+ .getLabel() + " ColorSpace is forbidden"));
+ break;
+ default:
+ processAllColorSpace(based);
+ }
+ }
+ catch (IOException e)
+ {
+ context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE,
+ "Unable to read Indexed Color Space : " + e.getMessage()));
+ }
+ }
}