Index: conf/fop.xconf
===================================================================
--- conf/fop.xconf (revision 900314)
+++ conf/fop.xconf (working copy)
@@ -396,6 +396,35 @@
+
+
Index: src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
===================================================================
--- src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java (revision 900314)
+++ src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java (working copy)
@@ -30,9 +30,12 @@
import org.apache.fop.afp.AFPResourceLevel;
import org.apache.fop.afp.AFPResourceLevelDefaults;
+import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.AFPFontCollection;
import org.apache.fop.afp.fonts.AFPFontInfo;
+import org.apache.fop.afp.fonts.AFPFontReader;
import org.apache.fop.afp.fonts.CharacterSet;
+import org.apache.fop.afp.fonts.DoubleByteFont;
import org.apache.fop.afp.fonts.FopCharacterSet;
import org.apache.fop.afp.fonts.OutlineFont;
import org.apache.fop.afp.fonts.RasterFont;
@@ -57,7 +60,7 @@
* AFP Renderer configurator
*/
public class AFPRendererConfigurator extends PrintRendererConfigurator
- implements IFDocumentHandlerConfigurator {
+implements IFDocumentHandlerConfigurator {
/**
* Default constructor
@@ -69,7 +72,7 @@
}
private AFPFontInfo buildFont(Configuration fontCfg, String fontPath)
- throws ConfigurationException {
+ throws ConfigurationException {
FontManager fontManager = this.userAgent.getFactory().getFontManager();
@@ -127,11 +130,33 @@
return null;
}
String encoding = afpFontCfg.getAttribute("encoding");
+
if (encoding == null) {
log.error("Mandatory afp-font configuration attribute 'encoding=' is missing");
return null;
}
+ AFPFont font = fontFromType(type, codepage, encoding, accessor, afpFontCfg);
+
+ return font != null ? new AFPFontInfo(font, tripletList) : null;
+ }
+
+
+ /**
+ * Create the AFPFont based on type and type-dependent configuration.
+ *
+ * @param type font type e.g. 'raster', 'outline'
+ * @param codepage codepage file
+ * @param encoding character encoding e.g. 'Cp500', 'UnicodeBigUnmarked'
+ * @param accessor
+ * @param afpFontCfg
+ * @return
+ * @throws ConfigurationException
+ */
+ private AFPFont fontFromType(String type, String codepage, String encoding,
+ ResourceAccessor accessor, Configuration afpFontCfg)
+ throws ConfigurationException {
+
if ("raster".equalsIgnoreCase(type)) {
String name = afpFontCfg.getAttribute("name", "Unknown");
@@ -161,27 +186,27 @@
if (base14 != null) {
try {
Class clazz = Class.forName("org.apache.fop.fonts.base14."
- + base14);
+ + base14);
try {
Typeface tf = (Typeface)clazz.newInstance();
font.addCharacterSet(sizeMpt, new FopCharacterSet(
- codepage, encoding, characterset, tf));
+ codepage, encoding, characterset, tf));
} catch (Exception ie) {
String msg = "The base 14 font class " + clazz.getName()
- + " could not be instantiated";
+ + " could not be instantiated";
log.error(msg);
}
} catch (ClassNotFoundException cnfe) {
String msg = "The base 14 font class for " + characterset
- + " could not be found";
+ + " could not be found";
log.error(msg);
}
} else {
font.addCharacterSet(sizeMpt, new CharacterSet(
- codepage, encoding, characterset, accessor));
+ codepage, encoding, characterset, accessor));
}
}
- return new AFPFontInfo(font, tripletList);
+ return font;
} else if ("outline".equalsIgnoreCase(type)) {
String characterset = afpFontCfg.getAttribute("characterset");
@@ -195,30 +220,83 @@
if (base14 != null) {
try {
Class clazz = Class.forName("org.apache.fop.fonts.base14."
- + base14);
+ + base14);
try {
Typeface tf = (Typeface)clazz.newInstance();
characterSet = new FopCharacterSet(
codepage, encoding, characterset, tf);
} catch (Exception ie) {
String msg = "The base 14 font class " + clazz.getName()
- + " could not be instantiated";
+ + " could not be instantiated";
log.error(msg);
}
} catch (ClassNotFoundException cnfe) {
String msg = "The base 14 font class for " + characterset
- + " could not be found";
+ + " could not be found";
log.error(msg);
}
} else {
characterSet = new CharacterSet(codepage, encoding, characterset, accessor);
}
+ // Return new font object
+ return new OutlineFont(name, characterSet);
+
+ } else if ("double-byte".equalsIgnoreCase(type)) {
+ String characterset = afpFontCfg.getAttribute("characterset");
+ if (characterset == null) {
+ log.error("Mandatory afp-font configuration attribute 'characterset=' is missing");
+ return null;
+ }
+ String name = afpFontCfg.getAttribute("name", characterset);
+ CharacterSet characterSet = null;
+ characterSet = new CharacterSet(codepage, encoding, characterset, accessor);
+ characterSet.setAFPFontReader(AFPFontReader.getDoubleByteInstance());
+
+
// Create a new font object
- OutlineFont font = new OutlineFont(name, characterSet);
- return new AFPFontInfo(font, tripletList);
+ DoubleByteFont font;
+
+ String fallbackTypeAttr = afpFontCfg.getAttribute("fallback-type", null);
+
+ if (fallbackTypeAttr != null) {
+ String fallbackValueAttr = afpFontCfg.getAttribute("fallback-value", null);
+ if (fallbackTypeAttr.equalsIgnoreCase("char") && fallbackValueAttr != null) {
+
+ try {
+ int fallbackChar;
+ if (fallbackValueAttr.matches("[Uu]\\+.*")) {
+ fallbackChar = Integer.parseInt(fallbackValueAttr.substring(2), 16);
+ } else {
+ fallbackChar = Integer.parseInt(fallbackValueAttr);
+ }
+
+ font = new DoubleByteFont(name, characterSet, fallbackChar);
+ } catch (NumberFormatException e) {
+ font = new DoubleByteFont(name, characterSet);
+ log.warn("The value of the fallback-value attribute is badly formed: '"
+ + fallbackValueAttr + "' not integral.");
+ }
+ } else if (fallbackTypeAttr.equalsIgnoreCase("em")) {
+ // use the em value
+ font = new DoubleByteFont(name, characterSet);
+ } else {
+
+ log.warn("The value of the fallback-type attribute '"
+ + fallbackTypeAttr + "' is not recognised.");
+ font = new DoubleByteFont(name, characterSet);
+ }
+
+ } else {
+ font = new DoubleByteFont(name, characterSet);
+ }
+
+
+ return font;
+
} else {
log.error("No or incorrect type attribute");
}
+
return null;
}
@@ -230,7 +308,7 @@
* @throws ConfigurationException if something's wrong with the config data
*/
private List/**/ buildFontListFromConfiguration(Configuration cfg)
- throws FOPException, ConfigurationException {
+ throws FOPException, ConfigurationException {
Configuration fonts = cfg.getChild("fonts");
FontManager fontManager = this.userAgent.getFactory().getFontManager();
@@ -261,9 +339,9 @@
FontTriplet triplet = (FontTriplet) fontTriplets.get(j);
if (log.isDebugEnabled()) {
log.debug(" Font triplet "
- + triplet.getName() + ", "
- + triplet.getStyle() + ", "
- + triplet.getWeight());
+ + triplet.getName() + ", "
+ + triplet.getStyle() + ", "
+ + triplet.getWeight());
}
if ((referencedFontsMatcher != null && referencedFontsMatcher.matches(triplet))
@@ -346,7 +424,7 @@
// a default external resource group file setting
Configuration resourceGroupFileCfg
- = cfg.getChild("resource-group-file", false);
+ = cfg.getChild("resource-group-file", false);
if (resourceGroupFileCfg != null) {
String resourceGroupDest = null;
try {
@@ -358,14 +436,15 @@
customizable.setDefaultResourceGroupFilePath(resourceGroupDest);
} else {
log.warn("Unable to write to default external resource group file '"
- + resourceGroupDest + "'");
+ + resourceGroupDest + "'");
}
}
} catch (ConfigurationException e) {
LogUtil.handleException(log, e,
userAgent.getFactory().validateUserConfigStrictly());
} catch (IOException ioe) {
- throw new FOPException("Could not create default external resource group file", ioe);
+ throw new FOPException("Could not create default external resource group file"
+ , ioe);
}
}
@@ -401,7 +480,7 @@
/** {@inheritDoc} */
public void setupFontInfo(IFDocumentHandler documentHandler, FontInfo fontInfo)
- throws FOPException {
+ throws FOPException {
FontManager fontManager = userAgent.getFactory().getFontManager();
List fontCollections = new java.util.ArrayList();
Index: src/java/org/apache/fop/afp/modca/MapCodedFont.java
===================================================================
--- src/java/org/apache/fop/afp/modca/MapCodedFont.java (revision 900314)
+++ src/java/org/apache/fop/afp/modca/MapCodedFont.java (working copy)
@@ -29,6 +29,7 @@
import org.apache.fop.afp.AFPConstants;
import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.CharacterSet;
+import org.apache.fop.afp.fonts.DoubleByteFont;
import org.apache.fop.afp.fonts.FontRuntimeException;
import org.apache.fop.afp.fonts.OutlineFont;
import org.apache.fop.afp.fonts.RasterFont;
@@ -217,6 +218,24 @@
AFPConstants.EBCIDIC_ENCODING)
+ " must have a fixed length of 8 characters.");
}
+ } else if (font instanceof DoubleByteFont) {
+ DoubleByteFont outline = (DoubleByteFont) font;
+ CharacterSet cs = outline.getCharacterSet();
+ fontDefinition.characterSet = cs.getNameBytes();
+
+ // There are approximately 72 points to 1 inch or 20 1440ths per point.
+
+ fontDefinition.scale = 20 * size / 1000;
+
+ fontDefinition.codePage = cs.getCodePage().getBytes(
+ AFPConstants.EBCIDIC_ENCODING);
+
+ if (fontDefinition.codePage.length != 8) {
+ throw new IllegalArgumentException("The code page "
+ + new String(fontDefinition.codePage,
+ AFPConstants.EBCIDIC_ENCODING)
+ + " must have a fixed length of 8 characters.");
+ }
} else {
String msg = "Font of type " + font.getClass().getName()
+ " not recognized.";
Index: src/java/org/apache/fop/afp/fonts/OutlineFont.java
===================================================================
--- src/java/org/apache/fop/afp/fonts/OutlineFont.java (revision 900314)
+++ src/java/org/apache/fop/afp/fonts/OutlineFont.java (working copy)
@@ -21,163 +21,17 @@
/**
- * A font defined as a set of lines and curves as opposed to a bitmap font. An
- * outline font can be scaled to any size and otherwise transformed more easily
- * than a bitmap font, and with more attractive results.
+ * Default implementation of AbstractOutlineFont.
*
*/
-public class OutlineFont extends AFPFont {
+public class OutlineFont extends AbstractOutlineFont {
- /** The character set for this font */
- private CharacterSet charSet = null;
-
- /**
- * Constructor for an outline font.
- *
- * @param name
- * the name of the font
- * @param charSet
- * the chracter set
- */
+ /** {@inheritDoc} */
public OutlineFont(String name, CharacterSet charSet) {
- super(name);
- this.charSet = charSet;
- }
+ super(name, charSet);
- /**
- * Get the character set metrics.
- *
- * @return the character set
- */
- public CharacterSet getCharacterSet() {
-
- return charSet;
-
}
- /**
- * Get the character set metrics.
- * @param size ignored
- * @return the character set
- */
- public CharacterSet getCharacterSet(int size) {
- return charSet;
- }
-
- /**
- * Get the first character in this font.
- * @return the first character in this font
- */
- public int getFirstChar() {
- return charSet.getFirstChar();
- }
-
- /**
- * Get the last character in this font.
- * @return the last character in this font
- */
- public int getLastChar() {
- return charSet.getLastChar();
- }
-
- /**
- * The ascender is the part of a lowercase letter that extends above the
- * "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also
- * used to denote the part of the letter extending above the x-height.
- *
- * @param size the font size (in mpt)
- * @return the ascender for the given size
- */
- public int getAscender(int size) {
- return charSet.getAscender() * size;
- }
-
- /**
- * Obtains the height of capital letters for the specified point size.
- *
- * @param size the font size (in mpt)
- * @return the cap height for the given size
- */
- public int getCapHeight(int size) {
- return charSet.getCapHeight() * size;
- }
-
- /**
- * The descender is the part of a lowercase letter that extends below the
- * base line, such as "g", "j", or "p". Also used to denote the part of the
- * letter extending below the base line.
- *
- * @param size the font size (in mpt)
- * @return the descender for the given size
- */
- public int getDescender(int size) {
- return charSet.getDescender() * size;
- }
-
- /**
- * The "x-height" (the height of the letter "x").
- *
- * @param size the font size (in mpt)
- * @return the x height for the given size
- */
- public int getXHeight(int size) {
- return charSet.getXHeight() * size;
- }
-
- /**
- * Obtain the width of the character for the specified point size.
- * @param character the character
- * @param size the font size (in mpt)
- * @return the width of the character for the specified point size
- */
- public int getWidth(int character, int size) {
- return charSet.getWidth(character) * size;
- }
-
- /**
- * Get the getWidth (in 1/1000ths of a point size) of all characters in this
- * character set.
- *
- * @param size the font size (in mpt)
- * @return the widths of all characters
- */
- public int[] getWidths(int size) {
- int[] widths = charSet.getWidths();
- for (int i = 0; i < widths.length; i++) {
- widths[i] = widths[i] * size;
- }
- return widths;
- }
-
- /**
- * Get the getWidth (in 1/1000ths of a point size) of all characters in this
- * character set.
- *
- * @return the widths of all characters
- */
- public int[] getWidths() {
- return getWidths(1000);
- }
-
- /** {@inheritDoc} */
- public boolean hasChar(char c) {
- return charSet.hasChar(c);
- }
-
- /**
- * Map a Unicode character to a code point in the font.
- * @param c character to map
- * @return the mapped character
- */
- public char mapChar(char c) {
- return charSet.mapChar(c);
- }
-
- /** {@inheritDoc} */
- public String getEncodingName() {
- return charSet.getEncoding();
- }
-
}
\ No newline at end of file
Index: src/java/org/apache/fop/afp/fonts/CharacterSet.java
===================================================================
--- src/java/org/apache/fop/afp/fonts/CharacterSet.java (revision 900314)
+++ src/java/org/apache/fop/afp/fonts/CharacterSet.java (working copy)
@@ -60,7 +60,7 @@
public class CharacterSet {
/** Static logging instance */
- protected static final Log log = LogFactory.getLog(CharacterSet.class.getName());
+ protected static final Log LOG = LogFactory.getLog(CharacterSet.class.getName());
/** default codepage */
public static final String DEFAULT_CODEPAGE = "T1V10500";
@@ -98,6 +98,9 @@
/** The nominal vertical size (in millipoints) for bitmap fonts. 0 for outline fonts. */
private int nominalVerticalSize = 0;
+ /** The AFPFontReader for extracting font metrics */
+ private AFPFontReader afpFontReader = AFPFontReader.getInstance();
+
/**
* Constructor for the CharacterSetMetric object, the character set is used
* to load the font information from the actual AFP font.
@@ -126,7 +129,7 @@
if (name.length() > MAX_NAME_LEN) {
String msg = "Character set name '" + name + "' must be a maximum of "
+ MAX_NAME_LEN + " characters";
- log.error("Constructor:: " + msg);
+ LOG.error("Constructor:: " + msg);
throw new IllegalArgumentException(msg);
}
@@ -286,13 +289,12 @@
*/
private void load() {
if (!isMetricsLoaded) {
- AFPFontReader afpFontReader = new AFPFontReader();
try {
afpFontReader.loadCharacterSetMetric(this);
isMetricsLoaded = true;
} catch (IOException e) {
String msg = "Failed to load the character set metrics for code page " + codePage;
- log.error(msg);
+ LOG.error(msg);
throw new RuntimeException(e.getMessage());
}
}
@@ -318,7 +320,7 @@
nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
} catch (UnsupportedEncodingException usee) {
nameBytes = name.getBytes();
- log.warn(
+ LOG.warn(
"UnsupportedEncodingException translating the name " + name);
}
return nameBytes;
@@ -417,4 +419,21 @@
return c;
}
+ /**
+ *The AFPFontReader is used to extract font metric data
+ * @param afpFontReader to set
+ */
+ public void setAFPFontReader(AFPFontReader afpFontReader) {
+ this.afpFontReader = afpFontReader;
+ }
+
+ /**
+ *
+ * @return the number units per em
+ */
+ public int getEmSpaceIncrement() {
+ load();
+ return getCharacterSetOrientation().getUnitsPerEm();
+ }
+
}
Index: src/java/org/apache/fop/afp/fonts/AFPFontReader.java
===================================================================
--- src/java/org/apache/fop/afp/fonts/AFPFontReader.java (revision 900314)
+++ src/java/org/apache/fop/afp/fonts/AFPFontReader.java (working copy)
@@ -49,14 +49,13 @@
* files in order to determine the correct metrics to use when rendering the
* formatted object.
*
- * @author Pete Townsend
*/
-public final class AFPFontReader {
+public class AFPFontReader {
/**
* Static logging instance
*/
- protected static final Log log = LogFactory.getLog(AFPFontReader.class);
+ protected static final Log LOG = LogFactory.getLog(AFPFontReader.class);
/**
* Template used to convert lists to arrays.
@@ -97,16 +96,36 @@
private final Map/*>*/ codePagesCache
= new java.util.HashMap/*>*/();
+
+ private AFPFontReader() { }
+
/**
+ * Factory method for the single-byte implementation of AFPFontReader.
+ * @return AFPFontReader
+ */
+ public static AFPFontReader getInstance() {
+ return new AFPFontReader();
+ }
+
+ /**
+ * Factory method for the double-byte (CID Keyed font (Type 0)) implementation of AFPFontReader.
+ * @return AFPFontReader
+ */
+ public static AFPFontReader getDoubleByteInstance() {
+ return new DoubleByteAFPFontReader();
+ }
+
+
+ /**
* Returns an InputStream to a given file path and filename
*
- * @param path the file path
+ * * @param accessor the resource accessor
* @param filename the file name
* @return an inputStream
*
* @throws IOException in the event that an I/O exception of some sort has occurred
*/
- private InputStream openInputStream(ResourceAccessor accessor, String filename)
+ protected InputStream openInputStream(ResourceAccessor accessor, String filename)
throws IOException {
URI uri;
try {
@@ -124,14 +143,14 @@
*
* @param inputStream the inputstream to close
*/
- private void closeInputStream(InputStream inputStream) {
+ protected void closeInputStream(InputStream inputStream) {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (Exception ex) {
// Lets log at least!
- log.error(ex.getMessage());
+ LOG.error(ex.getMessage());
}
}
@@ -229,8 +248,9 @@
* the encoding to use for the character decoding
* @param accessor the resource accessor
* @returns a code page mapping
+ * @throws IOException if an I/O exception of some sort has occurred.
*/
- private Map/**/ loadCodePage(String codePage, String encoding,
+ protected Map/**/ loadCodePage(String codePage, String encoding,
ResourceAccessor accessor) throws IOException {
// Create the HashMap to store code page information
@@ -277,8 +297,10 @@
*
* @param structuredFieldReader the structured field reader
* @return a class representing the font descriptor
+ * @throws IOException if an I/O exception of some sort has occurred.
*/
- private static FontDescriptor processFontDescriptor(StructuredFieldReader structuredFieldReader)
+ protected static FontDescriptor processFontDescriptor(
+ StructuredFieldReader structuredFieldReader)
throws IOException {
byte[] fndData = structuredFieldReader.getNext(FONT_DESCRIPTOR_SF);
@@ -290,8 +312,10 @@
*
* @param structuredFieldReader
* the structured field reader
+ * @return the FontControl
+ * @throws IOException if an I/O exception of some sort has occurred.
*/
- private FontControl processFontControl(StructuredFieldReader structuredFieldReader)
+ protected FontControl processFontControl(StructuredFieldReader structuredFieldReader)
throws IOException {
byte[] fncData = structuredFieldReader.getNext(FONT_CONTROL_SF);
@@ -320,8 +344,10 @@
*
* @param structuredFieldReader
* the structured field reader
+ * @return CharacterSetOrientation array
+ * @throws IOException if an I/O exception of some sort has occurred.
*/
- private CharacterSetOrientation[] processFontOrientation(
+ protected CharacterSetOrientation[] processFontOrientation(
StructuredFieldReader structuredFieldReader) throws IOException {
byte[] data = structuredFieldReader.getNext(FONT_ORIENTATION_SF);
@@ -381,8 +407,9 @@
* the array of CharacterSetOrientation objects
* @param metricNormalizationFactor factor to apply to the metrics to get normalized
* font metric values
+ * @throws IOException if an I/O exception of some sort has occurred.
*/
- private void processFontPosition(StructuredFieldReader structuredFieldReader,
+ protected void processFontPosition(StructuredFieldReader structuredFieldReader,
CharacterSetOrientation[] characterSetOrientations, double metricNormalizationFactor)
throws IOException {
@@ -437,8 +464,9 @@
* @param codepage the map of code pages
* @param metricNormalizationFactor factor to apply to the metrics to get normalized
* font metric values
+ * @throws IOException if an I/O exception of some sort has occurred.
*/
- private void processFontIndex(StructuredFieldReader structuredFieldReader,
+ protected void processFontIndex(StructuredFieldReader structuredFieldReader,
CharacterSetOrientation cso, Map/**/ codepage,
double metricNormalizationFactor)
throws IOException {
@@ -485,8 +513,8 @@
double diffPercent = 100 * diff / (double)width;
//if difference > 2%
if (diffPercent > 2) {
- if (log.isTraceEnabled()) {
- log.trace(gcgiString + ": "
+ if (LOG.isTraceEnabled()) {
+ LOG.trace(gcgiString + ": "
+ a + " + " + b + " + " + c + " = " + (a + b + c)
+ " but found: " + width);
}
@@ -516,9 +544,9 @@
cso.setFirstChar(lowest);
cso.setLastChar(highest);
- if (log.isDebugEnabled() && firstABCMismatch != null) {
+ if (LOG.isDebugEnabled() && firstABCMismatch != null) {
//Debug level because it usually is no problem.
- log.debug("Font has metrics inconsitencies where A+B+C doesn't equal the"
+ LOG.debug("Font has metrics inconsitencies where A+B+C doesn't equal the"
+ " character increment. The first such character found: "
+ firstABCMismatch);
}
@@ -584,4 +612,115 @@
}
}
+ /**
+ * Double-byte (CID Keyed font (Type 0)) implementation of AFPFontReader.
+ */
+ private static class DoubleByteAFPFontReader extends AFPFontReader {
+
+ protected Map/**/ loadCodePage(String codePage, String encoding,
+ ResourceAccessor accessor) throws IOException {
+
+ // Create the HashMap to store code page information
+ Map/**/ codePages = new java.util.HashMap/**/();
+
+ InputStream inputStream = null;
+ try {
+ inputStream = openInputStream(accessor, codePage.trim());
+
+ StructuredFieldReader structuredFieldReader
+ = new StructuredFieldReader(inputStream);
+ byte[] data; // = structuredFieldReader.getNext(CHARACTER_TABLE_SF);
+ while ((data = structuredFieldReader.getNext(CHARACTER_TABLE_SF)) != null) {
+ int position = 0;
+
+ byte[] gcgiBytes = new byte[8];
+ byte[] charBytes = new byte[2];
+ // Read data, ignoring bytes 0 - 2
+ for (int index = 3; index < data.length; index++) {
+
+ if (position < 8) {
+ // Build the graphic character global identifier key
+ gcgiBytes[position] = data[index];
+ position++;
+ } else if (position == 9) {
+ // Set the character
+ charBytes[0] = data[index];
+ position++;
+ } else if (position == 10) {
+ position = 0;
+ // Set the character
+ charBytes[1] = data[index];
+
+ String gcgiString = new String(gcgiBytes,
+ AFPConstants.EBCIDIC_ENCODING);
+ String charString = new String(charBytes, encoding);
+ codePages.put(gcgiString, charString);
+
+ }
+ else {
+ position++;
+ }
+ }
+ }
+ } finally {
+ closeInputStream(inputStream);
+ }
+
+ return codePages;
+ }
+
+ protected CharacterSetOrientation[] processFontOrientation(
+ StructuredFieldReader structuredFieldReader) throws IOException {
+
+ byte[] data = structuredFieldReader.getNext(FONT_ORIENTATION_SF);
+
+ int position = 0;
+ byte[] fnoData = new byte[26];
+
+ List orientations = new java.util.ArrayList();
+
+ // Read data, ignoring bytes 0 - 2
+ for (int index = 3; index < data.length; index++) {
+ // Build the font orientation record
+ fnoData[position] = data[index];
+ position++;
+
+ if (position == 26) {
+
+ position = 0;
+
+ int orientation = 0;
+
+ switch (fnoData[2]) {
+ case 0x00:
+ orientation = 0;
+ break;
+ case 0x2D:
+ orientation = 90;
+ break;
+ case 0x5A:
+ orientation = 180;
+ break;
+ case (byte) 0x87:
+ orientation = 270;
+ break;
+ default:
+ System.out.println("ERROR: Oriantation");
+ }
+
+ // Em-Space Increment
+ int em = ((fnoData[14] & 0xFF ) << 8) + (fnoData[15] & 0xFF);
+
+ CharacterSetOrientation cso = new CharacterSetOrientation(
+ orientation, em);
+ orientations.add(cso);
+
+ }
+ }
+
+ return (CharacterSetOrientation[]) orientations
+ .toArray(EMPTY_CSO_ARRAY);
+ }
+ }
+
}
Index: src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java
===================================================================
--- src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java (revision 900314)
+++ src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java (working copy)
@@ -19,6 +19,8 @@
package org.apache.fop.afp.fonts;
+import java.util.Arrays;
+
/**
* The IBM Font Object Content Architecture (FOCA) supports presentation
* of character shapes by defining their characteristics, which include
@@ -58,7 +60,7 @@
/**
* The character widths in the character set
*/
- private int[] charsWidths = new int[256];
+ private int[] charsWidths = null;
/**
* The height of lowercase letters
@@ -82,15 +84,33 @@
private int orientation = 0;
/**
+ * Units per em
+ */
+ private int unitsPerEm = -1;
+ /**
* Constructor for the CharacterSetOrientation, the orientation is
* expressed as the degrees rotation (i.e 0, 90, 180, 270)
* @param orientation the character set orientation
*/
public CharacterSetOrientation(int orientation) {
this.orientation = orientation;
+ charsWidths = new int[256];
+ Arrays.fill(charsWidths, -1);
}
/**
+ * Constructor for the CharacterSetOrientation, the orientation is
+ * expressed as the degrees rotation (i.e 0, 90, 180, 270)
+ * @param orientation the character set orientation
+ * @param unitsPerEm the units per em
+ */
+ public CharacterSetOrientation(int orientation, int unitsPerEm) {
+ this(orientation);
+ this.unitsPerEm = unitsPerEm;
+
+ }
+
+ /**
* Ascender height is the distance from the character baseline to the
* top of the character box. A negative ascender height signifies that
* all of the graphic character is below the character baseline. For
@@ -245,8 +265,10 @@
public void setWidth(int character, int width) {
if (character >= charsWidths.length) {
// Increase the size of the array if necessary
+ // TODO Can we remove firstChar? surely firstChar==0 at this stage?
int[] arr = new int[(character - firstChar) + 1];
System.arraycopy(charsWidths, 0, arr, 0, charsWidths.length);
+ Arrays.fill(arr, charsWidths.length, character - firstChar, -1);
charsWidths = arr;
}
charsWidths[character] = width;
@@ -261,4 +283,13 @@
public void setXHeight(int xHeight) {
this.xHeight = xHeight;
}
+
+ /**
+ *
+ * @return units per em
+ */
+
+ public int getUnitsPerEm(){
+ return this.unitsPerEm;
+ }
}
Index: src/java/org/apache/fop/afp/fonts/DoubleByteFont.java
===================================================================
--- src/java/org/apache/fop/afp/fonts/DoubleByteFont.java (revision 0)
+++ src/java/org/apache/fop/afp/fonts/DoubleByteFont.java (revision 0)
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+/* $Id: OutlineFont.java 791781 2009-07-07 10:21:07Z cbowditch $ */
+
+package org.apache.fop.afp.fonts;
+
+import java.util.HashSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * Implementation of AbstractOutlineFont that supports double-byte fonts (CID Keyed font (Type 0)).
+ * The width of characters that are not prescribed a width metrics in the font resource use
+ * a fallback width. The default width is 1 em. A character can be supplied and queried for the
+ * fallback width of all non-ideograph characters.
+ */
+public class DoubleByteFont extends AbstractOutlineFont {
+
+ private static final Log LOG = LogFactory.getLog(DoubleByteFont.class);
+
+ private static final HashSet IDEOGRAPHIC = new HashSet();
+ static {
+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS);
+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT);
+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS);
+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A);
+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B);
+ }
+
+ /* The fallback character is used for assigning width metrics to characters
+ with no mapped width in font resource*/
+ private int fallbackChar;
+
+ // lazy assigned fallbackCharWidth
+ private int fallbackCharWidth = -1; // -1 to code for not assigned
+ // lazy assigned emWidth
+ private int emWidth = -1; // -1 to code for not assigned
+ // use em as fallback width
+ private boolean isFallbackEmWidth = true;
+
+
+ /**
+ * Constructor for an double-byte outline font.
+ *
+ * @param name
+ * the name of the font
+ * @param charSet
+ * the character set
+
+ */
+ public DoubleByteFont(String name, CharacterSet charSet) {
+ super(name, charSet);
+
+ }
+
+ /**
+ * Constructor for an outline font.
+ *
+ * @param name
+ * the name of the font
+ * @param charSet
+ * the character set
+ * @param fallbackCharacter
+ * fallback character for assigning width metrics to characters
+ * with no mapped width in font resource
+ */
+ public DoubleByteFont(String name, CharacterSet charSet, int fallbackCharacter) {
+ super(name, charSet);
+ this.fallbackChar = fallbackCharacter;
+ this.isFallbackEmWidth = false;
+ }
+
+
+
+
+ /** {@inheritDoc} */
+ public int getWidth(int character, int size) {
+ int charWidth;
+ try {
+ charWidth = charSet.getWidth(character);
+ } catch (IllegalArgumentException e) {
+ // We shall try and handle characters that have no mapped width metric in font resource
+ charWidth = -1;
+ }
+
+ if (charWidth == -1) {
+ charWidth = inferCharWidth(character);
+ }
+ return charWidth * size;
+ }
+
+
+
+ private int inferCharWidth(int character) {
+
+ //Is this character an ideograph?
+ boolean isIdeographic = false;
+ Character.UnicodeBlock charBlock = Character.UnicodeBlock.of(character);
+ if (charBlock == null) {
+ isIdeographic = false;
+ } else if (IDEOGRAPHIC.contains(charBlock)) {
+ isIdeographic = true;
+ } else { //default
+ isIdeographic = false;
+ }
+
+ return isIdeographic ? getEmWidth() : getFallbackWidth();
+ }
+
+
+ private int getEmWidth() {
+
+ if (emWidth == -1) {
+
+ int width = charSet.getEmSpaceIncrement();
+
+ LOG.debug("em is " + width);
+
+ if (width == -1) {
+ LOG.warn("Could not determine 'em' of font " + name
+ + ".\n\tUsing the fallback width instead.)");
+ width = 0;
+ }
+ emWidth = width;
+ }
+
+ return emWidth;
+
+ }
+
+ private int getFallbackWidth() {
+ //We shall cache the width in fallbackCharWidth
+
+ if (isFallbackEmWidth) {
+ return getEmWidth();
+ } else {
+ if (fallbackCharWidth == -1) {
+ // cache the
+ try {
+ fallbackCharWidth = charSet.getWidth(fallbackChar);
+
+ if (fallbackCharWidth == -1) {
+ LOG.warn("No width metric found for the FALLBACK character (codepoint="
+ + fallbackChar + ") in font " + name);
+ fallbackCharWidth = getEmWidth();
+ }
+ } catch (IllegalArgumentException e) {
+ LOG.warn("No width metric found for the FALLBACK character (codepoint="
+ + fallbackChar + ") in font " + name);
+ fallbackCharWidth = getEmWidth();
+ }
+ LOG.warn("Fallback width of font " + name + " is "
+ + fallbackCharWidth + "*font-size");
+ }
+ return fallbackCharWidth;
+ }
+
+ }
+
+
+}
Index: src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java
===================================================================
--- src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java (revision 0)
+++ src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java (revision 0)
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+
+/* $Id:$ */
+
+package org.apache.fop.afp.fonts;
+
+
+/**
+ * A font defined as a set of lines and curves as opposed to a bitmap font. An
+ * outline font can be scaled to any size and otherwise transformed more easily
+ * than a bitmap font, and with more attractive results.
+ *
+ */
+public abstract class AbstractOutlineFont extends AFPFont {
+
+ /** The character set for this font */
+ protected CharacterSet charSet = null;
+
+ /**
+ * Constructor for an outline font.
+ *
+ * @param name
+ * the name of the font
+ * @param charSet
+ * the chracter set
+ */
+ public AbstractOutlineFont(String name, CharacterSet charSet) {
+ super(name);
+ this.charSet = charSet;
+ }
+
+ /**
+ * Get the character set metrics.
+ *
+ * @return the character set
+ */
+ public CharacterSet getCharacterSet() {
+
+ return charSet;
+
+ }
+
+ /**
+ * Get the character set metrics.
+ * @param size ignored
+ * @return the character set
+ */
+ public CharacterSet getCharacterSet(int size) {
+
+ return charSet;
+
+ }
+
+ /**
+ * Get the first character in this font.
+ * @return the first character in this font
+ */
+ public int getFirstChar() {
+ return charSet.getFirstChar();
+ }
+
+ /**
+ * Get the last character in this font.
+ * @return the last character in this font
+ */
+ public int getLastChar() {
+ return charSet.getLastChar();
+ }
+
+ /**
+ * The ascender is the part of a lowercase letter that extends above the
+ * "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also
+ * used to denote the part of the letter extending above the x-height.
+ *
+ * @param size the font size (in mpt)
+ * @return the ascender for the given size
+ */
+ public int getAscender(int size) {
+ return charSet.getAscender() * size;
+ }
+
+ /**
+ * Obtains the height of capital letters for the specified point size.
+ *
+ * @param size the font size (in mpt)
+ * @return the cap height for the given size
+ */
+ public int getCapHeight(int size) {
+ return charSet.getCapHeight() * size;
+ }
+
+ /**
+ * The descender is the part of a lowercase letter that extends below the
+ * base line, such as "g", "j", or "p". Also used to denote the part of the
+ * letter extending below the base line.
+ *
+ * @param size the font size (in mpt)
+ * @return the descender for the given size
+ */
+ public int getDescender(int size) {
+ return charSet.getDescender() * size;
+ }
+
+ /**
+ * The "x-height" (the height of the letter "x").
+ *
+ * @param size the font size (in mpt)
+ * @return the x height for the given size
+ */
+ public int getXHeight(int size) {
+ return charSet.getXHeight() * size;
+ }
+
+ /**
+ * Obtain the width of the character for the specified point size.
+ * @param character the character
+ * @param size the font size (in mpt)
+ * @return the width of the character for the specified point size
+ */
+ public int getWidth(int character, int size) {
+ return charSet.getWidth(character) * size;
+ }
+
+ /**
+ * Get the getWidth (in 1/1000ths of a point size) of all characters in this
+ * character set.
+ *
+ * @param size the font size (in mpt)
+ * @return the widths of all characters
+ */
+ public int[] getWidths(int size) {
+ int[] widths = charSet.getWidths();
+ for (int i = 0; i < widths.length; i++) {
+ widths[i] = widths[i] * size;
+ }
+ return widths;
+ }
+
+ /**
+ * Get the getWidth (in 1/1000ths of a point size) of all characters in this
+ * character set.
+ *
+ * @return the widths of all characters
+ */
+ public int[] getWidths() {
+ return getWidths(1000);
+ }
+
+ /** {@inheritDoc} */
+ public boolean hasChar(char c) {
+ return charSet.hasChar(c);
+ }
+
+ /**
+ * Map a Unicode character to a code point in the font.
+ * @param c character to map
+ * @return the mapped character
+ */
+ public char mapChar(char c) {
+ return charSet.mapChar(c);
+ }
+
+ /** {@inheritDoc} */
+ public String getEncodingName() {
+ return charSet.getEncoding();
+ }
+
+}
\ No newline at end of file