Search in sources :

Example 1 with GlyphException

use of org.apache.pdfbox.preflight.font.util.GlyphException in project pdfbox by apache.

the class FontContainer method checkWidthsConsistency.

/**
 * Test if both widths are consistent. At the end of this method, the CID is
 * marked as valid or invalid.
 *
 * @param code character code
 * @param expectedWidth expected with given in the PDF file
 * @param foundWidth the glyph width found in the font program, a negative
 * value if the CID is missing from the font.
 * @throws GlyphException the appropriate exception if the CID is invalid.
 */
private void checkWidthsConsistency(int code, float expectedWidth, float foundWidth) throws GlyphException {
    // 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, code, "Width (" + foundWidth + ") of the character \"" + code + "\" in the font program \"" + this.font.getName() + "\" is inconsistent with the width (" + expectedWidth + ") in the PDF dictionary.");
        markAsInvalid(code, e);
        throw e;
    }
    markAsValid(code);
}
Also used : GlyphException(org.apache.pdfbox.preflight.font.util.GlyphException)

Example 2 with GlyphException

use of org.apache.pdfbox.preflight.font.util.GlyphException in project pdfbox by apache.

the class PreflightContentStream method validateText.

/**
 * 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 validateText(byte[] string) throws IOException {
    // TextSize accessible through the TextState
    PDTextState textState = getGraphicsState().getTextState();
    final RenderingMode renderingMode = textState.getRenderingMode();
    final PDFont font = textState.getFont();
    if (font == null) {
        // Unable to decode the Text without Font
        registerError("Text operator can't be processed without a Font", ERROR_FONTS_UNKNOWN_FONT_REF);
        return;
    }
    FontContainer<?> fontContainer = context.getFontContainer(font.getCOSObject());
    if (renderingMode == RenderingMode.NEITHER && (fontContainer == null || !fontContainer.isEmbeddedFont())) {
        // font not embedded and rendering mode is 3. Valid case and nothing to check
        return;
    } else if (fontContainer == null) {
        // Font Must be embedded if the RenderingMode isn't 3
        if (font.getName() == null) {
            registerError("invalid font dictionary", ERROR_FONTS_UNKNOWN_FONT_REF);
        } else {
            registerError("font '" + font.getName() + "' is missing", ERROR_FONTS_UNKNOWN_FONT_REF);
        }
        return;
    } else if (!fontContainer.isValid() && !fontContainer.errorsAleadyMerged()) {
        context.addValidationErrors(fontContainer.getAllErrors());
        fontContainer.setErrorsAlreadyMerged(true);
        return;
    }
    if (!fontContainer.isValid() && fontContainer.errorsAleadyMerged()) {
        // font already computed
        return;
    }
    InputStream in = new ByteArrayInputStream(string);
    while (in.available() > 0) {
        try {
            int code = font.readCode(in);
            fontContainer.checkGlyphWidth(code);
        } catch (IOException e) {
            registerError("Encoding can't interpret the character code", ERROR_FONTS_ENCODING_ERROR, e);
            return;
        } catch (GlyphException e) {
            if (renderingMode != RenderingMode.NEITHER) {
                registerError(e.getMessage(), e.getErrorCode(), e);
                return;
            }
        }
    }
}
Also used : PDFont(org.apache.pdfbox.pdmodel.font.PDFont) RenderingMode(org.apache.pdfbox.pdmodel.graphics.state.RenderingMode) ByteArrayInputStream(java.io.ByteArrayInputStream) GlyphException(org.apache.pdfbox.preflight.font.util.GlyphException) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) PDTextState(org.apache.pdfbox.pdmodel.graphics.state.PDTextState) IOException(java.io.IOException)

Example 3 with GlyphException

use of org.apache.pdfbox.preflight.font.util.GlyphException in project pdfbox by apache.

the class Type3FontValidator method checkCharProcsAndMetrics.

/**
 * 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.
 */
