/*****************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
package org.apache.padaf.preflight.font;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.padaf.preflight.ValidationConstants;
import org.apache.padaf.preflight.ValidationResult.ValidationError;
import org.apache.pdfbox.pdmodel.font.PDFont;
public abstract class AbstractFontContainer {
/**
* PDFBox object which contains the Font Dictionary
*/
protected PDFont font = null;
protected Map<Integer, GlyphDetail> cidKnownByFont = new HashMap<Integer, GlyphDetail>();
/**
* Boolean used to know if the Font Program is embedded.
*/
protected boolean isFontProgramEmbedded = true;
/**
* Errors which occurs during the Font Validation
*/
protected List<ValidationError> errors = new ArrayList<ValidationError>(0);
/**
* The FontContainer Constructor. The type attribute is initialized according
* to the given PDFont object.
*
* @param fd
* Font object of the PDFBox API. (Mandatory)
* @throws NullPointerException
* If the fd is null.
*/
public AbstractFontContainer(PDFont fd) {
this.font = fd;
}
/**
* Return the PDFont object
*
* @return
*/
public PDFont getFont() {
return font;
}
public void addCID(Integer cid, GlyphDetail details) {
this.cidKnownByFont.put(cid, details);
}
/**
* @return the isFontProgramEmbedded
*/
public boolean isFontProgramEmbedded() {
return isFontProgramEmbedded;
}
/**
* @param isFontProgramEmbedded
* the isFontProgramEmbedded to set
*/
public void setFontProgramEmbedded(boolean isFontProgramEmbedded) {
this.isFontProgramEmbedded = isFontProgramEmbedded;
}
/**
* Addition of a validation error.
*
* @param error
*/
public void addError(ValidationError error) {
this.errors.add(error);
}
/**
* This method returns the validation state of the font.
*
* If the list of errors is empty, the validation is successful (State :
* VALID). If the size of the list is 1 and if the error is about EmbeddedFont,
* the state is "MAYBE" because the font can be valid if
* it isn't used (for Width error) or if the rendering mode is 3 (For not
* embedded font). Otherwise, the validation failed (State : INVALID)
*
* @return
*/
public State isValid() {
if (this.errors.isEmpty()) {
return State.VALID;
}
if ((this.errors.size() == 1)
&& !this.isFontProgramEmbedded) {
return State.MAYBE;
}
// else more than one error, the validation failed
return State.INVALID;
}
/**
* @return the errors
*/
public List<ValidationError> getErrors() {
return errors;
}
public static enum State {
VALID, MAYBE, INVALID;
}
/**
* Check if the cid is present and consistent in the contained font.
* @param cid the cid
* @return true if cid is present and consistent, false otherwise
*/
public abstract void checkCID (int cid) throws GlyphException;
void addKnownCidElement(GlyphDetail glyphDetail) {
this.cidKnownByFont.put(glyphDetail.getCID(), glyphDetail);
}
protected boolean isAlreadyComputedCid(int cid) throws GlyphException {
boolean already = false;
GlyphDetail gdetail = this.cidKnownByFont.get(cid);
if (gdetail != null) {
gdetail.throwExceptionIfNotValid();
already = true;
}
return already;
}
protected void checkWidthsConsistency(int cid, float widthProvidedByPdfDictionary, float widthInFontProgram) throws GlyphException {
// a delta of 1/1000 unit is allowed
final float epsilon = widthInFontProgram/1000;
if(!(Math.floor(widthInFontProgram-epsilon) <= widthProvidedByPdfDictionary && Math.round(widthInFontProgram+epsilon) >= widthProvidedByPdfDictionary)) {
GlyphException e = new GlyphException(ValidationConstants.ERROR_FONTS_METRICS, cid,
"Width of the character \"" + cid
+ "\" in the font program \""
+ this.font.getBaseFont()
+ "\"is inconsistent with the width in the PDF dictionary.");
addKnownCidElement(new GlyphDetail(cid, e));
throw e;
}
}
}