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 2012/07/14 21:53:50 UTC

svn commit: r1361579 [1/3] - in /pdfbox/trunk: pdfbox/src/main/java/org/apache/pdfbox/cos/ preflight/src/main/java/org/apache/padaf/preflight/contentstream/ preflight/src/main/java/org/apache/pdfbox/preflight/ preflight/src/main/java/org/apache/pdfbox/...

Author: leleueri
Date: Sat Jul 14 19:53:48 2012
New Revision: 1361579

URL: http://svn.apache.org/viewvc?rev=1361579&view=rev
Log:
[https://issues.apache.org/jira/browse/PDFBOX-1312] Font validation refactoring

Added:
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType0FontValidator.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType2FontValidator.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/DescendantFontValidator.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type0FontValidator.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType0Container.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType2Container.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/FontContainer.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/TrueTypeContainer.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type0Container.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type1Container.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type3Container.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType0DescriptorHelper.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType2DescriptorHelper.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/FontDescriptorHelper.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/TrueTypeDescriptorHelper.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/Type1DescriptorHelper.java   (with props)
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/CIDToGIDMap.java
      - copied, changed from r1355309, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDToGIDMap.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/FontMetaDataValidation.java
      - copied, changed from r1359830, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/FontMetaDataValidation.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/GlyphDescription.java
      - copied, changed from r1355309, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/type1/GlyphDescription.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/GlyphDetail.java
      - copied, changed from r1355309, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/GlyphDetail.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/GlyphException.java
      - copied, changed from r1355309, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/GlyphException.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/PDFAType3StreamParser.java
      - copied, changed from r1355309, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/PDFAType3StreamParser.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/PeekInputStream.java
      - copied, changed from r1355309, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/type1/PeekInputStream.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1.java
      - copied, changed from r1355309, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/type1/Type1.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/util/Type1Parser.java
      - copied, changed from r1355309, pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/type1/Type1Parser.java
Removed:
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/AbstractFontContainer.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/AbstractFontValidator.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CFFType0FontContainer.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CFFType2FontContainer.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDToGIDMap.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CompositeFontContainer.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CompositeFontValidator.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/FontMetaDataValidation.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/GlyphDetail.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/GlyphException.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/PDFAType3StreamParser.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/TrueTypeFontContainer.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type1FontContainer.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type1MetricHelper.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type3FontContainer.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/UndefFontContainer.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/type1/
Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
    pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamWrapper.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightConstants.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightContext.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/FontValidator.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/SimpleFontValidator.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/TrueTypeFontValidator.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type1FontValidator.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type3FontValidator.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/process/reflect/FontValidationProcess.java
    pdfbox/trunk/preflight/src/test/java/org/apache/pdfbox/preflight/TestInvalidDirectory.java
    pdfbox/trunk/preflight/src/test/java/org/apache/pdfbox/preflight/TestValidDirectory.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java Sat Jul 14 19:53:48 2012
@@ -779,6 +779,7 @@ public final class COSName extends COSBa
      */
     public static final COSName LENGTH1 = new COSName( "Length1" );
 
+    public static final COSName LENGTH2 = new COSName( "Length2" );
     /**
      * A common COSName value.
      */

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamWrapper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamWrapper.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamWrapper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamWrapper.java Sat Jul 14 19:53:48 2012
@@ -344,7 +344,7 @@ public class ContentStreamWrapper extend
 			} catch (IOException e) {
 				throwContentStreamException("Encoding can't interpret the character code", ERROR_FONTS_ENCODING_ERROR);
 			}
