You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by gb...@apache.org on 2013/03/06 17:46:37 UTC

svn commit: r1453416 [7/16] - in /pdfbox/trunk/preflight: ./ src/main/java/org/apache/pdfbox/preflight/ src/main/java/org/apache/pdfbox/preflight/action/ src/main/java/org/apache/pdfbox/preflight/annotation/ src/main/java/org/apache/pdfbox/preflight/an...

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type3FontValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type3FontValidator.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type3FontValidator.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type3FontValidator.java Wed Mar  6 16:46:35 2013
@@ -57,333 +57,413 @@ import org.apache.pdfbox.preflight.font.
 import org.apache.pdfbox.preflight.utils.COSUtils;
 import org.apache.pdfbox.preflight.utils.ContextHelper;
 
-public class Type3FontValidator extends FontValidator<Type3Container> {
-	protected COSDictionary fontDictionary;
-	protected COSDocument cosDocument;
-	protected Encoding encoding;
-
-	public Type3FontValidator(PreflightContext context, PDFont font) {
-		super(context, font, new Type3Container(font));
-		this.cosDocument = context.getDocument().getDocument();
-		this.fontDictionary = (COSDictionary)font.getCOSObject();
-	}
-
-	public void validate() throws ValidationException {
-		checkMandatoryField();
-		checkFontBBox();
-		checkFontMatrix();
-		checkEncoding();
-		checkResources();
-		checkCharProcsAndMetrics();
-		checkToUnicode();
-	}
-
-	protected void checkMandatoryField() {
-		boolean areFieldsPResent = fontDictionary.containsKey(COSName.FONT_BBOX);
-		areFieldsPResent &= fontDictionary.containsKey(COSName.FONT_MATRIX);
-		areFieldsPResent &= fontDictionary.containsKey(COSName.CHAR_PROCS);
-		areFieldsPResent &= fontDictionary.containsKey(COSName.ENCODING);
-		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."));
-		}
-	}
-
-	/**
-	 * Check that the FontBBox element has the right format as declared in the PDF reference document.
-	 */
-	private void checkFontBBox() {
-		COSBase fontBBox = fontDictionary.getItem(COSName.FONT_BBOX);
-
-		if (!COSUtils.isArray(fontBBox, cosDocument)) {
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,	"The FontBBox element isn't an array"));
-			return;
-		}
-
-		/*
-		 * check the content of the FontBBox.
-		 * Should be an array with 4 numbers
-		 */
-		COSArray bbox = COSUtils.getAsArray(fontBBox, cosDocument);
-		if (bbox.size() != 4) {
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The FontBBox element is invalid"));
-			return ;
-		} else {
-			for (int i = 0; i < 4; i++) {
-				COSBase elt = bbox.get(i);
-				if (!(COSUtils.isFloat(elt, cosDocument) || COSUtils.isInteger(elt, cosDocument))) {
-					this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "An element of FontBBox isn't a number"));
-					return;
-				}
-			}
-		}
-	}
-
-	/**
-	 * Check that the FontMatrix element has the right format as declared in the PDF reference document.
-	 */
-	private void checkFontMatrix() {
-		COSBase fontMatrix = fontDictionary.getItem(COSName.FONT_MATRIX);
-
-		if (!COSUtils.isArray(fontMatrix, cosDocument)) {
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,	"The FontMatrix element isn't an array"));
-			return;
-		}
-
-		/*
-		 * Check the content of the FontMatrix.
-		 * Should be an array with 6 numbers
-		 */
-		COSArray matrix = COSUtils.getAsArray(fontMatrix, cosDocument);
-		if (matrix.size() != 6) {
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The FontMatrix element is invalid"));
-			return;
-		} else {
-			for (int i = 0; i < 6; i++) {
-				COSBase elt = matrix.get(i);
-				if (!(COSUtils.isFloat(elt, cosDocument) || COSUtils.isInteger(elt, cosDocument))) {
-					this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,	"An element of FontMatrix isn't a number"));
-					return;
-				}
-			}
-		}
-	}
-
-	@Override
-	/**
-	 * For a Type3 font, the mapping between the Character Code and the Character
-	 * name is entirely defined in the Encoding Entry. The Encoding Entry can be a
-	 * Name (For the 5 predefined Encoding) or a Dictionary. If it is a
-	 * dictionary, the "Differences" array contains the correspondence between a
-	 * character code and a set of character name which are different from the
-	 * encoding entry of the dictionary.
-	 * 
-	 * This method checks that the encoding is :
-	 * <UL>
-	 * <li>An existing encoding name.
-	 * <li>A dictionary with an existing encoding name (the name is optional) and
-	 * a well formed "Differences" array (the array is optional)
-	 * </UL>
-	 * 
-	 * At the end of this method, if the validation succeed the Font encoding is kept in the {@link #encoding} attribute
-	 * @return
-	 */
-	protected void checkEncoding() {
-		COSBase fontEncoding = fontDictionary.getItem(COSName.ENCODING);
-		if (COSUtils.isString(fontEncoding, cosDocument)) {
-			checkEncodingAsString(fontEncoding);
-		} else if (COSUtils.isDictionary(fontEncoding, cosDocument)) {
-			checkEncodingAsDictionary(fontEncoding);
-		} else {
-			// the encoding entry is invalid
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED,"The Encoding entry doesn't have the right type"));
-		}
-	}
-
-	/**
-	 * This method is called by the CheckEncoding method if the Encoding entry is a String.
-	 * In this case, the String must be an existing encoding name. (WinAnsi, MacRoman...)
-	 * @param fontEncoding
-	 */
-	private void checkEncodingAsString(COSBase fontEncoding) {
-		EncodingManager emng = new EncodingManager();
-		// Encoding is a Name, check if it is an Existing Encoding
-		String enc = COSUtils.getAsString(fontEncoding, cosDocument);
-		try {
-			this.encoding = emng.getEncoding(COSName.getPDFName(enc));
-		} catch (IOException e) {
-			// the encoding doesn't exist
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING));
-			return;
-		}
-	}
-
-	/**
-	 * This method is called by the CheckEncoding method if the Encoding entry is an instance of COSDictionary.
-	 * In this case, a new instance of {@link DictionaryEncoding} is created. If an IOException is thrown by the DictionaryEncoding
-	 * constructor the {@link PreflightConstants.ERROR_FONTS_ENCODING} is pushed in the FontContainer.
-	 * 
-	 * Differences entry validation is implicitly done by the DictionaryEncoding constructor.
-	 * @param fontEncoding
-	 */
-	private void checkEncodingAsDictionary(COSBase fontEncoding) {
-		COSDictionary encodingDictionary = COSUtils.getAsDictionary(fontEncoding, cosDocument);
-		try {
-			this.encoding = new DictionaryEncoding(encodingDictionary);
-		} catch (IOException e) {
-			// the encoding doesn't exist
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING));
-			return;
-		}
-	}
-
-	/**
-	 * CharProcs is a dictionary where the key is a character name and the value
-	 * is a Stream which contains the glyph representation of the key.
-	 * 
-	 * This method checks that all characters codes defined in the Widths Array
-	 * exist in the CharProcs dictionary. If the CharProcs doesn't know the
-	 * Character, it is mapped with the .notdef one.
-	 * 
-	 * For each character, the Glyph width must be the same as the Width value
-	 * declared in the Widths array.
-	 * 
-	 * @param errors
-	 * @return
-	 */
-	private void checkCharProcsAndMetrics() throws ValidationException {
-		List<Float> widths = font.getWidths();
-		if (widths == null || widths.isEmpty()) {
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,	"The Witdhs array is unreachable"));
-			return;
-		}
-
-		COSDictionary charProcs = COSUtils.getAsDictionary(fontDictionary.getItem(COSName.CHAR_PROCS), cosDocument);
-		if (charProcs == null) {
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,	"The CharProcs element isn't a dictionary"));
-			return;
-		}
-
-		int fc = this.font.getFirstChar();
-		int lc = this.font.getLastChar();
-
-		/*
-		 * wArr length = (lc - fc) + 1 and it is an array of int.
-		 * If FirstChar is greater than LastChar, the validation will fail
-		 * because of the array will have an expected size <= 0.
-		 */
-		int expectedLength = (lc - fc) + 1;
-		if (widths.size() != expectedLength) {
-			this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
-					"The length of Witdhs array is invalid. Expected : \"" + expectedLength + "\" Current : \"" + widths.size() + "\""));
-			return;
-		}
-
-		// Check width consistency
-		PDResources pResources = getPDResources();
-		for (int i = 0; i < expectedLength; i++) {
-			int cid = fc + i;
-			float width = widths.get(i);
-			
-			COSStream charStream = getCharacterStreamDescription(cid, charProcs);
-			
-			if (charStream != null) {
-				try {
-					
-					float fontProgamWidth = getWidthFromCharacterStream(pResources, charStream);
-					if (width == fontProgamWidth) {
-						// Glyph is OK, we keep the CID.
-						this.fontContainer.markCIDAsValid(cid);
-					} else {
-						GlyphException glyphEx = new GlyphException(ERROR_FONTS_METRICS, cid, 
-								"The character with CID\"" + cid	+ "\" should have a width equals to " + width);
-						this.fontContainer.markCIDAsInvalid(cid, glyphEx);
-					}
-				} catch (ContentStreamException e) {
-					// TODO spaces/isartor-6-2-3-3-t02-fail-h.pdf --> si ajout de l'erreur dans le container le test echoue... pourquoi si la font est utilisée ca devrait planter???
-					this.context.addValidationError(new ValidationError(((ContentStreamException)e).getErrorCode(),	e.getMessage()));
-					return;
-				} catch (IOException e) {
-					this.fontContainer.push(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED, "The CharProcs references an element which can't be read"));
-					return;
-				}
-			}
-		}
-	}
-
-	private PDResources getPDResources() {
-		COSBase res = this.fontDictionary.getItem(COSName.RESOURCES);
-		PDResources pResources = null;
-		COSDictionary resAsDict = COSUtils.getAsDictionary(res, cosDocument);
-		if (resAsDict != null) {
-			pResources = new PDResources(resAsDict);
-		}
-		return pResources;
-	}
-
-	
-	private COSStream getCharacterStreamDescription(int cid, COSDictionary charProcs) throws ValidationException {
-		String charName = getCharNameFromEncoding(cid);
-		COSBase item = charProcs.getItem(COSName.getPDFName(charName));
-		COSStream charStream = COSUtils.getAsStream(item, cosDocument);
-		if (charStream == null) {
-			/* 
-			 * There are no character description, we declare the Glyph as Invalid.
-			 * If the character is used in a Stream, the GlyphDetail will throw an exception.
-			 */
-			GlyphException glyphEx = new GlyphException(ERROR_FONTS_METRICS, cid,	"The CharProcs \"" + charName	+ "\" doesn't exist");
-			this.fontContainer.markCIDAsInvalid(cid, glyphEx);
-		} 
-		return charStream;
-	}
-	
-	private String getCharNameFromEncoding(int cid) throws ValidationException {
-		try {
-			return this.encoding.getName(cid);
-		} catch (IOException e) {
-			// shouldn't occur
-			throw new ValidationException("Unable to check Widths consistency", e);
-		}
-	}
-	
-	/**
-	 * Parse the Glyph description to obtain the Width
-	 * @return the width of the character 
-	 */
-	private float getWidthFromCharacterStream(PDResources resources, COSStream charStream) throws IOException {
-		PreflightPath vPath = context.getValidationPath();
-		PDFAType3StreamParser parser = new PDFAType3StreamParser(context, vPath.getClosestPathElement(PDPage.class));
-		parser.resetEngine();
-		parser.processSubStream(null, resources, charStream);
-		return parser.getWidth();
-	}
-	
-	/**
-	 * If the Resources entry is present, this method check its content. Only
-	 * fonts and Images are checked because this resource describes glyphs.
-	 * 
-	 * @return
-	 */
-	private void checkResources() throws ValidationException {
-		COSBase resources = this.fontDictionary.getItem(COSName.RESOURCES);
-		if (resources != null) {
-
-			COSDictionary dictionary = COSUtils.getAsDictionary(resources, cosDocument);
-			if (dictionary == null) {
-				this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,	"The Resources element isn't a dictionary"));
-				return;
-			}
-
-			// process Fonts and XObjects
-			ContextHelper.validateElement(context, new PDResources(dictionary), RESOURCES_PROCESS);
-			COSBase cbFont = dictionary.getItem(COSName.FONT);
-
-			if (cbFont != null) {
-				/*
-				 * Check that all referenced object are present in the PDF file
-				 */
-				COSDictionary dicFonts = COSUtils.getAsDictionary(cbFont, cosDocument);
-				Set<COSName> keyList = dicFonts.keySet();
-				for (Object key : keyList) {
-
-					COSBase item = dicFonts.getItem((COSName) key);
-					COSDictionary xObjFont = COSUtils.getAsDictionary(item, cosDocument);
-
-					try {
-						PDFont aFont = PDFontFactory.createFont(xObjFont);
-						FontContainer aContainer = this.context.getFontContainer(aFont.getCOSObject());
-						// another font is used in the Type3, check if the font is valid.
-						if (!aContainer.isValid()) {
-							this.fontContainer.push(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED, "The Resources dictionary of type 3 font contains invalid font"));
-						}
-					} catch (IOException e) {
-						throw new ValidationException("Unable to valid the Type3 : " + e.getMessage());
-					}
-				}
-			}
-		}
-	}
+public class Type3FontValidator extends FontValidator<Type3Container>
+{
+    protected COSDictionary fontDictionary;
+    protected COSDocument cosDocument;
+    protected Encoding encoding;
+
+    public Type3FontValidator(PreflightContext context, PDFont font)
+    {
+        super(context, font, new Type3Container(font));
+        this.cosDocument = context.getDocument().getDocument();
+        this.fontDictionary = (COSDictionary) font.getCOSObject();
+    }
+
+    public void validate() throws ValidationException
+    {
+        checkMandatoryField();
+        checkFontBBox();
+        checkFontMatrix();
+        checkEncoding();
+        checkResources();
+        checkCharProcsAndMetrics();
+        checkToUnicode();
+    }
+
+    protected void checkMandatoryField()
+    {
+        boolean areFieldsPResent = fontDictionary.containsKey(COSName.FONT_BBOX);
+        areFieldsPResent &= fontDictionary.containsKey(COSName.FONT_MATRIX);
+        areFieldsPResent &= fontDictionary.containsKey(COSName.CHAR_PROCS);
+        areFieldsPResent &= fontDictionary.containsKey(COSName.ENCODING);
+        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."));
+        }
+    }
+
+    /**
+     * Check that the FontBBox element has the right format as declared in the PDF reference document.
+     */
+    private void checkFontBBox()
+    {
+        COSBase fontBBox = fontDictionary.getItem(COSName.FONT_BBOX);
+
+        if (!COSUtils.isArray(fontBBox, cosDocument))
+        {
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                    "The FontBBox element isn't an array"));
+            return;
+        }
+
+        /*
+         * check the content of the FontBBox. Should be an array with 4 numbers
+         */
+        COSArray bbox = COSUtils.getAsArray(fontBBox, cosDocument);
+        if (bbox.size() != 4)
+        {
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                    "The FontBBox element is invalid"));
+            return;
+        }
+        else
+        {
+            for (int i = 0; i < 4; i++)
+            {
+                COSBase elt = bbox.get(i);
+                if (!(COSUtils.isFloat(elt, cosDocument) || COSUtils.isInteger(elt, cosDocument)))
+                {
+                    this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                            "An element of FontBBox isn't a number"));
+                    return;
+                }
+            }
+        }
+    }
+
+    /**
+     * Check that the FontMatrix element has the right format as declared in the PDF reference document.
+     */
+    private void checkFontMatrix()
+    {
+        COSBase fontMatrix = fontDictionary.getItem(COSName.FONT_MATRIX);
+
+        if (!COSUtils.isArray(fontMatrix, cosDocument))
+        {
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                    "The FontMatrix element isn't an array"));
+            return;
+        }
+
+        /*
+         * Check the content of the FontMatrix. Should be an array with 6 numbers
+         */
+        COSArray matrix = COSUtils.getAsArray(fontMatrix, cosDocument);
+        if (matrix.size() != 6)
+        {
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                    "The FontMatrix element is invalid"));
+            return;
+        }
+        else
+        {
+            for (int i = 0; i < 6; i++)
+            {
+                COSBase elt = matrix.get(i);
+                if (!(COSUtils.isFloat(elt, cosDocument) || COSUtils.isInteger(elt, cosDocument)))
+                {
+                    this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                            "An element of FontMatrix isn't a number"));
+                    return;
+                }
+            }
+        }
+    }
+
+    @Override
+    /**
+     * For a Type3 font, the mapping between the Character Code and the Character
+     * name is entirely defined in the Encoding Entry. The Encoding Entry can be a
+     * Name (For the 5 predefined Encoding) or a Dictionary. If it is a
+     * dictionary, the "Differences" array contains the correspondence between a
+     * character code and a set of character name which are different from the
+     * encoding entry of the dictionary.
+     * 
+     * This method checks that the encoding is :
+     * <UL>
+     * <li>An existing encoding name.
+     * <li>A dictionary with an existing encoding name (the name is optional) and
+     * a well formed "Differences" array (the array is optional)
+     * </UL>
+     * 
+     * At the end of this method, if the validation succeed the Font encoding is kept in the {@link #encoding} attribute
+     * @return
+     */
+    protected void checkEncoding()
+    {
+        COSBase fontEncoding = fontDictionary.getItem(COSName.ENCODING);
+        if (COSUtils.isString(fontEncoding, cosDocument))
+        {
+            checkEncodingAsString(fontEncoding);
+        }
+        else if (COSUtils.isDictionary(fontEncoding, cosDocument))
+        {
+            checkEncodingAsDictionary(fontEncoding);
+        }
+        else
+        {
+            // the encoding entry is invalid
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED,
+                    "The Encoding entry doesn't have the right type"));
+        }
+    }
+
+    /**
+     * This method is called by the CheckEncoding method if the Encoding entry is a String. In this case, the String
+     * must be an existing encoding name. (WinAnsi, MacRoman...)
+     * 
+     * @param fontEncoding
+     */
+    private void checkEncodingAsString(COSBase fontEncoding)
+    {
+        EncodingManager emng = new EncodingManager();
+        // Encoding is a Name, check if it is an Existing Encoding
+        String enc = COSUtils.getAsString(fontEncoding, cosDocument);
+        try
+        {
+            this.encoding = emng.getEncoding(COSName.getPDFName(enc));
+        }
+        catch (IOException e)
+        {
+            // the encoding doesn't exist
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING));
+            return;
+        }
+    }
+
+    /**
+     * This method is called by the CheckEncoding method if the Encoding entry is an instance of COSDictionary. In this
+     * case, a new instance of {@link DictionaryEncoding} is created. If an IOException is thrown by the
+     * DictionaryEncoding constructor the {@link PreflightConstants.ERROR_FONTS_ENCODING} is pushed in the
+     * FontContainer.
+     * 
+     * Differences entry validation is implicitly done by the DictionaryEncoding constructor.
+     * 
+     * @param fontEncoding
+     */
+    private void checkEncodingAsDictionary(COSBase fontEncoding)
+    {
+        COSDictionary encodingDictionary = COSUtils.getAsDictionary(fontEncoding, cosDocument);
+        try
+        {
+            this.encoding = new DictionaryEncoding(encodingDictionary);
+        }
+        catch (IOException e)
+        {
+            // the encoding doesn't exist
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_ENCODING));
+            return;
+        }
+    }
+
+    /**
+     * CharProcs is a dictionary where the key is a character name and the value is a Stream which contains the glyph
+     * representation of the key.
+     * 
+     * This method checks that all characters codes defined in the Widths Array exist in the CharProcs dictionary. If
+     * the CharProcs doesn't know the Character, it is mapped with the .notdef one.
+     * 
+     * For each character, the Glyph width must be the same as the Width value declared in the Widths array.
+     * 
+     * @param errors
+     * @return
+     */
+    private void checkCharProcsAndMetrics() throws ValidationException
+    {
+        List<Float> widths = font.getWidths();
+        if (widths == null || widths.isEmpty())
+        {
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                    "The Witdhs array is unreachable"));
+            return;
+        }
+
+        COSDictionary charProcs = COSUtils.getAsDictionary(fontDictionary.getItem(COSName.CHAR_PROCS), cosDocument);
+        if (charProcs == null)
+        {
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                    "The CharProcs element isn't a dictionary"));
+            return;
+        }
+
+        int fc = this.font.getFirstChar();
+        int lc = this.font.getLastChar();
+
+        /*
+         * wArr length = (lc - fc) + 1 and it is an array of int. If FirstChar is greater than LastChar, the validation
+         * will fail because of the array will have an expected size <= 0.
+         */
+        int expectedLength = (lc - fc) + 1;
+        if (widths.size() != expectedLength)
+        {
+            this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                    "The length of Witdhs array is invalid. Expected : \"" + expectedLength + "\" Current : \""
+                            + widths.size() + "\""));
+            return;
+        }
+
+        // Check width consistency
+        PDResources pResources = getPDResources();
+        for (int i = 0; i < expectedLength; i++)
+        {
+            int cid = fc + i;
+            float width = widths.get(i);
+
+            COSStream charStream = getCharacterStreamDescription(cid, charProcs);
+
+            if (charStream != null)
+            {
+                try
+                {
+
+                    float fontProgamWidth = getWidthFromCharacterStream(pResources, charStream);
+                    if (width == fontProgamWidth)
+                    {
+                        // Glyph is OK, we keep the CID.
+                        this.fontContainer.markCIDAsValid(cid);
+                    }
+                    else
+                    {
+                        GlyphException glyphEx = new GlyphException(ERROR_FONTS_METRICS, cid,
+                                "The character with CID\"" + cid + "\" should have a width equals to " + width);
+                        this.fontContainer.markCIDAsInvalid(cid, glyphEx);
+                    }
+                }
+                catch (ContentStreamException e)
+                {
+                    // TODO spaces/isartor-6-2-3-3-t02-fail-h.pdf --> si ajout de l'erreur dans le container le test
+                    // echoue... pourquoi si la font est utilisée ca devrait planter???
+                    this.context.addValidationError(new ValidationError(((ContentStreamException) e).getErrorCode(), e
+                            .getMessage()));
+                    return;
+                }
+                catch (IOException e)
+                {
+                    this.fontContainer.push(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED,
+                            "The CharProcs references an element which can't be read"));
+                    return;
+                }
+            }
+        }
+    }
+
+    private PDResources getPDResources()
+    {
+        COSBase res = this.fontDictionary.getItem(COSName.RESOURCES);
+        PDResources pResources = null;
+        COSDictionary resAsDict = COSUtils.getAsDictionary(res, cosDocument);
+        if (resAsDict != null)
+        {
+            pResources = new PDResources(resAsDict);
+        }
+        return pResources;
+    }
+
+    private COSStream getCharacterStreamDescription(int cid, COSDictionary charProcs) throws ValidationException
+    {
+        String charName = getCharNameFromEncoding(cid);
+        COSBase item = charProcs.getItem(COSName.getPDFName(charName));
+        COSStream charStream = COSUtils.getAsStream(item, cosDocument);
+        if (charStream == null)
+        {
+            /*
+             * There are no character description, we declare the Glyph as Invalid. If the character is used in a
+             * Stream, the GlyphDetail will throw an exception.
+             */
+            GlyphException glyphEx = new GlyphException(ERROR_FONTS_METRICS, cid, "The CharProcs \"" + charName
+                    + "\" doesn't exist");
+            this.fontContainer.markCIDAsInvalid(cid, glyphEx);
+        }
+        return charStream;
+    }
+
+    private String getCharNameFromEncoding(int cid) throws ValidationException
+    {
+        try
+        {
+            return this.encoding.getName(cid);
+        }
+        catch (IOException e)
+        {
+            // shouldn't occur
+            throw new ValidationException("Unable to check Widths consistency", e);
+        }
+    }
+
+    /**
+     * Parse the Glyph description to obtain the Width
+     * 
+     * @return the width of the character
+     */
+    private float getWidthFromCharacterStream(PDResources resources, COSStream charStream) throws IOException
+    {
+        PreflightPath vPath = context.getValidationPath();
+        PDFAType3StreamParser parser = new PDFAType3StreamParser(context, vPath.getClosestPathElement(PDPage.class));
+        parser.resetEngine();
+        parser.processSubStream(null, resources, charStream);
+        return parser.getWidth();
+    }
+
+    /**
+     * If the Resources entry is present, this method check its content. Only fonts and Images are checked because this
+     * resource describes glyphs.
+     * 
+     * @return
+     */
+    private void checkResources() throws ValidationException
+    {
+        COSBase resources = this.fontDictionary.getItem(COSName.RESOURCES);
+        if (resources != null)
+        {
+
+            COSDictionary dictionary = COSUtils.getAsDictionary(resources, cosDocument);
+            if (dictionary == null)
+            {
+                this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID,
+                        "The Resources element isn't a dictionary"));
+                return;
+            }
+
+            // process Fonts and XObjects
+            ContextHelper.validateElement(context, new PDResources(dictionary), RESOURCES_PROCESS);
+            COSBase cbFont = dictionary.getItem(COSName.FONT);
+
+            if (cbFont != null)
+            {
+                /*
+                 * Check that all referenced object are present in the PDF file
+                 */
+                COSDictionary dicFonts = COSUtils.getAsDictionary(cbFont, cosDocument);
+                Set<COSName> keyList = dicFonts.keySet();
+                for (Object key : keyList)
+                {
+
+                    COSBase item = dicFonts.getItem((COSName) key);
+                    COSDictionary xObjFont = COSUtils.getAsDictionary(item, cosDocument);
+
+                    try
+                    {
+                        PDFont aFont = PDFontFactory.createFont(xObjFont);
+                        FontContainer aContainer = this.context.getFontContainer(aFont.getCOSObject());
+                        // another font is used in the Type3, check if the font is valid.
+                        if (!aContainer.isValid())
+                        {
+                            this.fontContainer.push(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED,
+                                    "The Resources dictionary of type 3 font contains invalid font"));
+                        }
+                    }
+                    catch (IOException e)
+                    {
+                        throw new ValidationException("Unable to valid the Type3 : " + e.getMessage());
+                    }
+                }
+            }
+        }
+    }
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType0Container.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType0Container.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType0Container.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType0Container.java Wed Mar  6 16:46:35 2013
@@ -30,65 +30,82 @@ import org.apache.fontbox.cff.CFFFont;
 import org.apache.fontbox.cff.CFFFont.Mapping;
 import org.apache.pdfbox.pdmodel.font.PDFont;
 
