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