-
+			
 			try {
 				fontContainer.checkCID(cid);
 			} catch (GlyphException e) {

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightConstants.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightConstants.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightConstants.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightConstants.java Sat Jul 14 19:53:48 2012
@@ -85,7 +85,6 @@ public interface PreflightConstants {
 
 	String DICTIONARY_KEY_XOBJECT = "XObject";
 	String DICTIONARY_KEY_PATTERN = "Pattern";
-	String DICTIONARY_KEY_FONT = "Font";
 
 	String DICTIONARY_KEY_PATTERN_TYPE = "PatternType";
 	int DICTIONARY_PATTERN_TILING = 1;
@@ -147,18 +146,12 @@ public interface PreflightConstants {
 	String FONT_DICTIONARY_KEY_DESCENT = "Descent";
 	String FONT_DICTIONARY_KEY_CAPHEIGHT = "CapHeight";
 	String FONT_DICTIONARY_KEY_STEMV = "StemV";
-	String FONT_DICTIONARY_KEY_LENGTH1 = "Length1";
 	String FONT_DICTIONARY_KEY_LENGTH2 = "Length2";
 	String FONT_DICTIONARY_KEY_LENGTH3 = "Length3";
 	String FONT_DICTIONARY_KEY_METADATA = "Metadata";
 	String FONT_DICTIONARY_KEY_BASEENCODING = "BaseEncoding";
-	String FONT_DICTIONARY_KEY_DIFFERENCES = "Differences";
 	String FONT_DICTIONARY_KEY_DESCENDANT_FONTS = "DescendantFonts";
-	String FONT_DICTIONARY_KEY_CID_SYSINFO = "CIDSystemInfo";
 	String FONT_DICTIONARY_KEY_CID_GIDMAP = "CIDToGIDMap";
-	String FONT_DICTIONARY_KEY_SYSINFO_REGISTRY = "Registry";
-	String FONT_DICTIONARY_KEY_SYSINFO_ORDERING = "Ordering";
-	String FONT_DICTIONARY_KEY_SYSINFO_SUPPLEMENT = "Supplement";
 	String FONT_DICTIONARY_KEY_CMAP_NAME = "CMapName";
 	String FONT_DICTIONARY_KEY_CMAP_WMODE = "WMode";
 	String FONT_DICTIONARY_KEY_CMAP_USECMAP = "UseCMap";
@@ -834,6 +827,14 @@ public interface PreflightConstants {
 	 */
 	String ERROR_METADATA_FORMAT_UNKOWN = "7.1.3";
 	/**
+	 * Invalid metadata, unable to process the font due to IOException
+	 */
+	String ERROR_METADATA_FORMAT_STREAM = "7.1.4";
+	/**
+	 * Invalid metadata, unable to process the font due to Invalid XPacket exception
+	 */
+	String ERROR_METADATA_FORMAT_XPACKET = "7.1.5";
+	/**
 	 * Metadata mismatch between PDF Dictionnary and xmp
 	 */
 	String ERROR_METADATA_MISMATCH = "7.2";

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightContext.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightContext.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightContext.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/PreflightContext.java Sat Jul 14 19:53:48 2012
@@ -30,7 +30,7 @@ import javax.activation.DataSource;
 import org.apache.padaf.xmpbox.XMPMetadata;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
-import org.apache.pdfbox.preflight.font.AbstractFontContainer;
+import org.apache.pdfbox.preflight.font.container.FontContainer;
 import org.apache.pdfbox.preflight.graphic.ICCProfileWrapper;
 import org.apache.pdfbox.preflight.javacc.extractor.ExtractorTokenManager;
 import org.apache.pdfbox.preflight.utils.COSUtils;
@@ -39,8 +39,8 @@ public class PreflightContext {
 	/**
 	 * Contains the list of font name embedded in the PDF document.
 	 */
-	protected Map<COSBase, AbstractFontContainer> embeddedFonts = new HashMap<COSBase, AbstractFontContainer>();
-
+	protected Map<COSBase, FontContainer> fontContainers = new HashMap<COSBase, FontContainer>();
+	
 	/**
 	 * The PDFbox object representation of the PDF source.
 	 */
@@ -148,23 +148,21 @@ public class PreflightContext {
 	 * @param fKey
 	 * @param fc
 	 */
-	public void addFont(COSBase cBase, AbstractFontContainer fc) {
-		this.embeddedFonts.put(cBase, fc);
+	public void addFontContainer(COSBase cBase, FontContainer fc) {
+		this.fontContainers.put(cBase, fc);
 	}
 
-
-
 	/**
 	 * Return the FontContainer identified by the COSBase. If the given object
-	 * is missing from the emmbeddedFont map, the null value is returned.
+	 * is missing from the {@link #fontContainers} map, the null value is returned.
 	 * 
 	 * @param fKey
 	 * @return
 	 */
-	public AbstractFontContainer getFont(COSBase cBase) {
-		return this.embeddedFonts.get(cBase);
+	public FontContainer getFontContainer(COSBase cBase) {
+		return this.fontContainers.get(cBase);
 	}
-
+	
 	/**
 	 * @return the iccProfileWrapper
 	 */

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java Sat Jul 14 19:53:48 2012
@@ -22,7 +22,6 @@
 package org.apache.pdfbox.preflight.content;
 
 import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_ENCODING_ERROR;
-import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_FONT_FILEX_INVALID;
 import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_UNKNOWN_FONT_REF;
 import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT;
 import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_SYNTAX_CONTENT_STREAM_UNSUPPORTED_OP;
@@ -47,9 +46,8 @@ import org.apache.pdfbox.pdmodel.text.PD
 import org.apache.pdfbox.preflight.PreflightContext;
 import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
 import org.apache.pdfbox.preflight.exception.ValidationException;
-import org.apache.pdfbox.preflight.font.AbstractFontContainer;
-import org.apache.pdfbox.preflight.font.AbstractFontContainer.State;
-import org.apache.pdfbox.preflight.font.GlyphException;
+import org.apache.pdfbox.preflight.font.container.FontContainer;
+import org.apache.pdfbox.preflight.font.util.GlyphException;
 import org.apache.pdfbox.util.PDFOperator;
 import org.apache.pdfbox.util.operator.OperatorProcessor;
 
@@ -280,42 +278,36 @@ public class ContentStreamWrapper extend
 	 * @throws IOException
 	 */
 	public void validText(byte[] string) throws IOException {
-		// --- TextSize accessible through the TextState
+		// TextSize accessible through the TextState
 		PDTextState textState = getGraphicsState().getTextState();
 		final int renderingMode = textState.getRenderingMode();
 		final PDFont font = textState.getFont();
 
 		if (font == null) {
-			// ---- Unable to decode the Text without Font
+			// Unable to decode the Text without Font
 			throwContentStreamException("Text operator can't be process without Font", ERROR_FONTS_UNKNOWN_FONT_REF);
 		}
 
-		AbstractFontContainer fontContainer = context.getFont(font.getCOSObject());
-
-		if (fontContainer != null && fontContainer.isValid() == State.INVALID) {
-			context.addValidationErrors(fontContainer.getErrors());
-			return;
-		}
-
-		if (renderingMode == 3 && (fontContainer == null || !fontContainer.isFontProgramEmbedded())) {
+		FontContainer fontContainer = context.getFontContainer(font.getCOSObject());
+		if (renderingMode == 3 && (fontContainer == null || !fontContainer.isEmbeddedFont())) {
 			// font not embedded and rendering mode is 3. Valid case and nothing to check
 			return ;
-		}
-
-		if (fontContainer == null) {
-			// ---- Font Must be embedded if the RenderingMode isn't 3
+		} else if (fontContainer == null) {
+			// Font Must be embedded if the RenderingMode isn't 3
 			throwContentStreamException(font.getBaseFont() + " is unknown wasn't found by the FontHelperValdiator", ERROR_FONTS_UNKNOWN_FONT_REF);	
+		} else if (!fontContainer.isValid() && ! fontContainer.errorsAleadyMerged()) {
+			context.addValidationErrors(fontContainer.getAllErrors());
+			fontContainer.setErrorsAleadyMerged(true);
 		}
 
-		if (!fontContainer.isFontProgramEmbedded()) {
-			throwContentStreamException(font.getBaseFont() + " isn't embedded and the rendering mode isn't 3", ERROR_FONTS_FONT_FILEX_INVALID);
-		}
 
 		int codeLength = 1;
 		for (int i = 0; i < string.length; i += codeLength) {
+			// explore the string to detect character code (length can be 1 or 2 bytes)
 			int cid = -1; 
 			codeLength = 1;
 			try {
+				// according to the encoding, extract the character identifier
 				cid = font.encodeToCID(string, i, codeLength);
 				if (cid == -1 && i + 1 < string.length) {
 					// maybe a multibyte encoding
@@ -327,7 +319,7 @@ public class ContentStreamWrapper extend
 			}
 
 			try {
-				fontContainer.checkCID(cid);
+				fontContainer.checkGlyphWith(cid);
 			} catch (GlyphException e) {
 				if (renderingMode != 3) {
 					throwContentStreamException(e.getMessage(), e.getErrorCode());

Added: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType0FontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType0FontValidator.java?rev=1361579&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType0FontValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType0FontValidator.java Sat Jul 14 19:53:48 2012
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * 
+ * 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.pdfbox.preflight.font;
+
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.preflight.PreflightContext;
+import org.apache.pdfbox.preflight.font.container.CIDType0Container;
+import org.apache.pdfbox.preflight.font.descriptor.CIDType0DescriptorHelper;
+
+public class CIDType0FontValidator extends DescendantFontValidator<CIDType0Container> {
+
+	public CIDType0FontValidator(PreflightContext context, PDFont font) {
+		super(context, font, new CIDType0Container(font));
+	}
+
+	@Override
+	protected void checkCIDToGIDMap(COSBase ctog) {
+		checkCIDToGIDMap(ctog, false);
+	}
+
+	@Override
+	protected void createFontDescriptorHelper() {
+		this.descriptorHelper = new CIDType0DescriptorHelper(context, font, fontContainer);
+	}
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType0FontValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType2FontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType2FontValidator.java?rev=1361579&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType2FontValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType2FontValidator.java Sat Jul 14 19:53:48 2012
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ * 
+ * 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.pdfbox.preflight.font;
+
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.preflight.PreflightContext;
+import org.apache.pdfbox.preflight.font.container.CIDType2Container;
+import org.apache.pdfbox.preflight.font.descriptor.CIDType2DescriptorHelper;
+import org.apache.pdfbox.preflight.font.util.CIDToGIDMap;
+
+public class CIDType2FontValidator extends DescendantFontValidator<CIDType2Container> {
+
+	public CIDType2FontValidator(PreflightContext context, PDFont font) {
+		super(context, font, new CIDType2Container(font));
+	}
+
+	@Override
+	protected void checkCIDToGIDMap(COSBase ctog) {
+		CIDToGIDMap cidToGid = checkCIDToGIDMap(ctog, true);
+		this.fontContainer.setCidToGid(cidToGid);
+	}
+
+	@Override
+	protected void createFontDescriptorHelper() {
+		this.descriptorHelper = new CIDType2DescriptorHelper(context, font, fontContainer);
+	}
+
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/CIDType2FontValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/DescendantFontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/DescendantFontValidator.java?rev=1361579&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/DescendantFontValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/DescendantFontValidator.java Sat Jul 14 19:53:48 2012
@@ -0,0 +1,139 @@
+/*****************************************************************************
+ * 
+ * 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.pdfbox.preflight.font;
+
+import static org.apache.pdfbox.preflight.PreflightConstants.*;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_DICTIONARY_INVALID;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSDocument;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.preflight.PreflightContext;
+import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
+import org.apache.pdfbox.preflight.font.container.FontContainer;
+import org.apache.pdfbox.preflight.font.util.CIDToGIDMap;
+import org.apache.pdfbox.preflight.utils.COSUtils;
+
+public abstract class DescendantFontValidator <T extends FontContainer> extends SimpleFontValidator<T> {
+
+	protected COSDocument cosDocument = null;
+	
+	public DescendantFontValidator(PreflightContext context, PDFont font,	T fContainer) {
+		super(context, font, fContainer);
+		cosDocument = context.getDocument().getDocument();
+	}
+
+	@Override
+	protected void checkMandatoryField() {
+		COSDictionary fontDictionary = (COSDictionary)font.getCOSObject();
+
+		boolean arePresent =fontDictionary.containsKey(COSName.TYPE);
+		arePresent &= fontDictionary.containsKey(COSName.SUBTYPE);
+		arePresent &= fontDictionary.containsKey(COSName.BASE_FONT);
+		arePresent &= fontDictionary.containsKey(COSName.CIDSYSTEMINFO);
+		arePresent &= fontDictionary.containsKey(COSName.FONT_DESC);
+
+		if (!arePresent) {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,	"Required keys are missing"));
+		}
+
+		checkCIDSystemInfo(fontDictionary.getItem(COSName.CIDSYSTEMINFO));
+		checkCIDToGIDMap(fontDictionary.getItem(COSName.CID_TO_GID_MAP));
+	}
+
+	/**
+	 * Check the content of the CIDSystemInfo dictionary. A CIDSystemInfo dictionary must contain :
+	 * <UL>
+	 * <li>a Name - Registry
+	 * <li>a Name - Ordering
+	 * <li>a Integer - Supplement
+	 * </UL>
+	 * 
+	 * @param sysinfo
+	 * @return
+	 */
+	protected void checkCIDSystemInfo(COSBase sysinfo) {
+		COSDictionary cidSysInfo = COSUtils.getAsDictionary(sysinfo, cosDocument);
+		if (cidSysInfo != null) {
+			COSBase reg = cidSysInfo.getItem(COSName.REGISTRY);
+			COSBase ord = cidSysInfo.getItem(COSName.ORDERING);
+			COSBase sup = cidSysInfo.getItem(COSName.SUPPLEMENT);
+
+			if (!(COSUtils.isString(reg, cosDocument) && COSUtils.isString(ord, cosDocument) && COSUtils.isInteger(sup, cosDocument))) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_SYSINFO));
+			}
+
+		} else {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_SYSINFO));
+		}
+	}
+
+	/**
+	 * This method checks the CIDtoGIDMap entry of the Font dictionary.
+	 * call the {@linkplain #checkCIDToGIDMap(COSBase, boolean)} with right parameters
+	 * according to the instance of DescendantFontValidator
+	 *  
+	 * @param ctog
+	 */
+	protected abstract void checkCIDToGIDMap(COSBase ctog);
+
+	/**
+	 * This method checks the CIDtoGIDMap entry of the Font dictionary. This
+	 * element must be a Stream or a Name. If it is a name, it must be "Identity"
+	 * otherwise, the PDF file isn't a PDF/A-1b.
+	 * 
+	 * If the validation fails the list of errors in the FontContainer is updated.
+	 * 
+	 * If the CIDtoGIDMap is a Stream, it is parsed as a CMap and the result is returned.
+	 * @param ctog
+	 * @param mandatory true for CIDType2 , false for CIDType0
+	 * @return
+	 */
+	protected CIDToGIDMap checkCIDToGIDMap(COSBase ctog,boolean mandatory) {
+		CIDToGIDMap cidToGidMap = null;
+		
+		if (COSUtils.isString(ctog, cosDocument)) {
+			// ---- valid only if the string is Identity
+			String ctogStr = COSUtils.getAsString(ctog, cosDocument);
+			if (!FONT_DICTIONARY_VALUE_CMAP_IDENTITY.equals(ctogStr)) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_CIDTOGID,"The CIDToGID entry is invalid"));
+			}
+		} else if (COSUtils.isStream(ctog, cosDocument)) {
+			try {
+				COSStream ctogMap = COSUtils.getAsStream(ctog, cosDocument);
+				cidToGidMap = new CIDToGIDMap();
+				cidToGidMap.parseStream(ctogMap);
+			} catch (IOException e) {
+				// map can be invalid, return a Validation Error
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_CIDTOGID));
+			}
+		} else if (mandatory) {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_CIDTOGID));
+		}
+		return cidToGidMap;
+	}
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/DescendantFontValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/FontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/FontValidator.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/FontValidator.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/FontValidator.java Sat Jul 14 19:53:48 2012
@@ -21,33 +21,49 @@
 
 package org.apache.pdfbox.preflight.font;
 
-import org.apache.pdfbox.preflight.font.AbstractFontContainer.State;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.preflight.PreflightContext;
 import org.apache.pdfbox.preflight.exception.ValidationException;
+import org.apache.pdfbox.preflight.font.container.FontContainer;
+import org.apache.pdfbox.preflight.font.descriptor.FontDescriptorHelper;
 
-
-public interface FontValidator {
-
-  /**
-   * Call this method to validate the font wrapped by this interface
-   * implementation. Return true if the validation succeed, false otherwise. If
-   * the validation failed, the error is updated in the FontContainer with the
-   * right error code.
-   * 
-   * @return
-   */
-  public abstract void validate() throws ValidationException;
-
-  /**
-   * Return the State of the Font Validation. Three values are possible :
-   * <UL>
-   * <li>VALID : there are no errors
-   * <li>MAYBE : Metrics aren't consistent of the FontProgram isn't embedded,
-   * but it can be valid.
-   * <li>INVALID : the validation fails
-   * </UL>
-   * 
-   * @return
-   */
-  public State getState();
-
+public abstract class FontValidator <T extends FontContainer> {
+	
+	protected T fontContainer;
+	protected PreflightContext context;
+	protected PDFont font;
+	protected FontDescriptorHelper<T> descriptorHelper;
+
+	private static final String subSetPattern = "^[A-Z]{6}\\+.*";
+
+	public FontValidator(PreflightContext context, PDFont font, T fContainer) {
+		super();
+		this.context = context;
+		this.font = font;
+		this.fontContainer = fContainer;
+		this.context.addFontContainer(font.getCOSObject(), fContainer);
+	}
+
+  public static boolean isSubSet(String fontName) {
+    return fontName.matches(subSetPattern);
+  }
+
+  public static String getSubSetPatternDelimiter() {
+    return "\\+";
+  }
+ 	
+	public abstract void validate() throws ValidationException;
+	
+	protected void checkEncoding() {
+		// nothing to check for PDF/A-1b
+	}
+
+	protected void checkToUnicode() {
+		// nothing to check for PDF/A-1b
+	}
+
+	public T getFontContainer() {
+		return fontContainer;
+	}
+	
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/SimpleFontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/SimpleFontValidator.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/SimpleFontValidator.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/SimpleFontValidator.java Sat Jul 14 19:53:48 2012
@@ -21,206 +21,58 @@
 
 package org.apache.pdfbox.preflight.font;
 
-
-import java.util.List;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_DICTIONARY_INVALID;
 
 import org.apache.pdfbox.cos.COSDictionary;
-import org.apache.pdfbox.cos.COSDocument;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.pdmodel.font.PDFont;
-import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
-import org.apache.pdfbox.pdmodel.font.PDFontDescriptorAFM;
-import org.apache.pdfbox.pdmodel.font.PDFontDescriptorDictionary;
-import org.apache.pdfbox.preflight.PreflightConstants;
 import org.apache.pdfbox.preflight.PreflightContext;
-import org.apache.pdfbox.preflight.ValidationResult;
 import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
 import org.apache.pdfbox.preflight.exception.ValidationException;
+import org.apache.pdfbox.preflight.font.container.FontContainer;
 
-public abstract class SimpleFontValidator extends AbstractFontValidator {
-	protected String basefont;
-	protected int firstChar;
-	protected int lastChar;
-	protected List<Float> widths;
-	/**
-	 * The PdfBox font descriptor dictionary wrapper.
-	 */
-	protected PDFontDescriptor pFontDesc = null;
-
-	public SimpleFontValidator(PreflightContext context, PDFont font)
-			throws ValidationException {
-		super(context, font);
-		this.pFontDesc = font.getFontDescriptor();
-	}
-
-	/**
-	 * Extract element from the COSObject to avoid useless access to this object.
-	 */
-	private void extractElementsToCheck() {
-		// here is required elements
-		this.basefont = pFont.getBaseFont();
-		this.firstChar = pFont.getFirstChar();
-		this.lastChar = pFont.getLastChar();
-		this.widths = pFont.getWidths();
-	}
-
-	/**
-	 * Check if All required fields of a Font Dictionary are present. If there are
-	 * some missing fields, this method returns false and the FontContainer is
-	 * updated.
-	 * 
-	 * @return
-	 */
-	protected boolean checkMandatoryFields() {
-		String type = pFont.getBaseFont();
-		String subtype = pFont.getSubType();
-
-		if (this.pFontDesc == null) {
-			this.fontContainer
-			.addError(new ValidationError(ERROR_FONTS_FONT_FILEX_INVALID,
-					"The FontDescriptor is missing, so the Font Program isn't embedded."));
-			this.fontContainer.setFontProgramEmbedded(false);
-			return false;
-		}
-
-		if ((type == null || "".equals(type))
-				|| (subtype == null || "".equals(subtype))) {
-			this.fontContainer.addError(new ValidationError(
-					ERROR_FONTS_DICTIONARY_INVALID,
-					"Type and/or Subtype keys are missing"));
-			return false;
-		} else {
-			extractElementsToCheck();
-			// ---- according to the subtype, the validation process isn't the same.
-			return checkSpecificMandatoryFields();
-		}
-	}
-
-	/**
-	 * This method checks the presence of some fields according to the Font type
-	 * 
-	 * @return
-	 */
-	protected abstract boolean checkSpecificMandatoryFields();
-
-	/**
-	 * Check if the widths array contains integer and if its length is valid. If
-	 * the validation fails, the FontContainer is updated.
-	 * 
-	 * @param cDoc
-	 */
-	protected boolean checkWidthsArray(COSDocument cDoc) {
-		if (widths == null) {
-			this.fontContainer.addError(new ValidationError(
-					ERROR_FONTS_DICTIONARY_INVALID, "The Widths array is unreachable"));
-			return false;
-		}
-
-		int expectedLength = (lastChar - firstChar) + 1;
-		if (widths.size() != expectedLength) {
-			this.fontContainer.addError(new ValidationError(
-					ERROR_FONTS_DICTIONARY_INVALID,
-					"The length of Witdhs array is invalid. Expected : \""
-							+ expectedLength + "\" Current : \"" + widths.size() + "\""));
-			return false;
-		}
-		return true;
-	}
-
-	protected boolean checkEncoding(COSDocument cDoc) {
-		return true;
-	}
-
-	protected boolean checkToUnicode(COSDocument cDoc) {
-		// Check the toUnicode -- Useless for PDF/A 1-b
-		return true;
+public abstract class SimpleFontValidator <T extends FontContainer> extends FontValidator<T> {
+	
+	public SimpleFontValidator(PreflightContext context, PDFont font,	T fContainer) {
+		super(context, font, fContainer);
 	}
 
 	/**
-	 * This method checks the font descriptor dictionary and embedded font files.
-	 * If the FontDescriptor validation fails, the FontContainer is updated.
-	 * 
-	 * @return
-	 */
-	protected abstract boolean checkFontDescriptor() throws ValidationException;
+   * Call this method to validate the font wrapped by this object.
+   * If the validation failed, the error is updated in the FontContainer 
+   * with the right error code.
+   * 
+   * Errors that are saved in the container will be added on the PreflightContext if the font is used later.
+   * 
+   * @return
+   */
+	public void validate() throws ValidationException {
+		checkMandatoryField();
 
-	/**
-	 * Check if all required fields are present in the PDF file to describe the
-	 * Font Descriptor. If validation fails, FontConatiner is updated and false is
-	 * returned.
-	 */
-	protected boolean checkFontDescriptorMandatoryFields() throws ValidationException {
-		boolean fname = false, flags = false, itangle = false, cheight = false;
-		boolean fbbox = false, asc = false, desc = false, stemv = false;
-
-		if(pFontDesc instanceof PDFontDescriptorDictionary) {
-			COSDictionary fDescriptor = ((PDFontDescriptorDictionary) pFontDesc).getCOSDictionary();
-			for (Object key : fDescriptor.keySet()) {
-				if (!(key instanceof COSName)) {
-					this.fontContainer.addError(new ValidationResult.ValidationError(
-							PreflightConstants.ERROR_SYNTAX_DICTIONARY_KEY_INVALID,
-							"Invalid key in The font descriptor"));
-					return false;
-				}
-
-				String cosName = ((COSName) key).getName();
-				if (cosName.equals(FONT_DICTIONARY_KEY_FONTNAME)) {
-					fname = true;
-				}
-				if (cosName.equals(FONT_DICTIONARY_KEY_FLAGS)) {
-					flags = true;
-				}
-				if (cosName.equals(FONT_DICTIONARY_KEY_ITALICANGLE)) {
-					itangle = true;
-				}
-				if (cosName.equals(FONT_DICTIONARY_KEY_CAPHEIGHT)) {
-					cheight = true;
-				}
-				if (cosName.equals(FONT_DICTIONARY_KEY_FONTBBOX)) {
-					fbbox = true;
-				}
-				if (cosName.equals(FONT_DICTIONARY_KEY_ASCENT)) {
-					asc = true;
-				}
-				if (cosName.equals(FONT_DICTIONARY_KEY_DESCENT)) {
-					desc = true;
-				}
-				if (cosName.equals(FONT_DICTIONARY_KEY_STEMV)) {
-					stemv = true;
-				}
-			}
-
-			if (!(fname && flags && itangle && cheight && fbbox && asc && desc && stemv)) {
-				this.fontContainer.addError(new ValidationError(
-						ERROR_FONTS_DESCRIPTOR_INVALID, "Some mandatory fields are missing"));
-				return false;
-			}
-		} else if(pFontDesc instanceof PDFontDescriptorAFM) {
-			this.fontContainer.addError(new ValidationError(
-					ERROR_FONTS_DESCRIPTOR_INVALID, "Font Descriptor is missing"));
-			return false;
-		} else {
-			throw new ValidationException("Invalid FontDescription object, expected PDFontDescriptorDictionary");
+		createFontDescriptorHelper();
+		processFontDescriptorValidation();
+		
+		checkEncoding();
+		checkToUnicode();
+	}
+
+	protected void checkMandatoryField() {
+		COSDictionary fontDictionary = (COSDictionary)font.getCOSObject();
+		boolean areFieldsPResent = fontDictionary.containsKey(COSName.TYPE);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.SUBTYPE);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.BASE_FONT);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.FIRST_CHAR);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.LAST_CHAR);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.WIDTHS);
+		
+		if (!areFieldsPResent) {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "Some required fields are missing from the Font dictionary."));
 		}
-		return true;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * net.awl.edoc.pdfa.validation.font.FontValidator#validate(java.util.List)
-	 */
-	public void validate() throws ValidationException {
-		COSDocument cDoc = context.getDocument().getDocument();
-		if (!checkMandatoryFields()) {
-			return ;
-		}
-
-		boolean result = true;
-		result = result && checkWidthsArray(cDoc);
-		result = result && checkFontDescriptor();
-		result = result && checkEncoding(cDoc);
-		result = result && checkToUnicode(cDoc);
+	protected abstract void createFontDescriptorHelper();
+	
+	protected void processFontDescriptorValidation() {
+		this.descriptorHelper.validate();
 	}
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/TrueTypeFontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/TrueTypeFontValidator.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/TrueTypeFontValidator.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/TrueTypeFontValidator.java Sat Jul 14 19:53:48 2012
@@ -21,245 +21,52 @@
 
 package org.apache.pdfbox.preflight.font;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.fontbox.ttf.CMAPEncodingEntry;
-import org.apache.fontbox.ttf.CMAPTable;
-import org.apache.fontbox.ttf.TTFParser;
-import org.apache.fontbox.ttf.TrueTypeFont;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_ENCODING;
+
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
-import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.encoding.Encoding;
 import org.apache.pdfbox.encoding.MacRomanEncoding;
 import org.apache.pdfbox.encoding.WinAnsiEncoding;
-import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.pdmodel.font.PDFont;
-import org.apache.pdfbox.pdmodel.font.PDFontDescriptorDictionary;
-import org.apache.pdfbox.preflight.PreflightConstants;
+import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
 import org.apache.pdfbox.preflight.PreflightContext;
-import org.apache.pdfbox.preflight.ValidationResult;
 import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
-import org.apache.pdfbox.preflight.exception.ValidationException;
-
-public class TrueTypeFontValidator extends SimpleFontValidator {
-
-
-	public TrueTypeFontValidator(PreflightContext context, PDFont font) 
-			throws ValidationException {
-		super(context, font);
-	}
-
-	/**
-	 * Check if mandatory fields are present. Return false if a field is missing,
-	 * true otherwise. If validation fails, the FontContainer is updated.
-	 */
-	protected boolean checkSpecificMandatoryFields() {
-		// ---- name is required only in a PDF-1.0.
-		// ---- Currently our grammar matches only with PDF-1.[1-4]
-		// ---- BaseFont is required and is usually the FontName
-		if (basefont == null || "".equals(basefont)) {
-			this.fontContainer.addError(new ValidationError(
-					ERROR_FONTS_DICTIONARY_INVALID, "BaseFont is missing"));
-			// continue to process this font dictionary is useless
-			return false;
-		}
-
-		boolean allPresent = (firstChar >=  0 && lastChar >=  0 && widths != null);
-		if (!allPresent) {
-			this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "Required keys are missing"));
-			return false;
-		} // else  ok
-
+import org.apache.pdfbox.preflight.font.container.TrueTypeContainer;
+import org.apache.pdfbox.preflight.font.descriptor.TrueTypeDescriptorHelper;
 
-		return true;
-	}
+public class TrueTypeFontValidator extends SimpleFontValidator<TrueTypeContainer> {
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * net.awl.edoc.pdfa.validation.font.SimpleFontValidator#checkFontDescriptor()
-	 */
-	@Override
-	protected boolean checkFontDescriptor() throws ValidationException {
-		boolean res = checkFontDescriptorMandatoryFields();
-		res = res && checkFontName();
-		res = res && checkFontFileElement();
-		return res;
+	public TrueTypeFontValidator(PreflightContext context, PDFont font) {
+		super(context, font, new TrueTypeContainer(font));
 	}
-
-	/**
-	 * If the FontName is missing from the FontDescriptor dictionary, this method
-	 * returns false and the FontContainer is updated.
-	 * 
-	 * @return
-	 */
-	protected boolean checkFontName() {
-		String fontName = this.pFontDesc.getFontName();
-		if (fontName == null) {
-			this.fontContainer.addError(new ValidationResult.ValidationError(
-					PreflightConstants.ERROR_FONTS_DESCRIPTOR_INVALID,
-					"The FontName in font descriptor is null"));
-			return false;
-		}
-		return true;
-	}
-
-	/**
-	 * This methods validates the Font Stream. If the font is damaged or missing
-	 * the FontContainer is updated and false is returned. Moreover, this method
-	 * checks the Encoding property of the FontDescriptor dictionary.
-	 * 
-	 * @return
-	 */
-	protected boolean checkFontFileElement() throws ValidationException {
-		if (pFontDesc instanceof PDFontDescriptorDictionary) {
-			PDStream ff1 = ((PDFontDescriptorDictionary)pFontDesc).getFontFile();
-			PDStream ff2 = ((PDFontDescriptorDictionary)pFontDesc).getFontFile2();
-			PDStream ff3 = ((PDFontDescriptorDictionary)pFontDesc).getFontFile3();
-			boolean onlyOne = (ff1 != null && ff2 == null && ff3 == null)
-					|| (ff1 == null && ff2 != null && ff3 == null)
-					|| (ff1 == null && ff2 == null && ff3 != null);
-
-			if (ff2 == null || !onlyOne) {
-				this.fontContainer.addError(new ValidationResult.ValidationError(
-						PreflightConstants.ERROR_FONTS_FONT_FILEX_INVALID,
-						"The FontFile2 is invalid"));
-				return false;
-			}
-
-			// ---- Stream validation should be done by the StreamValidateHelper.
-			// ---- Process font specific check
-			COSStream stream = ff2.getStream();
-			if (stream == null) {
-				this.fontContainer.addError(new ValidationResult.ValidationError(
-						PreflightConstants.ERROR_FONTS_FONT_FILEX_INVALID,
-						"The FontFile is missing"));
-				this.fontContainer.setFontProgramEmbedded(false);
-				return false;
-			}
-
-			boolean hasLength1 = stream.getInt(COSName.getPDFName(FONT_DICTIONARY_KEY_LENGTH1)) > 0;
-			if (!hasLength1) {
-				this.fontContainer.addError(new ValidationResult.ValidationError(
-						PreflightConstants.ERROR_FONTS_FONT_FILEX_INVALID,
-						"The FontFile is invalid"));
-				return false;
-			}
-
-			// ---- check the encoding part.
-			if (pFontDesc.isNonSymbolic()) {
-				// ---- only MacRomanEncoding or WinAnsiEncoding are allowed for a non
-				// symbolic font
-				Encoding encodingValue = this.pFont.getFontEncoding();
-				if (encodingValue == null
-						|| !(encodingValue instanceof MacRomanEncoding || encodingValue instanceof WinAnsiEncoding)) {
-					this.fontContainer.addError(new ValidationResult.ValidationError(
-							PreflightConstants.ERROR_FONTS_ENCODING,
-							"The Encoding is invalid for the NonSymbolic TTF"));
-					return false;
+	
+	protected void createFontDescriptorHelper() {
+		this.descriptorHelper = new TrueTypeDescriptorHelper(context, font, fontContainer);
+	}
+	
+	protected void checkEncoding() {		
+		PDFontDescriptor fd = this.font.getFontDescriptor();
+		if(fd != null) {
+			/* 
+			 * only MacRomanEncoding or WinAnsiEncoding are allowed for a non symbolic font.
+			 */
+			if (fd.isNonSymbolic()) {
+				Encoding encodingValue = this.font.getFontEncoding();
+				if (encodingValue == null	|| !(encodingValue instanceof MacRomanEncoding || encodingValue instanceof WinAnsiEncoding)) {
+					this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING, "The Encoding is invalid for the NonSymbolic TTF"));
 				}
-			} else if (pFontDesc.isSymbolic()) {
-				// ---- For symbolic font, no encoding entry is allowed and only one
-				// encoding entry is expected into the FontFile CMap
-				if (((COSDictionary) this.pFont.getCOSObject()).getItem(COSName
-						.getPDFName(FONT_DICTIONARY_KEY_ENCODING)) != null) {
-					this.fontContainer.addError(new ValidationResult.ValidationError(
-							PreflightConstants.ERROR_FONTS_ENCODING,
-							"The Encoding should be missing for the Symbolic TTF"));
-					return false;
-				} // else check the content of the Font CMap (see below)
-
-			} else {
-				// ----- should never happen
-				return true;
-			}
+			} 
 
 			/*
-			 * ---- try to load the font using the TTFParser object. If the font is
-			 * invalid, an exception will be thrown. Because of it is a Embedded Font
-			 * Program, some tables are required and other are optional see PDF
-			 * Reference (§5.8)
+			 * For symbolic font, no encoding entry is allowed and only one
+			 * encoding entry is expected into the FontFile CMap (Check latter when 
+			 * the FontFile stream will be checked)
 			 */
-			ByteArrayInputStream bis = null;
-			try {
-				bis = new ByteArrayInputStream(ff2.getByteArray());
-				TrueTypeFont ttf = new TTFParser(true).parseTTF(bis);
-				if (pFontDesc.isSymbolic() && ttf.getCMAP().getCmaps().length != 1) {
-					this.fontContainer.addError(new ValidationResult.ValidationError(
-							PreflightConstants.ERROR_FONTS_ENCODING,
-							"The Encoding should be missing for the Symbolic TTF"));
-					return false;
-				}
-
-				((TrueTypeFontContainer)this.fontContainer).setFontObjectAndInitializeInnerFields(ttf);
-				((TrueTypeFontContainer)this.fontContainer).setCMap(getCMapOfFontProgram(ttf));
-
-				return checkFontFileMetaData(pFontDesc, ff2);
-			} catch (IOException e) {
-				this.fontContainer.addError(new ValidationResult.ValidationError(
-						PreflightConstants.ERROR_FONTS_TRUETYPE_DAMAGED,
-						"The FontFile can't be read"));
-				return false;
-			} finally {
-				if (bis != null) {
-					IOUtils.closeQuietly(bis);
-				}
-			}
-		} else {
-			throw new ValidationException("Invalid FontDescription object, expected PDFontDescriptorDictionary");
-		}
-	}
-
-	/**
-	 * Return the CMap encoding entry to use. This CMap belong to the TrueType
-	 * Font Program.
-	 * 
-	 * Here the selection rules :
-	 * <UL>
-	 * <li>For a Symbolic TrueType, the Font Program has only one CMap (Checked in
-	 * the checkFontFileElement method)
-	 * <li>For a Non-Symbolic TrueType, only two CMap can be used (WinAnsi
-	 * (plateformId : 3 / encodingId : 1) or MacRoman (plateformId : 1 /
-	 * encodingId : 0) ). This CMap returns the CMap which corresponds to the
-	 * Encoding value of the FontDescriptor dictionary.
-	 * </UL>
-	 * 
-	 * @param ttf
-	 *          The FontBox object which manages a TrueType Font program.
-	 * @return
-	 * @throws ValidationException
-	 *           if the FontProgram doesn't have the expected CMap
-	 */
-	protected CMAPEncodingEntry[] getCMapOfFontProgram(TrueTypeFont ttf)
-			throws ValidationException {
-		CMAPTable cmap = ttf.getCMAP();
-		if (this.pFontDesc.isSymbolic()) {
-			return cmap.getCmaps();
-		} else {
-			List<CMAPEncodingEntry> res = new ArrayList<CMAPEncodingEntry>();
-			boolean firstIs31 = false;
-			for (CMAPEncodingEntry cmapEntry : cmap.getCmaps()) {
-				// ---- Returns the WinAnsiEncoding CMap
-				if ((cmapEntry.getPlatformId() == 3) && (cmapEntry.getPlatformEncodingId() == 1)) {
-					res.add(0,cmapEntry);
-					firstIs31 = true;
-				} else if ((cmapEntry.getPlatformId() == 1)&& (cmapEntry.getPlatformEncodingId() == 0)) {
-					if (firstIs31) {
-						res.add(1, cmapEntry);
-					} else {
-						res.add(0, cmapEntry);
-					}
-				} else {
-					res.add(cmapEntry);
-				}
-			}
-			return res.toArray(new CMAPEncodingEntry[res.size()]);
+			if (fd.isSymbolic() && 
+					((COSDictionary)this.font.getCOSObject()).getItem(COSName.ENCODING) != null) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING, "The Encoding should be missing for the Symbolic TTF"));
+			} 
 		}
 	}
 }

Added: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type0FontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type0FontValidator.java?rev=1361579&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type0FontValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type0FontValidator.java Sat Jul 14 19:53:48 2012
@@ -0,0 +1,295 @@
+/*****************************************************************************
+ * 
+ * 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.pdfbox.preflight.font;
+
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_CIDKEYED_CMAP_INVALID_OR_MISSING;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_CIDKEYED_INVALID;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_CIDKEYED_SYSINFO;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_CID_CMAP_DAMAGED;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_DICTIONARY_INVALID;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_DEFAULT_CMAP_WMODE;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_KEY_CMAP_NAME;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_KEY_CMAP_USECMAP;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_KEY_CMAP_WMODE;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_CMAP_IDENTITY_H;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_CMAP_IDENTITY_V;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_TYPE0;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_TYPE2;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_TYPE_CMAP;
+
+import java.io.IOException;
+
+import org.apache.fontbox.cmap.CMap;
+import org.apache.fontbox.cmap.CMapParser;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSDocument;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType0Font;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType2Font;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.preflight.PreflightContext;
+import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
+import org.apache.pdfbox.preflight.exception.ValidationException;
+import org.apache.pdfbox.preflight.font.container.FontContainer;
+import org.apache.pdfbox.preflight.font.container.Type0Container;
+import org.apache.pdfbox.preflight.utils.COSUtils;
+
+public class Type0FontValidator extends FontValidator<Type0Container> {
+
+	protected COSDocument cosDocument = null;
+
+	public Type0FontValidator(PreflightContext context, PDFont font) {
+		super(context, font, new Type0Container(font));
+		cosDocument = this.context.getDocument().getDocument();
+	}
+
+	@Override
+	public void validate() throws ValidationException {
+		checkMandatoryFields();
+		
+		processDescendantFont();
+
+		checkEncoding();
+		checkToUnicode();
+	}
+
+	/**
+	 * This methods extracts from the Font dictionary all mandatory fields. If a
+	 * mandatory field is missing, the list of ValidationError in the
+	 * FontContainer is updated. 
+	 */
+	protected void checkMandatoryFields() {
+		COSDictionary fontDictionary = (COSDictionary)font.getCOSObject();
+		boolean areFieldsPResent = fontDictionary.containsKey(COSName.TYPE);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.SUBTYPE);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.BASE_FONT);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.DESCENDANT_FONTS);
+		areFieldsPResent &= fontDictionary.containsKey(COSName.ENCODING);
+
+		if (!areFieldsPResent) {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,	"Some keys are missing from composite font dictionary"));
+		}
+	}
+
+	/**
+	 * Extract the single CIDFont from the Descendant array.
+	 * Create a FontValidator for this CODFont and launch its validation.
+	 */
+	protected void processDescendantFont() throws ValidationException {
+		COSDictionary fontDictionary = (COSDictionary)font.getCOSObject();
+		// a CIDFont is contained in the DescendantFonts array
+		COSArray array = COSUtils.getAsArray(fontDictionary.getItem(COSName.DESCENDANT_FONTS), cosDocument);
+		if (array == null || array.size() != 1) {
+			/*
+			 * in PDF 1.4, this array must contain only one element,
+			 * because of a PDF/A should be a PDF 1.4, this method 
+			 * returns an error if the array has more than one element.
+			 */
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_INVALID, "CIDFont is missing from the DescendantFonts array or the size of array is greater than 1"));
+			return;
+		}
+
+		COSDictionary cidFont = COSUtils.getAsDictionary(array.get(0), cosDocument);
+		if (cidFont == null) {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_INVALID,	"The DescendantFonts array should have one element with is a dictionary."));
+			return;
+		}
+
+		FontValidator<? extends FontContainer> cidFontValidator = createDescendantValidator(cidFont);
+		if (cidFontValidator != null) {
+			this.fontContainer.setDelegateFontContainer(cidFontValidator.getFontContainer());
+			cidFontValidator.validate();
+		}
+	}
+
+	protected FontValidator<? extends FontContainer> createDescendantValidator(COSDictionary cidFont) {
+		String subtype = cidFont.getNameAsString(COSName.SUBTYPE);
+		FontValidator<? extends FontContainer> cidFontValidator = null;
+		if (FONT_DICTIONARY_VALUE_TYPE0.equals(subtype)) {
+			cidFontValidator = createCIDType0FontValidator(cidFont);
+		} else if (FONT_DICTIONARY_VALUE_TYPE2.equals(subtype)) {
+			cidFontValidator = createCIDType2FontValidator(cidFont);
+		} else {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "Type and/or Subtype keys are missing"));
+		}
+		return cidFontValidator;
+	}
+	
+	/**
+	 * Create the validation object for CIDType0 Font
+	 * @return
+	 */
+	protected FontValidator<? extends FontContainer> createCIDType0FontValidator(COSDictionary fDict) {
+		return new CIDType0FontValidator(context, new PDCIDFontType0Font(fDict));
+	}
+	
+	/**
+	 * Create the validation object for CIDType2 Font
+	 * @return
+	 */
+	protected FontValidator<? extends FontContainer> createCIDType2FontValidator(COSDictionary fDict) {
+		return new CIDType2FontValidator(context, new PDCIDFontType2Font(fDict));
+	}
+	
+	/**
+	 * Check the CMap entry.
+	 * 
+	 * The CMap entry must be a dictionary in a PDF/A. This entry can be a String
+	 * only if the String value is Identity-H or Identity-V
+	 * 
+	 * @param encoding
+	 */
+	protected void checkEncoding() {
+		COSBase encoding = ((COSDictionary)font.getCOSObject()).getItem(COSName.ENCODING);
+		checkCMapEncoding(encoding);
+	}
+
+	protected void checkCMapEncoding(COSBase encoding) {
+		if (COSUtils.isString(encoding, cosDocument)) {
+			// if encoding is a string, only 2 values are allowed
+			String str = COSUtils.getAsString(encoding, cosDocument);
+			if (!(FONT_DICTIONARY_VALUE_CMAP_IDENTITY_V.equals(str) || FONT_DICTIONARY_VALUE_CMAP_IDENTITY_H.equals(str))) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_INVALID,	"The CMap is a string but it isn't an Identity-H/V"));
+				return;
+			} 
+		} else if (COSUtils.isStream(encoding, cosDocument)) {
+			/*
+			 * If the CMap is a stream, some fields are mandatory
+			 * and the CIDSytemInfo must be compared with the CIDSystemInfo
+			 * entry of the CIDFont.
+			 */
+			processCMapAsStream(COSUtils.getAsStream(encoding, cosDocument));
+		} else {
+			// CMap type is invalid
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_CMAP_INVALID_OR_MISSING,	"The CMap type is invalid"));
+		}
+	}
+
+	/**
+	 * Standard information of a stream element will be checked by the StreamValidationProcess.
+	 * 
+	 * This method checks mandatory fields of the CMap stream. This method checks
+	 * too if the CMap stream is damaged using the CMapParser of the fontbox api.
+	 * 
+	 * @param aCMap
+	 * @return
+	 */
+	private void processCMapAsStream(COSStream aCMap) {
+
+		COSBase sysinfo = aCMap.getItem(COSName.CIDSYSTEMINFO);
+		checkCIDSystemInfo(sysinfo);
+
+		try {
+			// extract information from the CMap stream
+			CMap fontboxCMap = new CMapParser().parse(null, aCMap.getUnfilteredStream());
+			int wmValue = fontboxCMap.getWMode();
+			String cmnValue = fontboxCMap.getName();
+
+			/*
+			 * According to the getInt javadoc, -1 is returned if there are no result.
+			 * In the PDF Reference v1.7 p449, we can read that Default value is 0.
+			 */
+			int wmode = aCMap.getInt(COSName.getPDFName(FONT_DICTIONARY_KEY_CMAP_WMODE), FONT_DICTIONARY_DEFAULT_CMAP_WMODE);
+			String type = aCMap.getNameAsString(COSName.TYPE);
+			String cmapName = aCMap.getNameAsString(COSName.getPDFName(FONT_DICTIONARY_KEY_CMAP_NAME));
+
+			if (cmapName == null || "".equals(cmapName) || wmode > 1) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_CMAP_INVALID_OR_MISSING,	"Some elements in the CMap dictionary are missing or invalid"));
+			} else if (!(wmValue == wmode && cmnValue.equals(cmapName))) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_CMAP_INVALID_OR_MISSING, "CMapName or WMode is inconsistent"));
+			} else if (!FONT_DICTIONARY_VALUE_TYPE_CMAP.equals(type)) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_CMAP_INVALID_OR_MISSING,	"The CMap type is invalid"));
+			}
+		} catch (IOException e) {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_CID_CMAP_DAMAGED, "The CMap type is damaged"));
+		}
+
+		COSDictionary cmapUsed = (COSDictionary)aCMap.getDictionaryObject(COSName.getPDFName(FONT_DICTIONARY_KEY_CMAP_USECMAP));
+		if (cmapUsed != null) {
+			checkCMapEncoding(cmapUsed);
+		}
+		compareCIDSystemInfo(aCMap);
+	}
+
+	/**
+	 * Check the content of the CIDSystemInfo dictionary. A CIDSystemInfo dictionary must contain :
+	 * <UL>
+	 * <li>a Name - Registry
+	 * <li>a Name - Ordering
+	 * <li>a Integer - Supplement
+	 * </UL>
+	 * 
+	 * @param sysinfo
+	 * @return
+	 */
+	protected boolean checkCIDSystemInfo(COSBase sysinfo) {
+		boolean result = true;
+		COSDictionary cidSysInfo = COSUtils.getAsDictionary(sysinfo, cosDocument);
+
+		if (cidSysInfo != null) {
+			COSBase reg = cidSysInfo.getItem(COSName.REGISTRY);
+			COSBase ord = cidSysInfo.getItem(COSName.ORDERING);
+			COSBase sup = cidSysInfo.getItem(COSName.SUPPLEMENT);
+
+			if (!(COSUtils.isString(reg, cosDocument) && COSUtils.isString(ord, cosDocument) && COSUtils.isInteger(sup, cosDocument))) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_SYSINFO));
+				result = false;
+			}
+
+		} else {
+			this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_SYSINFO));
+			result = false;
+		}
+		return result;
+	}
+
+	/**
+	 * The CIDSystemInfo must have the same Registry and Ordering for CMap and
+	 * CIDFont. This control is useless if CMap is Identity-H or Identity-V so
+	 * this method is called by the checkCMap method.
+	 * 
+	 * @param cmap
+	 * @return
+	 */
+	private void compareCIDSystemInfo(COSDictionary cmap) {
+		COSDictionary fontDictionary = (COSDictionary)font.getCOSObject();
+		COSArray array = COSUtils.getAsArray(fontDictionary.getItem(COSName.DESCENDANT_FONTS), cosDocument);
+
+		if (array != null && array.size() > 0) {
+			COSDictionary cidFont = COSUtils.getAsDictionary(array.get(0), cosDocument);
+			COSDictionary cmsi = COSUtils.getAsDictionary(cmap.getItem(COSName.CIDSYSTEMINFO), cosDocument);
+			COSDictionary cfsi = COSUtils.getAsDictionary(cidFont.getItem(COSName.CIDSYSTEMINFO), cosDocument);
+
+			String regCM = COSUtils.getAsString(cmsi.getItem(COSName.REGISTRY), cosDocument);
+			String ordCM = COSUtils.getAsString(cmsi.getItem(COSName.ORDERING), cosDocument);
+			String regCF = COSUtils.getAsString(cfsi.getItem(COSName.REGISTRY), cosDocument);
+			String ordCF = COSUtils.getAsString(cfsi.getItem(COSName.ORDERING), cosDocument);
+
+			if (!regCF.equals(regCM) || !ordCF.equals(ordCM)) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_CIDKEYED_SYSINFO, "The CIDSystemInfo is inconsistent"));
+			}
+		}
+	}
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type0FontValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type1FontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type1FontValidator.java?rev=1361579&r1=1361578&r2=1361579&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type1FontValidator.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type1FontValidator.java Sat Jul 14 19:53:48 2012
@@ -21,269 +21,52 @@
 
 package org.apache.pdfbox.preflight.font;
 