-public class CIDType0Container extends FontContainer {
-	protected List<CFFFont> lCFonts = new ArrayList<CFFFont>();
-
-	public CIDType0Container(PDFont font) {
-		super(font);
-	}
-	
-	@Override
-	protected float getFontProgramWidth(int cid) {
-		// build the font container and keep it in the Handler.
-	  boolean cidFound = false;
-		for (CFFFont font : this.lCFonts) {
-			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;
-					break;
-				}
-			}
-			if (cidFound) {
-			    break;
-			}
-		}
-
-		float widthInFontProgram = 0;
-		if (cidFound || cid == 0) { 
-
-			float defaultGlyphWidth = 0;
-			if (this.font.getFontDescriptor() != null) {
-				defaultGlyphWidth = this.font.getFontDescriptor().getMissingWidth();
-			}
-			
-			try {
-				// Search the CID in all CFFFont in the FontProgram
-				for (CFFFont cff : this.lCFonts) {
-					widthInFontProgram = cff.getWidth(cid);
-					if (widthInFontProgram != defaultGlyphWidth) {
-						break;
-					}
-				}
-			} catch (IOException e) {
-				widthInFontProgram = -1;
-			}
-		}else {
-			/*
-			 * Cid 0 is commonly used as the NotDef Glyph. this glyph can be used as Space.
-			 * IN PDF/A-1 the Notdef glyph can be used as space. Not in PDF/A-2
-			 */
-			widthInFontProgram = -1;
-		}
-		return widthInFontProgram;	
-	}
-
-	public void setlCFonts(List<CFFFont> lCFonts) {
-		this.lCFonts = lCFonts;
-	}
+public class CIDType0Container extends FontContainer
+{
+    protected List<CFFFont> lCFonts = new ArrayList<CFFFont>();
+
+    public CIDType0Container(PDFont font)
+    {
+        super(font);
+    }
+
+    @Override
+    protected float getFontProgramWidth(int cid)
+    {
+        // build the font container and keep it in the Handler.
+        boolean cidFound = false;
+        for (CFFFont font : this.lCFonts)
+        {
+            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;
+                    break;
+                }
+            }
+            if (cidFound)
+            {
+                break;
+            }
+        }
+
+        float widthInFontProgram = 0;
+        if (cidFound || cid == 0)
+        {
+
+            float defaultGlyphWidth = 0;
+            if (this.font.getFontDescriptor() != null)
+            {
+                defaultGlyphWidth = this.font.getFontDescriptor().getMissingWidth();
+            }
+
+            try
+            {
+                // Search the CID in all CFFFont in the FontProgram
+                for (CFFFont cff : this.lCFonts)
+                {
+                    widthInFontProgram = cff.getWidth(cid);
+                    if (widthInFontProgram != defaultGlyphWidth)
+                    {
+                        break;
+                    }
+                }
+            }
+            catch (IOException e)
+            {
+                widthInFontProgram = -1;
+            }
+        }
+        else
+        {
+            /*
+             * Cid 0 is commonly used as the NotDef Glyph. this glyph can be used as Space. IN PDF/A-1 the Notdef glyph
+             * can be used as space. Not in PDF/A-2
+             */
+            widthInFontProgram = -1;
+        }
+        return widthInFontProgram;
+    }
+
+    public void setlCFonts(List<CFFFont> lCFonts)
+    {
+        this.lCFonts = lCFonts;
+    }
 
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType2Container.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType2Container.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType2Container.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/CIDType2Container.java Wed Mar  6 16:46:35 2013
@@ -25,63 +25,73 @@ import org.apache.fontbox.ttf.TrueTypeFo
 import org.apache.pdfbox.pdmodel.font.PDFont;
 import org.apache.pdfbox.preflight.font.util.CIDToGIDMap;
 
