You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2011/07/24 16:02:33 UTC
svn commit: r1150373 [7/12] - in /pdfbox/trunk/preflight: ./ src/ src/main/
src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/padaf/ src/main/java/org/apache/padaf/preflight/
src/main/java/org/apache/padaf/preflight/a...
Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,461 @@
+/*****************************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+package org.apache.padaf.preflight.font.type1;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+
+import org.apache.padaf.preflight.ValidationConstants;
+import org.apache.padaf.preflight.font.GlyphException;
+import org.apache.pdfbox.encoding.Encoding;
+
+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(ValidationConstants.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
Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1Parser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1Parser.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1Parser.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1Parser.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,583 @@
+/*****************************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+package org.apache.padaf.preflight.font.type1;
+
+import static org.apache.padaf.preflight.ValidationConstants.FONT_DICTIONARY_VALUE_ENCODING_MAC;
+import static org.apache.padaf.preflight.ValidationConstants.FONT_DICTIONARY_VALUE_ENCODING_MAC_EXP;
+import static org.apache.padaf.preflight.ValidationConstants.FONT_DICTIONARY_VALUE_ENCODING_PDFDOC;
+import static org.apache.padaf.preflight.ValidationConstants.FONT_DICTIONARY_VALUE_ENCODING_WIN;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.fontbox.cff.Type1CharStringParser;
+import org.apache.fontbox.cff.Type1FontUtil;
+import org.apache.pdfbox.encoding.Encoding;
+import org.apache.pdfbox.encoding.MacRomanEncoding;
+import org.apache.pdfbox.encoding.PdfDocEncoding;
+import org.apache.pdfbox.encoding.StandardEncoding;
+import org.apache.pdfbox.encoding.WinAnsiEncoding;
+
+public class Type1Parser {
+ 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) {
+ readCharStringElement(stream, lenIV);
+ --numberOfElements;
+ }
+ }
+
+ private void goToBeginOfCharStringElements(PeekInputStream stream) throws IOException {
+ byte[] token = new byte[0];
+ do {
+ token = readToken(stream);
+ } while(isNotBeginKeyWord(token));
+ }
+
+ private void readCharStringElement(PeekInputStream stream, int lenIV) throws IOException {
+ byte[] labelToken = readToken(stream);
+ String label = new String(labelToken, TOKEN_ENCODING);
+
+ 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();
+ List<Object> operations = t1p.parse(description);
+ type1Font.addGlyphDescription(label, new GlyphDescription(operations));
+
+ readToken(stream); // skip "ND" or "|-" 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 "/Encoding".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
Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/type1/Type1Parser.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/AbstractXObjValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/AbstractXObjValidator.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/AbstractXObjValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/AbstractXObjValidator.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,182 @@
+/*****************************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+package org.apache.padaf.preflight.graphics;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import org.apache.padaf.preflight.DocumentHandler;
+import org.apache.padaf.preflight.ValidationConstants;
+import org.apache.padaf.preflight.ValidationException;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.padaf.preflight.utils.COSUtils;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDocument;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
+
+import static org.apache.padaf.preflight.ValidationConstants.*;
+
+/**
+ * This class processes commons validations of XObjects.
+ */
+public abstract class AbstractXObjValidator implements XObjectValidator {
+ /**
+ * The XObject to validate as a COSStream.
+ */
+ protected COSStream xobject = null;
+ /**
+ * The document handler which contains useful information to process
+ * validation.
+ */
+ protected DocumentHandler handler = null;
+ /**
+ * The PDF document as COSDocument.
+ */
+ protected COSDocument cosDocument = null;
+
+ public AbstractXObjValidator(DocumentHandler handler, COSStream xobj) {
+ this.xobject = xobj;
+ this.handler = handler;
+ this.cosDocument = handler.getDocument().getDocument();
+ }
+
+ /**
+ * This method checks the SMask entry in the XObject dictionary. According to
+ * the PDF Reference, a SMask in a XObject is a Stream. So if it is not null,
+ * it should be an error but a SMask with the name None is authorized in the
+ * PDF/A Specification 6.4. If the validation fails (SMask not null and
+ * different from None), the error list is updated with the error code
+ * ERROR_GRAPHIC_TRANSPARENCY_SMASK (2.2.2).
+ *
+ * @param error
+ * the list of error to update if the validation fails
+ * @return true if the SMask is valid, false otherwise.
+ */
+ protected boolean checkSMask(List<ValidationError> error) {
+ COSBase smask = xobject.getItem(COSName
+ .getPDFName(TRANSPARENCY_DICTIONARY_KEY_SOFT_MASK));
+ //
+ if (smask != null
+ && !(COSUtils.isString(smask, cosDocument) && TRANSPARENCY_DICTIONARY_VALUE_SOFT_MASK_NONE
+ .equals(COSUtils.getAsString(smask, cosDocument)))) {
+ error.add(new ValidationError(ERROR_GRAPHIC_TRANSPARENCY_SMASK, "Soft Mask must be null or None"));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * According the ISO 190005:1-2005 specification, a XObject can't have an OPI
+ * entry in its dictionary. If the XObject has a OPI entry, the error list is
+ * updated with the error code ERROR_GRAPHIC_UNEXPECTED_KEY (2.3).
+ *
+ * @param errors
+ * the list of error to update if the validation fails.
+ * @return true if the OPI is missing, false otherwise.
+ */
+ protected boolean checkOPI(List<ValidationError> errors) {
+ // 6.2.4 and 6.2.5 no OPI
+ if (this.xobject.getItem(COSName.getPDFName("OPI")) != null) {
+ errors.add(new ValidationError(
+ ValidationConstants.ERROR_GRAPHIC_UNEXPECTED_KEY,
+ "Unexpected 'OPI' Key"));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * According the ISO 190005:1-2005 specification, a XObject can't have an Ref
+ * entry in its dictionary. If the XObject has a Ref entry, the error list is
+ * updated with the error code ERROR_GRAPHIC_UNEXPECTED_KEY (2.3).
+ *
+ * @param errors
+ * the list of error to update if the validation fails.
+ * @return true if the Ref is missing, false otherwise.
+ */
+ protected boolean checkReferenceXObject(List<ValidationError> errors) {
+ // 6.2.6 No reference xobject
+ if (this.xobject.getItem(COSName.getPDFName("Ref")) != null) {
+ errors.add(new ValidationError(ERROR_GRAPHIC_UNEXPECTED_KEY,
+ "No reference Xobject allowed in PDF/A"));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * According the ISO 190005:1-2005 specification, PostSCript XObject are
+ * forbidden. If the XObject is a PostScript XObject, the error list is
+ * updated with the error code ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY (2.3.2).
+ *
+ * To know the if the object a Postscript XObject, "Subtype" and "Subtype2"
+ * entries are checked.
+ *
+ * @param errors
+ * the list of error to update if the validation fails.
+ * @return true if the XObject isn't a Postscript XObject, false otherwise.
+ */
+ protected boolean checkPostscriptXObject(List<ValidationError> errors) {
+ // 6.2.7 No PostScript XObjects
+ if (this.xobject.getItem(COSName.SUBTYPE) != null
+ && XOBJECT_DICTIONARY_VALUE_SUBTYPE_POSTSCRIPT.equals(this.xobject
+ .getNameAsString(COSName.SUBTYPE))) {
+ errors.add(new ValidationError(ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY,
+ "No Postscript Xobject allowed in PDF/A"));
+ return false;
+ }
+ if (this.xobject.getItem(COSName.getPDFName("Subtype2")) != null) {
+ errors.add(new ValidationError(ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY,
+ "No Postscript Xobject allowed in PDF/A (Subtype2)"));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This method checks if required fields are present.
+ *
+ * @param result
+ * the list of error to update if the validation fails.
+ * @return true if all fields are present, false otherwise.
+ */
+ protected abstract boolean checkMandatoryFields(List<ValidationError> result);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.graphics.XObjectValidator#validate()
+ */
+ public List<ValidationError> validate() throws ValidationException {
+ List<ValidationError> result = new ArrayList<ValidationError>(0);
+ if (checkMandatoryFields(result)) {
+ checkOPI(result);
+ checkSMask(result);
+ checkReferenceXObject(result);
+ checkPostscriptXObject(result);
+ }
+ return result;
+ }
+}
Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/AbstractXObjValidator.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ExtGStateContainer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ExtGStateContainer.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ExtGStateContainer.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ExtGStateContainer.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,275 @@
+/*****************************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+package org.apache.padaf.preflight.graphics;
+
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_TRANSPARENCY_EXT_GS_BLEND_MODE;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_TRANSPARENCY_EXT_GS_CA;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_TRANSPARENCY_EXT_GS_SOFT_MASK;
+import static org.apache.padaf.preflight.ValidationConstants.TRANPARENCY_DICTIONARY_KEY_EXTGSTATE;
+import static org.apache.padaf.preflight.ValidationConstants.TRANPARENCY_DICTIONARY_KEY_EXTGSTATE_ENTRY_REGEX;
+import static org.apache.padaf.preflight.ValidationConstants.TRANSPARENCY_DICTIONARY_KEY_BLEND_MODE;
+import static org.apache.padaf.preflight.ValidationConstants.TRANSPARENCY_DICTIONARY_KEY_LOWER_CA;
+import static org.apache.padaf.preflight.ValidationConstants.TRANSPARENCY_DICTIONARY_KEY_SOFT_MASK;
+import static org.apache.padaf.preflight.ValidationConstants.TRANSPARENCY_DICTIONARY_KEY_UPPER_CA;
+import static org.apache.padaf.preflight.ValidationConstants.TRANSPARENCY_DICTIONARY_VALUE_BM_COMPATIBLE;
+import static org.apache.padaf.preflight.ValidationConstants.TRANSPARENCY_DICTIONARY_VALUE_BM_NORMAL;
+import static org.apache.padaf.preflight.ValidationConstants.TRANSPARENCY_DICTIONARY_VALUE_SOFT_MASK_NONE;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import org.apache.padaf.preflight.ValidationConstants;
+import org.apache.padaf.preflight.ValidationException;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.padaf.preflight.utils.COSUtils;
+import org.apache.padaf.preflight.utils.RenderingIntents;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSDocument;
+import org.apache.pdfbox.cos.COSName;
+
+/**
+ * This class wraps a list of COSDictionary which represent an extended graphics
+ * state dictionary.
+ */
+public class ExtGStateContainer {
+ /**
+ * The COSDocument which contains the extended graphic states.
+ */
+ private COSDocument cDoc = null;
+ /**
+ * A list of Extended Graphic States.
+ */
+ private List<COSDictionary> listOfExtGState = new ArrayList<COSDictionary>(0);
+
+ /**
+ * Create an instance of ExtGStateContainer using a Resource dictionary and a
+ * COSDocument. This constructor initializes the listOfExtGState attribute
+ * using the given Resource dictionary and the COSDocument.
+ *
+ * @param resources
+ * a resource COSDictionary
+ * @param cDoc
+ * the COSDocument which contains the Resource dictionary
+ * @throws ValidationException
+ * thrown if a the Extended Graphic State isn't valid
+ */
+ public ExtGStateContainer(COSDictionary resources, COSDocument cDoc)
+ throws ValidationException {
+ this.cDoc = cDoc;
+ COSBase egsEntry = resources.getItem(COSName
+ .getPDFName(TRANPARENCY_DICTIONARY_KEY_EXTGSTATE));
+ COSDictionary extGStates = COSUtils.getAsDictionary(egsEntry, cDoc);
+
+ if (extGStates != null) {
+ for (Object object : extGStates.keySet()) {
+ COSName key = (COSName) object;
+ if (key.getName().matches(
+ TRANPARENCY_DICTIONARY_KEY_EXTGSTATE_ENTRY_REGEX)) {
+ COSBase gsBase = extGStates.getItem(key);
+ COSDictionary gsDict = COSUtils.getAsDictionary(gsBase, cDoc);
+ if (gsDict == null) {
+ throw new ValidationException(
+ "The Extended Graphics State dictionary is invalid");
+ }
+ this.listOfExtGState.add(gsDict);
+ }
+ }
+ }
+ //else if there are no ExtGState, the list will be empty.
+
+ }
+
+ /**
+ * Validate all ExtGState dictionaries of this container
+ *
+ * @param error
+ * the list of error to update if the validation fails.
+ * @return true if all Graphic States are valid, false otherwise.
+ */
+ public boolean validateTransparencyRules(List<ValidationError> error) {
+ boolean res = true;
+
+ for (COSDictionary egs : listOfExtGState) {
+ res = res && checkSoftMask(egs, error);
+ res = res && checkCA(egs, error);
+ res = res && checkBlendMode(egs, error);
+ res = res && checkTRKey(egs, error);
+ res = res && checkTR2Key(egs, error);
+ }
+
+ return res;
+ }
+
+ /**
+ * This method checks the SMask value of the ExtGState dictionary. The Soft
+ * Mask is optional but must be "None" if it is present.
+ *
+ * @param egs
+ * the Graphic state to check
+ * @param error
+ * the list of error to update if the validation fails.
+ * @return true if SMask is missing or equals to None
+ */
+ private boolean checkSoftMask(COSDictionary egs, List<ValidationError> error) {
+ COSBase smVal = egs.getItem(COSName
+ .getPDFName(TRANSPARENCY_DICTIONARY_KEY_SOFT_MASK));
+ if (smVal != null) {
+ // ---- Soft Mask is valid only if it is a COSName equals to None
+ if (!(smVal instanceof COSName && TRANSPARENCY_DICTIONARY_VALUE_SOFT_MASK_NONE
+ .equals(((COSName) smVal).getName()))) {
+ error.add(new ValidationError(ERROR_TRANSPARENCY_EXT_GS_SOFT_MASK, "SoftMask must be null or None"));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * This method checks the BM value of the ExtGState dictionary. The Blend Mode
+ * is optional but must be "Normal" or "Compatible" if it is present.
+ *
+ * @param egs
+ * the graphic state to check
+ * @param error
+ * the list of error to update if the validation fails.
+ * @return true if BM is missing or equals to "Normal" or "Compatible"
+ */
+ private boolean checkBlendMode(COSDictionary egs, List<ValidationError> error) {
+ COSBase bmVal = egs.getItem(COSName
+ .getPDFName(TRANSPARENCY_DICTIONARY_KEY_BLEND_MODE));
+ if (bmVal != null) {
+ // ---- Blend Mode is valid only if it is equals to Normal or Compatible
+ if (!(bmVal instanceof COSName && (TRANSPARENCY_DICTIONARY_VALUE_BM_NORMAL
+ .equals(((COSName) bmVal).getName()) || TRANSPARENCY_DICTIONARY_VALUE_BM_COMPATIBLE
+ .equals(((COSName) bmVal).getName())))) {
+ error.add(new ValidationError(ERROR_TRANSPARENCY_EXT_GS_BLEND_MODE,"BlendMode value isn't valid (only Normal and Compatible are authorized)"));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * This method checks the "CA" and "ca" values of the ExtGState dictionary.
+ * They are optional but must be 1.0 if they are present.
+ *
+ * @param egs
+ * the graphic state to check
+ * @param error
+ * the list of error to update if the validation fails.
+ * @return true if CA/ca is missing or equals to 1.0
+ */
+ private boolean checkCA(COSDictionary egs, List<ValidationError> error) {
+ COSBase uCA = egs.getItem(COSName
+ .getPDFName(TRANSPARENCY_DICTIONARY_KEY_UPPER_CA));
+ COSBase lCA = egs.getItem(COSName
+ .getPDFName(TRANSPARENCY_DICTIONARY_KEY_LOWER_CA));
+ if (uCA != null) {
+ // ---- If CA is present only the value 1.0 is authorized
+ Float fca = COSUtils.getAsFloat(uCA, cDoc);
+ Integer ica = COSUtils.getAsInteger(uCA, cDoc);
+ if (!(fca != null && fca == 1.0f) && !(ica != null && ica == 1)) {
+ error.add(new ValidationError(ERROR_TRANSPARENCY_EXT_GS_CA,"CA entry in a ExtGState is invalid"));
+ return false;
+ }
+ }
+
+ if (lCA != null) {
+ // ---- If ca is present only the value 1.0 is authorized
+ Float fca = COSUtils.getAsFloat(lCA, cDoc);
+ Integer ica = COSUtils.getAsInteger(lCA, cDoc);
+ if (!(fca != null && fca == 1.0f) && !(ica != null && ica == 1)) {
+ error.add(new ValidationError(ERROR_TRANSPARENCY_EXT_GS_CA,"ca entry in a ExtGState is invalid."));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check the TR entry. A valid ExtGState hasn't TR entry.
+ *
+ * @param egs
+ * the graphic state to check
+ * @param error
+ * the list of error to update if the validation fails.
+ * @return true if TR entry is missing, false otherwise.
+ */
+ protected boolean checkTRKey(COSDictionary egs, List<ValidationError> error) {
+ if (egs.getItem(COSName.getPDFName("TR")) != null) {
+ error.add(new ValidationError(
+ ValidationConstants.ERROR_GRAPHIC_UNEXPECTED_KEY,
+ "No TR key expected in Extended graphics state"));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check the TR2 entry. A valid ExtGState hasn't TR2 entry or a TR2 entry
+ * equals to "default".
+ *
+ * @param egs
+ * the graphic state to check
+ * @param error
+ * the list of error to update if the validation fails.
+ * @return true if TR2 entry is missing or equals to "default", false
+ * otherwise.
+ */
+ protected boolean checkTR2Key(COSDictionary egs, List<ValidationError> error) {
+ if (egs.getItem(COSName.getPDFName("TR2")) != null) {
+ String s = egs.getNameAsString(COSName.getPDFName("TR2"));
+ if (!"default".equals(s)) {
+ error.add(new ValidationError(
+ ValidationConstants.ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY,
+ "TR2 key only expect 'default' value, not '" + s + "'"));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check the RI entry of the Graphic State. If the rendering intent entry is
+ * present, the value must be one of the four values defined in the PDF
+ * reference. (@see net.awl.edoc.pdfa.validation.utils.RenderingIntents)
+ *
+ * @param egs
+ * the graphic state to check
+ * @param error
+ * the list of error to update if the validation fails.
+ * @return true if RI entry is valid, false otherwise.
+ */
+ protected boolean checkRIKey(COSDictionary egs, List<ValidationError> error) {
+ String rendenringIntent = egs.getNameAsString(COSName.getPDFName("RI"));
+ if (rendenringIntent != null && !"".equals(rendenringIntent)
+ && !RenderingIntents.contains(rendenringIntent)) {
+ error.add(new ValidationError(
+ ValidationConstants.ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY,
+ "Invalid rendering intent value in Extended graphics state"));
+ return false;
+ }
+ return true;
+ }
+}
Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ExtGStateContainer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ICCProfileWrapper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ICCProfileWrapper.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ICCProfileWrapper.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ICCProfileWrapper.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,90 @@
+/*****************************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+package org.apache.padaf.preflight.graphics;
+
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ICC_Profile;
+
+/**
+ * This class embeds an instance of java.awt.color.ICC_Profile which represent
+ * the ICCProfile defined by the DestOutputItents key of the OutputIntents of
+ * the PDF.
+ */
+public class ICCProfileWrapper {
+ /**
+ * The ICCProfile extracted from DestOutputItents
+ */
+ private ICC_Profile profile = null;
+
+ /**
+ * The ICC ColorSpace created using the ICCProfile
+ */
+ private ICC_ColorSpace colorSpace = null;
+
+ public ICCProfileWrapper(ICC_Profile _profile) {
+ this.profile = _profile;
+ this.colorSpace = new ICC_ColorSpace(_profile);
+ }
+
+ /**
+ * Call the ICC_ColorSpace.getType method and return the value.
+ *
+ * @return
+ */
+ public int getColorSpaceType() {
+ return colorSpace.getType();
+ }
+
+ /**
+ * @return the profile
+ */
+ public ICC_Profile getProfile() {
+ return profile;
+ }
+
+ /**
+ * Return true if the ColourSpace is RGB
+ *
+ * @return
+ */
+ public boolean isRGBColorSpace() {
+ return ICC_ColorSpace.TYPE_RGB == colorSpace.getType();
+ }
+
+ /**
+ * Return true if the ColourSpace is CMYK
+ *
+ * @return
+ */
+ public boolean isCMYKColorSpace() {
+ return ICC_ColorSpace.TYPE_CMYK == colorSpace.getType();
+ }
+
+ /**
+ * Return true if the ColourSpace is Gray scale
+ *
+ * @return
+ */
+ public boolean isGrayColorSpace() {
+ return ICC_ColorSpace.TYPE_GRAY == colorSpace.getType();
+ }
+}
Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ICCProfileWrapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ShadingPattern.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ShadingPattern.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ShadingPattern.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ShadingPattern.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,172 @@
+/*****************************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+package org.apache.padaf.preflight.graphics;
+
+import static org.apache.padaf.preflight.ValidationConstants.DICTIONARY_KEY_TYPE;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_PATTERN_DEFINITION;
+import static org.apache.padaf.preflight.ValidationConstants.PATTERN_KEY_SHADING;
+import static org.apache.padaf.preflight.ValidationConstants.PATTERN_KEY_SHADING_TYPE;
+import static org.apache.padaf.preflight.ValidationConstants.TRANPARENCY_DICTIONARY_KEY_EXTGSTATE;
+import static org.apache.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_KEY_COLOR_SPACE;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import org.apache.padaf.preflight.DocumentHandler;
+import org.apache.padaf.preflight.ValidationException;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.padaf.preflight.graphics.color.ColorSpaceHelper;
+import org.apache.padaf.preflight.graphics.color.ColorSpaceHelperFactory;
+import org.apache.padaf.preflight.graphics.color.ColorSpaceHelperFactory.ColorSpaceRestriction;
+import org.apache.padaf.preflight.utils.COSUtils;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSDocument;
+import org.apache.pdfbox.cos.COSName;
+
+/**
+ * This class process the validation of a ShadingPattern object.
+ */
+public class ShadingPattern implements XObjectValidator {
+ /**
+ * COSDictionary which represent the shading pattern.
+ */
+ private COSDictionary pattern = null;
+ /**
+ * The COSDocument which contains the shading pattern to check.
+ */
+ private COSDocument cosDoc = null;
+ /**
+ * The document handler which contains useful information to process the
+ * validation.
+ */
+ private DocumentHandler documentHandler = null;
+
+ /**
+ * @param _handler
+ * DocumentHandler used to initialize "documentHandler" and "cosDoc"
+ * attributes.
+ * @param _pattern
+ * COSDictionary used to initialize the shading pattern to validate.
+ */
+ public ShadingPattern(DocumentHandler _handler, COSDictionary _pattern) {
+ this.documentHandler = _handler;
+ this.pattern = _pattern;
+ this.cosDoc = this.documentHandler.getDocument().getDocument();
+ }
+
+ /**
+ * Because of a Shading Pattern can be used as an Indirect Object or Directly
+ * define in an other dictionary, there are two ways to obtain the Shading
+ * Pattern dictionary according to the pattern attribute. This method returns
+ * the Shading pattern dictionary represented by the pattern attribute or
+ * contained in it.
+ *
+ * This is the first method called by the validate method.
+ *
+ * @param errors
+ * the list of error to update if there are no Shading pattern in the
+ * pattern COSDictionary.
+ * @return the ShadingPattern dictionary
+ */
+ protected COSDictionary getShadingDictionary(List<ValidationError> errors) {
+ if (!"Shading".equals(pattern.getNameAsString(COSName
+ .getPDFName(DICTIONARY_KEY_TYPE)))) {
+ COSBase shading = pattern
+ .getItem(COSName.getPDFName(PATTERN_KEY_SHADING));
+ if (shading == null) {
+ errors
+ .add(new ValidationError(ERROR_GRAPHIC_INVALID_PATTERN_DEFINITION));
+ return null;
+ }
+ return COSUtils.getAsDictionary(shading, cosDoc);
+ } else {
+ return pattern;
+ }
+ }
+
+ /**
+ * Checks if the given shading pattern contains the ShadingType entry and if
+ * the ColorSapce entry is consistent which rules of the PDF Reference and the
+ * ISO 190005-1:2005 Specification.
+ *
+ * This method is called by the validate method.
+ *
+ * @param shadingDict
+ * the Shading pattern dictionary to check
+ * @param errors
+ * the list of error to update if the validation fails
+ * @return true if the Shading pattern is valid, false otherwise.
+ * @throws ValidationException
+ */
+ protected boolean checkShadingDictionary(COSDictionary shadingDict,
+ List<ValidationError> errors) throws ValidationException {
+ if (shadingDict.getItem(COSName.getPDFName(PATTERN_KEY_SHADING_TYPE)) == null) {
+ errors.add(new ValidationError(ERROR_GRAPHIC_INVALID_PATTERN_DEFINITION));
+ return false;
+ }
+
+ COSBase csImg = shadingDict.getItem(COSName
+ .getPDFName(XOBJECT_DICTIONARY_KEY_COLOR_SPACE));
+ ColorSpaceHelper csh = ColorSpaceHelperFactory.getColorSpaceHelper(csImg,
+ documentHandler, ColorSpaceRestriction.NO_PATTERN);
+ return csh.validate(errors);
+ }
+
+ /**
+ * Check the Extended Graphic State contains in the ShadingPattern dictionary
+ * if it is present. To check this ExtGState, this method uses the
+ * net.awl.edoc.pdfa.validation.graphics.ExtGStateContainer object.
+ *
+ * @param errors
+ * the list of error to update if the validation fails
+ * @return true is the ExtGState is missing or valid, false otherwise.
+ * @throws ValidationException
+ */
+ protected boolean checkGraphicState(List<ValidationError> errors)
+ throws ValidationException {
+ COSDictionary resources = (COSDictionary) this.pattern
+ .getDictionaryObject(TRANPARENCY_DICTIONARY_KEY_EXTGSTATE);
+ if (resources != null) {
+ ExtGStateContainer extContainer = new ExtGStateContainer(resources,
+ cosDoc);
+ return extContainer.validateTransparencyRules(errors);
+ }
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.graphics.XObjectValidator#validate()
+ */
+ public List<ValidationError> validate() throws ValidationException {
+ List<ValidationError> result = new ArrayList<ValidationError>();
+ COSDictionary shading = getShadingDictionary(result);
+ if (shading != null) {
+ boolean isValid = checkShadingDictionary(shading, result);
+ isValid = isValid && checkGraphicState(result);
+ }
+ return result;
+ }
+}
Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/ShadingPattern.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/TilingPattern.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/TilingPattern.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/TilingPattern.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/TilingPattern.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,114 @@
+/*****************************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+package org.apache.padaf.preflight.graphics;
+
+import static org.apache.padaf.preflight.ValidationConstants.DICTIONARY_KEY_RESOURCES;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_PATTERN_DEFINITION;
+import static org.apache.padaf.preflight.ValidationConstants.PATTERN_KEY_BBOX;
+import static org.apache.padaf.preflight.ValidationConstants.PATTERN_KEY_PAINT_TYPE;
+import static org.apache.padaf.preflight.ValidationConstants.PATTERN_KEY_TILING_TYPE;
+import static org.apache.padaf.preflight.ValidationConstants.PATTERN_KEY_XSTEP;
+import static org.apache.padaf.preflight.ValidationConstants.PATTERN_KEY_YSTEP;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import org.apache.padaf.preflight.DocumentHandler;
+import org.apache.padaf.preflight.ValidationException;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.padaf.preflight.contentstream.ContentStreamWrapper;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
+
+public class TilingPattern implements XObjectValidator {
+ /**
+ * The COSStream which represents the TilingPattern.
+ */
+ private COSStream pattern = null;
+ /**
+ * The document handler which contains useful information to process the
+ * validation.
+ */
+ private DocumentHandler documentHandler = null;
+
+ public TilingPattern(DocumentHandler _handler, COSStream _pattern) {
+ this.documentHandler = _handler;
+ this.pattern = _pattern;
+ }
+
+ /**
+ * Validate the Pattern content like Color and Show Text Operators using an
+ * instance of ContentStreamWrapper.
+ *
+ * @param errors
+ * the list of error to update if the validation fails.
+ * @return
+ * @throws ValidationException
+ */
+ protected boolean parsePatternContent(List<ValidationError> errors)
+ throws ValidationException {
+ ContentStreamWrapper csWrapper = new ContentStreamWrapper(documentHandler);
+ List<ValidationError> csParseErrors = csWrapper
+ .validPatternContentStream(pattern);
+ if (csParseErrors == null
+ || (csParseErrors != null && csParseErrors.isEmpty())) {
+ return true;
+ }
+ errors.addAll(csParseErrors);
+ return false;
+ }
+
+ /**
+ * This method checks if required fields are present.
+ *
+ * @param result
+ * the list of error to update if the validation fails.
+ * @return true if all fields are present, false otherwise.
+ */
+ protected boolean checkMandatoryFields(List<ValidationError> errors) {
+ boolean res = pattern.getItem(COSName.getPDFName(DICTIONARY_KEY_RESOURCES)) != null;
+ res = res && pattern.getItem(COSName.getPDFName(PATTERN_KEY_BBOX)) != null;
+ res = res
+ && pattern.getItem(COSName.getPDFName(PATTERN_KEY_PAINT_TYPE)) != null;
+ res = res
+ && pattern.getItem(COSName.getPDFName(PATTERN_KEY_TILING_TYPE)) != null;
+ res = res && pattern.getItem(COSName.getPDFName(PATTERN_KEY_XSTEP)) != null;
+ res = res && pattern.getItem(COSName.getPDFName(PATTERN_KEY_YSTEP)) != null;
+ if (!res) {
+ errors.add(new ValidationError(ERROR_GRAPHIC_INVALID_PATTERN_DEFINITION));
+ }
+ return res;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.graphics.XObjectValidator#validate()
+ */
+ public List<ValidationError> validate() throws ValidationException {
+ List<ValidationError> result = new ArrayList<ValidationError>();
+ boolean isValid = checkMandatoryFields(result);
+ isValid = isValid && parsePatternContent(result);
+ return result;
+ }
+}
Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/TilingPattern.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/XObjFormValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/XObjFormValidator.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/XObjFormValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/XObjFormValidator.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,256 @@
+/*****************************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+package org.apache.padaf.preflight.graphics;
+
+import static org.apache.padaf.preflight.ValidationConstants.DICTIONARY_KEY_TYPE;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_BBOX;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_MISSING_FIELD;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_TRANSPARENCY_GROUP;
+import static org.apache.padaf.preflight.ValidationConstants.PATTERN_KEY_SHADING;
+import static org.apache.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_KEY_BBOX;
+import static org.apache.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_KEY_GROUP;
+import static org.apache.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_KEY_GROUP_S;
+import static org.apache.padaf.preflight.ValidationConstants.XOBJECT_DICTIONARY_VALUE_S_TRANSPARENCY;
+
+import java.util.List;
+
+
+import org.apache.padaf.preflight.DocumentHandler;
+import org.apache.padaf.preflight.ValidationConstants;
+import org.apache.padaf.preflight.ValidationException;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.padaf.preflight.contentstream.ContentStreamWrapper;
+import org.apache.padaf.preflight.utils.COSUtils;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;
+
+/**
+ * This class validates XObject with the Form subtype.
+ */
+public class XObjFormValidator extends AbstractXObjValidator {
+ /**
+ * High level object which represents the XObjectForm
+ */
+ PDXObjectForm pdXObj = null;
+
+ public XObjFormValidator(DocumentHandler handler, COSStream xobj) {
+ super(handler, xobj);
+ this.pdXObj = new PDXObjectForm(xobj);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.graphics.AbstractXObjValidator#validate()
+ */
+ @Override
+ public List<ValidationError> validate() throws ValidationException {
+ List<ValidationError> result = super.validate();
+ checkExtGraphicState(result);
+ checkGroup(result);
+ checkSubtype2Value(result);
+ validateXObjectContent(result);
+ validateShadingPattern(result);
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seenet.awl.edoc.pdfa.validation.graphics.AbstractXObjValidator#
+ * checkMandatoryFields(java.util.List)
+ */
+ @Override
+ protected boolean checkMandatoryFields(List<ValidationError> result) {
+ boolean lastMod = this.xobject.getItem(COSName.getPDFName("LastModified")) != null;
+ boolean pieceInfo = this.xobject.getItem(COSName.getPDFName("PieceInfo")) != null;
+ // type and subtype checked before to create the Validator.
+ if (lastMod ^ pieceInfo) {
+ result.add(new ValidationError(ERROR_GRAPHIC_MISSING_FIELD));
+ return false;
+ }
+
+ COSBase bbBase = this.xobject.getItem(COSName
+ .getPDFName(XOBJECT_DICTIONARY_KEY_BBOX));
+ // ---- BBox is an Array (Rectangle)
+ if (bbBase == null || !COSUtils.isArray(bbBase, cosDocument)) {
+ result.add(new ValidationError(ERROR_GRAPHIC_INVALID_BBOX));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * An Form XObject is a ContentStream. This method method uses an instance of
+ * ContentStreamWrapper to check the Stream of this Form XObject.
+ *
+ * @param result
+ * the list of error to update if the validation fails.
+ * @return true if the validation succeed, false otherwise.
+ * @throws ValidationException
+ */
+ protected boolean validateXObjectContent(List<ValidationError> result)
+ throws ValidationException {
+
+ ContentStreamWrapper csWrapper = new ContentStreamWrapper(handler);
+ List<ValidationError> csParseErrors = csWrapper
+ .validXObjContentStream(pdXObj);
+ if (csParseErrors == null
+ || (csParseErrors != null && csParseErrors.isEmpty())) {
+ return true;
+ }
+
+ result.addAll(csParseErrors);
+ return false;
+ }
+
+ /**
+ * A Form XObject may contain a Group object (Key =" Group"). If a Group
+ * object is present, this method checks if the S entry is present and if its
+ * value is different from "Transparency".
+ *
+ * @param error
+ * the list of error to update if the validation fails.
+ * @return true if the validation succeed, false otherwise
+ * @throws ValidationException
+ */
+ protected boolean checkGroup(List<ValidationError> error)
+ throws ValidationException {
+ COSBase baseGroup = this.xobject.getItem(COSName
+ .getPDFName(XOBJECT_DICTIONARY_KEY_GROUP));
+
+ COSDictionary groupDictionary = COSUtils.getAsDictionary(baseGroup,
+ cosDocument);
+ if (groupDictionary != null) {
+ if (!XOBJECT_DICTIONARY_KEY_GROUP.equals(groupDictionary
+ .getNameAsString(DICTIONARY_KEY_TYPE))) {
+ throw new ValidationException(
+ "The Group dictionary hasn't Group as Type value");
+ }
+
+ String sVal = groupDictionary
+ .getNameAsString(XOBJECT_DICTIONARY_KEY_GROUP_S);
+ if (sVal == null || XOBJECT_DICTIONARY_VALUE_S_TRANSPARENCY.equals(sVal)) {
+ error.add(new ValidationError(ERROR_GRAPHIC_TRANSPARENCY_GROUP , "Group has a transparency S entry or the S entry is null."));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check the Extended Graphic State contains in the Form XObject if it is
+ * present. To check this ExtGState, this method uses the
+ * net.awl.edoc.pdfa.validation.graphics.ExtGStateContainer object.
+ *
+ * @param errors
+ * the list of error to update if the validation fails
+ * @return true is the ExtGState is missing or valid, false otherwise.
+ * @throws ValidationException
+ */
+ protected boolean checkExtGraphicState(List<ValidationError> error)
+ throws ValidationException {
+ PDResources resources = this.pdXObj.getResources();
+ if (resources != null) {
+ ExtGStateContainer extContainer = new ExtGStateContainer(resources
+ .getCOSDictionary(), this.cosDocument);
+ return extContainer.validateTransparencyRules(error);
+ }
+ return true;
+ }
+
+ /**
+ * This method check the Shading entry of the resource dictionary if exists.
+ * To process this validation, an instance of ShadinPattern is used.
+ *
+ * @param result
+ * the list of error to update if the validation fails
+ * @return true if the validation succeed, false otherwise.
+ * @throws ValidationException
+ */
+ protected boolean validateShadingPattern(List<ValidationError> result)
+ throws ValidationException {
+ PDResources resources = this.pdXObj.getResources();
+ boolean res = true;
+ if (resources != null) {
+ COSDictionary shadings = (COSDictionary) resources.getCOSDictionary()
+ .getDictionaryObject(PATTERN_KEY_SHADING);
+ if (shadings != null) {
+ for (Object key : shadings.keySet()) {
+ COSDictionary aShading = (COSDictionary) shadings
+ .getDictionaryObject((COSName) key);
+ ShadingPattern sp = new ShadingPattern(handler, aShading);
+ List<ValidationError> lErrors = sp.validate();
+ if (lErrors != null && !lErrors.isEmpty()) {
+ result.addAll(lErrors);
+ res = false;
+ }
+ }
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Check if there are no PS entry in the Form XObject dictionary
+ *
+ * @param errors
+ * the list of error to update if the validation fails.
+ * @return true if PS entry is missing, false otherwise
+ */
+ protected boolean checkPS(List<ValidationError> errors) {
+ // 6.2.4 and 6.2.5 no PS
+ if (this.xobject.getItem(COSName.getPDFName("PS")) != null) {
+ errors.add(new ValidationError(
+ ValidationConstants.ERROR_GRAPHIC_UNEXPECTED_KEY,
+ "Unexpected 'PS' Key"));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check the SUbtype2 entry according to the §6.2.5 of the ISO 190005-1:2005
+ * specification.
+ *
+ * @param errors
+ * the list of error to update if the validation fails.
+ * @return true if Subtype2 is missing or different from PS, false otherwise
+ */
+ protected boolean checkSubtype2Value(List<ValidationError> errors) {
+ // 6.2.5 if Subtype2, value not PS
+ if (this.xobject.getItem(COSName.getPDFName("Subtype2")) != null) {
+ if ("PS".equals(this.xobject.getNameAsString(COSName
+ .getPDFName("Subtype2")))) {
+ errors.add(new ValidationError(
+ ValidationConstants.ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY,
+ "Unexpected 'PS' value for 'Subtype2' Key"));
+ return false;
+ }
+ }
+ return true;
+ }
+}
Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/graphics/XObjFormValidator.java
------------------------------------------------------------------------------
svn:eol-style = native