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 [4/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/annotation/SquareCircleAnnotationValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/SquareCircleAnnotationValidator.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/SquareCircleAnnotationValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/SquareCircleAnnotationValidator.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,134 @@
+/*****************************************************************************
+ * 
+ * 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.annotation;
+
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_F;
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_RECT;
+import static org.apache.padaf.preflight.ValidationConstants.DICTIONARY_KEY_SUBTYPE;
+
+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;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationSquareCircle;
+
+/**
+ * Validation class for the Square/Circle Annotation
+ */
+public class SquareCircleAnnotationValidator extends AnnotationValidator {
+  /**
+   * PDFBox object which wraps the annotation dictionary
+   */
+  protected PDAnnotationSquareCircle pdSquareCircle = null;
+
+  public SquareCircleAnnotationValidator(DocumentHandler handler,
+      COSDictionary annotDictionary) {
+    super(handler, annotDictionary);
+    this.pdSquareCircle = new PDAnnotationSquareCircle(annotDictionary);
+    this.pdAnnot = this.pdSquareCircle;
+  }
+
+  /**
+   * In addition of the AnnotationValidator.validate() method, this method
+   * executes the the checkIColors method.
+   * 
+   * @see org.apache.padaf.preflight.annotation.AnnotationValidator#validate(java.util.List)
+   */
+  @Override
+  public boolean validate(List<ValidationError> errors)
+      throws ValidationException {
+    boolean isValide = super.validate(errors);
+    isValide = isValide && checkIColors(errors);
+    return isValide;
+  }
+
+  /**
+   * Return true if the IC field is present in the Annotation dictionary and if
+   * the RGB profile is used in the DestOutputProfile of the OutputIntent
+   * dictionary.
+   * 
+   * @param errors
+   *          list of errors with is updated if no RGB profile is found when the
+   *          IC element is present
+   * @return
+   */
+  protected boolean checkIColors(List<ValidationError> errors) {
+    if (this.pdSquareCircle.getInteriorColour() != null) {
+      if (!searchRGBProfile()) {
+        errors.add(new ValidationResult.ValidationError(
+            ValidationConstants.ERROR_ANNOT_FORBIDDEN_COLOR,"Annotation uses a Color profile which isn't the same than the profile contained by the OutputIntent"));
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seenet.awl.edoc.pdfa.validation.annotation.AnnotationValidator#
+   * checkMandatoryFields(java.util.List)
+   */
+  protected boolean checkMandatoryFields(List<ValidationError> errors) {
+    boolean subtype = false;
+    boolean rect = false;
+    boolean f = false;
+
+    for (Object key : this.annotDictionary.keySet()) {
+      if (!(key instanceof COSName)) {
+        errors.add(new ValidationResult.ValidationError(
+            ValidationConstants.ERROR_SYNTAX_DICTIONARY_KEY_INVALID,
+            "Invalid key in The Annotation dictionary"));
+        return false;
+      }
+
+      String cosName = ((COSName) key).getName();
+      if (cosName.equals(DICTIONARY_KEY_SUBTYPE)) {
+        subtype = true;
+      }
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_RECT)) {
+        rect = true;
+      }
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_F)) {
+        f = true;
+      }
+    }
+
+    /*
+     * ---- After PDF 1.4, all additional entries in this annotation are
+     * optional and they seem to be compatible with the PDF/A specification.
+     */
+    boolean result = (subtype && rect && f);
+    if (!result) {
+      errors.add(new ValidationResult.ValidationError(
+          ValidationConstants.ERROR_ANNOT_MISSING_FIELDS));
+    }
+    return result;
+  }
+
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/SquareCircleAnnotationValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TextAnnotationValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TextAnnotationValidator.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TextAnnotationValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TextAnnotationValidator.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * 
+ * 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.annotation;
+
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_CONTENTS;
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_F;
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_RECT;
+import static org.apache.padaf.preflight.ValidationConstants.DICTIONARY_KEY_SUBTYPE;
+
+import java.util.List;
+
+
+import org.apache.padaf.preflight.DocumentHandler;
+import org.apache.padaf.preflight.ValidationConstants;
+import org.apache.padaf.preflight.ValidationResult;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationText;
+
+/**
+ * Validation class for Text Annotation
+ */
+public class TextAnnotationValidator extends AnnotationValidator {
+  /**
+   * PDFBox object which wraps the annotation dictionary
+   */
+  protected PDAnnotationText pdText = null;
+
+  public TextAnnotationValidator(DocumentHandler handler,
+      COSDictionary annotDictionary) {
+    super(handler, annotDictionary);
+    this.pdText = new PDAnnotationText(annotDictionary);
+    this.pdAnnot = this.pdText;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * net.awl.edoc.pdfa.validation.annotation.AnnotationValidator#checkFlags(
+   * java.util.List)
+   */
+  protected boolean checkFlags(List<ValidationError> errors) {
+    // ---- call common flags settings
+    boolean result = super.checkFlags(errors);
+
+    // ---- For Text Annotation, this two flags should be set to avoid potential
+    // ambiguity between the annotation dictionary and the reader behavior.
+    result = result && this.pdAnnot.isNoRotate();
+    result = result && this.pdAnnot.isNoZoom();
+    if (!result) {
+      errors.add(new ValidationResult.ValidationError(
+          ValidationConstants.ERROR_ANNOT_NOT_RECOMMENDED_FLAG));
+    }
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seenet.awl.edoc.pdfa.validation.annotation.AnnotationValidator#
+   * checkMandatoryFields(java.util.List)
+   */
+  protected boolean checkMandatoryFields(List<ValidationError> errors) {
+    boolean subtype = false;
+    boolean rect = false;
+    boolean f = false;
+    boolean contents = false;
+
+    for (Object key : this.annotDictionary.keySet()) {
+      if (!(key instanceof COSName)) {
+        errors.add(new ValidationResult.ValidationError(
+            ValidationConstants.ERROR_SYNTAX_DICTIONARY_KEY_INVALID,
+            "Invalid key in The Annotation dictionary"));
+        return false;
+      }
+
+      String cosName = ((COSName) key).getName();
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_RECT)) {
+        rect = true;
+      }
+      if (cosName.equals(DICTIONARY_KEY_SUBTYPE)) {
+        subtype = true;
+      }
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_F)) {
+        f = true;
+      }
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_CONTENTS)) {
+        contents = true;
+      }
+    }
+
+    /*
+     * ---- Since PDF 1.5, two optional entries are possible. These new entries
+     * seem to e compatible with the PDF/A specification (used to set a State to
+     * the annotation - ex : rejected, reviewed...)
+     */
+    boolean result = (subtype && rect && f && contents);
+    if (!result) {
+      errors.add(new ValidationResult.ValidationError(
+          ValidationConstants.ERROR_ANNOT_MISSING_FIELDS));
+    }
+    return result;
+  }
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TextAnnotationValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TrapNetAnnotationValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TrapNetAnnotationValidator.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TrapNetAnnotationValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TrapNetAnnotationValidator.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ * 
+ * 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.annotation;
+
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_F;
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_RECT;
+import static org.apache.padaf.preflight.ValidationConstants.DICTIONARY_KEY_SUBTYPE;
+
+import java.util.List;
+
+
+import org.apache.padaf.preflight.DocumentHandler;
+import org.apache.padaf.preflight.ValidationConstants;
+import org.apache.padaf.preflight.ValidationResult;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationUnknown;
+
+/**
+ * Validation class for the TrapNet annotation
+ */
+public class TrapNetAnnotationValidator extends AnnotationValidator {
+  /**
+   * PDFBox object which wraps the annotation dictionary
+   */
+  protected PDAnnotationUnknown pdUnk = null;
+
+  public TrapNetAnnotationValidator(DocumentHandler handler,
+      COSDictionary annotDictionary) {
+    super(handler, annotDictionary);
+    this.pdUnk = new PDAnnotationUnknown(annotDictionary);
+    this.pdAnnot = this.pdUnk;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seenet.awl.edoc.pdfa.validation.annotation.AnnotationValidator#
+   * checkMandatoryFields(java.util.List)
+   */
+  protected boolean checkMandatoryFields(List<ValidationError> errors) {
+    boolean subtype = false;
+    boolean rect = false;
+    boolean f = false;
+
+    for (Object key : this.annotDictionary.keySet()) {
+      if (!(key instanceof COSName)) {
+        errors.add(new ValidationResult.ValidationError(
+            ValidationConstants.ERROR_SYNTAX_DICTIONARY_KEY_INVALID,
+            "Invalid key in The Annotation dictionary"));
+        return false;
+      }
+
+      String cosName = ((COSName) key).getName();
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_RECT)) {
+        rect = true;
+      }
+      if (cosName.equals(DICTIONARY_KEY_SUBTYPE)) {
+        subtype = true;
+      }
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_F)) {
+        f = true;
+      }
+    }
+
+    boolean result = (subtype && rect && f);
+    if (!result) {
+      errors.add(new ValidationResult.ValidationError(
+          ValidationConstants.ERROR_ANNOT_MISSING_FIELDS));
+    }
+    return result;
+  }
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/TrapNetAnnotationValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/WidgetAnnotationValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/WidgetAnnotationValidator.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/WidgetAnnotationValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/WidgetAnnotationValidator.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * 
+ * 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.annotation;
+
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_F;
+import static org.apache.padaf.preflight.ValidationConstants.ANNOT_DICTIONARY_KEY_RECT;
+import static org.apache.padaf.preflight.ValidationConstants.DICTIONARY_KEY_SUBTYPE;
+
+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;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
+
+/**
+ * Validation class for the Widget Annotation
+ */
+public class WidgetAnnotationValidator extends AnnotationValidator {
+  /**
+   * PDFBox object which wraps the annotation dictionary
+   */
+  protected PDAnnotationWidget pdWidget = null;
+
+  public WidgetAnnotationValidator(DocumentHandler handler,
+      COSDictionary annotDictionary) {
+    super(handler, annotDictionary);
+    this.pdWidget = new PDAnnotationWidget(annotDictionary);
+    this.pdAnnot = this.pdWidget;
+  }
+
+  /**
+   * In addition of the AnnotationValidator.validate() method, this method
+   * executes the the checkAAField method.
+   * 
+   * @see org.apache.padaf.preflight.annotation.AnnotationValidator#validate(java.util.List)
+   */
+  @Override
+  public boolean validate(List<ValidationError> errors)
+      throws ValidationException {
+    boolean isValide = super.validate(errors);
+    isValide = isValide && checkAAField(errors);
+    return isValide;
+  }
+
+  /**
+   * The AA field is forbidden for the Widget annotation when the PDF is a
+   * PDF/A. This method return false and update the errors list if this key is
+   * present. returns true otherwise
+   * 
+   * @param errors
+   * @return
+   */
+  protected boolean checkAAField(List<ValidationError> errors) {
+    if (this.pdWidget.getActions() != null) {
+      errors.add(new ValidationResult.ValidationError(
+          ValidationConstants.ERROR_ANNOT_FORBIDDEN_AA));
+      return false;
+    }
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @seenet.awl.edoc.pdfa.validation.annotation.AnnotationValidator#
+   * checkMandatoryFields(java.util.List)
+   */
+  protected boolean checkMandatoryFields(List<ValidationError> errors) {
+    boolean subtype = false;
+    boolean rect = false;
+    boolean f = false;
+
+    for (Object key : this.annotDictionary.keySet()) {
+      if (!(key instanceof COSName)) {
+        errors.add(new ValidationResult.ValidationError(
+            ValidationConstants.ERROR_SYNTAX_DICTIONARY_KEY_INVALID,
+            "Invalid key in The Annotation dictionary"));
+        return false;
+      }
+
+      String cosName = ((COSName) key).getName();
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_RECT)) {
+        rect = true;
+      }
+      if (cosName.equals(DICTIONARY_KEY_SUBTYPE)) {
+        subtype = true;
+      }
+      if (cosName.equals(ANNOT_DICTIONARY_KEY_F)) {
+        f = true;
+      }
+    }
+
+    boolean result = (subtype && rect && f);
+    if (!result) {
+      errors.add(new ValidationResult.ValidationError(
+          ValidationConstants.ERROR_ANNOT_MISSING_FIELDS));
+    }
+    return result;
+  }
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/annotation/WidgetAnnotationValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamException.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamException.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamException.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamException.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * 
+ * 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.contentstream;
+
+import java.io.IOException;
+
+/**
+ * This exception inherits from the IOException to be thrown by classes which
+ * inherit from org.apache.pdfbox.util.PDFStreamEngine.
+ * 
+ * This exception contains a validationError code.
+ */
+public class ContentStreamException extends IOException {
+  private String validationError = "";
+
+  public ContentStreamException() {
+    super();
+  }
+
+  public ContentStreamException(String arg0, Throwable arg1) {
+    super(arg0);
+  }
+
+  public ContentStreamException(String arg0) {
+    super(arg0);
+  }
+
+  public ContentStreamException(Throwable arg0) {
+    super(arg0.getMessage());
+  }
+
+  /**
+   * @return the validationError
+   */
+  public String getValidationError() {
+    return validationError;
+  }
+
+  /**
+   * @param validationError
+   *          the validationError to set
+   */
+  public void setValidationError(String validationError) {
+    this.validationError = validationError;
+  }
+
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 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=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamWrapper.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamWrapper.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,365 @@
+/*****************************************************************************
+ * 
+ * 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.contentstream;
+
+import static org.apache.padaf.preflight.ValidationConstants.DICTIONARY_KEY_RESOURCES;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_FONTS_ENCODING_ERROR;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_FONTS_FONT_FILEX_INVALID;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_FONTS_UNKNOWN_FONT_REF;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_SYNTAX_CONTENT_STREAM_UNSUPPORTED_OP;
+
+import java.io.IOException;
+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.font.AbstractFontContainer;
+import org.apache.padaf.preflight.font.GlyphException;
+import org.apache.padaf.preflight.font.AbstractFontContainer.State;
+import org.apache.padaf.preflight.utils.ContentStreamEngine;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSFloat;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.graphics.PDGraphicsState;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;
+import org.apache.pdfbox.pdmodel.text.PDTextState;
+import org.apache.pdfbox.util.PDFOperator;
+import org.apache.pdfbox.util.operator.OperatorProcessor;
+
+public class ContentStreamWrapper extends ContentStreamEngine {
+
+	public ContentStreamWrapper(DocumentHandler handler) {
+		super(handler);
+	}
+
+	/**
+	 * Process the validation of a PageContent (The page is initialized by the
+	 * constructor)
+	 * 
+	 * @return A list of validation error. This list is empty if the validation
+	 *         succeed.
+	 * @throws ValidationException.
+	 */
+	public List<ValidationError> validPageContentStream(PDPage page)
+	throws ValidationException {
+		List<ValidationError> errors = new ArrayList<ValidationError>();
+
+		try {
+			PDStream pstream = page.getContents();
+			if (pstream != null) {
+				processStream(page, page.findResources(), pstream.getStream());
+			}
+		} catch (ContentStreamException e) {
+			errors.add(new ValidationError(e.getValidationError(), e.getMessage()));
+		} catch (IOException e) {
+			throw new ValidationException("Unable to check the ContentStream : "
+					+ e.getMessage(), e);
+		}
+
+		return errors;
+	}
+
+	/**
+	 * Process the validation of a XObject Form
+	 * 
+	 * @param xobj
+	 * @return A list of validation error. This list is empty if the validation
+	 *         succeed.
+	 * @throws ValidationException
+	 */
+	public List<ValidationError> validXObjContentStream(PDXObjectForm xobj)
+	throws ValidationException {
+		List<ValidationError> errors = new ArrayList<ValidationError>();
+
+		try {
+			resetEnginContext();
+			processSubStream(null, xobj.getResources(), xobj.getCOSStream());
+		} catch (ContentStreamException e) {
+			errors.add(new ValidationError(e.getValidationError(), e.getMessage()));
+		} catch (IOException e) {
+			throw new ValidationException("Unable to check the ContentStream : "
+					+ e.getMessage(), e);
+		}
+
+		return errors;
+	}
+
+	/**
+	 * Process the validation of a Tiling Pattern
+	 * 
+	 * @param pattern
+	 * @return A list of validation error. This list is empty if the validation
+	 *         succeed.
+	 * @throws ValidationException
+	 */
+	public List<ValidationError> validPatternContentStream(COSStream pattern)
+	throws ValidationException {
+		List<ValidationError> errors = new ArrayList<ValidationError>();
+
+		try {
+			COSDictionary res = (COSDictionary) pattern
+			.getDictionaryObject(DICTIONARY_KEY_RESOURCES);
+			resetEnginContext();
+			processSubStream(null, new PDResources(res), pattern);
+		} catch (ContentStreamException e) {
+			errors.add(new ValidationError(e.getValidationError(), e.getMessage()));
+		} catch (IOException e) {
+			throw new ValidationException("Unable to check the ContentStream : "
+					+ e.getMessage(), e);
+		}
+
+		return errors;
+	}
+
+	public final void resetEnginContext() {
+		this.setGraphicsState(new PDGraphicsState());
+		this.setTextMatrix(null);
+		this.setTextLineMatrix(null);
+		this.getGraphicsStack().clear();
+		// this.streamResourcesStack.clear();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.apache.pdfbox.util.PDFStreamEngine#processOperator(org.apache.pdfbox
+	 * .util.PDFOperator, java.util.List)
+	 */
+	protected void processOperator(PDFOperator operator, List arguments)
+	throws IOException {
+
+		// ---- Here is a copy of the super method because the else block is
+		// different. (If the operator is unknown, throw an exception)
+		String operation = operator.getOperation();
+		OperatorProcessor processor = (OperatorProcessor) contentStreamEngineOperators.get(operation);
+		if (processor != null) {
+			processor.setContext(this);
+			processor.process(operator, arguments);
+		} else {
+			throwContentStreamException("The operator \"" + operation
+					+ "\" isn't supported.", ERROR_SYNTAX_CONTENT_STREAM_UNSUPPORTED_OP);
+		}
+
+		// --- Process Specific Validation
+		// --- The Generic Processing is useless for PDFA validation
+		if ("BI".equals(operation)) {
+			validImageFilter(operator);
+			validImageColorSpace(operator);
+		}
+
+		checkShowTextOperators(operator, arguments);
+		checkColorOperators(operation);
+		validRenderingIntent(operator, arguments);
+		checkSetColorSpaceOperators(operator, arguments);
+		validNumberOfGraphicStates(operator);
+	}
+
+	/**
+	 * Process Text Validation. According to the operator one of the both method
+	 * will be called. (validStringDefinition(PDFOperator operator, List<?>
+	 * arguments) / validStringArray(PDFOperator operator, List<?> arguments))
+	 * 
+	 * @param operator
+	 * @param arguments
+	 * @throws ContentStreamException
+	 * @throws IOException
+	 */
+	protected void checkShowTextOperators(PDFOperator operator, List<?> arguments)
+	throws ContentStreamException, IOException {
+		String op = operator.getOperation();
+		if ("Tj".equals(op)
+				|| "'".equals(op)
+				|| "\"".equals(op)) {
+			validStringDefinition(operator, arguments);
+		}
+
+		if ("TJ".equals(op)) {
+			validStringArray(operator, arguments);
+		}
+	}
+
+	/**
+	 * Process Text Validation for the Operands of a Tj, "'" and "\"" operator.
+	 * 
+	 * If the validation fails for an unexpected reason, a IOException is thrown.
+	 * If the validation fails due to validation error, a ContentStreamException
+	 * is thrown. (Use the ValidationError attribute to know the cause)
+	 * 
+	 * @param operator
+	 * @param arguments
+	 * @throws ContentStreamException
+	 * @throws IOException
+	 */
+	private void validStringDefinition(PDFOperator operator, List<?> arguments)
+	throws ContentStreamException, IOException {
+		// ---- For a Text operator, the arguments list should contain only one
+		// COSString object
+		if ("\"".equals(operator.getOperation())) {
+			if (arguments.size() != 3) {
+				throwContentStreamException("Invalid argument for the operator : "
+						+ operator.getOperation(),
+						ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+			}
+			Object arg0 = arguments.get(0);
+			Object arg1 = arguments.get(1);
+			Object arg2 = arguments.get(2);
+			if (!(arg0 instanceof COSInteger || arg0 instanceof COSFloat) || 
+					!(arg1 instanceof COSInteger || arg1 instanceof COSFloat) ) {
+				throwContentStreamException("Invalid argument for the operator : "
+						+ operator.getOperation(),
+						ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);				
+			}
+
+			if (arg2 instanceof COSString) {
+				validText(((COSString) arg2).getBytes());
+			} else {
+				throwContentStreamException("Invalid argument for the operator : "
+						+ operator.getOperation(),
+						ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+			}
+		} else {
+			Object objStr = arguments.get(0);
+			if (objStr instanceof COSString) {
+				validText(((COSString) objStr).getBytes());
+			} else if (!(objStr instanceof COSInteger)) {
+				throwContentStreamException("Invalid argument for the operator : "
+						+ operator.getOperation(),
+						ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+			}
+		}
+	}
+
+	/**
+	 * Process Text Validation for the Operands of a TJ operator.
+	 * 
+	 * If the validation fails for an unexpected reason, a IOException is thrown.
+	 * If the validation fails due to validation error, a ContentStreamException
+	 * is thrown. (Use the ValidationError attribute to know the cause)
+	 * 
+	 * @param operator
+	 * @param arguments
+	 * @throws ContentStreamException
+	 * @throws IOException
+	 */
+	private void validStringArray(PDFOperator operator, List<?> arguments)
+	throws ContentStreamException, IOException {
+		for (Object object : arguments) {
+			if (object instanceof COSArray) {
+				validStringArray(operator, ((COSArray) object).toList());
+			} else if (object instanceof COSString) {
+				validText(((COSString) object).getBytes());
+			} else if (!(object instanceof COSInteger || object instanceof COSFloat)) {
+				throwContentStreamException("Invalid argument for the operator : "
+						+ operator.getOperation(),
+						ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+			}
+		}
+	}
+
+	/**
+	 * Process the validation of a Text operand contains in a ContentStream This
+	 * validation checks that :
+	 * <UL>
+	 * <li>The font isn't missing if the Rendering Mode isn't 3
+	 * <li>The font metrics are consistent
+	 * <li>All character used in the text are defined in the font program.
+	 * </UL>
+	 * 
+	 * @param string
+	 * @throws IOException
+	 */
+	public void validText(byte[] string) throws IOException {
+		// --- 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
+			throwContentStreamException("Text operator can't be process without Font", ERROR_FONTS_UNKNOWN_FONT_REF);
+		}
+
+		// FontContainer fontContainer = documentHandler.retrieveFontContainer(font);
+		AbstractFontContainer fontContainer = documentHandler.getFont(font.getCOSObject());
+
+		if (fontContainer != null && fontContainer.isValid() == State.INVALID) {
+			return;
+		}
+
+		if (renderingMode == 3 && (fontContainer == null || !fontContainer.isFontProgramEmbedded())) {
+			// 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
+			throwContentStreamException(font.getBaseFont() + " is unknown wasn't found by the FontHelperValdiator", ERROR_FONTS_UNKNOWN_FONT_REF);	
+		}
+
+		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) {
+			// Decode the value to a Unicode character
+			codeLength = 1;
+			String c = null;
+			try {
+				c = font.encode(string, i, codeLength);
+				if (c == null && i + 1 < string.length) {
+					// maybe a multibyte encoding
+					codeLength++;
+					c = font.encode(string, i, codeLength);
+				}
+			} catch (IOException e) {
+				throwContentStreamException("Encoding can't interpret the character code", ERROR_FONTS_ENCODING_ERROR);
+			}
+
+			// ---- According to the length of the character encoding,
+			// convert the character to CID
+			int cid = 0;
+			for (int j = 0; j < codeLength; j++) {
+				cid <<= 8;
+				cid += ((string[i + j] + 256) % 256);
+			}
+
+			try {
+				fontContainer.checkCID(cid);
+			} catch (GlyphException e) {
+				throwContentStreamException(e.getMessage(), e.getErrorCode());  
+			}
+		}
+	}
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/ContentStreamWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/StubOperator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/StubOperator.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/StubOperator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/StubOperator.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,334 @@
+/*****************************************************************************
+ * 
+ * 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.contentstream;
+
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_SYNTAX_ARRAY_TOO_LONG;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_SYNTAX_LITERAL_TOO_LONG;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_SYNTAX_NAME_TOO_LONG;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_SYNTAX_NUMERIC_RANGE;
+import static org.apache.padaf.preflight.ValidationConstants.ERROR_SYNTAX_TOO_MANY_ENTRIES;
+import static org.apache.padaf.preflight.ValidationConstants.MAX_ARRAY_ELEMENTS;
+import static org.apache.padaf.preflight.ValidationConstants.MAX_DICT_ENTRIES;
+import static org.apache.padaf.preflight.ValidationConstants.MAX_NAME_SIZE;
+import static org.apache.padaf.preflight.ValidationConstants.MAX_NEGATIVE_FLOAT;
+import static org.apache.padaf.preflight.ValidationConstants.MAX_POSITIVE_FLOAT;
+import static org.apache.padaf.preflight.ValidationConstants.MAX_STRING_LENGTH;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSFloat;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.util.PDFOperator;
+import org.apache.pdfbox.util.operator.OperatorProcessor;
+
+/**
+ * This implementation of OperatorProcessor allow the operator validation
+ * according PDF/A rules without compute the operator actions.
+ */
+public class StubOperator extends OperatorProcessor {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.pdfbox.util.operator.OperatorProcessor#process(org.apache.pdfbox
+   * .util.PDFOperator, java.util.List)
+   */
+  @Override
+  public void process(PDFOperator operator, List<COSBase> arguments)
+      throws IOException {
+	String op = operator.getOperation();
+    if ("S".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("B".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("f".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("F".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("f*".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("b".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("B*".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("b*".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("s".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("EMC".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("BMC".equals(op)) {
+      checkStringOperands(arguments, 1);
+    } else if ("BDC".equals(op)) {
+      checkTagAndPropertyOperands(arguments);
+    } else if ("DP".equals(op)) {
+      checkTagAndPropertyOperands(arguments);
+    } else if ("c".equals(op)) {
+      checkNumberOperands(arguments, 6);
+    } else if ("v".equals(op)) {
+      checkNumberOperands(arguments, 4);
+    } else if ("y".equals(op)) {
+      checkNumberOperands(arguments, 4);
+    } else if ("d0".equals(op)) {
+      checkNumberOperands(arguments, 2);
+    } else if ("d1".equals(op)) {
+      checkNumberOperands(arguments, 6);
+    } else if ("g".equals(op)) {
+      checkNumberOperands(arguments, 1);
+    } else if ("G".equals(op)) {
+      checkNumberOperands(arguments, 1);
+    } else if ("gs".equals(op)) {
+      checkStringOperands(arguments, 1);
+    } else if ("h".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("i".equals(op)) {
+      checkNumberOperands(arguments, 1);
+    } else if ("l".equals(op)) {
+      checkNumberOperands(arguments, 2);
+    } else if ("m".equals(op)) {
+      checkNumberOperands(arguments, 2);
+    } else if ("M".equals(op)) {
+      checkNumberOperands(arguments, 1);
+    } else if ("MP".equals(op)) {
+      checkStringOperands(arguments, 1);
+    } else if ("n".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("re".equals(op)) {
+      checkNumberOperands(arguments, 4);
+    } else if ("ri".equals(op)) {
+      checkStringOperands(arguments, 1);
+    } else if ("s".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("S".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("sh".equals(op)) {
+      checkStringOperands(arguments, 1);
+    } else if ("'".equals(op)) {
+      checkStringOperands(arguments, 1);
+    } else if ("Tj".equals(op)) {
+      checkStringOperands(arguments, 1);
+    } else if ("TJ".equals(op)) {
+      checkArrayOperands(arguments, 1);
+    } else if ("W".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("W*".equals(op)) {
+      checkNoOperands(arguments);
+    } else if ("\"".equals(op)) {
+      checkNumberOperands(arguments.subList(0, 2), 2);
+      checkStringOperands(arguments.subList(2, arguments.size()), 1);
+    } 
+    // else 
+    // ---- Some operators are processed by PDFBox Objects.
+    // ---- Other operators are authorized but it isn't used.
+    
+  }
+
+  /**
+   * If the arguments list of Operator isn't empty, this method throws a
+   * ContentStreamException.
+   * 
+   * @param arguments
+   * @throws ContentStreamException
+   */
+  private void checkNoOperands(List<COSBase> arguments)
+      throws ContentStreamException {
+    if (arguments != null && !arguments.isEmpty()) {
+      throw createInvalidArgumentsError();
+    }
+  }
+
+  /**
+   * If the arguments list of Operator doesn't have String parameter, this
+   * method throws a ContentStreamException.
+   * 
+   * @param arguments
+   * @param length
+   * @throws ContentStreamException
+   */
+  private void checkStringOperands(List<COSBase> arguments, int length)
+      throws ContentStreamException {
+    if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
+      throw createInvalidArgumentsError();
+    }
+
+    for (int i = 0; i < length; ++i) {
+      COSBase arg = arguments.get(i);
+      if (!(arg instanceof COSName) && !(arg instanceof COSString)) {
+        throw createInvalidArgumentsError();
+      }
+
+      if (arg instanceof COSName
+          && ((COSName) arg).getName().length() > MAX_NAME_SIZE) {
+        throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
+      }
+
+      if (arg instanceof COSString
+          && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH) {
+        throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
+      }
+    }
+  }
+
+  /**
+   * If the arguments list of Operator doesn't have Array parameter, this method
+   * throws a ContentStreamException.
+   * 
+   * @param arguments
+   * @param length
+   * @throws ContentStreamException
+   */
+  private void checkArrayOperands(List<COSBase> arguments, int length)
+      throws ContentStreamException {
+    if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
+      throw createInvalidArgumentsError();
+    }
+
+    for (int i = 0; i < length; ++i) {
+      COSBase arg = arguments.get(i);
+      if (!(arg instanceof COSArray)) {
+        throw createInvalidArgumentsError();
+      }
+
+      if (((COSArray) arg).size() > MAX_ARRAY_ELEMENTS) {
+        throw createLimitError(ERROR_SYNTAX_ARRAY_TOO_LONG, "Array has " + ((COSArray) arg).size() + " elements");
+      }
+    }
+  }
+
+  /**
+   * If the arguments list of Operator doesn't have Number parameters (Int,
+   * float...), this method throws a ContentStreamException.
+   * 
+   * @param arguments
+   *          the arguments list to check
+   * @param length
+   *          the expected size of the list
+   * @throws ContentStreamException
+   */
+  private void checkNumberOperands(List<COSBase> arguments, int length)
+      throws ContentStreamException {
+    if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
+      throw createInvalidArgumentsError();
+    }
+
+    for (int i = 0; i < length; ++i) {
+      COSBase arg = arguments.get(i);
+      if (!(arg instanceof COSFloat) && !(arg instanceof COSInteger)) {
+        throw createInvalidArgumentsError();
+      }
+
+      if (arg instanceof COSInteger
+          && (((COSInteger) arg).longValue() > Integer.MAX_VALUE || ((COSInteger) arg)
+              .longValue() < Integer.MIN_VALUE)) {
+        throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid integer range in a Number operands");
+      }
+
+      if (arg instanceof COSFloat
+          && (((COSFloat) arg).doubleValue() > MAX_POSITIVE_FLOAT || ((COSFloat) arg)
+              .doubleValue() < MAX_NEGATIVE_FLOAT)) {
+        throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid float range in a Number operands");
+      }
+    }
+  }
+
+  /**
+   * The given arguments list is valid only if the first argument is a Tag (A
+   * String) and if the second argument is a String or a Dictionary
+   * 
+   * @param arguments
+   * @throws ContentStreamException
+   */
+  private void checkTagAndPropertyOperands(List<COSBase> arguments)
+      throws ContentStreamException {
+    if (arguments == null || arguments.isEmpty() || arguments.size() != 2) {
+      throw createInvalidArgumentsError();
+    }
+
+    COSBase arg = arguments.get(0);
+    if (!(arg instanceof COSName) && !(arg instanceof COSString)) {
+      throw createInvalidArgumentsError();
+    }
+
+    if (arg instanceof COSName
+        && ((COSName) arg).getName().length() > MAX_NAME_SIZE) {
+      throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG,"A Name operand is too long");
+    }
+
+    if (arg instanceof COSString
+        && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH) {
+      throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG,"A String operand is too long");
+    }
+
+    COSBase arg2 = arguments.get(1);
+    if (!(arg2 instanceof COSName) && !(arg2 instanceof COSString)
+        && !(arg2 instanceof COSDictionary)) {
+      throw createInvalidArgumentsError();
+    }
+
+    if (arg2 instanceof COSName
+        && ((COSName) arg2).getName().length() > MAX_NAME_SIZE) {
+      throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG,"A Name operand is too long");
+    }
+
+    if (arg2 instanceof COSString
+        && ((COSString) arg2).getString().getBytes().length > MAX_STRING_LENGTH) {
+      throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG,"A String operand is too long");
+    }
+
+    if (arg2 instanceof COSDictionary
+        && ((COSDictionary) arg2).size() > MAX_DICT_ENTRIES) {
+      throw createLimitError(ERROR_SYNTAX_TOO_MANY_ENTRIES, "Dictionary has " + ((COSDictionary) arg2).size() + " entries");
+    }
+  }
+
+  /**
+   * Create a ContentStreamException with
+   * ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
+   * 
+   * @return
+   */
+  private ContentStreamException createInvalidArgumentsError() {
+    ContentStreamException ex = new ContentStreamException();
+    ex.setValidationError(ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+    return ex;
+  }
+
+  /**
+   * Create a ContentStreamException with
+   * ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
+   * 
+   * @return
+   */
+  private ContentStreamException createLimitError(String errorCode, String details) {
+    ContentStreamException ex = new ContentStreamException(details);
+    ex.setValidationError(errorCode);
+    return ex;
+  }
+}

Propchange: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/contentstream/StubOperator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/AbstractFontContainer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/AbstractFontContainer.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/AbstractFontContainer.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/AbstractFontContainer.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.font;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+import org.apache.padaf.preflight.ValidationConstants;
+import org.apache.padaf.preflight.ValidationResult.ValidationError;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+
+public abstract class AbstractFontContainer {
+  /**
+   * PDFBox object which contains the Font Dictionary
+   */
+  protected PDFont font = null;
+
+  protected Map<Integer, GlyphDetail> cidKnownByFont = new HashMap<Integer, GlyphDetail>();
+
+  /**
+   * Boolean used to know if the Font Program is embedded.
+   */
+  protected boolean isFontProgramEmbedded = true;
+
+  /**
+   * Errors which occurs during the Font Validation
+   */
+  protected List<ValidationError> errors = new ArrayList<ValidationError>(0);
+
+  /**
+   * The FontContainer Constructor. The type attribute is initialized according
+   * to the given PDFont object.
+   * 
+   * @param fd
+   *          Font object of the PDFBox API. (Mandatory)
+   * @throws NullPointerException
+   *           If the fd is null.
+   */
+  public AbstractFontContainer(PDFont fd) {
+    this.font = fd;
+  }
+
+  /**
+   * Return the PDFont object
+   * 
+   * @return
+   */
+  public PDFont getFont() {
+    return font;
+  }
+
+  public void addCID(Integer cid, GlyphDetail details) {
+    this.cidKnownByFont.put(cid, details);
+  }
+
+  /**
+   * @return the isFontProgramEmbedded
+   */
+  public boolean isFontProgramEmbedded() {
+    return isFontProgramEmbedded;
+  }
+
+  /**
+   * @param isFontProgramEmbedded
+   *          the isFontProgramEmbedded to set
+   */
+  public void setFontProgramEmbedded(boolean isFontProgramEmbedded) {
+    this.isFontProgramEmbedded = isFontProgramEmbedded;
+  }
+
+  /**
+   * Addition of a validation error.
+   * 
+   * @param error
+   */
+  public void addError(ValidationError error) {
+    this.errors.add(error);
+  }
+
+  /**
+   * This method returns the validation state of the font.
+   * 
+   * If the list of errors is empty, the validation is successful (State :
+   * VALID). If the size of the list is 1 and if the error is about EmbeddedFont,
+   * the state is "MAYBE" because the font can be valid if
+   * it isn't used (for Width error) or if the rendering mode is 3 (For not
+   * embedded font). Otherwise, the validation failed (State : INVALID)
+   * 
+   * @return
+   */
+  public State isValid() {
+    if (this.errors.isEmpty()) {
+      return State.VALID;
+    }
+
+    if ((this.errors.size() == 1)
+        && !this.isFontProgramEmbedded) {
+      return State.MAYBE;
+    }
+
+    // else more than one error, the validation failed
+    return State.INVALID;
+  }
+
+  /**
+   * @return the errors
+   */
+  public List<ValidationError> getErrors() {
+    return errors;
+  }
+
+  public static enum State {
+    VALID, MAYBE, INVALID;
+  }
+
+  
+  /**
+   * Check if the cid is present and consistent in the contained font.
+   * @param cid the cid
+   * @return true if cid is present and consistent, false otherwise
+   */
+  public abstract void checkCID (int cid) throws GlyphException;
+
+  
+  void addKnownCidElement(GlyphDetail glyphDetail) {
+    this.cidKnownByFont.put(glyphDetail.getCID(), glyphDetail);
+  }
+  
+  protected boolean isAlreadyComputedCid(int cid) throws GlyphException {
+  	boolean already = false;
+	  GlyphDetail gdetail = this.cidKnownByFont.get(cid);
+	  if (gdetail != null) {
+		  gdetail.throwExceptionIfNotValid();
+		  already = true;
+	  }
+	  return already;
+  }
+
+  protected void checkWidthsConsistency(int cid, float widthProvidedByPdfDictionary, float widthInFontProgram) throws GlyphException {
+  	if(!(Math.floor(widthInFontProgram) == widthProvidedByPdfDictionary || Math.round(widthInFontProgram) == widthProvidedByPdfDictionary)) {
+  	  GlyphException e = new GlyphException(ValidationConstants.ERROR_FONTS_METRICS, cid, 
+				  				"Width of the character \"" + cid 
+				  				+ "\" in the font program \""
+				  				+ this.font.getBaseFont() 
+				  				+ "\"is inconsistent with the width in the PDF dictionary.");
+		  addKnownCidElement(new GlyphDetail(cid, e));
+		  throw e;
+	  }
+  }
+}

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

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/AbstractFontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/AbstractFontValidator.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/AbstractFontValidator.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/AbstractFontValidator.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,228 @@
+/*****************************************************************************
+ * 
+ * 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;
+
+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.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.font.AbstractFontContainer.State;
+import org.apache.padaf.xmpbox.XMPMetadata;
+import org.apache.padaf.xmpbox.parser.XMPDocumentBuilder;
+import org.apache.padaf.xmpbox.parser.XmpExpectedRdfAboutAttribute;
+import org.apache.padaf.xmpbox.parser.XmpParsingException;
+import org.apache.padaf.xmpbox.parser.XmpSchemaException;
+import org.apache.padaf.xmpbox.parser.XmpUnknownValueTypeException;
+import org.apache.padaf.xmpbox.parser.XmpXpacketEndException;
+import org.apache.padaf.xmpbox.type.BadFieldValueException;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.pdmodel.common.PDMetadata;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
+import org.apache.pdfbox.pdmodel.font.PDFontFactory;
+
+public abstract class AbstractFontValidator implements FontValidator,ValidationConstants {
+  /**
+   * DocumentHandler which contains all useful objects to validate a PDF/A ex :
+   * parser JavaCC
+   */
+  protected DocumentHandler handler = null;
+  /**
+   * The COSObject which is the starting point of the Font description in the
+   * PDF/A file. This object should be an insteance of COSDictionary
+   */
+  protected COSObject cObj = null;
+  /**
+   * The cObj casted as COSDictionary
+   */
+  protected COSDictionary fDictionary = null;
+  /**
+   * The PdfBox font dictionary wrapper.
+   */
+  protected PDFont pFont = null;
+
+  /**
+   * The Font Container contains the Font Validation state ( valid or not,
+   * why...) This Font Container is tested when the font is used as resource.
+   * According to the state of this font, the PDF File will be PDF/A conforming
+   * file or not. (Ex : if the FontContainer flags this font as not embedded,
+   * the PDF is a PDF/A only if the font is used in a Rendering Mode 3.)
+   */
+  protected AbstractFontContainer fontContainer = null;
+
+  /**
+   * Abstract Constructor
+   * @param handler the handled document
+   * @param cObj The cos object representing the font
+   * @throws ValidationException when object creation fails
+   */
+  public AbstractFontValidator(DocumentHandler handler, COSObject cObj)
+  throws ValidationException {
+    try {
+      this.handler = handler;
+      this.cObj = cObj;
+      this.fDictionary = (COSDictionary) cObj.getObject();
+      this.pFont = PDFontFactory.createFont(fDictionary);
+
+      this.fontContainer = instanciateContainer(this.pFont);
+      this.handler.addFont(this.pFont.getCOSObject(), this.fontContainer);
+    } catch (IOException e) {
+      throw new ValidationException(
+          "Unable to instantiate a FontValidator object : " + e.getMessage());
+    }
+  }
+
+  protected AbstractFontContainer instanciateContainer (PDFont fd) {
+    String subtype = fd.getSubType();
+    if (FONT_DICTIONARY_VALUE_TRUETYPE.equals(subtype)) {
+      return new TrueTypeFontContainer(fd);
+    } else if (FONT_DICTIONARY_VALUE_MMTYPE.equals(subtype)) {
+      return new Type1FontContainer(fd);
+    } else if (FONT_DICTIONARY_VALUE_TYPE1.equals(subtype)) {
+      return new Type1FontContainer(fd);
+    } else if (FONT_DICTIONARY_VALUE_TYPE3.equals(subtype)) {
+      return new Type3FontContainer(fd);
+    } else if (FONT_DICTIONARY_VALUE_COMPOSITE.equals(subtype)) {
+      return new CompositeFontContainer(fd);
+    } else {
+      return new UndefFontContainer(fd);
+    }
+  }
+
+  private static final String subSetPattern = "^[A-Z]{6}\\+.*";
+
+  public static boolean isSubSet(String fontName) {
+    return fontName.matches(subSetPattern);
+  }
+
+  public static String getSubSetPatternDelimiter() {
+    return "+";
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see net.awl.edoc.pdfa.validation.font.FontValidator#getState()
+   */
+  public State getState() {
+    return this.fontContainer.isValid();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see net.awl.edoc.pdfa.validation.font.FontValidator#getValdiationErrors()
+   */
+  public List<ValidationError> getValdiationErrors() {
+    return this.fontContainer.getErrors();
+  }
+
+  /**
+   * Type0, Type1 and TrueType FontValidatir call this method to check the
+   * FontFile meta data.
+   * 
+   * @param fontDesc
+   *          The FontDescriptor which contains the FontFile stream
+   * @param fontFile
+   *          The font file stream to check
+   * @return true if the meta data is valid, false otherwise
+   * @throws ValidationException when checking fails
+   */
+  protected boolean checkFontFileMetaData(PDFontDescriptor fontDesc,
+      PDStream fontFile) throws ValidationException {
+    PDMetadata metadata = fontFile.getMetadata();
+    if (metadata != null) {
+      // --- Filters are forbidden in a XMP stream
+      if (metadata.getFilters() != null && !metadata.getFilters().isEmpty()) {
+        fontContainer.addError(new ValidationError(
+            ValidationConstants.ERROR_SYNTAX_STREAM_INVALID_FILTER,
+        "Filter specified in font file metadata dictionnary"));
+        return false;
+      }
+
+      // --- extract the meta data content
+      byte[] mdAsBytes = null;
+      try {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        InputStream metaDataContent = metadata.createInputStream();
+        IOUtils.copyLarge(metaDataContent, bos);
+        IOUtils.closeQuietly(metaDataContent);
+        IOUtils.closeQuietly(bos);
+        mdAsBytes = bos.toByteArray();
+      } catch (IOException e) {
+        throw new ValidationException("Unable to read font metadata due to : "
+            + e.getMessage(), e);
+      }
+
+      try {
+
+        XMPDocumentBuilder xmpBuilder = new XMPDocumentBuilder();
+        XMPMetadata xmpMeta = xmpBuilder.parse(mdAsBytes);
+
+        FontMetaDataValidation fontMDval = new FontMetaDataValidation();
+        List<ValidationError> ve = new ArrayList<ValidationError>();
+        boolean isVal = fontMDval.analyseFontName(xmpMeta, fontDesc, ve);
+        isVal = isVal && fontMDval.analyseFontName(xmpMeta, fontDesc, ve);
+        for (ValidationError validationError : ve) {
+          fontContainer.addError(validationError);
+        }
+        return isVal;
+
+      } catch (XmpUnknownValueTypeException e) {
+        fontContainer.addError(new ValidationError(
+            ValidationConstants.ERROR_METADATA_UNKNOWN_VALUETYPE, e
+            .getMessage()));
+        return false;
+      } catch (XmpParsingException e) {
+        fontContainer.addError(new ValidationError(
+            ValidationConstants.ERROR_METADATA_FORMAT, e.getMessage()));
+        return false;
+      } catch (XmpSchemaException e) {
+        fontContainer.addError(new ValidationError(
+            ValidationConstants.ERROR_METADATA_FORMAT, e.getMessage()));
+        return false;
+      } catch (XmpExpectedRdfAboutAttribute e) {
+        fontContainer.addError(new ValidationError(ValidationConstants.ERROR_METADATA_RDF_ABOUT_ATTRIBUTE_MISSING,e.getMessage()));
+        return false;
+      } catch (BadFieldValueException e) {
+        fontContainer.addError(new ValidationError(ValidationConstants.ERROR_METADATA_CATEGORY_PROPERTY_INVALID,e.getMessage()));
+        return false;
+      } catch (XmpXpacketEndException e) {
+        throw new ValidationException("Unable to parse font metadata due to : "
+            + e.getMessage(), e);
+      }
+    }
+
+    // --- No MetaData, valid
+    return true;
+  }
+}

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

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,121 @@
+/*****************************************************************************
+ * 
+ * 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;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+
+import org.apache.fontbox.cff.CFFFont;
+import org.apache.fontbox.cff.CFFFont.Mapping;
+import org.apache.padaf.preflight.ValidationConstants;
+
+
+public class CFFType0FontContainer extends AbstractFontContainer {
+	private Map<Integer, Integer> widthsArray = new LinkedHashMap<Integer, Integer>(0);
+	/**
+	 * Represent the missingWidth value of the FontDescriptor dictionary.
+	 * According to the PDF Reference, if this value is missing, the default 
+	 * one is 0.
+	 */
+	private float defaultGlyphWidth = 0;
+	/**
+	 * Object which contains the CFF data extracted by the
+	 * CFFParser object
+	 */
+	private List<CFFFont> fontObject = null;
+
+	public CFFType0FontContainer(CompositeFontContainer container) {
+		super(container.getFont());
+		this.cidKnownByFont.putAll(container.cidKnownByFont);
+		this.isFontProgramEmbedded = container.isFontProgramEmbedded;
+		this.errors.addAll(container.errors);
+	}
+
+	@Override
+	public void checkCID(int cid) throws GlyphException {
+	  if (isAlreadyComputedCid(cid)) {
+		  return;
+	  }
+
+		// ---- build the font container and keep it in the Handler.
+	  boolean cidFound = false;
+		for (CFFFont font : this.fontObject) {
+			Collection<Mapping> cMapping = font.getMappings();
+			for (Mapping mapping : cMapping) {
+				// -- REMARK : May be this code must be changed like the Type1FontContainer to Map the SID with the character name?
+				// -- Not enough PDF with this kind of Font to test the current implementation
+				if (mapping.getSID()==cid) {
+					cidFound = true;
+				}
+			}
+		}
+
+		if (!cidFound) {
+			GlyphException ge = new GlyphException(ValidationConstants.ERROR_FONTS_GLYPH_MISSING, cid, 
+																							"CID " + cid + " is missing from the Composite Font format \"" 
+																							+ this.font.getBaseFont()+"\""	);
+		  addKnownCidElement(new GlyphDetail(cid, ge));
+			throw ge;
+		}
+
+
+		float widthProvidedByPdfDictionary = this.defaultGlyphWidth;
+		if (this.widthsArray.containsKey(cid)) {
+			widthProvidedByPdfDictionary = this.widthsArray.get(cid);
+		}
+		float widthInFontProgram = 0;
+
+		try {
+			// ---- Search the CID in all CFFFont in the FontProgram
+			for (CFFFont cff : fontObject) {
+				widthInFontProgram = cff.getWidth(cid);
+				if (widthInFontProgram != defaultGlyphWidth) {
+					break;
+				}
+			}
+		} catch (IOException e) {
+			GlyphException ge = new GlyphException(ValidationConstants.ERROR_FONTS_DAMAGED, cid, 
+					"Unable to get width of the CID/SID : " + cid);
+			addKnownCidElement(new GlyphDetail(cid, ge));
+			throw ge;
+		}
+
+		checkWidthsConsistency(cid, widthProvidedByPdfDictionary, widthInFontProgram);
+	  addKnownCidElement(new GlyphDetail(cid));
+	}
+
+	void setWidthsArray(Map<Integer, Integer> widthsArray) {
+		this.widthsArray = widthsArray;
+	}
+
+	void setDefaultGlyphWidth(float defaultGlyphWidth) {
+		this.defaultGlyphWidth = defaultGlyphWidth;
+	}
+
+	void setFontObject(List<CFFFont> fontObject) {
+		this.fontObject = fontObject;
+	}
+}
\ No newline at end of file

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

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType2FontContainer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType2FontContainer.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType2FontContainer.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType2FontContainer.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,160 @@
+/*****************************************************************************
+ * 
+ * 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;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+import org.apache.fontbox.cmap.CMap;
+import org.apache.fontbox.ttf.TrueTypeFont;
+import org.apache.padaf.preflight.ValidationConstants;
+
+
+public class CFFType2FontContainer extends AbstractFontContainer {
+	private Map<Integer, Integer> widthsArray = new LinkedHashMap<Integer, Integer>(0);
+	/**
+	 * Represent the missingWidth value of the FontDescriptor dictionary.
+	 * According to the PDF Reference, if this value is missing, the default 
+	 * one is 0.
+	 */
+	private float defaultGlyphWidth = 0;
+	/**
+	 * Object which contains the TrueType font data (used in the CFFType2 font) 
+	 * extracted by the TrueTypeParser object
+	 */
+	private TrueTypeFont fontObject = null;
+	private CMap cidToGidMap = null;
+	
+	private int numberOfLongHorMetrics;
+	private int unitsPerEm;
+	private int[] glyphWidths;
+
+	public CFFType2FontContainer(CompositeFontContainer container) {
+		super(container.getFont());
+		this.cidKnownByFont.putAll(container.cidKnownByFont);
+		this.isFontProgramEmbedded = container.isFontProgramEmbedded;
+		this.errors.addAll(container.errors);
+	}
+
+	@Override
+	public void checkCID(int cid) throws GlyphException {
+	  if (isAlreadyComputedCid(cid)) {
+		  return;
+	  }
+
+		float widthProvidedByPdfDictionary = this.defaultGlyphWidth;
+		if (this.widthsArray.containsKey(cid)) {
+			Integer i = this.widthsArray.get(cid);
+			widthProvidedByPdfDictionary = i.floatValue();
+		}
+
+		int glyphIndex = getGlyphIndex(cid);
+		
+		if(this.fontObject.getGlyph().getGlyphs().length <= glyphIndex) {
+			GlyphException ge = new GlyphException(ValidationConstants.ERROR_FONTS_GLYPH_MISSING, cid, 
+					"CID " + cid + " is missing from font \"" + this.font.getBaseFont() + "\"");
+		  addKnownCidElement(new GlyphDetail(cid, ge));
+			throw ge;
+		}
+			
+		// glyph exists we can check the width
+		float glypdWidth = glyphWidths[numberOfLongHorMetrics - 1];
+		if (glyphIndex < numberOfLongHorMetrics) {
+			glypdWidth = glyphWidths[glyphIndex];
+		}
+		float widthInFontProgram = ((glypdWidth * 1000) / unitsPerEm);
+
+	  checkWidthsConsistency(cid, widthProvidedByPdfDictionary, widthInFontProgram);
+	  addKnownCidElement(new GlyphDetail(cid));
+	}
+
+	/**
+	 * If CIDToGID map is Identity, the GID equals to the CID.
+	 * Otherwise the conversion is done by the CIDToGID map
+	 * @param cid
+	 * @return
+	 * @throws GlyphException
+	 */
+	private int getGlyphIndex(int cid) throws GlyphException {
+		int glyphIndex = cid;
+
+		if (this.cidToGidMap != null) {
+			byte[] cidAsByteArray = null;
+			if (cid < 256) {
+				cidAsByteArray = new byte[1];
+				cidAsByteArray[0] = (byte) (cid & 0xFF);
+			} else {
+				cidAsByteArray = new byte[1];
+				cidAsByteArray[0] = (byte) ((cid >> 8) & 0xFF);
+				cidAsByteArray[1] = (byte) (cid & 0xFF);
+			}
+
+			String glyphIdAsString = this.cidToGidMap.lookup(cidAsByteArray, 0,	cidAsByteArray.length);
+			// ---- glyphIdAsString should be a Integer
+			// TODO OD-PDFA-4 : A vérifier avec un PDF qui contient une stream pour
+			// CidToGid...
+			try {
+				glyphIndex = Integer.parseInt(glyphIdAsString);
+			} catch (NumberFormatException e) {
+				GlyphException ge = new GlyphException(ValidationConstants.ERROR_FONTS_GLYPH_MISSING, cid, 
+						"CID " + cid + " isn't linked with a GlyphIndex >> " + glyphIdAsString);
+			  addKnownCidElement(new GlyphDetail(cid, ge));
+				throw ge;
+			}
+		}
+		return glyphIndex;
+	}
+
+	void setPdfWidths(Map<Integer, Integer> widthsArray) {
+		this.widthsArray = widthsArray;
+	}
+
+	void setDefaultGlyphWidth(float defaultGlyphWidth) {
+		this.defaultGlyphWidth = defaultGlyphWidth;
+	}
+
+	void setFontObject(TrueTypeFont fontObject) {
+		this.fontObject = fontObject;
+	}
+
+	void setCmap(CMap cmap) {
+		this.cidToGidMap = cmap;
+	}
+
+	void setNumberOfLongHorMetrics(int numberOfLongHorMetrics) {
+		this.numberOfLongHorMetrics = numberOfLongHorMetrics;
+	}
+
+	void setUnitsPerEm(int unitsPerEm) {
+		this.unitsPerEm = unitsPerEm;
+	}
+
+	void setGlyphWidths(int[] _glyphWidths) {
+		this.glyphWidths = new int[_glyphWidths.length];
+		for( int i =0 ; i < _glyphWidths.length; ++i) {
+			this.glyphWidths[i] = _glyphWidths[i];
+		}
+	}
+
+}

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

Added: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CompositeFontContainer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CompositeFontContainer.java?rev=1150373&view=auto
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CompositeFontContainer.java (added)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CompositeFontContainer.java Sun Jul 24 14:02:12 2011
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * 
+ * 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;
+
+import org.apache.pdfbox.pdmodel.font.PDFont;
+
+public class CompositeFontContainer extends AbstractFontContainer {
+	private AbstractFontContainer delegatedContainer = null;
+
+  public CompositeFontContainer(PDFont fd) {
+    super(fd);
+  }
+
+  @Override
+  public void checkCID(int cid) throws GlyphException {
+    this.delegatedContainer.checkCID(cid);
+  }
+
+  CFFType0FontContainer getCFFType0() {
+  	if (delegatedContainer == null) {
+  		delegatedContainer = new CFFType0FontContainer(this);
+  	}
+  	return (CFFType0FontContainer)this.delegatedContainer;
+  }
+
+  CFFType2FontContainer getCFFType2() {
+  	if (delegatedContainer == null) {
+  		delegatedContainer = new CFFType2FontContainer(this);
+  	}
+  	return (CFFType2FontContainer)this.delegatedContainer;
+  }
+}

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