-public class CIDType2Container extends FontContainer {
+public class CIDType2Container extends FontContainer
+{
 
-	protected CIDToGIDMap cidToGid = null;
+    protected CIDToGIDMap cidToGid = null;
 
-	protected TrueTypeFont ttf = null;
+    protected TrueTypeFont ttf = null;
 
-	public CIDType2Container(PDFont font) {
-		super(font);
-	}
-	
-	@Override
-	protected float getFontProgramWidth(int cid) {
-		float foundWidth = - 1;
-		final int glyphIndex = getGlyphIndex(cid);
-		
-		// if glyph exists we can check the width
-		if(this.ttf != null && this.ttf.getGlyph().getGlyphs().length > glyphIndex) {
-			/* In a Mono space font program, the length of the AdvanceWidth array must be one.
-			 * According to the TrueType font specification, the Last Value of the AdvanceWidth array
-			 * is apply to the subsequent glyphs. So if the GlyphId is greater than the length of the array
-			 * the last entry is used.
-			 */
-			int numberOfLongHorMetrics = ttf.getHorizontalHeader().getNumberOfHMetrics();
-			int unitsPerEm = ttf.getHeader().getUnitsPerEm();
-			int[] advanceGlyphWidths = ttf.getHorizontalMetrics().getAdvanceWidth();
-			float glypdWidth = advanceGlyphWidths[numberOfLongHorMetrics - 1];
-			if (glyphIndex < numberOfLongHorMetrics) {
-				glypdWidth = advanceGlyphWidths[glyphIndex];
-			}
-			foundWidth = ((glypdWidth * 1000) / unitsPerEm);
-		}
-		return foundWidth;
-	}
-
-	/**
-	 * If CIDToGID map is Identity, the GID equals to the CID.
-	 * Otherwise the conversion is done by the CIDToGID map
-	 * @param cid
-	 * @return -1 CID doesn't match with a GID
-	 */
-	private int getGlyphIndex(int cid){
-		int glyphIndex = cid;
-		if (this.cidToGid != null) {
-			glyphIndex = cidToGid.getGID(cid);
-			if (glyphIndex==cidToGid.NOTDEF_GLYPH_INDEX) {
-				glyphIndex = -14;
-			}
-		}
-		return glyphIndex;
-	}
-
-	public void setCidToGid(CIDToGIDMap cidToGid) {
-		this.cidToGid = cidToGid;
-	}
-
-	public void setTtf(TrueTypeFont ttf) {
-		this.ttf = ttf;
-	}
+    public CIDType2Container(PDFont font)
+    {
+        super(font);
+    }
+
+    @Override
+    protected float getFontProgramWidth(int cid)
+    {
+        float foundWidth = -1;
+        final int glyphIndex = getGlyphIndex(cid);
+
+        // if glyph exists we can check the width
+        if (this.ttf != null && this.ttf.getGlyph().getGlyphs().length > glyphIndex)
+        {
+            /*
+             * In a Mono space font program, the length of the AdvanceWidth array must be one. According to the TrueType
+             * font specification, the Last Value of the AdvanceWidth array is apply to the subsequent glyphs. So if the
+             * GlyphId is greater than the length of the array the last entry is used.
+             */
+            int numberOfLongHorMetrics = ttf.getHorizontalHeader().getNumberOfHMetrics();
+            int unitsPerEm = ttf.getHeader().getUnitsPerEm();
+            int[] advanceGlyphWidths = ttf.getHorizontalMetrics().getAdvanceWidth();
+            float glypdWidth = advanceGlyphWidths[numberOfLongHorMetrics - 1];
+            if (glyphIndex < numberOfLongHorMetrics)
+            {
+                glypdWidth = advanceGlyphWidths[glyphIndex];
+            }
+            foundWidth = ((glypdWidth * 1000) / unitsPerEm);
+        }
+        return foundWidth;
+    }
+
+    /**
+     * If CIDToGID map is Identity, the GID equals to the CID. Otherwise the conversion is done by the CIDToGID map
+     * 
+     * @param cid
+     * @return -1 CID doesn't match with a GID
+     */
+    private int getGlyphIndex(int cid)
+    {
+        int glyphIndex = cid;
+        if (this.cidToGid != null)
+        {
+            glyphIndex = cidToGid.getGID(cid);
+            if (glyphIndex == cidToGid.NOTDEF_GLYPH_INDEX)
+            {
+                glyphIndex = -14;
+            }
+        }
+        return glyphIndex;
+    }
+
+    public void setCidToGid(CIDToGIDMap cidToGid)
+    {
+        this.cidToGid = cidToGid;
+    }
+
+    public void setTtf(TrueTypeFont ttf)
+    {
+        this.ttf = ttf;
+    }
 
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/FontContainer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/FontContainer.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/FontContainer.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/FontContainer.java Wed Mar  6 16:46:35 2013
@@ -32,141 +32,158 @@ import org.apache.pdfbox.preflight.Valid
 import org.apache.pdfbox.preflight.font.util.GlyphDetail;
 import org.apache.pdfbox.preflight.font.util.GlyphException;
 
-public abstract class FontContainer {
-	/**
-	 * List of validation errors that occur during the font validation.
-	 * If the font is used by an object in the PDF, all these errors will be appended 
-	 * to the Error list of the PreflightContext.
-	 */
-	protected List<ValidationError> errorBuffer = new ArrayList<ValidationError>();
-	/**
-	 * Boolean used to known if the font is embedded.
-	 */
-	protected boolean embeddedFont = true;
-
-	/**
-	 * Link CID to an Object that contain information about the Glyph state (Valid or no)
-	 */
-	protected Map<Integer, GlyphDetail> computedCid = new HashMap<Integer, GlyphDetail>();
-
-	protected boolean errorsAleadyMerged = false;
-	
-	protected PDFont font;
-
-	public FontContainer(PDFont font) {
-		super();
-		this.font = font;
-	}
-
-	public void push(ValidationError error) {
-		this.errorBuffer.add(error);
-	}
-
-	public void push(List<ValidationError> errors) {
-		this.errorBuffer.addAll(errors);
-	}
-
-	public List<ValidationError> getAllErrors() {
-		return this.errorBuffer;
-	}
-
-	public boolean isValid() {
-		return (this.errorBuffer.isEmpty() && isEmbeddedFont());
-	}
-	
-	public boolean errorsAleadyMerged() {
-		return errorsAleadyMerged;
-	}
-
-	public void setErrorsAleadyMerged(boolean errorsAleadyMerged) {
-		this.errorsAleadyMerged = errorsAleadyMerged;
-	}
-
-	public boolean isEmbeddedFont() {
-		return embeddedFont;
-	}
-
-	public void notEmbedded() {
-		this.embeddedFont = false;
-	}
-
-	/**
-	 * 
-	 * @param cid
-	 * @throws GlyphException
-	 */
-	public void checkGlyphWith(int cid) throws GlyphException {
-		if (isAlreadyComputedCid(cid)) {
-			return;
-		}
-
-		final float expectedWidth = this.font.getFontWidth(cid);
-		final float foundWidth = getFontProgramWidth(cid);
-		checkWidthsConsistency(cid, expectedWidth, foundWidth);
-	}
-
-	/**
-	 * Check if the given CID is already computed
-	 * 
-	 * @param cid the CID to check
-	 * @return true if the CID has previously been marked as valid, false otherwise
-	 * @throws GlyphException if the CID has previously been marked as invalid // TODO useful ??
-	 */
-	protected boolean isAlreadyComputedCid(int cid) throws GlyphException {
-		boolean already = false;
-		GlyphDetail gdetail = this.computedCid.get(cid);
-		if (gdetail != null) {
-			gdetail.throwExceptionIfNotValid();
-			already = true;
-		}
-		return already;
-	}
-	
-	/**
-	 * Extract the Glyph width for the given CID.
-	 * @param cid
-	 * @return The Glyph width in 'em' unit.
-	 */
-	protected abstract float getFontProgramWidth(int cid);
-	
-	/**
-	 * Test if both width are consistent. At the end of this method, the CID is marked as valid or invalid.
-	 * 
-	 * @param cid
-	 * @param expectedWidth
-	 * @param foundWidth the glyph width found in the font program, a negative value if the CID is missing from the font.
-	 * @throws GlyphException
-	 */
-	protected void checkWidthsConsistency(int cid, float expectedWidth, float foundWidth) throws GlyphException {
-		if (foundWidth < 0) {
-      GlyphException e = new GlyphException(PreflightConstants.ERROR_FONTS_GLYPH_MISSING, 
-      		cid, 
-      		"The character \"" + cid 
-      		+ "\" in the font program \""
-      		+ this.font.getBaseFont() 
-      		+ "\"is missing from the Charater Encoding.");
-      markCIDAsInvalid(cid, e);
-      throw e;	
-		}
-		
-		// consistent is defined to be a difference of no more than 1/1000 unit.
-		if(Math.abs(foundWidth-expectedWidth) > 1) {	
-			GlyphException e = new GlyphException(PreflightConstants.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.");
-			markCIDAsInvalid(cid, e);
-			throw e;
-		}
-		markCIDAsValid(cid);
-	}
-	
-	public final void markCIDAsValid(int cid) {
-		this.computedCid.put(cid, new GlyphDetail(cid));
-	}
-
-	public final void markCIDAsInvalid(int cid, GlyphException gex) {
-		this.computedCid.put(cid, new GlyphDetail(cid, gex));
-	}
+public abstract class FontContainer
+{
+    /**
+     * List of validation errors that occur during the font validation. If the font is used by an object in the PDF, all
+     * these errors will be appended to the Error list of the PreflightContext.
+     */
+    protected List<ValidationError> errorBuffer = new ArrayList<ValidationError>();
+    /**
+     * Boolean used to known if the font is embedded.
+     */
+    protected boolean embeddedFont = true;
+
+    /**
+     * Link CID to an Object that contain information about the Glyph state (Valid or no)
+     */
+    protected Map<Integer, GlyphDetail> computedCid = new HashMap<Integer, GlyphDetail>();
+
+    protected boolean errorsAleadyMerged = false;
+
+    protected PDFont font;
+
+    public FontContainer(PDFont font)
+    {
+        super();
+        this.font = font;
+    }
+
+    public void push(ValidationError error)
+    {
+        this.errorBuffer.add(error);
+    }
+
+    public void push(List<ValidationError> errors)
+    {
+        this.errorBuffer.addAll(errors);
+    }
+
+    public List<ValidationError> getAllErrors()
+    {
+        return this.errorBuffer;
+    }
+
+    public boolean isValid()
+    {
+        return (this.errorBuffer.isEmpty() && isEmbeddedFont());
+    }
+
+    public boolean errorsAleadyMerged()
+    {
+        return errorsAleadyMerged;
+    }
+
+    public void setErrorsAleadyMerged(boolean errorsAleadyMerged)
+    {
+        this.errorsAleadyMerged = errorsAleadyMerged;
+    }
+
+    public boolean isEmbeddedFont()
+    {
+        return embeddedFont;
+    }
+
+    public void notEmbedded()
+    {
+        this.embeddedFont = false;
+    }
+
+    /**
+     * 
+     * @param cid
+     * @throws GlyphException
+     */
+    public void checkGlyphWith(int cid) throws GlyphException
+    {
+        if (isAlreadyComputedCid(cid))
+        {
+            return;
+        }
+
+        final float expectedWidth = this.font.getFontWidth(cid);
+        final float foundWidth = getFontProgramWidth(cid);
+        checkWidthsConsistency(cid, expectedWidth, foundWidth);
+    }
+
+    /**
+     * Check if the given CID is already computed
+     * 
+     * @param cid
+     *            the CID to check
+     * @return true if the CID has previously been marked as valid, false otherwise
+     * @throws GlyphException
+     *             if the CID has previously been marked as invalid // TODO useful ??
+     */
+    protected boolean isAlreadyComputedCid(int cid) throws GlyphException
+    {
+        boolean already = false;
+        GlyphDetail gdetail = this.computedCid.get(cid);
+        if (gdetail != null)
+        {
+            gdetail.throwExceptionIfNotValid();
+            already = true;
+        }
+        return already;
+    }
+
+    /**
+     * Extract the Glyph width for the given CID.
+     * 
+     * @param cid
+     * @return The Glyph width in 'em' unit.
+     */
+    protected abstract float getFontProgramWidth(int cid);
+
+    /**
+     * Test if both width are consistent. At the end of this method, the CID is marked as valid or invalid.
+     * 
+     * @param cid
+     * @param expectedWidth
+     * @param foundWidth
+     *            the glyph width found in the font program, a negative value if the CID is missing from the font.
+     * @throws GlyphException
+     */
+    protected void checkWidthsConsistency(int cid, float expectedWidth, float foundWidth) throws GlyphException
+    {
+        if (foundWidth < 0)
+        {
+            GlyphException e = new GlyphException(PreflightConstants.ERROR_FONTS_GLYPH_MISSING, cid, "The character \""
+                    + cid + "\" in the font program \"" + this.font.getBaseFont()
+                    + "\"is missing from the Charater Encoding.");
+            markCIDAsInvalid(cid, e);
+            throw e;
+        }
+
+        // consistent is defined to be a difference of no more than 1/1000 unit.
+        if (Math.abs(foundWidth - expectedWidth) > 1)
+        {
+            GlyphException e = new GlyphException(PreflightConstants.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.");
+            markCIDAsInvalid(cid, e);
+            throw e;
+        }
+        markCIDAsValid(cid);
+    }
+
+    public final void markCIDAsValid(int cid)
+    {
+        this.computedCid.put(cid, new GlyphDetail(cid));
+    }
+
+    public final void markCIDAsInvalid(int cid, GlyphException gex)
+    {
+        this.computedCid.put(cid, new GlyphDetail(cid, gex));
+    }
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/TrueTypeContainer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/TrueTypeContainer.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/TrueTypeContainer.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/TrueTypeContainer.java Wed Mar  6 16:46:35 2013
@@ -31,140 +31,172 @@ import org.apache.fontbox.ttf.TrueTypeFo
 import org.apache.pdfbox.encoding.Encoding;
 import org.apache.pdfbox.pdmodel.font.PDFont;
 
-public class TrueTypeContainer extends FontContainer {
+public class TrueTypeContainer extends FontContainer
+{
 
-	protected TrueTypeFont ttFont;
+    protected TrueTypeFont ttFont;
 
-	private CMAPEncodingEntry[] cmapEncodingEntries = null;
+    private CMAPEncodingEntry[] cmapEncodingEntries = null;
 
-	public TrueTypeContainer(PDFont font) {
-		super(font);
-	}
-
-	public void setTrueTypeFont(TrueTypeFont ttFont) {
-		this.ttFont = ttFont;
-		initCMapEncodingEntries(); // TODO appel sur le checkWidth
-	}
-
-	/**
-	 * Initialize the {@linkplain #cmapEncodingEntries} with CMaps that 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, the list of CMap is reordered to provide WinAnsi CMap first
-	 * (plateformId : 3 / encodingId : 1) followed by MacRoman CMap (plateformId : 1 /
-	 * encodingId : 0). This CMap returns the CMap which corresponds to the
-	 * Encoding value of the FontDescriptor dictionary.
-	 * </UL>
-	 */
-	protected void initCMapEncodingEntries() {
-		if (this.cmapEncodingEntries != null) return;
-
-		CMAPTable cmap = this.ttFont.getCMAP();
-		if (this.font.getFontDescriptor().isSymbolic()) {
-			this.cmapEncodingEntries = cmap.getCmaps();
-		} else {
-			this.cmapEncodingEntries = orderCMapEntries(cmap);
-		}
-	}
-
-	private CMAPEncodingEntry[] orderCMapEntries(CMAPTable cmap) {
-		List<CMAPEncodingEntry> res = new ArrayList<CMAPEncodingEntry>();
-		boolean firstIs31 = false;
-		for (CMAPEncodingEntry cmapEntry :  cmap.getCmaps()) {
-			// WinAnsi 
-			if ((cmapEntry.getPlatformId() == 3) && (cmapEntry.getPlatformEncodingId() == 1)) {
-				res.add(0,cmapEntry);
-				firstIs31 = true;
-			} else if ((cmapEntry.getPlatformId() == 1)&& (cmapEntry.getPlatformEncodingId() == 0)) {
-				// MacRoman
-				if (firstIs31) { 
-					// WinAnsi is present, MacRoman is set in second position
-					res.add(1, cmapEntry);
-				} else {
-					// WinAnsi is missing, MacRoman has the priority
-					res.add(0, cmapEntry);
-				}
-			} else {
-				res.add(cmapEntry);
-			}
-		}
-		return res.toArray(new CMAPEncodingEntry[res.size()]);
-	}
-
-	@Override
-	protected float getFontProgramWidth(int cid) {
-		float result = -1f;
-		if (cmapEncodingEntries != null) {
-			for (CMAPEncodingEntry entry : cmapEncodingEntries) {
-				int glyphID = extractGlyphID(cid, entry);
-				if (glyphID > 0) {	
-					result = extractGlyphWidth(glyphID);
-					break;
-				}
-			}
-		}
-		return  result;
-	}
-
-	/**
-	 * TrueType has internal CMap that map the CID used in the PDF file with an internal character identifier.
-	 * This method converts the given CID in the internal font program identifier. (0 if no match found)
-	 * @param cid
-	 * @param cmap
-	 * @return
-	 */
-	private int extractGlyphID(int cid, CMAPEncodingEntry cmap) {
-		int notFoundGlyphID = 0;
-
-		int innerFontCid = cid;
-		if (cmap.getPlatformEncodingId() == 1 && cmap.getPlatformId() == 3) {
-			try {
-				Encoding fontEncoding = this.font.getFontEncoding();
-				String character = fontEncoding.getCharacter(cid);
-				if (character == null) {
-					return notFoundGlyphID;
-				}
-
-				char[] characterArray = character.toCharArray();
-				if (characterArray.length == 1 ) {
-					innerFontCid = (int)characterArray[0];
-				} else {
-					// TODO OD-PDFA-87 A faire?
-					innerFontCid = (int)characterArray[0];
-					for (int i = 1; i < characterArray.length; ++i) {
-						if (cmap.getGlyphId((int)characterArray[i]) == 0) {
-							return notFoundGlyphID; // TODO what we have to do here ???
-						}
-					}
-				}
-			} catch (IOException ioe) {
-				// should never happen 
-				return notFoundGlyphID;
-			}
-		}
-
-		// search glyph
-		return cmap.getGlyphId(innerFontCid);
-	}
-
-	private float extractGlyphWidth(int glyphID) {
-		int unitsPerEm = this.ttFont.getHeader().getUnitsPerEm();
-		int[] glyphWidths = this.ttFont.getHorizontalMetrics().getAdvanceWidth();
-		/*
-		 * In a Mono space font program, the length of the AdvanceWidth array must be one.
-		 * According to the TrueType font specification, the Last Value of the AdvanceWidth array
-		 * is apply to the subsequent glyphs. So if the GlyphId is greater than the length of the array
-		 * the last entry is used.
-		 */
-		int numberOfLongHorMetrics = this.ttFont.getHorizontalHeader().getNumberOfHMetrics();
-		float glypdWidth = glyphWidths[numberOfLongHorMetrics - 1];
-		if (glyphID < numberOfLongHorMetrics) {
-			glypdWidth = glyphWidths[glyphID];
-		}
-		return ((glypdWidth * 1000) / unitsPerEm);
-	}
+    public TrueTypeContainer(PDFont font)
+    {
+        super(font);
+    }
+
+    public void setTrueTypeFont(TrueTypeFont ttFont)
+    {
+        this.ttFont = ttFont;
+        initCMapEncodingEntries(); // TODO appel sur le checkWidth
+    }
+
+    /**
+     * Initialize the {@linkplain #cmapEncodingEntries} with CMaps that 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, the list of CMap is reordered to provide WinAnsi CMap first (plateformId : 3 /
+     * encodingId : 1) followed by MacRoman CMap (plateformId : 1 / encodingId : 0). This CMap returns the CMap which
+     * corresponds to the Encoding value of the FontDescriptor dictionary.
+     * </UL>
+     */
+    protected void initCMapEncodingEntries()
+    {
+        if (this.cmapEncodingEntries != null)
+            return;
+
+        CMAPTable cmap = this.ttFont.getCMAP();
+        if (this.font.getFontDescriptor().isSymbolic())
+        {
+            this.cmapEncodingEntries = cmap.getCmaps();
+        }
+        else
+        {
+            this.cmapEncodingEntries = orderCMapEntries(cmap);
+        }
+    }
+
+    private CMAPEncodingEntry[] orderCMapEntries(CMAPTable cmap)
+    {
+        List<CMAPEncodingEntry> res = new ArrayList<CMAPEncodingEntry>();
+        boolean firstIs31 = false;
+        for (CMAPEncodingEntry cmapEntry : cmap.getCmaps())
+        {
+            // WinAnsi
+            if ((cmapEntry.getPlatformId() == 3) && (cmapEntry.getPlatformEncodingId() == 1))
+            {
+                res.add(0, cmapEntry);
+                firstIs31 = true;
+            }
+            else if ((cmapEntry.getPlatformId() == 1) && (cmapEntry.getPlatformEncodingId() == 0))
+            {
+                // MacRoman
+                if (firstIs31)
+                {
+                    // WinAnsi is present, MacRoman is set in second position
+                    res.add(1, cmapEntry);
+                }
+                else
+                {
+                    // WinAnsi is missing, MacRoman has the priority
+                    res.add(0, cmapEntry);
+                }
+            }
+            else
+            {
+                res.add(cmapEntry);
+            }
+        }
+        return res.toArray(new CMAPEncodingEntry[res.size()]);
+    }
+
+    @Override
+    protected float getFontProgramWidth(int cid)
+    {
+        float result = -1f;
+        if (cmapEncodingEntries != null)
+        {
+            for (CMAPEncodingEntry entry : cmapEncodingEntries)
+            {
+                int glyphID = extractGlyphID(cid, entry);
+                if (glyphID > 0)
+                {
+                    result = extractGlyphWidth(glyphID);
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * TrueType has internal CMap that map the CID used in the PDF file with an internal character identifier. This
+     * method converts the given CID in the internal font program identifier. (0 if no match found)
+     * 
+     * @param cid
+     * @param cmap
+     * @return
+     */
+    private int extractGlyphID(int cid, CMAPEncodingEntry cmap)
+    {
+        int notFoundGlyphID = 0;
+
+        int innerFontCid = cid;
+        if (cmap.getPlatformEncodingId() == 1 && cmap.getPlatformId() == 3)
+        {
+            try
+            {
+                Encoding fontEncoding = this.font.getFontEncoding();
+                String character = fontEncoding.getCharacter(cid);
+                if (character == null)
+                {
+                    return notFoundGlyphID;
+                }
+
+                char[] characterArray = character.toCharArray();
+                if (characterArray.length == 1)
+                {
+                    innerFontCid = (int) characterArray[0];
+                }
+                else
+                {
+                    // TODO OD-PDFA-87 A faire?
+                    innerFontCid = (int) characterArray[0];
+                    for (int i = 1; i < characterArray.length; ++i)
+                    {
+                        if (cmap.getGlyphId((int) characterArray[i]) == 0)
+                        {
+                            return notFoundGlyphID; // TODO what we have to do here ???
+                        }
+                    }
+                }
+            }
+            catch (IOException ioe)
+            {
+                // should never happen
+                return notFoundGlyphID;
+            }
+        }
+
+        // search glyph
+        return cmap.getGlyphId(innerFontCid);
+    }
+
+    private float extractGlyphWidth(int glyphID)
+    {
+        int unitsPerEm = this.ttFont.getHeader().getUnitsPerEm();
+        int[] glyphWidths = this.ttFont.getHorizontalMetrics().getAdvanceWidth();
+        /*
+         * In a Mono space font program, the length of the AdvanceWidth array must be one. According to the TrueType
+         * font specification, the Last Value of the AdvanceWidth array is apply to the subsequent glyphs. So if the
+         * GlyphId is greater than the length of the array the last entry is used.
+         */
+        int numberOfLongHorMetrics = this.ttFont.getHorizontalHeader().getNumberOfHMetrics();
+        float glypdWidth = glyphWidths[numberOfLongHorMetrics - 1];
+        if (glyphID < numberOfLongHorMetrics)
+        {
+            glypdWidth = glyphWidths[glyphID];
+        }
+        return ((glypdWidth * 1000) / unitsPerEm);
+    }
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type0Container.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type0Container.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type0Container.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type0Container.java Wed Mar  6 16:46:35 2013
@@ -26,47 +26,58 @@ import java.util.List;
 import org.apache.pdfbox.pdmodel.font.PDFont;
 import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
 
-public class Type0Container extends FontContainer {
+public class Type0Container extends FontContainer
+{
 
-	protected FontContainer delegateFontContainer;
+    protected FontContainer delegateFontContainer;
 
-	public Type0Container(PDFont font) {
-		super(font);
-	}
-	
-	@Override
-	protected float getFontProgramWidth(int cid) {
-		float width = 0;
-		if (this.delegateFontContainer != null) {
-			width = this.delegateFontContainer.getFontProgramWidth(cid);
-		}
-		return width;
-	}
-
-	public void setDelegateFontContainer(FontContainer delegateFontContainer) {
-		this.delegateFontContainer = delegateFontContainer;
-	}
-	
-	public List<ValidationError> getAllErrors() {
-		if (this.delegateFontContainer != null) {
-			this.errorBuffer.addAll(this.delegateFontContainer.getAllErrors());
-		}
-		return this.errorBuffer;
-	}
-	
-	public boolean isValid() {
-		boolean result = (this.errorBuffer.isEmpty() && isEmbeddedFont()); 
-		if (this.delegateFontContainer != null) {
-			result &=  this.delegateFontContainer.isValid();
-		}
-		return result;
-	}
-	
-	public boolean isEmbeddedFont() {
-		boolean result = embeddedFont; 
-		if (this.delegateFontContainer != null) {
-			result &=  this.delegateFontContainer.isEmbeddedFont();
-		}
-		return result;
-	}
+    public Type0Container(PDFont font)
+    {
+        super(font);
+    }
+
+    @Override
+    protected float getFontProgramWidth(int cid)
+    {
+        float width = 0;
+        if (this.delegateFontContainer != null)
+        {
+            width = this.delegateFontContainer.getFontProgramWidth(cid);
+        }
+        return width;
+    }
+
+    public void setDelegateFontContainer(FontContainer delegateFontContainer)
+    {
+        this.delegateFontContainer = delegateFontContainer;
+    }
+
+    public List<ValidationError> getAllErrors()
+    {
+        if (this.delegateFontContainer != null)
+        {
+            this.errorBuffer.addAll(this.delegateFontContainer.getAllErrors());
+        }
+        return this.errorBuffer;
+    }
+
+    public boolean isValid()
+    {
+        boolean result = (this.errorBuffer.isEmpty() && isEmbeddedFont());
+        if (this.delegateFontContainer != null)
+        {
+            result &= this.delegateFontContainer.isValid();
+        }
+        return result;
+    }
+
+    public boolean isEmbeddedFont()
+    {
+        boolean result = embeddedFont;
+        if (this.delegateFontContainer != null)
+        {
+            result &= this.delegateFontContainer.isEmbeddedFont();
+        }
+        return result;
+    }
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type1Container.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type1Container.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type1Container.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type1Container.java Wed Mar  6 16:46:35 2013
@@ -30,73 +30,90 @@ import org.apache.pdfbox.pdmodel.font.PD
 import org.apache.pdfbox.preflight.font.util.GlyphException;
 import org.apache.pdfbox.preflight.font.util.Type1;
 
-public class Type1Container extends FontContainer {
-	/**
-	 * 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;
-
-	/**
-	 * true if information come from the FontFile1 Stream, 
-	 * false if they come from the FontFile3
-	 */
-	protected boolean isFontFile1 = true;
-
-	protected Type1 type1Font; 
-	protected List<CFFFont> lCFonts;
-
-	public Type1Container(PDFont font) {
-		super(font);
-	}
-
-	@Override
-	protected float getFontProgramWidth(int cid) {
-		float widthResult = -1;
-		try {
-			if (isFontFile1) {
-				if (type1Font != null) {
-					widthResult = this.type1Font.getWidthOfCID(cid);
-				}
-			} else {
-				/* 
-				 * Retrieves the SID with the Character Name in the encoding map
-				 * Need more PDF with a Type1C subfont to valid this implementation  
-				 */
-				String name = this.font.getFontEncoding().getName(cid);
-				for (CFFFont cff : lCFonts) {
-					int SID = cff.getEncoding().getSID(cid);
-					for (Mapping m : cff.getMappings() ){
-						if (m.getName().equals(name)) {
-							SID = m.getSID();
-							break;
-						}
-					}
-					widthResult = cff.getWidth(SID);
-					if (widthResult != defaultGlyphWidth) {
-						break;
-					}
-				}
-			}
-		} catch (GlyphException e) {
-			widthResult = -1;
-		} catch (IOException e) {
-			widthResult = -1; // TODO validation exception
-		}
-
-		return widthResult;
-	}
-
-	public void setType1Font(Type1 type1Font) {
-		this.type1Font = type1Font;
-	}
-
-	public void setFontFile1(boolean isFontFile1) {
-		this.isFontFile1 = isFontFile1;
-	}
-
-	public void setCFFFontObjects(List<CFFFont> lCFonts) {
-		this.lCFonts = lCFonts;
-	}
+public class Type1Container extends FontContainer
+{
+    /**
+     * 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;
+
+    /**
+     * true if information come from the FontFile1 Stream, false if they come from the FontFile3
+     */
+    protected boolean isFontFile1 = true;
+
+    protected Type1 type1Font;
+    protected List<CFFFont> lCFonts;
+
+    public Type1Container(PDFont font)
+    {
+        super(font);
+    }
+
+    @Override
+    protected float getFontProgramWidth(int cid)
+    {
+        float widthResult = -1;
+        try
+        {
+            if (isFontFile1)
+            {
+                if (type1Font != null)
+                {
+                    widthResult = this.type1Font.getWidthOfCID(cid);
+                }
+            }
+            else
+            {
+                /*
+                 * Retrieves the SID with the Character Name in the encoding map Need more PDF with a Type1C subfont to
+                 * valid this implementation
+                 */
+                String name = this.font.getFontEncoding().getName(cid);
+                for (CFFFont cff : lCFonts)
+                {
+                    int SID = cff.getEncoding().getSID(cid);
+                    for (Mapping m : cff.getMappings())
+                    {
+                        if (m.getName().equals(name))
+                        {
+                            SID = m.getSID();
+                            break;
+                        }
+                    }
+                    widthResult = cff.getWidth(SID);
+                    if (widthResult != defaultGlyphWidth)
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+        catch (GlyphException e)
+        {
+            widthResult = -1;
+        }
+        catch (IOException e)
+        {
+            widthResult = -1; // TODO validation exception
+        }
+
+        return widthResult;
+    }
+
+    public void setType1Font(Type1 type1Font)
+    {
+        this.type1Font = type1Font;
+    }
+
+    public void setFontFile1(boolean isFontFile1)
+    {
+        this.isFontFile1 = isFontFile1;
+    }
+
+    public void setCFFFontObjects(List<CFFFont> lCFonts)
+    {
+        this.lCFonts = lCFonts;
+    }
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type3Container.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type3Container.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type3Container.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type3Container.java Wed Mar  6 16:46:35 2013
@@ -24,19 +24,21 @@ package org.apache.pdfbox.preflight.font
 import org.apache.pdfbox.pdmodel.font.PDFont;
 
 /**
- * Because Type3 font program is an inner type of the PDF file, 
- * this font container is quite different from the other because
- * all character/glyph are already checked.
+ * Because Type3 font program is an inner type of the PDF file, this font container is quite different from the other
+ * because all character/glyph are already checked.
  */
-public class Type3Container extends FontContainer {
+public class Type3Container extends FontContainer
+{
 
-	public Type3Container(PDFont font) {
-		super(font);
-	}
-	
-	@Override
-	protected float getFontProgramWidth(int cid) {
-		return 0;
-	}
+    public Type3Container(PDFont font)
+    {
+        super(font);
+    }
+
+    @Override
+    protected float getFontProgramWidth(int cid)
+    {
+        return 0;
+    }
 
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType0DescriptorHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType0DescriptorHelper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType0DescriptorHelper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType0DescriptorHelper.java Wed Mar  6 16:46:35 2013
@@ -47,73 +47,89 @@ import org.apache.pdfbox.preflight.font.
 import org.apache.pdfbox.preflight.font.container.CIDType0Container;
 import org.apache.pdfbox.preflight.utils.COSUtils;
 
-public class CIDType0DescriptorHelper extends FontDescriptorHelper<CIDType0Container> {
+public class CIDType0DescriptorHelper extends FontDescriptorHelper<CIDType0Container>
+{
 
-	public CIDType0DescriptorHelper(PreflightContext context, PDFont font,	CIDType0Container fontContainer) {
-		super(context, font, fontContainer);
-	}
-
-	@Override
-	public PDStream extractFontFile(PDFontDescriptorDictionary fontDescriptor) {
-		PDStream ff3 = fontDescriptor.getFontFile3();
-		if (ff3 != null) {
-			/*
-			 * Stream validation should be done by the StreamValidateHelper.
-			 * Process font specific check 
-			 */
-			COSStream stream = ff3.getStream();
-			if (stream == null) {
-				this.fContainer.push(new ValidationError(	ERROR_FONTS_FONT_FILEX_INVALID, "The FontFile is missing for " + fontDescriptor.getFontName()));
-				this.fContainer.notEmbedded();
-			} else {
-				/*
-				 * Lengthx aren't mandatory for this type of font
-				 * But the Subtype is a mandatory field with specific values
-				 */
-				String st = stream.getNameAsString(COSName.SUBTYPE);
-				if (!(FONT_DICTIONARY_VALUE_TYPE0C.equals(st) || FONT_DICTIONARY_VALUE_TYPE1C.equals(st))) {
-					this.fContainer.push(new ValidationError(ERROR_FONTS_FONT_FILEX_INVALID,	"The FontFile3 stream doesn't have the right Subtype for " + fontDescriptor.getFontName()));
-				}
-
-				checkCIDSet(fontDescriptor);
-			}
-		}
-		return ff3;
-	}
-
-	/**
-	 * If the embedded font is a subset, the CIDSet entry is mandatory and must be
-	 * a Stream. If the CIDSet entry doesn't respects conditions, the FontContainer is updated.
-	 * 
-	 * @param pfDescriptor
-	 */
-	protected void checkCIDSet(PDFontDescriptorDictionary pfDescriptor) {
-		if (FontValidator.isSubSet(pfDescriptor.getFontName())) {
-			COSDocument cosDocument = context.getDocument().getDocument();
-			COSBase cidset = pfDescriptor.getCOSDictionary().getItem(COSName.getPDFName(FONT_DICTIONARY_KEY_CIDSET));
-			if (cidset == null	|| !COSUtils.isStream(cidset, cosDocument)) {
-				this.fContainer.push(new ValidationResult.ValidationError(ERROR_FONTS_CIDSET_MISSING_FOR_SUBSET,
-						"The CIDSet entry is missing for the Composite Subset"));
-			}
-		}
-	}
-
-	@Override
-	protected void processFontFile(PDFontDescriptorDictionary fontDescriptor,	PDStream fontFile) {
-		/*
-		 * try to load the font using the java.awt.font object.
-		 * if the font is invalid, an exception will be thrown
-		 */
-		try {
-			CFFParser cffParser = new CFFParser();
-			List<CFFFont> lCFonts = cffParser.parse(fontFile.getByteArray());
-			if (lCFonts == null || lCFonts.isEmpty()) {
-				this.fContainer.push(new ValidationError(ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read"));
-			}
-			fContainer.setlCFonts(lCFonts);
-		} catch (IOException e) {
-			this.fContainer.push(new ValidationError(ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read"));
-		}
-	}
+    public CIDType0DescriptorHelper(PreflightContext context, PDFont font, CIDType0Container fontContainer)
+    {
+        super(context, font, fontContainer);
+    }
+
+    @Override
+    public PDStream extractFontFile(PDFontDescriptorDictionary fontDescriptor)
+    {
+        PDStream ff3 = fontDescriptor.getFontFile3();
+        if (ff3 != null)
+        {
+            /*
+             * Stream validation should be done by the StreamValidateHelper. Process font specific check
+             */
+            COSStream stream = ff3.getStream();
+            if (stream == null)
+            {
+                this.fContainer.push(new ValidationError(ERROR_FONTS_FONT_FILEX_INVALID, "The FontFile is missing for "
+                        + fontDescriptor.getFontName()));
+                this.fContainer.notEmbedded();
+            }
+            else
+            {
+                /*
+                 * Lengthx aren't mandatory for this type of font But the Subtype is a mandatory field with specific
+                 * values
+                 */
+                String st = stream.getNameAsString(COSName.SUBTYPE);
+                if (!(FONT_DICTIONARY_VALUE_TYPE0C.equals(st) || FONT_DICTIONARY_VALUE_TYPE1C.equals(st)))
+                {
+                    this.fContainer.push(new ValidationError(ERROR_FONTS_FONT_FILEX_INVALID,
+                            "The FontFile3 stream doesn't have the right Subtype for " + fontDescriptor.getFontName()));
+                }
+
+                checkCIDSet(fontDescriptor);
+            }
+        }
+        return ff3;
+    }
+
+    /**
+     * If the embedded font is a subset, the CIDSet entry is mandatory and must be a Stream. If the CIDSet entry doesn't
+     * respects conditions, the FontContainer is updated.
+     * 
+     * @param pfDescriptor
+     */
+    protected void checkCIDSet(PDFontDescriptorDictionary pfDescriptor)
+    {
+        if (FontValidator.isSubSet(pfDescriptor.getFontName()))
+        {
+            COSDocument cosDocument = context.getDocument().getDocument();
+            COSBase cidset = pfDescriptor.getCOSDictionary().getItem(COSName.getPDFName(FONT_DICTIONARY_KEY_CIDSET));
+            if (cidset == null || !COSUtils.isStream(cidset, cosDocument))
+            {
+                this.fContainer.push(new ValidationResult.ValidationError(ERROR_FONTS_CIDSET_MISSING_FOR_SUBSET,
+                        "The CIDSet entry is missing for the Composite Subset"));
+            }
+        }
+    }
+
+    @Override
+    protected void processFontFile(PDFontDescriptorDictionary fontDescriptor, PDStream fontFile)
+    {
+        /*
+         * try to load the font using the java.awt.font object. if the font is invalid, an exception will be thrown
+         */
+        try
+        {
+            CFFParser cffParser = new CFFParser();
+            List<CFFFont> lCFonts = cffParser.parse(fontFile.getByteArray());
+            if (lCFonts == null || lCFonts.isEmpty())
+            {
+                this.fContainer.push(new ValidationError(ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read"));
+            }
+            fContainer.setlCFonts(lCFonts);
+        }
+        catch (IOException e)
+        {
+            this.fContainer.push(new ValidationError(ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read"));
+        }
+    }
 
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType2DescriptorHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType2DescriptorHelper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType2DescriptorHelper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/CIDType2DescriptorHelper.java Wed Mar  6 16:46:35 2013
@@ -44,69 +44,78 @@ import org.apache.pdfbox.preflight.font.
 import org.apache.pdfbox.preflight.font.container.CIDType2Container;
 import org.apache.pdfbox.preflight.utils.COSUtils;
 
-public class CIDType2DescriptorHelper extends FontDescriptorHelper<CIDType2Container> {
+public class CIDType2DescriptorHelper extends FontDescriptorHelper<CIDType2Container>
+{
 
-	public CIDType2DescriptorHelper(PreflightContext context, PDFont font,	CIDType2Container fontContainer) {
-		super(context, font, fontContainer);
-	}
-
-	/**
-	 * If the embedded font is a subset, the CIDSet entry is mandatory and must be
-	 * a Stream. If the CIDSet entry doesn't respects conditions, the FontContainer is updated.
-	 * 
-	 * @param pfDescriptor
-	 */
-	protected void checkCIDSet(PDFontDescriptorDictionary pfDescriptor) {
-		if (FontValidator.isSubSet(pfDescriptor.getFontName())) {
-			COSDocument cosDocument = context.getDocument().getDocument();
-			COSBase cidset = pfDescriptor.getCOSDictionary().getItem(COSName.getPDFName(FONT_DICTIONARY_KEY_CIDSET));
-			if (cidset == null	|| !COSUtils.isStream(cidset, cosDocument)) {
-				this.fContainer.push(new ValidationResult.ValidationError(ERROR_FONTS_CIDSET_MISSING_FOR_SUBSET,
-						"The CIDSet entry is missing for the Composite Subset"));
-			}
-		}
-	}
-
-	@Override
-	public PDStream extractFontFile(PDFontDescriptorDictionary fontDescriptor) {
-		PDStream ff2 = fontDescriptor.getFontFile2();
-		if (ff2 != null) {
-			/*
-			 * Stream validation should be done by the StreamValidateHelper.
-			 * Process font specific check
-			 */
-			COSStream stream = ff2.getStream();
-			if (stream == null) {
-				this.fContainer.push(new ValidationError(ERROR_FONTS_FONT_FILEX_INVALID, "The FontFile is missing for " + fontDescriptor.getFontName()));
-				this.fContainer.notEmbedded();
-			}
-		}
-		checkCIDSet(fontDescriptor);
-		return ff2;
-	}
-
-	@Override
-	protected void processFontFile(PDFontDescriptorDictionary fontDescriptor,	PDStream fontFile) {
-		/*
-		 * try to load the font using the java.awt.font object.
-		 * if the font is invalid, an exception will be thrown
-		 */
-		TrueTypeFont ttf = null;
-		try {
-			/*
-			 * According to PDF Reference, CIDFontType2 is a TrueType font.
-			 * Remark : Java.awt.Font throws exception when a CIDFontType2 is
-			 * parsed even if it is valid.
-			 */
-			ttf = new CIDFontType2Parser(true).parseTTF(new ByteArrayInputStream(fontFile.getByteArray()));
-			this.fContainer.setTtf(ttf);
-		} catch (Exception e) {
-			/*
-			 * Exceptionally, Exception is catched Here because of damaged font
-			 * can throw NullPointer Exception...
-			 */
-			this.fContainer.push(new ValidationError(ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read"));
-		}
-	}
+    public CIDType2DescriptorHelper(PreflightContext context, PDFont font, CIDType2Container fontContainer)
+    {
+        super(context, font, fontContainer);
+    }
+
+    /**
+     * If the embedded font is a subset, the CIDSet entry is mandatory and must be a Stream. If the CIDSet entry doesn't
+     * respects conditions, the FontContainer is updated.
+     * 
+     * @param pfDescriptor
+     */
+    protected void checkCIDSet(PDFontDescriptorDictionary pfDescriptor)
+    {
+        if (FontValidator.isSubSet(pfDescriptor.getFontName()))
+        {
+            COSDocument cosDocument = context.getDocument().getDocument();
+            COSBase cidset = pfDescriptor.getCOSDictionary().getItem(COSName.getPDFName(FONT_DICTIONARY_KEY_CIDSET));
+            if (cidset == null || !COSUtils.isStream(cidset, cosDocument))
+            {
+                this.fContainer.push(new ValidationResult.ValidationError(ERROR_FONTS_CIDSET_MISSING_FOR_SUBSET,
+                        "The CIDSet entry is missing for the Composite Subset"));
+            }
+        }
+    }
+
+    @Override
+    public PDStream extractFontFile(PDFontDescriptorDictionary fontDescriptor)
+    {
+        PDStream ff2 = fontDescriptor.getFontFile2();
+        if (ff2 != null)
+        {
+            /*
+             * Stream validation should be done by the StreamValidateHelper. Process font specific check
+             */
+            COSStream stream = ff2.getStream();
+            if (stream == null)
+            {
+                this.fContainer.push(new ValidationError(ERROR_FONTS_FONT_FILEX_INVALID, "The FontFile is missing for "
+                        + fontDescriptor.getFontName()));
+                this.fContainer.notEmbedded();
+            }
+        }
+        checkCIDSet(fontDescriptor);
+        return ff2;
+    }
+
+    @Override
+    protected void processFontFile(PDFontDescriptorDictionary fontDescriptor, PDStream fontFile)
+    {
+        /*
+         * try to load the font using the java.awt.font object. if the font is invalid, an exception will be thrown
+         */
+        TrueTypeFont ttf = null;
+        try
+        {
+            /*
+             * According to PDF Reference, CIDFontType2 is a TrueType font. Remark : Java.awt.Font throws exception when
+             * a CIDFontType2 is parsed even if it is valid.
+             */
+            ttf = new CIDFontType2Parser(true).parseTTF(new ByteArrayInputStream(fontFile.getByteArray()));
+            this.fContainer.setTtf(ttf);
+        }
+        catch (Exception e)
+        {
+            /*
+             * Exceptionally, Exception is catched Here because of damaged font can throw NullPointer Exception...
+             */
+            this.fContainer.push(new ValidationError(ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read"));
+        }
+    }
 
 }