private void checkCharProcsAndMetrics() throws ValidationException {
    List<Float> widths = getWidths(font);
    if (widths == null || widths.isEmpty()) {
        this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, font.getName() + ": 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, font.getName() + ": The CharProcs element isn't a dictionary"));
        return;
    }
    int fc = font.getCOSObject().getInt(COSName.FIRST_CHAR, -1);
    int lc = font.getCOSObject().getInt(COSName.LAST_CHAR, -1);
    /*
         * 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 &lt;= 0.
         */
    int expectedLength = (lc - fc) + 1;
    if (widths.size() != expectedLength) {
        this.fontContainer.push(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, font.getName() + ": The length of Witdhs array is invalid. Expected : \"" + expectedLength + "\" Current : \"" + widths.size() + "\""));
        return;
    }
    // Check width consistency
    for (int i = 0; i < expectedLength; i++) {
        int code = fc + i;
        float width = widths.get(i);
        PDType3CharProc charProc = getCharProc(code);
        if (charProc != null) {
            try {
                float fontProgramWidth = getWidthFromCharProc(charProc);
                if (Math.abs(width - fontProgramWidth) < 0.001f) {
                    // Glyph is OK, we keep the CID.
                    // PDF/A-1b only states that the width "shall be consistent".
                    // For PDF/A-2,3 the description has been enhanced and is now requesting
                    // "consistent is defined to be a difference of no more than 1/1000 unit"
                    // We interpret this as clarification of the PDF/A-1b requirement.
                    this.fontContainer.markAsValid(code);
                } else {
                    GlyphException glyphEx = new GlyphException(ERROR_FONTS_METRICS, code, font.getName() + ": The character with CID " + code + " should have a width equals to " + width + ", but has " + fontProgramWidth);
                    this.fontContainer.markAsInvalid(code, 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(e.getErrorCode(), e.getMessage(), e));
                return;
            } catch (IOException e) {
                this.fontContainer.push(new ValidationError(ERROR_FONTS_TYPE3_DAMAGED, font.getName() + ": The CharProcs references an element which can't be read", e));
                return;
            }
        }
    }
}
Also used : PDType3CharProc(org.apache.pdfbox.pdmodel.font.PDType3CharProc) ContentStreamException(org.apache.pdfbox.preflight.content.ContentStreamException) COSDictionary(org.apache.pdfbox.cos.COSDictionary) GlyphException(org.apache.pdfbox.preflight.font.util.GlyphException) ValidationError(org.apache.pdfbox.preflight.ValidationResult.ValidationError) IOException(java.io.IOException)

Example 4 with GlyphException

use of org.apache.pdfbox.preflight.font.util.GlyphException in project pdfbox by apache.

the class Type3FontValidator method getCharProc.

private PDType3CharProc getCharProc(int code) throws ValidationException {
    PDType3CharProc charProc = font.getCharProc(code);
    if (charProc == 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, code, font.getName() + ": The CharProcs \"" + font.getEncoding().getName(code) + "\" doesn't exist");
        this.fontContainer.markAsInvalid(code, glyphEx);
    }
    return charProc;
}
Also used : PDType3CharProc(org.apache.pdfbox.pdmodel.font.PDType3CharProc) GlyphException(org.apache.pdfbox.preflight.font.util.GlyphException)

Example 5 with GlyphException

use of org.apache.pdfbox.preflight.font.util.GlyphException in project pdfbox by apache.

the class FontContainer method checkGlyphWidth.

/**
 * Check that the Width or W entry in the PDF matches the widths in the embedded font program.
 *
 * @param code character code
 * @throws GlyphException
 */
public void checkGlyphWidth(int code) throws GlyphException {
    if (isAlreadyProcessed(code)) {
        return;
    }
    try {
        // check for missing glyphs
        if (!hasGlyph(code)) {
            GlyphException e = new GlyphException(PreflightConstants.ERROR_FONTS_GLYPH_MISSING, code, "The character code " + code + " in the font program \"" + font.getName() + "\" is missing from the Character Encoding");
            markAsInvalid(code, e);
            throw e;
        }
        // check widths
        float expectedWidth = font.getWidth(code);
        float foundWidth = font.getWidthFromFont(code);
        checkWidthsConsistency(code, expectedWidth, foundWidth);
    } catch (IOException e) {
        throw new GlyphException(PreflightConstants.ERROR_FONTS_GLYPH, code, "Unexpected error during the width validation for the character code " + code + " : " + e.getMessage(), e);
    }
}
Also used : GlyphException(org.apache.pdfbox.preflight.font.util.GlyphException) IOException(java.io.IOException)

Aggregations

GlyphException (org.apache.pdfbox.preflight.font.util.GlyphException)5 IOException (java.io.IOException)3 PDType3CharProc (org.apache.pdfbox.pdmodel.font.PDType3CharProc)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 InputStream (java.io.InputStream)1 COSDictionary (org.apache.pdfbox.cos.COSDictionary)1 PDFont (org.apache.pdfbox.pdmodel.font.PDFont)1 PDTextState (org.apache.pdfbox.pdmodel.graphics.state.PDTextState)1 RenderingMode (org.apache.pdfbox.pdmodel.graphics.state.RenderingMode)1 ValidationError (org.apache.pdfbox.preflight.ValidationResult.ValidationError)1 ContentStreamException (org.apache.pdfbox.preflight.content.ContentStreamException)1