-import java.awt.Font;
-import java.awt.FontFormatException;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.List;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_FONTS_ENCODING;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_ENCODING_MAC;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_ENCODING_MAC_EXP;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_ENCODING_PDFDOC;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_ENCODING_STD;
+import static org.apache.pdfbox.preflight.PreflightConstants.FONT_DICTIONARY_VALUE_ENCODING_WIN;
 
-import org.apache.commons.io.IOUtils;
-import org.apache.fontbox.cff.CFFFont;
-import org.apache.fontbox.cff.CFFParser;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSDocument;
 import org.apache.pdfbox.cos.COSName;
-import org.apache.pdfbox.cos.COSStream;
-import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.pdmodel.font.PDFont;
-import org.apache.pdfbox.pdmodel.font.PDFontDescriptorDictionary;
 import org.apache.pdfbox.preflight.PreflightContext;
-import org.apache.pdfbox.preflight.ValidationResult;
 import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
-import org.apache.pdfbox.preflight.exception.ValidationException;
-import org.apache.pdfbox.preflight.font.type1.Type1;
-import org.apache.pdfbox.preflight.font.type1.Type1Parser;
+import org.apache.pdfbox.preflight.font.container.Type1Container;
+import org.apache.pdfbox.preflight.font.descriptor.Type1DescriptorHelper;
 import org.apache.pdfbox.preflight.utils.COSUtils;
 
