You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2012/03/30 17:54:13 UTC
svn commit: r1307491 - in /pdfbox/trunk:
fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java
preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java
Author: leleueri
Date: Fri Mar 30 15:54:12 2012
New Revision: 1307491
URL: http://svn.apache.org/viewvc?rev=1307491&view=rev
Log:
[PDFBOX-1275] The use of ".notdef" glyph character is authorized by the PDF/A-1 specification if the CID is 0.
Modified:
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java
pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java?rev=1307491&r1=1307490&r2=1307491&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java Fri Mar 30 15:54:12 2012
@@ -38,175 +38,175 @@ import org.apache.fontbox.cff.encoding.C
public class CFFFont
{
- private String fontname = null;
- private Map<String, Object> topDict = new LinkedHashMap<String, Object>();
- private Map<String, Object> privateDict = new LinkedHashMap<String, Object>();
- private CFFEncoding fontEncoding = null;
- private CFFCharset fontCharset = null;
- private Map<String, byte[]> charStringsDict = new LinkedHashMap<String, byte[]>();
- private IndexData globalSubrIndex = null;
- private IndexData localSubrIndex = null;
-
- /**
- * The name of the font.
- * @return the name of the font
- */
- public String getName()
- {
- return fontname;
- }
-
- /**
- * Sets the name of the font.
- * @param name the name of the font
- */
- public void setName(String name)
- {
- fontname = name;
- }
-
- /**
- * Returns the value for the given name from the dictionary.
- * @param name the name of the value
- * @return the value of the name if available
- */
- public Object getProperty(String name)
- {
- Object topDictValue = topDict.get(name);
- if (topDictValue != null)
- {
- return topDictValue;
- }
- Object privateDictValue = privateDict.get(name);
- if (privateDictValue != null)
- {
- return privateDictValue;
- }
- return null;
- }
-
- /**
- * Adds the given key/value pair to the top dictionary.
- * @param name the given key
- * @param value the given value
- */
- public void addValueToTopDict(String name, Object value)
- {
- if (value != null)
- {
- topDict.put(name, value);
- }
- }
- /**
- * Returns the top dictionary.
- * @return the dictionary
- */
- public Map<String, Object> getTopDict()
- {
- return topDict;
- }
-
- /**
- * Adds the given key/value pair to the private dictionary.
- * @param name the given key
- * @param value the given value
- */
- public void addValueToPrivateDict(String name, Object value)
- {
- if (value != null)
- {
- privateDict.put(name, value);
- }
- }
- /**
- * Returns the private dictionary.
- * @return the dictionary
- */
- public Map<String, Object> getPrivateDict()
- {
- return privateDict;
- }
-
- /**
- * Get the mapping (code/SID/charname/bytes) for this font.
- * @return mappings for codes < 256 and for codes > = 256
- */
- public Collection<Mapping> getMappings()
- {
- List<Mapping> mappings = new ArrayList<Mapping>();
- Set<String> mappedNames = new HashSet<String>();
- for (CFFEncoding.Entry entry : fontEncoding.getEntries())
- {
- String charName = fontCharset.getName(entry.getSID());
- // Predefined encoding
- if (charName == null)
- {
- continue;
- }
- byte[] bytes = charStringsDict.get(charName);
- if (bytes == null)
- {
- continue;
- }
- Mapping mapping = new Mapping();
- mapping.setCode(entry.getCode());
- mapping.setSID(entry.getSID());
- mapping.setName(charName);
- mapping.setBytes(bytes);
- mappings.add(mapping);
- mappedNames.add(charName);
- }
- if (fontEncoding instanceof CFFParser.EmbeddedEncoding)
- {
- CFFParser.EmbeddedEncoding embeddedEncoding = (CFFParser.EmbeddedEncoding)fontEncoding;
-
- for (CFFParser.EmbeddedEncoding.Supplement supplement : embeddedEncoding.getSupplements())
- {
- String charName = fontCharset.getName(supplement.getGlyph());
- if (charName == null)
- {
- continue;
- }
- byte[] bytes = charStringsDict.get(charName);
- if (bytes == null)
- {
- continue;
- }
- Mapping mapping = new Mapping();
- mapping.setCode(supplement.getCode());
- mapping.setSID(supplement.getGlyph());
- mapping.setName(charName);
- mapping.setBytes(bytes);
- mappings.add(mapping);
- mappedNames.add(charName);
- }
- }
- // XXX
- int code = 256;
- for (CFFCharset.Entry entry : fontCharset.getEntries())
- {
- String name = entry.getName();
- if (mappedNames.contains(name))
- {
- continue;
- }
- byte[] bytes = this.charStringsDict.get(name);
- if (bytes == null)
- {
- continue;
- }
- Mapping mapping = new Mapping();
- mapping.setCode(code++);
- mapping.setSID(entry.getSID());
- mapping.setName(name);
- mapping.setBytes(bytes);
-
- mappings.add(mapping);
-
- mappedNames.add(name);
- }
- return mappings;
- }
+ private String fontname = null;
+ private Map<String, Object> topDict = new LinkedHashMap<String, Object>();
+ private Map<String, Object> privateDict = new LinkedHashMap<String, Object>();
+ private CFFEncoding fontEncoding = null;
+ private CFFCharset fontCharset = null;
+ private Map<String, byte[]> charStringsDict = new LinkedHashMap<String, byte[]>();
+ private IndexData globalSubrIndex = null;
+ private IndexData localSubrIndex = null;
+
+ /**
+ * The name of the font.
+ * @return the name of the font
+ */
+ public String getName()
+ {
+ return fontname;
+ }
+
+ /**
+ * Sets the name of the font.
+ * @param name the name of the font
+ */
+ public void setName(String name)
+ {
+ fontname = name;
+ }
+
+ /**
+ * Returns the value for the given name from the dictionary.
+ * @param name the name of the value
+ * @return the value of the name if available
+ */
+ public Object getProperty(String name)
+ {
+ Object topDictValue = topDict.get(name);
+ if (topDictValue != null)
+ {
+ return topDictValue;
+ }
+ Object privateDictValue = privateDict.get(name);
+ if (privateDictValue != null)
+ {
+ return privateDictValue;
+ }
+ return null;
+ }
+
+ /**
+ * Adds the given key/value pair to the top dictionary.
+ * @param name the given key
+ * @param value the given value
+ */
+ public void addValueToTopDict(String name, Object value)
+ {
+ if (value != null)
+ {
+ topDict.put(name, value);
+ }
+ }
+ /**
+ * Returns the top dictionary.
+ * @return the dictionary
+ */
+ public Map<String, Object> getTopDict()
+ {
+ return topDict;
+ }
+
+ /**
+ * Adds the given key/value pair to the private dictionary.
+ * @param name the given key
+ * @param value the given value
+ */
+ public void addValueToPrivateDict(String name, Object value)
+ {
+ if (value != null)
+ {
+ privateDict.put(name, value);
+ }
+ }
+ /**
+ * Returns the private dictionary.
+ * @return the dictionary
+ */
+ public Map<String, Object> getPrivateDict()
+ {
+ return privateDict;
+ }
+
+ /**
+ * Get the mapping (code/SID/charname/bytes) for this font.
+ * @return mappings for codes < 256 and for codes > = 256
+ */
+ public Collection<Mapping> getMappings()
+ {
+ List<Mapping> mappings = new ArrayList<Mapping>();
+ Set<String> mappedNames = new HashSet<String>();
+ for (CFFEncoding.Entry entry : fontEncoding.getEntries())
+ {
+ String charName = fontCharset.getName(entry.getSID());
+ // Predefined encoding
+ if (charName == null)
+ {
+ continue;
+ }
+ byte[] bytes = charStringsDict.get(charName);
+ if (bytes == null)
+ {
+ continue;
+ }
+ Mapping mapping = new Mapping();
+ mapping.setCode(entry.getCode());
+ mapping.setSID(entry.getSID());
+ mapping.setName(charName);
+ mapping.setBytes(bytes);
+ mappings.add(mapping);
+ mappedNames.add(charName);
+ }
+ if (fontEncoding instanceof CFFParser.EmbeddedEncoding)
+ {
+ CFFParser.EmbeddedEncoding embeddedEncoding = (CFFParser.EmbeddedEncoding)fontEncoding;
+
+ for (CFFParser.EmbeddedEncoding.Supplement supplement : embeddedEncoding.getSupplements())
+ {
+ String charName = fontCharset.getName(supplement.getGlyph());
+ if (charName == null)
+ {
+ continue;
+ }
+ byte[] bytes = charStringsDict.get(charName);
+ if (bytes == null)
+ {
+ continue;
+ }
+ Mapping mapping = new Mapping();
+ mapping.setCode(supplement.getCode());
+ mapping.setSID(supplement.getGlyph());
+ mapping.setName(charName);
+ mapping.setBytes(bytes);
+ mappings.add(mapping);
+ mappedNames.add(charName);
+ }
+ }
+ // XXX
+ int code = 256;
+ for (CFFCharset.Entry entry : fontCharset.getEntries())
+ {
+ String name = entry.getName();
+ if (mappedNames.contains(name))
+ {
+ continue;
+ }
+ byte[] bytes = this.charStringsDict.get(name);
+ if (bytes == null)
+ {
+ continue;
+ }
+ Mapping mapping = new Mapping();
+ mapping.setCode(code++);
+ mapping.setSID(entry.getSID());
+ mapping.setName(name);
+ mapping.setBytes(bytes);
+
+ mappings.add(mapping);
+
+ mappedNames.add(name);
+ }
+ return mappings;
+ }
/**
* Return the Width value of the given Glyph identifier
@@ -218,6 +218,7 @@ public class CFFFont
public int getWidth(int SID) throws IOException {
int nominalWidth = privateDict.containsKey("nominalWidthX") ? ((Number)privateDict.get("nominalWidthX")).intValue() : 0;
int defaultWidth = privateDict.containsKey("defaultWidthX") ? ((Number)privateDict.get("defaultWidthX")).intValue() : 1000 ;
+
for (Mapping m : getMappings() ){
if (m.getSID() == SID) {
@@ -238,207 +239,224 @@ public class CFFFont
}
}
- // ---- Width not found, return the default width
- return defaultWidth;
+ // ---- SID Width not found, return the nodef width
+ return getNotDefWidth(defaultWidth, nominalWidth);
+ }
+
+ protected int getNotDefWidth(int defaultWidth, int nominalWidth) throws IOException {
+ CharStringRenderer csr;
+ byte[] glyphDesc = this.getCharStringsDict().get(".notdef");
+ if (((Number)getProperty("CharstringType")).intValue() == 2 ) {
+ Type2CharStringParser parser = new Type2CharStringParser();
+ List<Object> lSeq = parser.parse(glyphDesc);
+ csr = new CharStringRenderer(false);
+ csr.render(lSeq);
+ } else {
+ Type1CharStringParser parser = new Type1CharStringParser();
+ List<Object> lSeq = parser.parse(glyphDesc);
+ csr = new CharStringRenderer();
+ csr.render(lSeq);
+ }
+ return csr.getWidth() != 0 ? csr.getWidth() + nominalWidth : defaultWidth;
+ }
+
+ /**
+ * Returns the CFFEncoding of the font.
+ * @return the encoding
+ */
+ public CFFEncoding getEncoding()
+ {
+ return fontEncoding;
+ }
+
+ /**
+ * Sets the CFFEncoding of the font.
+ * @param encoding the given CFFEncoding
+ */
+ public void setEncoding(CFFEncoding encoding)
+ {
+ fontEncoding = encoding;
}
-
- /**
- * Returns the CFFEncoding of the font.
- * @return the encoding
- */
- public CFFEncoding getEncoding()
- {
- return fontEncoding;
- }
-
- /**
- * Sets the CFFEncoding of the font.
- * @param encoding the given CFFEncoding
- */
- public void setEncoding(CFFEncoding encoding)
- {
- fontEncoding = encoding;
- }
-
- /**
- * Returns the CFFCharset of the font.
- * @return the charset
- */
- public CFFCharset getCharset()
- {
- return fontCharset;
- }
-
- /**
- * Sets the CFFCharset of the font.
- * @param charset the given CFFCharset
- */
- public void setCharset(CFFCharset charset)
- {
- fontCharset = charset;
- }
-
- /**
- * Returns the character strings dictionary.
- * @return the dictionary
- */
- public Map<String, byte[]> getCharStringsDict()
- {
- return charStringsDict;
- }
-
- /**
- * Creates a CharStringConverter for this font.
- * @return the new CharStringConverter
- */
- public CharStringConverter createConverter()
- {
- Number defaultWidthX = (Number) getProperty("defaultWidthX");
- Number nominalWidthX = (Number) getProperty("nominalWidthX");
- return new CharStringConverter(defaultWidthX.intValue(), nominalWidthX
- .intValue(), getGlobalSubrIndex(), getLocalSubrIndex());
- }
-
- /**
- * Creates a CharStringRenderer for this font.
- * @return the new CharStringRenderer
- */
- public CharStringRenderer createRenderer()
- {
- return new CharStringRenderer();
- }
-
- /**
- * {@inheritDoc}
- */
- public String toString()
- {
- return getClass().getName() + "[name=" + fontname + ", topDict=" + topDict
- + ", privateDict=" + privateDict + ", encoding=" + fontEncoding
- + ", charset=" + fontCharset + ", charStringsDict="
- + charStringsDict + "]";
- }
-
-
- /**
- * Sets the global subroutine index data.
- * @param globalSubrIndex the IndexData object containing the global subroutines
- */
- public void setGlobalSubrIndex(IndexData globalSubrIndex) {
+
+ /**
+ * Returns the CFFCharset of the font.
+ * @return the charset
+ */
+ public CFFCharset getCharset()
+ {
+ return fontCharset;
+ }
+
+ /**
+ * Sets the CFFCharset of the font.
+ * @param charset the given CFFCharset
+ */
+ public void setCharset(CFFCharset charset)
+ {
+ fontCharset = charset;
+ }
+
+ /**
+ * Returns the character strings dictionary.
+ * @return the dictionary
+ */
+ public Map<String, byte[]> getCharStringsDict()
+ {
+ return charStringsDict;
+ }
+
+ /**
+ * Creates a CharStringConverter for this font.
+ * @return the new CharStringConverter
+ */
+ public CharStringConverter createConverter()
+ {
+ Number defaultWidthX = (Number) getProperty("defaultWidthX");
+ Number nominalWidthX = (Number) getProperty("nominalWidthX");
+ return new CharStringConverter(defaultWidthX.intValue(), nominalWidthX
+ .intValue(), getGlobalSubrIndex(), getLocalSubrIndex());
+ }
+
+ /**
+ * Creates a CharStringRenderer for this font.
+ * @return the new CharStringRenderer
+ */
+ public CharStringRenderer createRenderer()
+ {
+ return new CharStringRenderer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[name=" + fontname + ", topDict=" + topDict
+ + ", privateDict=" + privateDict + ", encoding=" + fontEncoding
+ + ", charset=" + fontCharset + ", charStringsDict="
+ + charStringsDict + "]";
+ }
+
+
+ /**
+ * Sets the global subroutine index data.
+ * @param globalSubrIndex the IndexData object containing the global subroutines
+ */
+ public void setGlobalSubrIndex(IndexData globalSubrIndex) {
this.globalSubrIndex = globalSubrIndex;
}
- /**
- * Returns the global subroutine index data.
- * @return the dictionary
- */
+ /**
+ * Returns the global subroutine index data.
+ * @return the dictionary
+ */
public IndexData getGlobalSubrIndex() {
return globalSubrIndex;
}
-
- /**
- * Returns the local subroutine index data.
- * @return the dictionary
- */
+
+ /**
+ * Returns the local subroutine index data.
+ * @return the dictionary
+ */
public IndexData getLocalSubrIndex() {
return localSubrIndex;
}
-
- /**
- * Sets the local subroutine index data.
- * @param localSubrIndex the IndexData object containing the local subroutines
- */
+
+ /**
+ * Sets the local subroutine index data.
+ * @param localSubrIndex the IndexData object containing the local subroutines
+ */
public void setLocalSubrIndex(IndexData localSubrIndex) {
this.localSubrIndex = localSubrIndex;
}
/**
- * This class is used for the font mapping.
- *
- */
- public class Mapping
- {
- private int mappedCode;
- private int mappedSID;
- private String mappedName;
- private byte[] mappedBytes;
-
- /**
- * Converts the mapping into a Type1-sequence.
- * @return the Type1-sequence
- * @throws IOException if an error occurs during reading
- */
- public List<Object> toType1Sequence() throws IOException
- {
- CharStringConverter converter = createConverter();
- return converter.convert(toType2Sequence());
- }
-
- /**
- * Converts the mapping into a Type2-sequence.
- * @return the Type2-sequence
- * @throws IOException if an error occurs during reading
- */
- public List<Object> toType2Sequence() throws IOException
- {
- Type2CharStringParser parser = new Type2CharStringParser();
- return parser.parse(getBytes());
- }
-
- /**
- * Gets the value for the code.
- * @return the code
- */
- public int getCode()
- {
- return mappedCode;
- }
-
- private void setCode(int code)
- {
- mappedCode = code;
- }
-
- /**
- * Gets the value for the SID.
- * @return the SID
- */
- public int getSID()
- {
- return mappedSID;
- }
-
- private void setSID(int sid)
- {
- this.mappedSID = sid;
- }
-
- /**
- * Gets the value for the name.
- * @return the name
- */
- public String getName()
- {
- return mappedName;
- }
-
- private void setName(String name)
- {
- this.mappedName = name;
- }
-
- /**
- * Gets the value for the bytes.
- * @return the bytes
- */
- public byte[] getBytes()
- {
- return mappedBytes;
- }
-
- private void setBytes(byte[] bytes)
- {
- this.mappedBytes = bytes;
- }
- }
+ * This class is used for the font mapping.
+ *
+ */
+ public class Mapping
+ {
+ private int mappedCode;
+ private int mappedSID;
+ private String mappedName;
+ private byte[] mappedBytes;
+
+ /**
+ * Converts the mapping into a Type1-sequence.
+ * @return the Type1-sequence
+ * @throws IOException if an error occurs during reading
+ */
+ public List<Object> toType1Sequence() throws IOException
+ {
+ CharStringConverter converter = createConverter();
+ return converter.convert(toType2Sequence());
+ }
+
+ /**
+ * Converts the mapping into a Type2-sequence.
+ * @return the Type2-sequence
+ * @throws IOException if an error occurs during reading
+ */
+ public List<Object> toType2Sequence() throws IOException
+ {
+ Type2CharStringParser parser = new Type2CharStringParser();
+ return parser.parse(getBytes());
+ }
+
+ /**
+ * Gets the value for the code.
+ * @return the code
+ */
+ public int getCode()
+ {
+ return mappedCode;
+ }
+
+ private void setCode(int code)
+ {
+ mappedCode = code;
+ }
+
+ /**
+ * Gets the value for the SID.
+ * @return the SID
+ */
+ public int getSID()
+ {
+ return mappedSID;
+ }
+
+ private void setSID(int sid)
+ {
+ this.mappedSID = sid;
+ }
+
+ /**
+ * Gets the value for the name.
+ * @return the name
+ */
+ public String getName()
+ {
+ return mappedName;
+ }
+
+ private void setName(String name)
+ {
+ this.mappedName = name;
+ }
+
+ /**
+ * Gets the value for the bytes.
+ * @return the bytes
+ */
+ public byte[] getBytes()
+ {
+ return mappedBytes;
+ }
+
+ private void setBytes(byte[] bytes)
+ {
+ this.mappedBytes = bytes;
+ }
+ }
}
\ No newline at end of file
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java?rev=1307491&r1=1307490&r2=1307491&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFontROS.java Fri Mar 30 15:54:12 2012
@@ -141,21 +141,21 @@ public class CFFFontROS extends CFFFont
/**
* Returns the Width value of the given Glyph identifier
*
- * @param SID
+ * @param CID
* @return -1 if the SID is missing from the Font.
* @throws IOException
*/
- public int getWidth(int SID) throws IOException {
+ public int getWidth(int CID) throws IOException {
// ---- search the right FDArray index in the FDSelect according to the Character identifier
// this index will be used to access the private dictionary which contains useful values
// to compute width.
- int fdArrayIndex = this.fdSelect.getFd(SID);
- if (fdArrayIndex == -1 && SID == 0 ) { // --- notdef char
- return super.getWidth(SID);
+ int fdArrayIndex = this.fdSelect.getFd(CID);
+ if (fdArrayIndex == -1 && CID == 0 ) { // --- notdef char
+ return super.getWidth(CID);
} else if (fdArrayIndex == -1) {
return 1000;
}
-
+
Map<String, Object> fontDict = this.fontDictionaries.get(fdArrayIndex);
Map<String, Object> privDict = this.privateDictionaries.get(fdArrayIndex);
@@ -163,7 +163,7 @@ public class CFFFontROS extends CFFFont
int defaultWidth = privDict.containsKey("defaultWidthX") ? ((Number)privDict.get("defaultWidthX")).intValue() : 1000 ;
for (Mapping m : getMappings() ){
- if (m.getSID() == SID) {
+ if (m.getSID() == CID) {
CharStringRenderer csr = null;
Number charStringType = (Number)getProperty("CharstringType");
@@ -183,7 +183,7 @@ public class CFFFontROS extends CFFFont
}
}
- // ---- Width not found, return the default width
- return defaultWidth;
+ // ---- CID Width not found, return the notdef width
+ return getNotDefWidth(defaultWidth, nominalWidth);
}
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java?rev=1307491&r1=1307490&r2=1307491&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/padaf/preflight/font/CFFType0FontContainer.java Fri Mar 30 15:54:12 2012
@@ -63,7 +63,9 @@ public class CFFType0FontContainer exten
}
}
- if (!cidFound) {
+ if (!cidFound && cid != 0) {
+ // 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
GlyphException ge = new GlyphException(ValidationConstants.ERROR_FONTS_GLYPH_MISSING, cid,
"CID " + cid + " is missing from the Composite Font format \""
+ this.font.getBaseFont()+"\"" );