-public class Type1FontValidator extends SimpleFontValidator {
-
-	public Type1FontValidator(PreflightContext context, PDFont font)
-			throws ValidationException {
-		super(context, font);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @seenet.awl.edoc.pdfa.validation.font.SimpleFontValidator#
-	 * checkSpecificMandatoryFields()
-	 */
-	protected boolean checkSpecificMandatoryFields() {
-		// ---- name is required only in a PDF-1.0.
-		// ---- Currently our grammar matches only with PDF-1.[1-4]
-		// ---- baseFont is required and is usually the FontName
-		if (basefont == null || "".equals(basefont)) {
-			this.fontContainer.addError(new ValidationError(
-					ERROR_FONTS_DICTIONARY_INVALID, "BaseFont is missing"));
-			return false;
-		}
-
-		boolean allPresent = (firstChar >= 0 && lastChar >= 0 && widths != null);
-		if (!allPresent) {
-			this.fontContainer.addError(new ValidationError(
-					ERROR_FONTS_DICTIONARY_INVALID, "Required keys are missing"));
-			return false;
-		} 
-		// else
-		// ---- Event if the Font is one of the 14 standard Fonts, those keys are
-		// mandatory for a PDF/A
-		return true;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * net.awl.edoc.pdfa.validation.font.SimpleFontValidator#checkEncoding(org
-	 * .apache.pdfbox.cos.COSDocument)
-	 */
-	protected boolean checkEncoding() {
-		COSBase encoding = ((COSDictionary)pFont.getCOSObject()).getItem(COSName.ENCODING);
-		if (COSUtils.isString(encoding, cosDocument)) {
-			String encodingName = COSUtils.getAsString(encoding, cosDocument);
-			if (!(encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_MAC)
-					|| encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_MAC_EXP)
-					|| encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_WIN)
-					|| encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_PDFDOC) || encodingName
-					.equals(FONT_DICTIONARY_VALUE_ENCODING_STD))) {
-				this.fontContainer.addError(new ValidationError(ERROR_FONTS_ENCODING));
-				return false;
-			}
-		} else if (COSUtils.isDictionary(encoding, cosDocument)) {
-			this.pFont.getFontEncoding();
-		} else if (encoding != null) {
-			this.fontContainer.addError(new ValidationError(ERROR_FONTS_ENCODING));
-			return false;
-		} 
-		//else
-		// ---- According to PDF Reference, the encoding entry is optional.
-		// PDF/A specification only speaks of TrueType encoding
-
-		return true;
+public class Type1FontValidator extends SimpleFontValidator<Type1Container> {
+	
+	public Type1FontValidator(PreflightContext context, PDFont font) {
+		super(context, font, new Type1Container(font));
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * net.awl.edoc.pdfa.validation.font.SimpleFontValidator#checkFontDescriptor()
-	 */
 	@Override
-	protected boolean checkFontDescriptor() throws ValidationException {
-		boolean res = checkFontDescriptorMandatoryFields();
-		res = res && checkFontName();
-		res = res && checkFontFileElement();
-		return res;
+	protected void createFontDescriptorHelper() {
+		this.descriptorHelper = new Type1DescriptorHelper(context, font, fontContainer);
 	}
 
-	/**
-	 * Check if the font name is present and if fontName equals to the baseName.
-	 * If the validation fails, false is returned and the FontContainer is
-	 * updated.
-	 * 
-	 * @return
-	 */
-	boolean checkFontName() {
-		String fontName = this.pFontDesc.getFontName();
-		if (fontName == null) {
-			this.fontContainer
-			.addError(new ValidationResult.ValidationError(ERROR_FONTS_DESCRIPTOR_INVALID,
-					"The FontName in font descriptor isn't the same as the BaseFont in the Font dictionary"));
-			return false;
-		}
-
-		return true;
-	}
-
-	/**
-	 * This methods validates the Font Stream, if the font program is damaged or
-	 * missing the FontContainer is updated and false is returned.
-	 * 
-	 * @throws ValidationException
-	 */
-	protected boolean checkFontFileElement() throws ValidationException {
-		// ---- if the this font is a Subset, the CharSet entry must be present in
-		// the FontDescriptor
-		if (isSubSet(pFontDesc.getFontName())) {
-			String charsetStr = pFontDesc.getCharSet();
-			if (charsetStr == null || "".equals(charsetStr)) {
-				this.fontContainer.addError(new ValidationResult.ValidationError(
-						ERROR_FONTS_CHARSET_MISSING_FOR_SUBSET,
-						"The Charset entry is missing for the Type1 Subset"));
-				return false;
-			}
-		}
-
-		// ---- FontFile Validation
-		if (pFontDesc instanceof PDFontDescriptorDictionary) {
-			PDStream ff1 = ((PDFontDescriptorDictionary)pFontDesc).getFontFile();
-			PDStream ff2 = ((PDFontDescriptorDictionary)pFontDesc).getFontFile2();
-			PDStream ff3 = ((PDFontDescriptorDictionary)pFontDesc).getFontFile3();
-			boolean onlyOne = (ff1 != null && ff2 == null && ff3 == null)
-					|| (ff1 == null && ff2 != null && ff3 == null)
-					|| (ff1 == null && ff2 == null && ff3 != null);
-
-			if ((ff1 == null && (ff3 == null || !"Type1C".equals(((COSDictionary)ff3.getCOSObject()).getNameAsString(COSName.SUBTYPE)))) || !onlyOne) {
-				this.fontContainer.addError(new ValidationResult.ValidationError(
-						ERROR_FONTS_FONT_FILEX_INVALID, "The FontFile is invalid"));
-				return false;
-			}
-
-			if (ff1 != null) {
-				COSStream stream = ff1.getStream();
-				if (stream == null) {
-					this.fontContainer.addError(new ValidationResult.ValidationError(ERROR_FONTS_FONT_FILEX_INVALID, "The FontFile is missing"));
-					this.fontContainer.setFontProgramEmbedded(false);
-					return false;
+	protected void checkEncoding() {	
+		COSBase encoding = ((COSDictionary)font.getCOSObject()).getItem(COSName.ENCODING);
+		if (encoding != null) {
+			COSDocument cosDocument = context.getDocument().getDocument();
+			if (COSUtils.isString(encoding, cosDocument)) {
+				String encodingName = COSUtils.getAsString(encoding, cosDocument);
+				if (!(encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_MAC)
+						|| encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_MAC_EXP)
+						|| encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_WIN)
+						|| encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_PDFDOC) 
+						|| encodingName.equals(FONT_DICTIONARY_VALUE_ENCODING_STD))) {
+					this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING));
 				}
-
-				boolean hasLength1 = stream.getInt(COSName.getPDFName(FONT_DICTIONARY_KEY_LENGTH1)) > 0;
-				boolean hasLength2 = stream.getInt(COSName.getPDFName(FONT_DICTIONARY_KEY_LENGTH2)) > 0;
-				boolean hasLength3 = stream.getInt(COSName.getPDFName(FONT_DICTIONARY_KEY_LENGTH3)) > 0;
-				if (!(hasLength1 && hasLength2 && hasLength3)) {
-					this.fontContainer.addError(new ValidationResult.ValidationError(
-							ERROR_FONTS_FONT_FILEX_INVALID, "The FontFile is invalid"));
-					return false;
-				}
-
-				// ---- Stream validation should be done by the StreamValidateHelper.
-				// ---- Process font specific check
-				// ---- try to load the font using the java.awt.font object.
-				// ---- if the font is invalid, an exception will be thrown
-				ByteArrayInputStream bis = null;
-				try {
-					bis = new ByteArrayInputStream(ff1.getByteArray());
-					Font.createFont(Font.TYPE1_FONT, bis);
-					return checkFontMetricsDataAndFeedFontContainer(ff1) && checkFontFileMetaData(pFontDesc, ff1);
-				} catch (IOException e) {
-					this.fontContainer.addError(new ValidationResult.ValidationError(
-							ERROR_FONTS_TYPE1_DAMAGED, "The FontFile can't be read"));
-					return false;
-				} catch (FontFormatException e) {
-					this.fontContainer.addError(new ValidationResult.ValidationError(
-							ERROR_FONTS_TYPE1_DAMAGED, "The FontFile is damaged"));
-					return false;
-				} finally {
-					if (bis != null) {
-						IOUtils.closeQuietly(bis);
-					}
-				}
-			} else {
-				return checkCIDFontWidths(ff3) && checkFontFileMetaData(pFontDesc, ff3);
-			}
-		} else {
-			throw new ValidationException("Invalid FontDescription object, expected PDFontDescriptorDictionary");
-		}
-	}
-
-	/**
-	 * Type1C is a CFF font format, extract all CFFFont object from the stream
-	 * 
-	 * @param fontStream
-	 * @return
-	 * @throws ValidationException
-	 */
-	protected boolean checkCIDFontWidths(PDStream fontStream)
-			throws ValidationException {
-		try {
-			CFFParser cffParser = new CFFParser();
-			List<CFFFont> lCFonts = cffParser.parse(fontStream.getByteArray());
-
-			if (lCFonts == null || lCFonts.isEmpty()) {
-				this.fontContainer.addError(new ValidationResult.ValidationError(
-						ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read"));
-				return false;
-			}
-
-			((Type1FontContainer)this.fontContainer).setCFFFontObjects(lCFonts);
-
-			return true;
-		} catch (IOException e) {
-			this.fontContainer.addError(new ValidationResult.ValidationError(
-					ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read"));
-			return false;
-		}
-	}
-	/**
-	 * This method checks the metric consistency and adds the FontContainer in the
-	 * DocumentHandler.
-	 * 
-	 * @param fontStream
-	 * @return
-	 * @throws ValidationException
-	 */
-	protected boolean checkFontMetricsDataAndFeedFontContainer(PDStream fontStream)
-			throws ValidationException {
-		try {
-
-			// ---- Parse the Type1 Font program
-			ByteArrayInputStream bis = new ByteArrayInputStream(fontStream
-					.getByteArray());
-			COSStream streamObj = fontStream.getStream();
-			int length1 = streamObj.getInt(COSName
-					.getPDFName(FONT_DICTIONARY_KEY_LENGTH1));
-			int length2 = streamObj.getInt(COSName
-					.getPDFName(FONT_DICTIONARY_KEY_LENGTH2));
-
-			Type1Parser parserForMetrics = Type1Parser.createParserWithEncodingObject(bis, length1, length2, pFont.getFontEncoding());
-			Type1 parsedData = parserForMetrics.parse();
-
-			((Type1FontContainer)this.fontContainer).setFontObject(parsedData);
-
-			return true;
-		} catch (IOException e) {
-			throw new ValidationException("Unable to check Type1 metrics due to : "
-					+ e.getMessage(), e);
-		}
+			} else if (!COSUtils.isDictionary(encoding, cosDocument)) {
+				this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING));
+			} 
+		}	
 	}
+	
 }